UNPKG

@wix/design-system

Version:

@wix/design-system

397 lines (367 loc) 11.1 kB
## Feature Examples ### Structure - description: <p>An empty state has 4 optional elements:</p><li><code>image</code></li><li><code>title</code></li><li><code>subtitle</code></li><li><code>child container,</code> which can hold any component but is primarily reserved for CTA buttons.</li><p></p> - example: ```jsx <EmptyState image={<Image width="120px" height="120px" />} title="Title" subtitle="Subtitle" > <StorybookComponents.Placeholder>Child container</StorybookComponents.Placeholder> </EmptyState>; ``` ### Skin - description: <p>Control an empty state's appearance with the <code>skin</code> property. There are 3 types:</p><li><code>page</code> is for full-page empty states where data is displayed in a full-width table or a card.</li><li><code>page-no-border</code> is for full-page empty states where data is displayed in an unknown layout.</li><li><code>section</code> is the default theme for layout elements such as cards, tables or modals.</li> - example: ```jsx <StorybookComponents.Stack flexDirection="column" gap="48px"> <EmptyState image={<Image width="120px" height="120px" />} skin="page" title="Page theme" subtitle="A subtitle guides users to their next step." /> <EmptyState image={<Image width="120px" height="120px" />} skin="page-no-border" title="Page-no-border theme" subtitle="A subtitle guides users to their next step." /> <EmptyState image={<Image width="120px" height="120px" />} skin="section" title="Section theme" subtitle="A subtitle guides users to their next step." /> </StorybookComponents.Stack>; ``` ### Children - description: <p>Add 1 or more CTA buttons below the subtitle as child elements of the empty state.</p><p></p><p>Be sure to give the user clear next actions.</p> - example: ```jsx <StorybookComponents.Stack flexDirection="column"> <EmptyState skin="page-no-border" title="Add your first product" subtitle="Start adding products so customers can shop your online store." > <StorybookComponents.Placeholder height="36px"> Child elements </StorybookComponents.Placeholder> </EmptyState> <EmptyState skin="page-no-border" title="Add your first product" subtitle="Start adding products so customers can shop your online store." > <TextButton prefixIcon={<Icons.Add />}>Add Product</TextButton> </EmptyState> <EmptyState skin="page-no-border" title="Add your first product" subtitle="Start adding products so customers can shop your online store." > <StorybookComponents.Stack gap="16px"> <TextButton prefixIcon={<Icons.Add />}>Add New Product</TextButton> <TextButton prefixIcon={<Icons.DownloadImport />}> Import Products </TextButton> </StorybookComponents.Stack> </EmptyState> </StorybookComponents.Stack>; ``` ## Common Use Case Examples ### No data on a page - description: <p>Use the <code>page</code> or <code>page-no-border</code> skin to tell users what will appear on the page once there’s data to display, and if relevant, what they can do to get started.</p> - example: ```jsx <Page> <Page.Header title="Tasks and Reminders" actionsBar={<Button prefixIcon={<Icons.Add />}>Add Task</Button>} /> <Page.Content> <EmptyState skin="page" image={ <Image width="120px" height="120px" src="no_categories.png" transparent /> } title="Add your first task" subtitle="Manage tasks and reminders for your site to get more done." > {<TextButton prefixIcon={<Icons.Add />}>Add Task</TextButton>} </EmptyState> </Page.Content> </Page>; ``` ### No data in a card - description: <p>Use the <code>section</code> skin empty state to tell users what will appear on the card once there’s data to display and, if relevant, what they can do to get started.</p><p></p><p>Keep the design minimal and avoid using illustrations.</p> - example: ```jsx <Page> <Page.Header title="New Category" actionsBar={ <Box gap="SP2"> <Button skin="inverted">Cancel</Button> <Button>Save</Button> </Box> } breadcrumbs={ <Breadcrumbs activeId="3" items={[ { id: '1', value: 'Categories' }, { id: '2', value: 'New Category' }, ]} /> } showBackButton onBackClicked={() => {}} /> <Page.Content> <Layout> <Cell> <Card> <Card.Header title="Category details" /> <Card.Divider /> <Card.Content> <Layout> <Cell span={4}> <FormField label="Category name" required> <Input placeholder="e.g., Fitness Classes" /> </FormField> </Cell> </Layout> </Card.Content> </Card> </Cell> <Cell> <Card> <Card.Header title="Services" /> <Card.Divider /> <Card.Content> <EmptyState title="Add services to this category" subtitle="Choose the services you want included in this category or create new ones." > <TextButton prefixIcon={<Icons.Add />}>Add Services</TextButton> </EmptyState> </Card.Content> </Card> </Cell> <Cell> <Page.Footer divider> <Page.Footer.End> <Box gap="SP2"> <Button priority="secondary">Cancel</Button> <Button>Save</Button> </Box> </Page.Footer.End> </Page.Footer> </Cell> </Layout> </Page.Content> </Page>; ``` ### No search results - description: <p>Use an empty state when a search doesn’t return any results. Explain what happened and what users can do next to adjust their search.</p> - example: ```jsx () => { const [searchTerm, setSearchTerm] = React.useState(''); const [display, setDisplay] = React.useState('none'); const [records, setRecords] = React.useState([ { name: `Ballet shoes`, SKU: 'BP063001', price: '$78', inventory: 16, }, { name: `Chelsea boots`, SKU: 'BP063001', price: '$112', inventory: 32, }, { name: `Desert boots`, SKU: 'BP063001', price: '$89', inventory: 23, }, { name: `Platform shoes`, SKU: 'BP063001', price: '$45', inventory: 102, }, { name: `Espadrilles`, SKU: 'BP063001', price: '$96', inventory: 4, }, { name: `Moccasins`, SKU: 'BP063001', price: '$104', inventory: 45, }, ]); const columns = [ { title: 'Name', render: row => row.name, width: '30%', }, { title: 'SKU', render: row => row.SKU, width: '20%', }, { title: 'Price', render: row => row.price, width: '20%', }, { title: 'Inventory', render: row => row.inventory, width: '20%', }, ]; const clearSearch = () => { setSearchTerm(''); }; const renderSearch = expandable => { return ( <Search size="small" expandable={expandable} placeholder="Search..." onChange={e => { setSearchTerm(e.target.value); }} value={searchTerm} onClear={clearSearch} /> ); }; const getFilteredData = () => { let data = records; if (searchTerm !== '') { data = data.filter(row => row.name.toUpperCase().includes(searchTerm.toUpperCase()), ); } return data; }; const filteredData = getFilteredData(); const renderEmptyState = () => ( <Table.EmptyState title="No results found" subtitle="No items matched your search. Try searching for something else." image={ <Image width="120px" height="120px" transparent={true} src="EmptyState_Generic1.svg" /> } > <TextButton onClick={clearSearch}>Clear Search</TextButton> </Table.EmptyState> ); return ( <Card> <Table data={filteredData} columns={columns} rowVerticalPadding="medium"> <TableToolbar> <TableToolbar.ItemGroup position="start"> <TableToolbar.Item> <Text size="small" weight="normal"> 6 products </Text> </TableToolbar.Item> </TableToolbar.ItemGroup> <TableToolbar.ItemGroup position="end"> <TableToolbar.Item>{renderSearch(false)}</TableToolbar.Item> </TableToolbar.ItemGroup> </TableToolbar> {filteredData.length ? <Table.Titlebar /> : renderEmptyState()} <Table.Content titleBarVisible={false} /> </Table> </Card> ); }; ``` ### Failed to load - description: <p>Let users know that their data failed to load. If possible, provide a next action.</p> - example: ```jsx <Page> <Page.Header title="Website Widgets" subtitle="Widgets let you add features and functionality to your site." /> <Page.Content> <EmptyState skin="page-no-border" image={ <Image width="120px" src="EmptyState_ServerError.svg" transparent /> } title="We couldn't load this page" subtitle="Looks like there was a technical issue on our end. Wait a few minutes and try again." > <TextButton prefixIcon={<Icons.Refresh />}>Try Again</TextButton> </EmptyState> </Page.Content> </Page>; ``` ### App introduction - description: <p>Use an empty state in the main tab of the app settings panel to give a brief introduction to the app. </p><p></p><p>Place the app icon and a short description at the top, and provide main actions to help users get started using the app.</p> - example: ```jsx <SidePanel skin="floating" width="420px" onCloseButtonClick onHelpButtonClick> <SidePanel.Header title="Blog" /> <Box height="480px"> <VerticalTabs size="small" activeTabId={0} onChange={() => {}}> <VerticalTabs.TabItem id={0}>Main</VerticalTabs.TabItem> <VerticalTabs.TabItem id={1}>Display</VerticalTabs.TabItem> <VerticalTabs.TabItem id={2}>Layout</VerticalTabs.TabItem> <VerticalTabs.TabItem id={3}>Design</VerticalTabs.TabItem> <VerticalTabs.TabItem id={4}>Support</VerticalTabs.TabItem> </VerticalTabs> <Divider direction="vertical" /> <SidePanel.Content> <EmptyState theme="section" skin={ <Image width="120px" height="120px" src="onboarding_community.svg" transparent /> } title="Blog feed" subtitle="Customize the layout and design of your blog feed, or create a post." > <Box gap="SP2" direction="vertical"> <Button size="small">Create Post</Button> <Button size="small" priority="secondary"> Manage Posts </Button> </Box> </EmptyState> </SidePanel.Content> </Box> </SidePanel>; ```