-
Notifications
You must be signed in to change notification settings - Fork 535
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* wip * add memex example * add complex story * add changeset * add actionmenu2 to drafts * add docs! * polish the docs just a bit * move MenuContext + add warning * return null from selection * polish stories * fix story * remove draft from status * oops left a comment in * change setOpen to onOpenChange * Use Box instead of BorderBox in docs * missed role in bad merge! * remove component checklist import Co-authored-by: Cole Bemis <colebemis@github.com> Co-authored-by: Cole Bemis <colebemis@github.com>
- Loading branch information
1 parent
65b63e4
commit a13efa4
Showing
12 changed files
with
963 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@primer/components': minor | ||
--- | ||
|
||
Add composable `ActionMenu` to `@primer/components/drafts` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
--- | ||
title: ActionMenu | ||
status: Alpha | ||
source: https://github.com/primer/react/tree/main/src/ActionMenu | ||
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/components' | ||
import {ActionMenu, ActionList} from '@primer/components/drafts' | ||
import {Props} from '../../src/props' | ||
|
||
<br /> | ||
|
||
<Box sx={{border: '1px solid', borderColor: 'border.default', borderRadius: 2, padding: 6}}> | ||
<ActionMenu> | ||
<ActionMenu.Button>Menu</ActionMenu.Button> | ||
<ActionList> | ||
<ActionList.Item onSelect={() => onSelect('Copy link')}> | ||
Copy link | ||
<ActionList.TrailingVisual>⌘C</ActionList.TrailingVisual> | ||
</ActionList.Item> | ||
<ActionList.Item onSelect={() => onSelect('Quote reply')}> | ||
Quote reply | ||
<ActionList.TrailingVisual>⌘Q</ActionList.TrailingVisual> | ||
</ActionList.Item> | ||
<ActionList.Item onSelect={() => onSelect('Edit comment')}> | ||
Edit comment | ||
<ActionList.TrailingVisual>⌘E</ActionList.TrailingVisual> | ||
</ActionList.Item> | ||
<ActionList.Divider /> | ||
<ActionList.Item variant="danger" onSelect={() => onSelect('Delete file')}> | ||
Delete file | ||
<ActionList.TrailingVisual>⌘D</ActionList.TrailingVisual> | ||
</ActionList.Item> | ||
</ActionList> | ||
|
||
</ActionMenu> | ||
</Box> | ||
|
||
<br /> | ||
|
||
```js | ||
import {ActionMenu} from '@primer/components/drafts' | ||
``` | ||
|
||
<br /> | ||
|
||
## Examples | ||
|
||
### Minimal example | ||
|
||
`ActionMenu` ships with `ActionMenu.Button` which is an accessible trigger for the overlay. It's recommended to compose `ActionList` with this component. | ||
|
||
| ||
|
||
```javascript live noinline | ||
// import {ActionMenu, ActionList} from '@primer/components/drafts' | ||
const {ActionMenu, ActionList} = drafts // ignore docs silliness; import like that ↑ | ||
|
||
render( | ||
<ActionMenu> | ||
<ActionMenu.Button>Menu</ActionMenu.Button> | ||
|
||
<ActionList> | ||
<ActionList.Item onSelect={event => console.log('New file')}>New file</ActionList.Item> | ||
<ActionList.Item>Copy link</ActionList.Item> | ||
<ActionList.Item>Edit file</ActionList.Item> | ||
<ActionList.Divider /> | ||
<ActionList.Item variant="danger">Delete file</ActionList.Item> | ||
</ActionList> | ||
</ActionMenu> | ||
) | ||
``` | ||
|
||
### With a custom anchor | ||
|
||
You can choose to have a different _anchor_ for the Menu dependending on the application's context. | ||
|
||
| ||
|
||
```javascript live noinline | ||
// import {ActionMenu, ActionList} from '@primer/components/drafts' | ||
const {ActionMenu, ActionList} = drafts // ignore docs silliness; import like that ↑ | ||
|
||
render( | ||
<ActionMenu> | ||
<ActionMenu.Anchor> | ||
<ButtonInvisible aria-label="Open column options"> | ||
<KebabHorizontalIcon /> | ||
</ButtonInvisible> | ||
</ActionMenu.Anchor> | ||
|
||
<ActionList> | ||
<ActionList.Item> | ||
<ActionList.LeadingVisual> | ||
<PencilIcon /> | ||
</ActionList.LeadingVisual> | ||
Rename | ||
</ActionList.Item> | ||
<ActionList.Item> | ||
<ActionList.LeadingVisual> | ||
<ArchiveIcon /> | ||
</ActionList.LeadingVisual> | ||
Archive all cards | ||
</ActionList.Item> | ||
<ActionList.Item variant="danger"> | ||
<ActionList.LeadingVisual> | ||
<TrashIcon /> | ||
</ActionList.LeadingVisual> | ||
Delete | ||
</ActionList.Item> | ||
</ActionList> | ||
</ActionMenu> | ||
) | ||
``` | ||
|
||
### With Groups | ||
|
||
```javascript live noinline | ||
// import {ActionMenu, ActionList} from '@primer/components/drafts' | ||
const {ActionMenu, ActionList} = drafts // ignore docs silliness; import like that ↑ | ||
|
||
render( | ||
<ActionMenu> | ||
<ActionMenu.Button>Open column menu</ActionMenu.Button> | ||
|
||
<ActionList showDividers> | ||
<ActionList.Group title="Live query"> | ||
<ActionList.Item> | ||
<ActionList.LeadingVisual> | ||
<SearchIcon /> | ||
</ActionList.LeadingVisual> | ||
repo:github/memex,github/github | ||
</ActionList.Item> | ||
</ActionList.Group> | ||
<ActionList.Divider /> | ||
<ActionList.Group title="Layout" variant="subtle"> | ||
<ActionList.Item> | ||
<ActionList.LeadingVisual> | ||
<NoteIcon /> | ||
</ActionList.LeadingVisual> | ||
Table | ||
<ActionList.Description variant="block"> | ||
Information-dense table optimized for operations across teams | ||
</ActionList.Description> | ||
</ActionList.Item> | ||
<ActionList.Item role="listitem"> | ||
<ActionList.LeadingVisual> | ||
<ProjectIcon /> | ||
</ActionList.LeadingVisual> | ||
Board | ||
<ActionList.Description variant="block">Kanban-style board focused on visual states</ActionList.Description> | ||
</ActionList.Item> | ||
</ActionList.Group> | ||
<ActionList.Divider /> | ||
<ActionList.Group> | ||
<ActionList.Item> | ||
<ActionList.LeadingVisual> | ||
<FilterIcon /> | ||
</ActionList.LeadingVisual> | ||
Save sort and filters to current view | ||
</ActionList.Item> | ||
<ActionList.Item> | ||
<ActionList.LeadingVisual> | ||
<FilterIcon /> | ||
</ActionList.LeadingVisual> | ||
Save sort and filters to new view | ||
</ActionList.Item> | ||
</ActionList.Group> | ||
<ActionList.Divider /> | ||
<ActionList.Group> | ||
<ActionList.Item> | ||
<ActionList.LeadingVisual> | ||
<GearIcon /> | ||
</ActionList.LeadingVisual> | ||
View settings | ||
</ActionList.Item> | ||
</ActionList.Group> | ||
</ActionList> | ||
</ActionMenu> | ||
) | ||
``` | ||
|
||
### With External Anchor | ||
|
||
To create an anchor outside of the menu, you need to switch to controlled mode for the menu and pass it as `anchorRef` to `ActionMenu`: | ||
|
||
```javascript live noinline | ||
// import {ActionMenu, ActionList} from '@primer/components/drafts' | ||
const {ActionMenu, ActionList} = drafts // ignore docs silliness; import like that ↑ | ||
|
||
const Example = () => { | ||
const [open, setOpen] = React.useState(false) | ||
const anchorRef = React.createRef() | ||
|
||
return ( | ||
<> | ||
<Button ref={anchorRef} onClick={() => setOpen(!open)}> | ||
{open ? 'Close Menu' : 'Open Menu'} | ||
</Button> | ||
|
||
<ActionMenu open={open} onOpenChange={setOpen} anchorRef={anchorRef}> | ||
<ActionList> | ||
<ActionList.Item>Copy link</ActionList.Item> | ||
<ActionList.Item>Quote reply</ActionList.Item> | ||
<ActionList.Item>Edit comment</ActionList.Item> | ||
<ActionList.Divider /> | ||
<ActionList.Item variant="danger">Delete file</ActionList.Item> | ||
</ActionList> | ||
</ActionMenu> | ||
</> | ||
) | ||
} | ||
|
||
render(<Example />) | ||
``` | ||
|
||
## Props / API reference | ||
|
||
### ActionMenu | ||
|
||
| Name | Type | Default | Description | | ||
| :----------- | :-------------------------------------------------- | :-----: | :----------------------------------------------------------------------------------------------------------------------- | | ||
| children\* | `React.ReactElement[]` | - | Required. Recommended: `ActionMenu.Button` or `ActionMenu.Anchor` with [`ActionList`](/drafts/ActionList2) | | ||
| open | `boolean` | - | Optional. If defined, will control the open/closed state of the overlay. Must be used in conjuction with `onOpenChange`. | | ||
| onOpenChange | `(open: boolean) => void` | - | Optional. If defined, will control the open/closed state of the overlay. Must be used in conjuction with `open`. | | ||
| anchorRef | `React.RefObject<HTMLElement>` | - | Optional. Useful for defining an external anchor | | ||
| overlayProps | [`Partial<OverlayProps>`](/Overlay#component-props) | - | Optional. Props to be spread on the internal [`AnchoredOverlay`](/AnchoredOverlay) component. | | ||
|
||
### ActionMenu.Button | ||
|
||
| Type | Default | Description | | ||
| :-------------------------------------- | :-----: | :------------------------------------------------------------------------------------------------------------------- | | ||
| [ButtonProps](/Buttons#component-props) | - | Optional. You can pass all of the props that you would pass to a [`Button`](/Buttons) component like `variant`, `sx` | | ||
|
||
### ActionMenu.Anchor | ||
|
||
| Name | Type | Default | Description | | ||
| :--------- | :------------------- | :-----: | :-------------------------------- | | ||
| children\* | `React.ReactElement` | - | Required. Accepts a single child. | | ||
|
||
## Further reading | ||
|
||
[Interface guidelines: Action List + Menu](https://primer.style/design/components/action-list) | ||
|
||
## Related components | ||
|
||
- [ActionList](/drafts/ActionList2) | ||
- [DropdownMenu](/DropdownMenu) | ||
- [SelectPanel](/SelectPanel) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.