diff --git a/.changeset/deprecate-actionlistv1-promote-actionlistv2.md b/.changeset/deprecate-actionlistv1-promote-actionlistv2.md new file mode 100644 index 00000000000..8aa0e6f82e0 --- /dev/null +++ b/.changeset/deprecate-actionlistv1-promote-actionlistv2.md @@ -0,0 +1,154 @@ +--- +'@primer/react': major +--- + +### ActionList + +ActionList has been rewritten with a composable API, design updates and accessibility fixes. + +See full list of props and examples: https://primer.style/react/ActionList + + + + + + + + + + + + + + + + + +
Before (v34) After (v35)
+ +```jsx + +``` + + + +```jsx + + New file + Copy link + Edit file + + Delete file + +``` + +
+ +```jsx + , + text: 'mona', + description: 'Monalisa Octocat', + descriptionVariant: 'block' + }, + { + key: '2', + leadingVisual: GearIcon, + text: 'View Settings', + trailingVisual: ArrowRightIcon + } + ]} +/> +``` + + + +```jsx + + + + + + github/primer + + + + + + mona + Monalisa Octocat + + + + + + View settings + + + + + +``` + +
+ +```jsx + +``` + + + +```jsx + + + repo:github/github + + + + + Table + Board Description> + + + + View settings + +``` + +
+ +To continue to use the deprecated API for now, change the import path to `@primer/react/deprecated`: + +```js +import {ActionList} from '@primer/react/deprecated' +``` + +You can use the [one-time codemod](https://github.com/primer/react-migrate#readme) to change your import statements automatically. diff --git a/docs/content/ActionList.mdx b/docs/content/ActionList.mdx index 7eb5066cca2..be09bd7efee 100644 --- a/docs/content/ActionList.mdx +++ b/docs/content/ActionList.mdx @@ -3,98 +3,447 @@ componentId: action_list title: ActionList status: Alpha source: https://github.com/primer/react/tree/main/src/ActionList +storybook: '/react/storybook?path=/story/composite-components-actionlist' +description: An ActionList is a list of items that can be activated or selected. ActionList is the base component for many menu-type components, including DropdownMenu and ActionMenu. --- -An `ActionList` is a list of items which can be activated or selected. `ActionList` is the base component for many of our menu-type components, including `DropdownMenu` and `ActionMenu`. +import {Avatar} from '@primer/react' +import {ActionList} from '@primer/react' +import {LinkIcon, AlertIcon, ArrowRightIcon} from '@primer/octicons-react' +import InlineCode from '@primer/gatsby-theme-doctocat/src/components/inline-code' -## Minimal example + + + + + + + github.com/primer + + A React implementation of GitHub's Primer Design System + + + + + + + mona + Monalisa Octocat + + + + + + 4 vulnerabilities + + + + + + + +```js +import {ActionList} from '@primer/react' +``` + +## Examples + +### Minimal example ```jsx live - + + New file + Copy link + Edit file + + Delete file + ``` -## Example with grouped items +### With leading visual + +Leading visuals are optional and appear at the start of an item. They can be octicons, avatars, and other custom visuals that fit a small area. + ```jsx live - + + + + github.com/primer + + + + 4 vulnerabilities + + + + mona + + + ``` -## Example with custom item renderer - -```jsx - - }, - { - text: 'React Router link', - renderItem: props => - }, - { - text: 'NextJS style', - renderItem: props => ( - - - - ) - } - ]} -/> +### With trailing visual + +Trailing visual and trailing text can display auxiliary information. They're placed at the right of the item, and can denote status, keyboard shortcuts, or be used to set expectations about what the action does. + +```jsx live + + + New file + ⌘ + N + + + Copy link + ⌘ + C + + + Edit file + ⌘ + E + + + Delete file + + + +``` + +### With description and dividers + +Item dividers allow users to parse heavier amounts of information. They're placed between items and are useful in complex lists, particularly when descriptions or multi-line text is present. + +```jsx live + + + + + + mona + Monalisa Octocat + + + + + + hubot + Hubot + + + + + + primer-css + GitHub Design Systems Bot + + +``` + +### With links + +When you want to add links to the List instead of actions, use `ActionList.LinkItem` + + +```jsx live + + + + + + github/primer + + + + + + MIT License + + + + + + 1.4k stars + + +``` + +### With groups + +```javascript live noinline +const SelectFields = () => { + const [options, setOptions] = React.useState([ + {text: 'Status', selected: true}, + {text: 'Stage', selected: true}, + {text: 'Assignee', selected: true}, + {text: 'Team', selected: true}, + {text: 'Estimate', selected: false}, + {text: 'Due Date', selected: false} + ]) + + const visibleOptions = options.filter(option => option.selected) + const hiddenOptions = options.filter(option => !option.selected) + + const toggle = text => { + setOptions( + options.map(option => { + if (option.text === text) option.selected = !option.selected + return option + }) + ) + } + + return ( + + + {visibleOptions.map(option => ( + toggle(option.text)}> + {option.text} + + ))} + + + {hiddenOptions.map((option, index) => ( + toggle(option.text)}> + {option.text} + + ))} + {hiddenOptions.length === 0 && No hidden fields} + + + ) +} + +render() ``` ## Props -| Name | Type | Default | Description | -| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------ | -| items | `(ItemProps & Omit, keyof ItemProps>) \| ((Partial & {renderItem: RenderItemFn}) & {key?: Key})` | `undefined` | Required. A list of item objects conforming to the `ActionList.Item` props interface. | -| renderItem | `(props: ItemProps) => JSX.Element` | `ActionList.Item` | Optional. If defined, each item in `items` will be passed to this function, allowing for `ActionList`-wide custom item rendering. | -| groupMetadata | `GroupProps[]` | `undefined` | Optional. If defined, `ActionList` will group `items` into `ActionList.Group`s separated by `ActionList.Divider` according to their `groupId` property. | -| showItemDividers | `boolean` | `false` | Optional. If `true` dividers will be displayed above each `ActionList.Item` which does not follow an `ActionList.Header` or `ActionList.Divider` | +### ActionList + + + + + inset children are offset (vertically and horizontally) from list edges.{' '} + full children are flush (vertically and horizontally) with list edges + + } + /> + + + AriaRole + } + description={ + <> + ARIA role describing the function of the list. listbox and{' '} + menu are a common values. + + } + /> + + + +### ActionList.Item + + + + + danger indicates that the item is destructive. + + } + /> + + + + AriaRole + } + description={ + <> + ARIA role describing the function of the item. option is a common value. + + } + /> + + + +### ActionList.LinkItem + + + + MDN + } + /> + + +### ActionList.LeadingVisual + + + + + + +### ActionList.TrailingVisual + + + + + + +### ActionList.Description + + + + + inline descriptions are positioned beside primary text. block{' '} + descriptions are positioned below primary text. + + } + /> + + + +### ActionList.Group + + + + + + + inline descriptions are positioned beside primary text. block{' '} + descriptions are positioned below primary text. + + } + /> + + Set selectionVariant at the group level. + + } + /> + AriaRole + } + description={ + <> + ARIA role describing the function of the list inside the group. listbox and{' '} + menu are a common values. + + } + /> + + + +## Status + + + +## Further reading + +- [Interface guidelines: Action List](https://primer.style/design/components/action-list) + +## Related components + +- [ActionMenu](/drafts/ActionMenu2) +- [DropdownMenu](/DropdownMenu) +- [SelectPanel](/SelectPanel) diff --git a/docs/content/deprecated/ActionList.mdx b/docs/content/deprecated/ActionList.mdx new file mode 100644 index 00000000000..1bcf8880fc0 --- /dev/null +++ b/docs/content/deprecated/ActionList.mdx @@ -0,0 +1,136 @@ +--- +componentId: action_list +title: ActionList +status: Deprecated +source: https://github.com/primer/react/tree/main/src/deprecated/ActionList +--- + +An `ActionList` is a list of items which can be activated or selected. `ActionList` is the base component for many of our menu-type components, including `DropdownMenu` and `ActionMenu`. + +## Deprecation + +Use [new version of ActionList](/ActionList) with composable API, design updates and accessibility fixes. + +**Before** + +```jsx + +``` + +**After** + +```jsx + + New file + Copy link + Edit file + + Delete file + +``` + +Or continue using deprecated API: + +```js +import {ActionList} from '@primer/react/deprecated' +``` + +## Minimal example + +```jsx live deprecated + +``` + +## Example with grouped items + +```jsx live deprecated + +``` + +## Example with custom item renderer + +```jsx deprecated + + }, + { + text: 'React Router link', + renderItem: props => + }, + { + text: 'NextJS style', + renderItem: props => ( + + + + ) + } + ]} +/> +``` + +## Props + +| Name | Type | Default | Description | +| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------ | +| items | `(ItemProps & Omit, keyof ItemProps>) \| ((Partial & {renderItem: RenderItemFn}) & {key?: Key})` | `undefined` | Required. A list of item objects conforming to the `ActionList.Item` props interface. | +| renderItem | `(props: ItemProps) => JSX.Element` | `ActionList.Item` | Optional. If defined, each item in `items` will be passed to this function, allowing for `ActionList`-wide custom item rendering. | +| groupMetadata | `GroupProps[]` | `undefined` | Optional. If defined, `ActionList` will group `items` into `ActionList.Group`s separated by `ActionList.Divider` according to their `groupId` property. | +| showItemDividers | `boolean` | `false` | Optional. If `true` dividers will be displayed above each `ActionList.Item` which does not follow an `ActionList.Header` or `ActionList.Divider` | diff --git a/docs/content/drafts/ActionList2.mdx b/docs/content/drafts/ActionList2.mdx deleted file mode 100644 index bf842be1fe6..00000000000 --- a/docs/content/drafts/ActionList2.mdx +++ /dev/null @@ -1,449 +0,0 @@ ---- -componentId: action_list2 -title: ActionList v2 -status: Alpha -source: https://github.com/primer/react/tree/main/src/ActionList2 -storybook: '/react/storybook?path=/story/composite-components-actionlist2' -description: An ActionList is a list of items that can be activated or selected. ActionList is the base component for many menu-type components, including DropdownMenu and ActionMenu. ---- - -import {Avatar} from '@primer/react' -import {ActionList} from '@primer/react/drafts' -import {LinkIcon, AlertIcon, ArrowRightIcon} from '@primer/octicons-react' -import InlineCode from '@primer/gatsby-theme-doctocat/src/components/inline-code' - - - - - - - - github.com/primer - - A React implementation of GitHub's Primer Design System - - - - - - - mona - Monalisa Octocat - - - - - - 4 vulnerabilities - - - - - - - -```js -import {ActionList} from '@primer/react/drafts' -``` - -## Examples - -### Minimal example - -```jsx live drafts - - New file - Copy link - Edit file - - Delete file - -``` - -### With leading visual - -Leading visuals are optional and appear at the start of an item. They can be octicons, avatars, and other custom visuals that fit a small area. - - -```jsx live drafts - - - - github.com/primer - - - - 4 vulnerabilities - - - - mona - - - -``` - -### With trailing visual - -Trailing visual and trailing text can display auxiliary information. They're placed at the right of the item, and can denote status, keyboard shortcuts, or be used to set expectations about what the action does. - -```jsx live drafts - - - New file - ⌘ + N - - - Copy link - ⌘ + C - - - Edit file - ⌘ + E - - - Delete file - - - -``` - -### With description and dividers - -Item dividers allow users to parse heavier amounts of information. They're placed between items and are useful in complex lists, particularly when descriptions or multi-line text is present. - -```jsx live drafts - - - - - - mona - Monalisa Octocat - - - - - - hubot - Hubot - - - - - - primer-css - GitHub Design Systems Bot - - -``` - -### With links - -When you want to add links to the List instead of actions, use `ActionList.LinkItem` - - -```jsx live drafts - - - - - - github/primer - - - - - - MIT License - - - - - - 1.4k stars - - -``` - -### With groups - -```javascript live noinline drafts -const SelectFields = () => { - const [options, setOptions] = React.useState([ - {text: 'Status', selected: true}, - {text: 'Stage', selected: true}, - {text: 'Assignee', selected: true}, - {text: 'Team', selected: true}, - {text: 'Estimate', selected: false}, - {text: 'Due Date', selected: false} - ]) - - const visibleOptions = options.filter(option => option.selected) - const hiddenOptions = options.filter(option => !option.selected) - - const toggle = text => { - setOptions( - options.map(option => { - if (option.text === text) option.selected = !option.selected - return option - }) - ) - } - - return ( - - - {visibleOptions.map(option => ( - toggle(option.text)}> - {option.text} - - ))} - - - {hiddenOptions.map((option, index) => ( - toggle(option.text)}> - {option.text} - - ))} - {hiddenOptions.length === 0 && No hidden fields} - - - ) -} - -render() -``` - -## Props - -### ActionList - - - - - inset children are offset (vertically and horizontally) from list edges.{' '} - full children are flush (vertically and horizontally) with list edges - - } - /> - - - AriaRole - } - description={ - <> - ARIA role describing the function of the list. listbox and{' '} - menu are a common values. - - } - /> - - - -### ActionList.Item - - - - - danger indicates that the item is destructive. - - } - /> - - - - AriaRole - } - description={ - <> - ARIA role describing the function of the item. option is a common value. - - } - /> - - - -### ActionList.LinkItem - - - - MDN - } - /> - - -### ActionList.LeadingVisual - - - - - - -### ActionList.TrailingVisual - - - - - - -### ActionList.Description - - - - - inline descriptions are positioned beside primary text. block{' '} - descriptions are positioned below primary text. - - } - /> - - - -### ActionList.Group - - - - - - - inline descriptions are positioned beside primary text. block{' '} - descriptions are positioned below primary text. - - } - /> - - Set selectionVariant at the group level. - - } - /> - AriaRole - } - description={ - <> - ARIA role describing the function of the list inside the group. listbox and{' '} - menu are a common values. - - } - /> - - - -## Status - - - -## Further reading - -- [Interface guidelines: Action List](https://primer.style/design/components/action-list) - -## Related components - -- [ActionMenu](/drafts/ActionMenu2) -- [DropdownMenu](/DropdownMenu) -- [SelectPanel](/SelectPanel) diff --git a/docs/content/drafts/ActionMenu2.mdx b/docs/content/drafts/ActionMenu2.mdx index 4ccc9b3c5a3..5a1af58d8da 100644 --- a/docs/content/drafts/ActionMenu2.mdx +++ b/docs/content/drafts/ActionMenu2.mdx @@ -7,8 +7,8 @@ storybook: '/react/storybook?path=/story/composite-components-actionmenu2' description: An ActionMenu is an ActionList-based component for creating a menu of actions that expands through a trigger button. --- -import {Box, Avatar} from '@primer/react' -import {ActionMenu, ActionList} from '@primer/react/drafts' +import {Box, Avatar, ActionList} from '@primer/react' +import {ActionMenu} from '@primer/react/drafts' import {Props} from '../../src/props'
@@ -306,7 +306,7 @@ render( | Name | Type | Default | Description | | :--------------------------------------- | :-------------------- | :-----------------: | :-------------------------------------------------------------------------------------------- | -| children\* | `React.ReactElement[] | React.ReactElement` | Required. Recommended: [`ActionList`](/drafts/ActionList2) | +| children\* | `React.ReactElement[] | React.ReactElement` | Required. Recommended: [`ActionList`](/ActionList) | | [OverlayProps](/Overlay#component-props) | - | - | Optional. Props to be spread on the internal [`AnchoredOverlay`](/AnchoredOverlay) component. | ## Status @@ -336,6 +336,6 @@ render( ## Related components -- [ActionList](/drafts/ActionList2) +- [ActionList](/ActionList) - [SelectPanel](/SelectPanel) - [Button](/drafts/Button2) diff --git a/docs/content/drafts/DropdownMenu2.mdx b/docs/content/drafts/DropdownMenu2.mdx index 68cd522aa1e..8d517f5facb 100644 --- a/docs/content/drafts/DropdownMenu2.mdx +++ b/docs/content/drafts/DropdownMenu2.mdx @@ -7,8 +7,8 @@ storybook: '/react/storybook?path=/story/composite-components-dropdownmenu2' description: Use DropdownMenu to select a single option from a list of menu options. --- -import {Box, Avatar} from '@primer/react' -import {DropdownMenu, ActionList} from '@primer/react/drafts' +import {Box, Avatar, ActionList} from '@primer/react' +import {DropdownMenu} from '@primer/react/drafts' import {Props} from '../../src/props' import State from '../../components/State' import {CalendarIcon, IterationsIcon, NumberIcon, SingleSelectIcon, TypographyIcon} from '@primer/octicons-react' @@ -312,7 +312,7 @@ Use `DropdownMenu` to select an option from a small list. If you’re looking fo description={ <> Recommended:{' '} - + ActionList @@ -359,6 +359,6 @@ Use `DropdownMenu` to select an option from a small list. If you’re looking fo ## Related components -- [ActionList](/drafts/ActionList2) +- [ActionList](/ActionList) - [ActionMenu](/ActionMenu2) - [SelectPanel](/SelectPanel) diff --git a/docs/src/@primer/gatsby-theme-doctocat/nav.yml b/docs/src/@primer/gatsby-theme-doctocat/nav.yml index 0a313c91e00..2c977d13db0 100644 --- a/docs/src/@primer/gatsby-theme-doctocat/nav.yml +++ b/docs/src/@primer/gatsby-theme-doctocat/nav.yml @@ -35,6 +35,8 @@ # url: /useOverlay - title: Components children: + - title: ActionList + url: /ActionList - title: Autocomplete url: /Autocomplete - title: Avatar @@ -143,8 +145,6 @@ url: /drafts/LinkButton - title: IconButton url: /drafts/IconButton - - title: ActionList v2 - url: /drafts/ActionList2 - title: ActionMenu v2 url: /drafts/ActionMenu2 - title: Deprecated @@ -165,3 +165,5 @@ url: /FormGroup - title: SelectMenu url: /deprecated/SelectMenu + - title: ActionList + url: /deprecated/ActionList diff --git a/src/ActionList2/ActionListContainerContext.tsx b/src/ActionList/ActionListContainerContext.tsx similarity index 100% rename from src/ActionList2/ActionListContainerContext.tsx rename to src/ActionList/ActionListContainerContext.tsx diff --git a/src/ActionList2/Description.tsx b/src/ActionList/Description.tsx similarity index 100% rename from src/ActionList2/Description.tsx rename to src/ActionList/Description.tsx diff --git a/src/ActionList/Divider.tsx b/src/ActionList/Divider.tsx index 0513b60f1ce..e286448eb42 100644 --- a/src/ActionList/Divider.tsx +++ b/src/ActionList/Divider.tsx @@ -1,25 +1,29 @@ import React from 'react' -import styled from 'styled-components' +import Box from '../Box' import {get} from '../constants' - -export const StyledDivider = styled.div` - height: 1px; - background: ${get('colors.border.muted')}; - margin-top: calc(${get('space.2')} - 1px); - margin-bottom: ${get('space.2')}; -` +import {Theme} from '../ThemeProvider' +import {SxProp, merge} from '../sx' /** * Visually separates `Item`s or `Group`s in an `ActionList`. */ -export function Divider(): JSX.Element { - return -} -/** - * `Divider` fulfills the `ItemPropsWithCustomRenderer` contract, - * so it can be used inline in an `ActionList`’s `items` prop. - * In other words, `items={[ActionList.Divider]}` is supported as a concise - * alternative to `items={[{renderItem: () => }]}`. - */ -Divider.renderItem = Divider +export const Divider: React.FC = ({sx = {}}) => { + return ( +