UNPKG

@wix/design-system

Version:

@wix/design-system

909 lines (859 loc) 28.9 kB
## Feature Examples ### Structure - description: <p>Side panels are composed of up to four compound components: </p><li><code><SidePanel.Header/></code></li><li><code><SidePanel.Content/></code></li><li><code><SidePanel.Divider/></code></li><li><code><SidePanel.Footer/></code></li><p></p><p>All of these components are optional.</p> - example: ```jsx <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Header" /> <SidePanel.Content> <StorybookComponents.Placeholder height="480px"> Content </StorybookComponents.Placeholder> </SidePanel.Content> <SidePanel.Footer> <StorybookComponents.Placeholder height="36px" > Footer </StorybookComponents.Placeholder> </SidePanel.Footer> </SidePanel>; ``` ### Skin - description: <p>Control the component style with <code>skin</code> prop:</p><li><code>standard</code> is the default style used in all common cases.</li><li><code>floating</code> is used for settings panels that float on top of content in editor platforms (<a href="https://www.wix.com/">Wix</a> or <a href="https://www.wix.com/studio">Wix Studio</a>). </li> - example: ```jsx <StorybookComponents.Stack> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Standard" /> <SidePanel.Content> <StorybookComponents.Stack height="480px" /> </SidePanel.Content> </SidePanel> <SidePanel onCloseButtonClick={() => {}} skin="floating" width="288px"> <SidePanel.Header title="Floating" /> <SidePanel.Content> <StorybookComponents.Stack height="492px" /> </SidePanel.Content> </SidePanel> </StorybookComponents.Stack>; ``` ### Width - description: <p>Set the side panel’s width using the <code>width</code> property. The default width is 420px.</p> - example: ```jsx <StorybookComponents.Stack> <SidePanel onCloseButtonClick={() => {}} width="300px"> <SidePanel.Header title="Narrow panel" /> <SidePanel.Content> <StorybookComponents.Stack height="360px" /> </SidePanel.Content> </SidePanel> <SidePanel onCloseButtonClick={() => {}} width="600px"> <SidePanel.Header title="Wide panel" /> <SidePanel.Content> <StorybookComponents.Stack height="360px" /> </SidePanel.Content> </SidePanel> </StorybookComponents.Stack>; ``` ### Height - description: <p>By default, panel height depends on the amount of content it contains. To define the maximum height it can grow to use <code>maxHeight</code> property.</p><p></p><p>Fix the panel height to a specific number with <code>height</code> property. </p><p></p><p></p> - example: ```jsx <StorybookComponents.Stack> <SidePanel onCloseButtonClick={() => {}} maxHeight="480px"> <SidePanel.Header title="No height set" /> <SidePanel.Content> <StorybookComponents.Placeholder height="40px" /> </SidePanel.Content> </SidePanel> <SidePanel onCloseButtonClick={() => {}} height="480px"> <SidePanel.Header title="Fixed height set" /> <SidePanel.Content> <StorybookComponents.Placeholder height="40px" /> </SidePanel.Content> </SidePanel> </StorybookComponents.Stack>; ``` ### Padding - description: <p>Content padding is enabled in the side panel by default, but can be disabled with the <code>noPadding</code> property for:</p><li><code><SidePanel.Content/></code></li><li><code><SidePanel.Footer/></code></li><p></p><p>The padding can be removed to display lists or other components with built-in padding.</p><p></p> - example: ```jsx <StorybookComponents.Stack> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="With padding" /> <SidePanel.Content> <StorybookComponents.Placeholder height="360px" /> </SidePanel.Content> <SidePanel.Footer> <StorybookComponents.Placeholder height="42px" /> </SidePanel.Footer> </SidePanel> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="No padding" /> <SidePanel.Content noPadding={true}> <StorybookComponents.Placeholder height="360px" /> </SidePanel.Content> <SidePanel.Footer noPadding={true}> <StorybookComponents.Placeholder height="42px" /> </SidePanel.Footer> </SidePanel> </StorybookComponents.Stack>; ``` ### Dividers - description: <p>Dividers are enabled in the side panel by default but can be disabled using the <code>showDivider</code> property for:</p><li><code><SidePanel.Header/></code></li><li><code><SidePanel.Footer/></code></li><p></p><p>Always show dividers in the side panel if users have the option to scroll vertically inside the panel.</p> - example: ```jsx <StorybookComponents.Stack> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="With divider" /> <SidePanel.Content> <StorybookComponents.Stack height="360px" /> </SidePanel.Content> <SidePanel.Footer> <StorybookComponents.Stack height="42px" /> </SidePanel.Footer> </SidePanel> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="No divider" showDivider={false} /> <SidePanel.Content> <StorybookComponents.Stack height="360px" /> </SidePanel.Content> <SidePanel.Footer showDivider={false}> <StorybookComponents.Stack height="42px" /> </SidePanel.Footer> </SidePanel> </StorybookComponents.Stack>; ``` ### Header - description: <p>Customize the side panel’s header using these properties:</p><li><code>title</code> </li><li><code>subtitle </code></li> - example: ```jsx <StorybookComponents.Stack flexDirection="column"> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Title" showDivider={true} /> </SidePanel> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Title" subtitle="Subtitle" showDivider={true} /> </SidePanel> </StorybookComponents.Stack>; ``` ### Header Actions - description: <p>Header has these properties for actions available:</p><li><code>infoTooltipContent</code> - provides additional details or an explanation in a tooltip</li><li><code>onHelpButtonClick</code>- allows users to access help articles and contextual information</li><li><code>onBackButtonClick</code>- allows users to navigate back in the Side Panel</li><li><code>backButtonDescription</code> - sets content of the back button's tooltip</li> - example: ```jsx <StorybookComponents.Stack flexDirection="column"> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Title" subtitle="Subtitle" infoTooltipContent="Additional info here" showDivider={true} /> </SidePanel> <SidePanel onCloseButtonClick={() => {}} onHelpButtonClick={() => {}}> <SidePanel.Header title="Title" subtitle="Subtitle" showDivider={true} /> </SidePanel> <SidePanel onCloseButtonClick={() => {}} onBackButtonClick={() => {}} backButtonDescription="Back"> <SidePanel.Header title="Title" subtitle="Subtitle" showDivider={true} /> </SidePanel> </StorybookComponents.Stack>; ``` ### Custom header - description: <p>Create a custom header layout by adding children elements to the <code><SidePanel.Header/></code> container.</p> - example: ```jsx <StorybookComponents.Stack flexDirection="column"> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Title"> <StorybookComponents.Stack margin="0px 24px 12px 24px"> <StorybookComponents.Placeholder height="42px" /> </StorybookComponents.Stack> </SidePanel.Header> </SidePanel> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Title" showDivider={false}> <Tabs items={[ { id: 1, title: 'First Tab' }, { id: 2, title: 'Second Tab' }, ]} activeId={1} type="uniformSide" width="174px" /> </SidePanel.Header> </SidePanel> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Title"> <StorybookComponents.Stack margin="0px 24px 12px 24px"> <Search /> </StorybookComponents.Stack> </SidePanel.Header> </SidePanel> </StorybookComponents.Stack>; ``` ### Text overflow - description: <p>Panel title and subtitle wraps to multiple lines by default. Limit the amount of lines using <code>ellipsis</code> and <code>maxLines</code> properties.</p><p></p><p>Ellipsis do not apply to the subtitle, as its main purpose is to provide more information. </p> - example: ```jsx <StorybookComponents.Stack flexDirection="column"> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="A long title that needs to wrap into multiple lines" subtitle="A long subtitle that needs to wrap into multiple lines because it is so long." showDivider={true} /> </SidePanel> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header ellipsis maxLines={1} title="A long title that needs to wrap into multiple lines" subtitle="A long subtitle that needs to wrap into multiple lines because it is so long." showDivider={true} /> </SidePanel> </StorybookComponents.Stack>; ``` ### Content sections - description: <p>Create sections inside of a panel by adding multiple <code><SidePanel.Content/></code> areas.</p><p></p><p>Separate them from one another with a dedicated <code><SidePanel.Divider/></code> element. </p> - example: ```jsx <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Content sections" /> <SidePanel.Content> <StorybookComponents.Stack height="150px" /> </SidePanel.Content> <SidePanel.Divider /> <SidePanel.Content> <StorybookComponents.Stack height="150px" /> </SidePanel.Content> <SidePanel.Divider /> <SidePanel.Content> <StorybookComponents.Stack height="150px" /> </SidePanel.Content> </SidePanel>; ``` ### Content fields - description: <p>Separate controls inside of a panel from one another by wrapping each one into <code><SidePanel.Field/></code> container.</p> - example: ```jsx <StorybookComponents.Stack> <SidePanel onCloseButtonClick={() => {}}> <SidePanel.Header title="Content fields" /> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> </SidePanel> <SidePanel onCloseButtonClick={() => {}} skin="floating" width="288px"> <SidePanel.Header title="Content fields" /> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> <SidePanel.Field> <StorybookComponents.Placeholder height="48px" /> </SidePanel.Field> </SidePanel> </StorybookComponents.Stack> ``` ### Custom footer - description: <p>To display confirmation or close actions use the <code><SidePanel.Footer/></code> container.</p> - example: ```jsx <StorybookComponents.Stack flexDirection="column"> <SidePanel> <SidePanel.Footer> <StorybookComponents.Placeholder height="36px" /> </SidePanel.Footer> </SidePanel> <SidePanel> <SidePanel.Footer> <Button priority="secondary" fullWidth> Close </Button> </SidePanel.Footer> </SidePanel> <SidePanel> <SidePanel.Footer> <StorybookComponents.Stack justifyContent="flex-end" gap="12px"> <Button priority="secondary">Cancel</Button> <Button>Save</Button> </StorybookComponents.Stack> </SidePanel.Footer> </SidePanel> </StorybookComponents.Stack>; ``` ### Draggable - description: <p>Let users know that panel position on the screen can be changed by changing the mouse cursor to grab with <code>draggable</code> property.</p><p></p><p>The behaviour itself has to be developed separately.</p> - example: ```jsx <SidePanel onCloseButtonClick={() => {}} skin="floating" width="288px" draggable> <SidePanel.Header title="Draggable panel"/> <SidePanel.Content> <StorybookComponents.Stack height="492px" /> </SidePanel.Content> </SidePanel> ``` ## Common Use Case Examples ### Settings panel - description: <p>Use side panel to create settings panels that allow users to control the design and behavior aspects of their app.</p> - example: ```jsx <SidePanel onCloseButtonClick={() => {}} skin="floating" width="288px"> <SidePanel.Header title="Button Settings" /> <SidePanel.Field> <FormField label="Choose what displays"> <Dropdown size="small" selectedId={0} options={[ { id: 0, value: 'Text and icon' }, { id: 1, value: 'Icon only' }, { id: 2, value: 'Text only' }, { id: 3, value: 'Nothing' }, ]} /> </FormField> </SidePanel.Field> <SidePanel.Field> <FormField label="Text"> <Input size="small" value="New Folder" /> </FormField> </SidePanel.Field> <SidePanel.Field> <FieldSet legend="Icon" columns="auto 30px 30px" gap="small" alignment="center" > <ImageViewer height="102px" width="160px" /> <IconButton size="small" priority="secondary"> <Icons.ReplaceSmall /> </IconButton> <IconButton size="small" priority="secondary"> <Icons.DeleteSmall /> </IconButton> </FieldSet> </SidePanel.Field> <SidePanel.Field> <FormField label="Links to"> <Button size="small" priority="secondary" fullWidth suffixIcon={<Icons.LinkSmall />} > Choose a link </Button> </FormField> </SidePanel.Field> </SidePanel>; ``` ### Group content in settings panels - description: <p>Use <code><SidePanel.Section/></code> wrapper to organize panel info into categories.</p><p></p><p>It will make the whole panel easier to scan.</p> - example: ```jsx () => { const [selectedOption, setSelectedOption] = React.useState(0) const options = [ { id: 0, value: 'Monday' }, { id: 1, value: 'Sunday' }, ] return ( <SidePanel maxHeight="576px" width="288px" skin="floating" onCloseButtonClick={() => {}} > <SidePanel.Header title="Calendar Settings" /> <SidePanel.Content noPadding> <SidePanel.Field> <FormField label="Week starts on"> <Dropdown value="" size="small" options={options} onSelect={(option) => setSelectedOption(option.id)} selectedId={selectedOption} /> </FormField> </SidePanel.Field> <SidePanel.Field> <FieldSet legend="Set active days" legendSize="small" legendPlacement="top" direction="vertical" gap="12px" > <Checkbox size="small" checked> Monday </Checkbox> <Checkbox size="small" checked> Tuesday </Checkbox> <Checkbox size="small" checked> Wednesday </Checkbox> <Checkbox size="small" checked> Thursday </Checkbox> <Checkbox size="small" checked> Friday </Checkbox> <Checkbox size="small">Saturday</Checkbox> <Checkbox size="small">Sunday</Checkbox> </FieldSet> </SidePanel.Field> <SidePanel.Section title="Available dates"> <SidePanel.Field> <FieldSet alignment="end" direction="horizontal" legendPlacement="none" > <FormField label="From"> <DatePicker size="small" width="auto" placeholderText="Start" popoverProps={{ appendTo: 'window' }} /> </FormField> <FormField label="To"> <DatePicker size="small" width="auto" placeholderText="End" popoverProps={{ appendTo: 'window' }} /> </FormField> <Tooltip content="Delete"> <IconButton size="small" priority="secondary"> <Icons.DeleteSmall /> </IconButton> </Tooltip> </FieldSet> </SidePanel.Field> <SidePanel.Field> <TextButton size="small" prefixIcon={<Icons.AddSmall />}> Add Available Dates </TextButton> </SidePanel.Field> </SidePanel.Section> <SidePanel.Section title="Unavailable dates"> <SidePanel.Field> <FieldSet alignment="end" direction="horizontal" legendPlacement="none" > <FormField label="From"> <DatePicker size="small" width="auto" placeholderText="Start" popoverProps={{ appendTo: 'window' }} /> </FormField> <FormField label="To"> <DatePicker size="small" width="auto" placeholderText="End" popoverProps={{ appendTo: 'window' }} /> </FormField> <Tooltip content="Delete"> <IconButton size="small" priority="secondary"> <Icons.DeleteSmall /> </IconButton> </Tooltip> </FieldSet> </SidePanel.Field> <SidePanel.Field> <TextButton size="small" prefixIcon={<Icons.AddSmall />}> Add Unavailable Dates </TextButton> </SidePanel.Field> </SidePanel.Section> </SidePanel.Content> </SidePanel> ) } ``` ### Data filter - description: <p>Use side panels to display data filters. When opened, the panels should slide in from the right side of the screen. Add close buttons in the header and/or footer that can be used to close the panel.</p> - example: ```jsx () => { const [right, setRight] = React.useState(-440); const [records, setRecords] = React.useState([ { image: <Image width="42px" height="42px" />, }, { image: <Image width="42px" height="42px" />, }, { image: <Image width="42px" height="42px" />, }, { image: <Image width="42px" height="42px" />, }, { image: <Image width="42px" height="42px" />, }, { image: <Image width="42px" height="42px" />, }, { image: <Image width="42px" height="42px" />, }, ]); const columns = [ { title: '', render: row => row.image, }, ]; const openPanel = () => { setRight(0); }; const closePanel = () => { setRight(-440); }; return ( <div style={{ display: 'block', overflow: 'hidden', position: 'relative' }}> <Page height="780px" maxWidth="500px"> <Page.Header title="Products" /> <Page.Content> <Card> <Table data={records} columns={columns} rowVerticalPadding="tiny"> <TableToolbar> <TableToolbar.ItemGroup position="start"> <TableToolbar.Item> <TableToolbar.Label>7 products</TableToolbar.Label> </TableToolbar.Item> </TableToolbar.ItemGroup> <TableToolbar.ItemGroup position="end"> <TableToolbar.Item> <Button size="small" priority="secondary" prefixIcon={<Icons.ContentFilterSmall />} onClick={openPanel} > Filter </Button> </TableToolbar.Item> <TableToolbar.Item> <Search size="small" /> </TableToolbar.Item> </TableToolbar.ItemGroup> </TableToolbar> <Table.Content /> </Table> </Card> </Page.Content> </Page> <div style={{ position: 'absolute', top: 0, right: `${right}px`, height: '100%', boxShadow: '0 3px 24px 0 rgba(22, 45, 61, 0.18), 0 8px 8px 0 rgba(22, 45, 61, 0.12)', transition: 'right 0.4s ease 0s', zIndex: 1000, }} > <SidePanel title="Filter" onCloseButtonClick={closePanel}> <SidePanel.Header title="Filter" /> <SidePanel.Footer> <Button onClick={closePanel} priority="secondary" fullWidth> Close </Button> </SidePanel.Footer> </SidePanel> </div> </div> ); }; ``` ### Quick view - description: <p>Use side panels to provide quick views of list items. </p><p></p><p>Panels can either push the page content aside or overlay it, depending on the use case:</p><li>Overlay content when part of the page’s content can be covered.</li><li>Push content aside when the user should see all the information and actions on the main page.</li> - example: ```jsx () => { const [right, setRight] = React.useState(-440); const [records, setRecords] = React.useState([ { image: <Avatar size="size36" name="Jenny Wilson" />, }, { image: <Avatar size="size36" name="Robert Fox" />, }, { image: <Avatar size="size36" name="Albert Flores" />, }, { image: <Avatar size="size36" name="Floyd Miles" />, }, { image: <Avatar size="size36" name="Esther Howard" />, }, { image: <Avatar size="size36" name="Brooklyn Simmons" />, }, { image: <Avatar size="size36" name="Kathryn Murphy" />, }, { image: <Avatar size="size36" name="Dianne Russell" />, }, ]); const columns = [ { title: '', render: row => row.image, }, { render: () => ( <TableActionCell size="small" primaryAction={{ text: 'View', }} /> ), }, ]; const openPanel = () => { setRight(0); }; const closePanel = () => { setRight(-440); }; return ( <div style={{ display: 'block', overflow: 'hidden', position: 'relative' }}> <Page height="780px" maxWidth="500px"> <Page.Header title="Contacts" /> <Page.Content> <Card> <Table data={records} columns={columns} onRowClick={openPanel}> <TableToolbar> <TableToolbar.ItemGroup position="start"> <TableToolbar.Item> <TableToolbar.Label>8 contacts</TableToolbar.Label> </TableToolbar.Item> </TableToolbar.ItemGroup> </TableToolbar> <Table.Content /> </Table> </Card> </Page.Content> </Page> <div style={{ position: 'absolute', top: 0, right: `${right}px`, height: '100%', boxShadow: '0 3px 24px 0 rgba(22, 45, 61, 0.18), 0 8px 8px 0 rgba(22, 45, 61, 0.12)', transition: 'right 0.4s ease 0s', zIndex: 1000, }} > <SidePanel title="Filter" onCloseButtonClick={closePanel}> <SidePanel.Header showDivider={false}> <Box direction="vertical" align="center" marginBottom="12px"> <Avatar size="size72" /> </Box> <Tabs items={[ { id: 1, title: 'Overview' }, { id: 2, title: 'Inbox' }, ]} activeId={1} type="uniformSide" width="174px" /> </SidePanel.Header> </SidePanel> </div> </div> ); }; ``` ### Composer actions - description: <p>Use side panels to display composer settings and actions. These should be anchored to the left edge of the screen since they're opened through the <code><ComposerSidebar/></code>. </p> - example: ```jsx () => { const [selectedSidebar, setSelectedSidebar] = React.useState(0); const [activeTab, setActiveTab] = React.useState(0); const [toggleImage, setToggleImage] = React.useState(true); const [togglePosts, setTogglePosts] = React.useState(false); const [toggleCommenting, setToggleCommenting] = React.useState(false); const [descriptionValue, setDescriptionValue] = React.useState(''); const [authorTags, setAuthorTags] = React.useState([]); const [categories, setCategories] = React.useState([ { id: 0, label: 'Other posts', isChecked: false, }, { id: 1, label: 'Recipes', isChecked: false, }, { id: 2, label: 'Lifestyle', isChecked: false, }, ]); const [publishDate, setPublishDate] = React.useState(); const [themeTags, setThemeTags] = React.useState([ { id: '1', label: 'Sport' }, { id: '2', label: 'Routine' }, ]); const [author, setAuthor] = React.useState(); const items = [ { id: 0, label: 'Settings', icon: <Icons.Settings />, }, { id: 1, label: 'Categories', icon: <Icons.Category />, }, { id: 2, label: 'Tags', icon: <Icons.Tag />, }, ]; const handleSelectTag = (tag, previousTags, setTags) => setTags([...previousTags, { id: tag.id, label: tag.value }]); const handleRemoveTag = (tag, previousTags, setTags) => setTags(previousTags.filter(currTag => currTag.id !== tag)); const handleSidebarClick = id => { setSelectedSidebar(id); }; const handleCloseSidePanel = () => { setSelectedSidebar(); }; const renderSettingsPanel = () => ( <SidePanel onCloseButtonClick={handleCloseSidePanel} width="300px"> <SidePanel.Header title="Post settings" showDivider={false}> <Tabs items={[ { id: 0, title: 'General' }, { id: 1, title: 'Advanced' }, ]} activeId={activeTab} type="uniformSide" width="114px" onClick={value => setActiveTab(value.id)} /> </SidePanel.Header> <SidePanel.Content></SidePanel.Content> </SidePanel> ); const renderTagPanel = () => ( <SidePanel onCloseButtonClick={handleCloseSidePanel} width="300px"> <SidePanel.Header title="Tags" showDivider={false} /> <SidePanel.Content /> </SidePanel> ); const renderCategoryPanel = () => { return ( <SidePanel onCloseButtonClick={handleCloseSidePanel} width="300px"> <SidePanel.Header title="Categories" showDivider={false} /> <SidePanel.Content /> </SidePanel> ); }; return ( <Layout gap={0}> <Cell> <ComposerHeader backButtonValue="Back"> <ComposerHeader.Actions justifyContent="flex-end"> <ToggleButton labelValue="Undo"> <Icons.Undo /> </ToggleButton> <ToggleButton labelValue="Redo"> <Icons.Redo /> </ToggleButton> </ComposerHeader.Actions> <ComposerHeader.MainActions> <Button skin="inverted">Preview</Button> <Button>Publish</Button> </ComposerHeader.MainActions> </ComposerHeader> </Cell> <Cell> <Box direction="vertical" backgroundColor="D70"> <Box gap="0" height="660px"> <ComposerSidebar labelPlacement="bottom" items={items} selectedId={selectedSidebar} onClick={(_, { id }) => handleSidebarClick(id)} /> {selectedSidebar === 0 && renderSettingsPanel()} {selectedSidebar === 1 && renderCategoryPanel()} {selectedSidebar === 2 && renderTagPanel()} </Box> </Box> </Cell> </Layout> ); }; ```