Skip to content

feat: #246 new v5 EmptyData #267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 30, 2025
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`EmptyData > should render default component properly and match snapshot 1`] = `
<DocumentFragment>
<div
class="mocked-styled-3 el-empty-data"
>
<p
class="mocked-styled-0 el-empty-data-description"
>
Description
</p>
<p
class="mocked-styled-1 el-empty-data-secondary-description"
>
Secondary Description
</p>
<button
class="mocked-styled-2 el-empty-data-action-button"
>
Action Button Text
</button>
</div>
</DocumentFragment>
`;
15 changes: 15 additions & 0 deletions src/components/empty-data/__tests__/empty-data.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { render } from '@testing-library/react'
import { EmptyData } from '..'

describe('EmptyData', () => {
it('should render default component properly and match snapshot', () => {
const { asFragment } = render(
<EmptyData>
<EmptyData.Description>Description</EmptyData.Description>
<EmptyData.SecondaryDescription>Secondary Description</EmptyData.SecondaryDescription>
<EmptyData.ActionButton onClick={console.log}>Action Button Text</EmptyData.ActionButton>
</EmptyData>,
)
expect(asFragment()).toMatchSnapshot()
})
})
32 changes: 32 additions & 0 deletions src/components/empty-data/empty-data.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Meta, Canvas, Controls, Description } from '@storybook/blocks'
import { RenderHtmlMarkup } from '../../storybook/render-html-markup'
import * as EmptyDataStories from './empty-data.stories'

<Meta of={EmptyDataStories} />


# Empty Data

<Description of={EmptyDataStories.Default} />

<Controls />

## Default

<Canvas of={EmptyDataStories.Default} />

<RenderHtmlMarkup of={EmptyDataStories.Default} />

## Description Only

<Canvas of={EmptyDataStories.DescriptionOnly} />

<RenderHtmlMarkup of={EmptyDataStories.DescriptionOnly} />


## Action Only

<Canvas of={EmptyDataStories.ActionOnly} />

<RenderHtmlMarkup of={EmptyDataStories.ActionOnly} />

49 changes: 49 additions & 0 deletions src/components/empty-data/empty-data.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { Meta, StoryObj } from '@storybook/react'
import { EmptyData } from './empty-data'

const meta: Meta<typeof EmptyData> = {
title: 'Components/Empty Data',
}

export default meta
type Story = StoryObj<typeof EmptyData>

/**
* The EmptyData component is designed to emphasize that current section of the page
* has empty data, but could possibly have different content when there is data available.
*
* There are three variants available for the EmptyData component:
* Default (full version), Description Only, and Action Only.
* See the examples below for more details of the usage.
*/
export const Default: Story = {
render() {
return (
<EmptyData>
<EmptyData.Description>No items found</EmptyData.Description>
<EmptyData.SecondaryDescription>Secondary text</EmptyData.SecondaryDescription>
<EmptyData.ActionButton onClick={console.log}>Add Item</EmptyData.ActionButton>
</EmptyData>
)
},
}

export const DescriptionOnly: Story = {
render() {
return (
<EmptyData>
<EmptyData.Description>No items found</EmptyData.Description>
<EmptyData.SecondaryDescription>Secondary text</EmptyData.SecondaryDescription>
</EmptyData>
)
},
}
export const ActionOnly: Story = {
render() {
return (
<EmptyData>
<EmptyData.ActionButton onClick={console.log}>Action</EmptyData.ActionButton>
</EmptyData>
)
},
}
17 changes: 17 additions & 0 deletions src/components/empty-data/empty-data.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { HTMLAttributes } from 'react'
import { ElEmptyData, ElEmptyDataActionButton, ElEmptyDataDescription, ElEmptyDataSecondaryDescription } from './styles'
import type React from 'react'

type EmptyDataFC = React.FC<HTMLAttributes<HTMLDivElement>> & {
Description: typeof ElEmptyDataDescription
SecondaryDescription: typeof ElEmptyDataSecondaryDescription
ActionButton: typeof ElEmptyDataActionButton
}

const EmptyData: EmptyDataFC = ({ children, ...props }) => <ElEmptyData {...props}>{children}</ElEmptyData>

EmptyData.Description = ElEmptyDataDescription
EmptyData.SecondaryDescription = ElEmptyDataSecondaryDescription
EmptyData.ActionButton = ElEmptyDataActionButton

export { EmptyData }
2 changes: 2 additions & 0 deletions src/components/empty-data/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './empty-data'
export * from './styles'
52 changes: 52 additions & 0 deletions src/components/empty-data/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { styled } from '@linaria/react'

export const ElEmptyDataDescription = styled.p`
color: var(--text-primary);
font-size: var(--font-size-base);
font-weight: var(--font-weight-regular);
line-height: var(--line-height-base);
letter-spacing: var(--letter-spacing-base);
text-align: center;
`

export const ElEmptyDataSecondaryDescription = styled.p`
color: var(--text-secondary);
font-size: var(--font-size-sm,);
font-weight: var(--font-weight-regular,);
line-height: var(--line-height-sm,);
letter-spacing: var(--letter-spacing-sm);
text-align: center;
`

export const ElEmptyDataActionButton = styled.button`
color: var(--text-action);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
line-height: var(--line-height-sm);
letter-spacing: var(--letter-spacing-sm);

text-align: center;
border: none;
background: none;
cursor: pointer;
`

export const ElEmptyData = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: var(--size-40);
padding: var(--spacing-6);
border-radius: var(--corner-lg);
background: var(--fill-default-lightest);

${ElEmptyDataSecondaryDescription} + ${ElEmptyDataActionButton} {
margin-top: var(--spacing-1);
}

& * {
font-family: var(--font-family);
}
`
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export * from './components/skeleton'
export * from './components/tooltip'
export * from './components/table/table-container'
export * from './components/table/table-toolbar'
export * from './components/empty-data'

export * from './hooks/use-portal'
export * from './hooks/use-snack'
Expand Down