UNPKG

@wix/design-system

Version:

@wix/design-system

539 lines (489 loc) 17.8 kB
## Feature Examples ### Size - description: <p>Control button size with <code>size</code> prop:</p><p></p><p><code>large</code> is best for calls to action that require more emphasis.</p><p><code>medium</code> is for main page actions and common use cases.</p><p><code>small</code> fits into smaller UI elements like cards and widgets.</p><p><code>tiny</code> is used for dense layouts.</p> - example: ```jsx <Box> <StorybookComponents.Stack> <SplitAction size="large"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction size="medium"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction size="small"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction size="tiny"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> </StorybookComponents.Stack> </Box> ``` ### Skin - description: <p>Change the appearance of a button with a <code>skin</code> prop.</p><p></p><p><code>standard</code> is for general primary actions.</p><p><code>light</code> is for primary actions that are on dark backgrounds.</p><p><code>dark</code> should be used with buttons on backgrounds with colors.</p><p><code>transparent</code> is for general actions on backgrounds with vivid colors or images.</p><p><code>premium</code> is for actions that prompt users to upgrade their plans to premium subscription.</p><p></p><p>Each action can be primary or secondary. There should only be one primary action per page.</p><p></p><p><em>Note:</em> Secondary buttons should be used alongside primary buttons for less utilized actions, such as cancel or back.</p> - example: ```jsx <StorybookComponents.Stack flexDirection="column" gap="40px"> <Box gap="20px"> <SplitAction skin="standard"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction skin="standard" priority="secondary"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> </Box> <Box gap="20px" backgroundColor="#000" padding="6px"> <SplitAction skin="light"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction skin="light" priority="secondary"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> </Box> <Box gap="20px"> <SplitAction skin="dark"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction skin="dark" priority="secondary"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> </Box> <Box gap="20px" backgroundColor="#a0c4ff" padding="6px"> <SplitAction skin="transparent"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction skin="transparent" priority="secondary"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> </Box> <Box gap="20px"> <SplitAction skin="premium"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> <SplitAction skin="premium" priority="secondary"> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton ariaLabel="More options"/> </SplitAction> </Box> </StorybookComponents.Stack>; ``` ### Affix - description: <p>Add more context to actions with affix icons:</p><p></p><p>Emphasize the button action with a <code>prefixIcon</code>.</p><p></p><p><em>Note:</em> Avoid using a <code>suffixIcon</code>, especially chevrons or directional indicators. These can be confused with the split icon button’s dropdown trigger and make the interaction unclear.</p> - example: ```jsx <StorybookComponents.Stack flexDirection="column"> <StorybookComponents.Stack> <SplitAction size="large"> <SplitActionButton prefixIcon={<Icons.Add />}> Publish </SplitActionButton> <SplitActionIconButton ariaLabel="More options" /> </SplitAction> </StorybookComponents.Stack> <StorybookComponents.Stack> <SplitAction size="medium"> <SplitActionButton prefixIcon={<Icons.Add />}> Publish </SplitActionButton> <SplitActionIconButton ariaLabel="More options" /> </SplitAction> </StorybookComponents.Stack> <StorybookComponents.Stack> <SplitAction size="small"> <SplitActionButton prefixIcon={<Icons.Add />}> Publish </SplitActionButton> <SplitActionIconButton ariaLabel="More options" /> </SplitAction> </StorybookComponents.Stack> <StorybookComponents.Stack> <SplitAction size="tiny"> <SplitActionButton size="tiny" prefixIcon={<Icons.Add />}> Publish </SplitActionButton> <SplitActionIconButton ariaLabel="More options" /> </SplitAction> </StorybookComponents.Stack> </StorybookComponents.Stack>; ``` ### Grouping - description: <p>Place up to 2–3 visible actions inside the <code><SplitAction/></code> group, and move the rest under the chevron icon button.</p><p></p><p><em>Note: </em>Limiting visible actions keeps the primary decision clear and UI uncluttered. If you need more than three visible actions, consider whether a full toolbar pattern fits better or use separate buttons.</p> - example: ```jsx () => ( <Box direction="vertical" gap="18px"> <Box direction="vertical" gap="6px"> <SplitAction> <SplitActionButton onClick={() => {}}>Publish</SplitActionButton> <SplitActionButton onClick={() => {}}>Preview</SplitActionButton> <SplitActionButton onClick={() => {}}>Save</SplitActionButton> <PopoverMenu appendTo="window" placement="bottom-end" triggerElement={({ toggle }) => ( <SplitActionIconButton onClick={toggle} ariaLabel="More post actions" /> )} > <PopoverMenu.MenuItem text="Schedule" prefixIcon={<Icons.Time />} onClick={() => {}} /> <PopoverMenu.MenuItem text="Duplicate" prefixIcon={<Icons.Duplicate />} onClick={() => {}} /> <PopoverMenu.Divider /> <PopoverMenu.MenuItem text="Delete" prefixIcon={<Icons.Delete />} skin="destructive" onClick={() => {}} /> </PopoverMenu> </SplitAction> </Box> <Box direction="vertical" gap="6px"> <SplitAction> <SplitActionButton onClick={() => {}}>Publish</SplitActionButton> <SplitActionButton onClick={() => {}}>Preview</SplitActionButton> <SplitActionButton onClick={() => {}}>Save</SplitActionButton> </SplitAction> </Box> <Box direction="vertical" gap="6px"> <SplitAction> <SplitActionIconButton ariaLabel="Increase"> <Icons.Add /> </SplitActionIconButton> <SplitActionIconButton ariaLabel="Decrease"> <Icons.Minus /> </SplitActionIconButton> </SplitAction> </Box> </Box> ); ``` ### Disabled - description: <p>To disable a split button, use the <code>disabled</code> prop which indicates a button can't be selected.</p> - example: ```jsx <SplitAction disabled> <SplitActionButton>Publish</SplitActionButton> <SplitActionIconButton/> </SplitAction>; ``` ### Text overflow - description: <p>Use the <code>ellipsis</code> prop for overflow text. The full text will be displayed in a <code><Tooltip/></code> when a user hovers over the button. Control the style of the tooltip using the <code>tooltipProps</code>.</p><p></p><p><em>Note: </em>Try to avoid lengthy action labels. CTA text should be short and clear – one to two words, or max three for specific use cases.</p> - example: ```jsx <StorybookComponents.Stack flexDirection="column" width="180px"> <SplitAction> <SplitActionButton ellipsis >This label exceeds available space and is shown in a tooltip</SplitActionButton> <SplitActionIconButton></SplitActionIconButton> </SplitAction> </StorybookComponents.Stack>; ``` ## Developer Examples ### Styling - description: <p>Properties are applied through a parent <code><SplitAction/></code> container and they control all child elements within a group.</p> - example: ```jsx <Box direction="horizontal" align="center"> <SplitAction size="medium" skin="premium"> <SplitActionButton>Publish</SplitActionButton> <PopoverMenu appendTo="window" placement="bottom-end" triggerElement={({ toggle }) => ( <SplitActionIconButton onClick={toggle} ariaLabel="More options" /> )} > <PopoverMenu.MenuItem text="Schedule" prefixIcon={<Icons.Time />} onClick={() => {}} /> <PopoverMenu.MenuItem text="Save as Draft" prefixIcon={<Icons.Saved />} onClick={() => {}} /> <PopoverMenu.Divider /> <PopoverMenu.MenuItem text="Duplicate" prefixIcon={<Icons.Duplicate />} onClick={() => {}} /> </PopoverMenu> </SplitAction> </Box> ``` ## Common Use Case Examples ### Composer - description: <p>Use <code><SplitAction/></code> in composer headers to pair a primary CTA with additional overflow actions e.g. schedule, save as draft, duplicate.</p> - example: ```jsx () => { 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 authorOptions = [ listItemSelectBuilder({ id: 0, prefix: <Avatar size="size18" />, title: 'Doe John', label: 'Doe John', }), listItemSelectBuilder({ id: 1, prefix: <Avatar size="size18" />, title: 'John Doe', label: 'John Doe', }), listItemActionBuilder({ title: 'New Author', prefixIcon: <Icons.Add />, }), ]; 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> <SplitAction> <SplitActionButton>Publish</SplitActionButton> <PopoverMenu appendTo="window" placement="bottom-end" triggerElement={({ toggle }) => ( <SplitActionIconButton onClick={toggle} ariaLabel="More publish options" /> )} > <PopoverMenu.MenuItem text="Schedule" prefixIcon={<Icons.Time />} onClick={() => {}} /> <PopoverMenu.MenuItem text="Save as Draft" prefixIcon={<Icons.Saved />} onClick={() => {}} /> <PopoverMenu.Divider /> <PopoverMenu.MenuItem text="Duplicate" prefixIcon={<Icons.Duplicate />} onClick={() => {}} /> </PopoverMenu> </SplitAction> </ComposerHeader.MainActions> </ComposerHeader> </Cell> <Cell> <Box direction="vertical"> <Box gap="0" height="600px"> <ComposerSidebar labelPlacement="bottom" items={items} /> <Box width="100%"> <Box width="100%" padding={4}> <StorybookComponents.Placeholder> <Box verticalAlign="middle" align="center" height="100%"> <Text>Composer content area</Text> </Box> </StorybookComponents.Placeholder> </Box> </Box> </Box> </Box> </Cell> </Layout> ); }; ``` ### Modal - description: <p>Use <code><SplitAction/></code> in modal footers to pair a primary CTA with additional overflow actions e.g. save & add another, save as draft, save as template.</p> - example: ```jsx <CustomModalLayout onCloseButtonClick={() => {}} title="Add menu" sideActions={ <Box width="100%" align="right" gap="SP2"> <Button priority="secondary" onClick={() => {}}> Cancel </Button> <SplitAction> <SplitActionButton onClick={() => {}}>Save</SplitActionButton> <PopoverMenu appendTo="window" placement="top-end" triggerElement={({ toggle }) => ( <SplitActionIconButton onClick={toggle} ariaLabel="More save options" /> )} > <PopoverMenu.MenuItem text="Save & Add Another" prefixIcon={<Icons.Add />} onClick={() => {}} /> <PopoverMenu.MenuItem text="Save as Draft" prefixIcon={<Icons.Saved />} onClick={() => {}} /> <PopoverMenu.Divider /> <PopoverMenu.MenuItem text="Save as Template" prefixIcon={<Icons.Duplicate />} onClick={() => {}} /> </PopoverMenu> </SplitAction> </Box> } > <Layout> <Cell> <FormField label="Name"> <Input value="Brunch Menu" /> </FormField> </Cell> <Cell> <FormField label="Description"> <InputArea value="Brunch includes pastries, fruits, omelettes, coffee, and more." /> </FormField> </Cell> <Cell> <Box> <FormField label="Visible to customers" labelPlacement="right" stretchContent={false} > <ToggleSwitch checked /> </FormField> </Box> </Cell> </Layout> </CustomModalLayout> ``` ### Card - description: <p>Use <code><SplitAction/></code> on content cards to surface a primary action alongside secondary options e.g. duplicate, cancel, without overcrowding the row.</p> - example: ```jsx () => { const renderImage = () => <Image width={230} borderRadius={0}></Image>; const renderContent = () => ( <Box direction="vertical" verticalAlign="space-between" padding="24px 29px 27px" flexGrow={1} > <Box direction="vertical" gap={1}> <Text weight="bold">JAVA meetup</Text> <Text size="small" weight="thin" secondary light> Jan 20, 2021, 10:00 AM, Location will be announced later </Text> </Box> <Box align="space-between"> <Box /> <Box gap="SP2" verticalAlign="middle"> <Button priority="secondary" size="small" prefixIcon={<Icons.PromoteSmall />} > Promote </Button> <SplitAction size="small" priority="secondary"> <SplitActionButton prefixIcon={<Icons.EditSmall />}> Edit </SplitActionButton> <PopoverMenu textSize="small" appendTo="window" placement="bottom-end" triggerElement={({ toggle }) => ( <SplitActionIconButton onClick={toggle} ariaLabel="More actions" /> )} > <PopoverMenu.MenuItem text="Edit SEO settings" prefixIcon={<Icons.SettingsSmall />} onClick={() => {}} /> <PopoverMenu.Divider /> <PopoverMenu.MenuItem text="Duplicate as draft" prefixIcon={<Icons.DuplicateSmall />} onClick={() => {}} /> <PopoverMenu.MenuItem text="Cancel event" skin="destructive" prefixIcon={<Icons.BlockSmall />} onClick={() => {}} /> </PopoverMenu> </SplitAction> </Box> </Box> </Box> ); return ( <Card hideOverflow> <Box minHeight={200}> {renderImage()} {renderContent()} </Box> </Card> ); }; ```