@wix/design-system
Version:
@wix/design-system
539 lines (489 loc) • 17.8 kB
Markdown
## 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>
);
};
```