Skip to content

Commit

Permalink
feat(menu): add destructive menu item variant (#2604)
Browse files Browse the repository at this point in the history
* feat(menu): add destructive menu item variant

* feat(menu): add destructive menu item variant

* fix(menu): move disabled styles

* chore(changeset): remove website from changeset

* chore(website): update menu item docs

* fix(menu): declare props being used
  • Loading branch information
loreina committed Aug 19, 2022
1 parent 7e75f81 commit 563dff9
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 24 deletions.
6 changes: 6 additions & 0 deletions .changeset/thirty-seas-jog.md
@@ -0,0 +1,6 @@
---
'@twilio-paste/menu': minor
'@twilio-paste/core': minor
---

- [menu] add menu item destructive variant
18 changes: 9 additions & 9 deletions packages/paste-core/components/menu/src/MenuItem.tsx
Expand Up @@ -7,17 +7,17 @@ import {MenuItemVariants} from './constants';
import {MenuGroupContext} from './MenuGroup';

export const StyledMenuItem = React.forwardRef<HTMLDivElement | HTMLAnchorElement, MenuItemProps>(
({element = 'STYLED_MENU_ITEM', ...props}, ref) => {
({element = 'STYLED_MENU_ITEM', href, variant, tabIndex, children, ...props}, ref) => {
return (
<Box
{...(props.href && secureExternalLink(props.href))}
as={props.href ? 'a' : 'button'}
{...(href && secureExternalLink(href))}
as={href ? 'a' : 'button'}
{...safelySpreadBoxProps(props)}
element={element}
appearance="none"
background="none"
border="none"
color={props['aria-disabled'] ? 'colorTextWeaker' : 'colorText'}
color={variant === MenuItemVariants.DESTRUCTIVE ? 'colorTextLinkDestructive' : 'colorText'}
display="block"
textAlign="left"
fontFamily="inherit"
Expand All @@ -27,19 +27,19 @@ export const StyledMenuItem = React.forwardRef<HTMLDivElement | HTMLAnchorElemen
margin="space0"
outline="none"
paddingY="space30"
paddingX={props.variant === MenuItemVariants.GROUP_ITEM ? 'space90' : 'space70'}
textDecoration={props.tabIndex === 0 ? 'underline' : 'none'}
paddingX={variant === MenuItemVariants.GROUP_ITEM ? 'space90' : 'space70'}
textDecoration={tabIndex === 0 ? 'underline' : 'none'}
width="100%"
_hover={{
cursor: 'pointer',
}}
_focus={{
color: 'colorTextLink',
color: `${variant === MenuItemVariants.DESTRUCTIVE ? 'colorTextLinkDestructiveStronger' : 'colorTextLink'}`,
}}
_disabled={{cursor: 'not-allowed'}}
_disabled={{color: 'colorTextWeaker', cursor: 'not-allowed'}}
ref={ref}
>
{props.children}
{children}
</Box>
);
}
Expand Down
1 change: 1 addition & 0 deletions packages/paste-core/components/menu/src/constants.ts
@@ -1,4 +1,5 @@
export const MenuItemVariants = {
DEFAULT: 'default',
DESTRUCTIVE: 'destructive',
GROUP_ITEM: 'group_item',
} as const;
39 changes: 39 additions & 0 deletions packages/paste-core/components/menu/stories/index.stories.tsx
Expand Up @@ -27,6 +27,9 @@ const PlainMenu: React.FC = () => {
<MenuItem {...menu} href="http://www.google.com" onClick={onClick}>
Has a link
</MenuItem>
<MenuItem {...menu} variant="destructive" href="http://www.google.com" onClick={onClick}>
Destructive link
</MenuItem>
<MenuItem {...menu} disabled>
Extensions
</MenuItem>
Expand Down Expand Up @@ -276,6 +279,9 @@ export const MenuDropdown = (): React.ReactNode => {
return (
<Menu {...menuMockProps} aria-label={`Code ${uniqueMenuLabelID}`} placement="auto">
<MenuItem {...menuItemMockProps}>Default</MenuItem>
<MenuItem {...menuItemMockProps} variant="destructive">
Destructive
</MenuItem>
<MenuItem {...menuItemMockProps} disabled>
Disabled
</MenuItem>
Expand Down Expand Up @@ -308,11 +314,44 @@ export const MenuDropdown = (): React.ReactNode => {
</MediaFigure>
</MediaObject>
</MenuItem>
<MenuItem variant="destructive" {...menuItemMockProps}>
Suuuuuuuuuuuuuuuuuuuuuuper long menu item
</MenuItem>
<MenuItem variant="destructive" {...menuItemMockProps}>
<MediaObject verticalAlign="center">
<MediaFigure spacing="space20">
<AttachIcon decorative={false} title="information" />
</MediaFigure>
<MediaBody>Got an icon</MediaBody>
</MediaObject>
</MenuItem>
<MenuItem variant="destructive" {...menuItemMockProps}>
<MediaObject verticalAlign="center">
<MediaBody>Got a right icon</MediaBody>
<MediaFigure spacing="space20" align="end">
<AttachIcon decorative={false} title="information" />
</MediaFigure>
</MediaObject>
</MenuItem>
<MenuItem variant="destructive" {...menuItemMockProps}>
<MediaObject verticalAlign="center">
<MediaFigure spacing="space20">
<AttachIcon decorative={false} title="information" />
</MediaFigure>
<MediaBody>Got two icons</MediaBody>
<MediaFigure spacing="space20" align="end">
<AttachIcon decorative={false} title="information" />
</MediaFigure>
</MediaObject>
</MenuItem>
<MenuSeparator />
<MenuGroup icon={<ProductVoiceIcon decorative />} label="Search Options">
<MenuItem {...menuItemMockProps} href="https://google.com">
Search with Google
</MenuItem>
<MenuItem variant="destructive" {...menuItemMockProps} href="https://google.com">
Search with Yahoo
</MenuItem>
<MenuItem {...menuItemMockProps} disabled>
Search with Bing
</MenuItem>
Expand Down
16 changes: 11 additions & 5 deletions packages/paste-website/src/component-examples/MenuExamples.ts
Expand Up @@ -30,14 +30,14 @@ const MenuGroupExample = () => {
</MenuButton>
<Menu {...menu} aria-label="Actions">
<MenuGroup label="Social media" icon={<AttachIcon decorative />}>
<MenuItem {...menu}>Twitter</MenuItem>
<MenuItem {...menu}>Myspace</MenuItem>
<MenuItem {...menu}>Dribbble</MenuItem>
<MenuItem {...menu}>Twitter</MenuItem>
<MenuItem {...menu}>Myspace</MenuItem>
<MenuItem {...menu}>Dribbble</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup label="Search engines">
<MenuItem {...menu}>Ecosia</MenuItem>
<MenuItem {...menu}>DuckDuckGo</MenuItem>
<MenuItem {...menu}>Ecosia</MenuItem>
<MenuItem {...menu}>DuckDuckGo</MenuItem>
</MenuGroup>
</Menu>
</>
Expand Down Expand Up @@ -154,6 +154,12 @@ const ItemsExample = () => {
Menu item content <ChevronDownIcon decorative />
</MenuButton>
<Menu {...menu} aria-label="Preferences">
<MenuItem {...menu}>
Default item
</MenuItem>
<MenuItem variant="destructive" {...menu}>
Destructive item
</MenuItem>
<MenuItem {...menu}>
<MediaObject verticalAlign="center">
<MediaFigure spacing="space20">
Expand Down
23 changes: 13 additions & 10 deletions packages/paste-website/src/pages/components/menu/index.mdx
Expand Up @@ -244,6 +244,8 @@ To do so, either set `href` with a valid url to go to a new page, or set the `on
</CalloutText>
</Callout>

Use the `variant` prop in `MenuItem` to use a default or destructive item. We recommend naming the menu item as something commonly understood as a destructive (e.g., "Delete" or "Cancel").

<LivePreview
scope={{
useMenuState,
Expand Down Expand Up @@ -289,19 +291,19 @@ See the [button](/components/button) component.

#### Default

| Property | Default token | Modifiable? |
| -------------- | ------------------------------------------------- | ----------- |
| color | color-text (default) color-text-weaker (disabled) | No |
| padding-top | space-30 | No |
| padding-bottom | space-30 | No |
| padding-left | space-90 (in-group) or space-70 (regular) | No |
| padding-right | space-90 (in-group) or space-70 (regular) | No |
| Property | Default token | Modifiable? |
| -------------- | --------------------------------------------------------------------------------------------- | ----------- |
| color | color-text (default), color-text-link-destructive (destructive), color-text-weaker (disabled) | No |
| padding-top | space-30 | No |
| padding-bottom | space-30 | No |
| padding-left | space-90 (in-group) or space-70 (regular) | No |
| padding-right | space-90 (in-group) or space-70 (regular) | No |

#### Hover & focused

| Property | Default token | Modifiable? |
| -------- | --------------- | ----------- |
| color | color-text-link | No |
| Property | Default token | Modifiable? |
| -------- | ----------------------------------------------------------------------------- | ----------- |
| color | color-text-link (default), color-text-link-destructive-stronger (destructive) | No |

### MenuGroup

Expand Down Expand Up @@ -434,6 +436,7 @@ These props are returned by the state hook. You can spread them into this compon

| Prop | Type | Description | Default |
| -------- | -------------------- | ----------------------------------------------------------------------------------------- | ----------- |
| variant | `MenuItemVariants` | Swaps the menu item variant. Options are `default` and `destructive`. | `default` |
| disabled | `boolean, undefined` | Same as the HTML attribute. | |
| id | `string, undefined` | Same as the HTML attribute. | |
| onClick | `() => void` | Same as the HTML attribute. | |
Expand Down

0 comments on commit 563dff9

Please sign in to comment.