Skip to content
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
4c54a2f
initialize RAC submenu
reidbarber Jan 3, 2024
75edf1f
use cached children
reidbarber Jan 11, 2024
dbc2cf8
cleanup
reidbarber Jan 11, 2024
8bdd954
use one useRenderProps
reidbarber Jan 11, 2024
5d7c9a6
types
reidbarber Jan 11, 2024
da103f0
cleanup
reidbarber Jan 11, 2024
0100aa5
fix trigger ref
reidbarber Jan 11, 2024
bd95e34
typescript
reidbarber Jan 11, 2024
2e6b265
add chevron style to submenu trigger
reidbarber Jan 11, 2024
c3cb412
types
reidbarber Jan 11, 2024
a61d762
cleanup
reidbarber Jan 11, 2024
acc9144
pass submenu ref
reidbarber Jan 11, 2024
afb26c0
Merge remote-tracking branch 'origin/main' into rac-submenu-2
reidbarber Jan 11, 2024
f7bbc67
add submenu story to menu story file
reidbarber Jan 11, 2024
9537ac5
fix nested case
reidbarber Jan 12, 2024
5eeaefe
cleanup
reidbarber Jan 12, 2024
e41c580
add nested story
reidbarber Jan 12, 2024
0fab5de
fix trigger attribute
reidbarber Jan 12, 2024
74c94e5
add tests
reidbarber Jan 12, 2024
93eae69
update jsdoc
reidbarber Jan 12, 2024
0ac5950
add docs
reidbarber Jan 12, 2024
531f880
update storybook styles
reidbarber Jan 12, 2024
0353aad
Merge branch 'main' into rac-submenu-2
reidbarber Jan 12, 2024
78bb709
fix docs types
reidbarber Jan 12, 2024
46ee9ca
Merge branch 'rac-submenu-2' of https://github.com/adobe/react-spectr…
reidbarber Jan 12, 2024
444a051
cleanup tests
reidbarber Jan 12, 2024
268619e
move imports in docs closer to example
reidbarber Jan 12, 2024
e7c1207
typescript
reidbarber Jan 12, 2024
a11f588
add example to homepage
reidbarber Jan 12, 2024
a7405f9
close all submenus if underlay is clicked
reidbarber Jan 12, 2024
10862de
revert autoformatting from headwind
reidbarber Jan 16, 2024
5193143
add to small example, fix imports and labels
reidbarber Jan 16, 2024
2461c4c
render via portal
reidbarber Jan 17, 2024
9f215a2
add render props and data attributes
reidbarber Jan 17, 2024
774a524
add || undefined
reidbarber Jan 17, 2024
4a6064d
add many items example
reidbarber Jan 17, 2024
2f1c070
add keys for storybook
reidbarber Jan 17, 2024
ff34be5
imrove styles on docs page
reidbarber Jan 17, 2024
7c45618
improve homepage styles
reidbarber Jan 17, 2024
de49d82
move chevron into item wrapper
reidbarber Jan 17, 2024
ffcbbd4
Merge remote-tracking branch 'origin/main' into rac-submenu-2
reidbarber Jan 17, 2024
e00dd27
ts lint
reidbarber Jan 17, 2024
d6509a2
lint
reidbarber Jan 17, 2024
d8fdc04
story style update
reidbarber Jan 17, 2024
087315b
style isSubmenuOpen states
reidbarber Jan 18, 2024
2613335
add dynamic example to dcs
reidbarber Jan 19, 2024
c52c8c5
don't allow submenu trigger to be a link
reidbarber Jan 19, 2024
e9777b6
clarify submenutrigger children order in types
reidbarber Jan 19, 2024
5aee52b
use proper hover state from useHover
reidbarber Jan 19, 2024
6cd4870
update tests
reidbarber Jan 19, 2024
db7f438
update docs to clarify children
reidbarber Jan 19, 2024
ed2fb5c
remove top -5 offset
reidbarber Jan 22, 2024
292fac0
add disabled submenu example
reidbarber Jan 22, 2024
05c89e3
fix iOS VO submenu closing issue
reidbarber Jan 22, 2024
14f5584
add Select story with many items
reidbarber Jan 22, 2024
5db5718
move docs chevron styles from inline to CSS snippet
reidbarber Jan 23, 2024
8e1f11c
export SubmenuTrigger directly without forwardRef
reidbarber Jan 23, 2024
63ee502
update render props
reidbarber Jan 23, 2024
dcea397
fix indentation
reidbarber Jan 23, 2024
544f5e1
add has-submenu to tailwind plugin
reidbarber Jan 23, 2024
d136d0a
remove offset
reidbarber Jan 23, 2024
b15ba52
Merge remote-tracking branch 'origin/main' into rac-submenu-2
reidbarber Jan 23, 2024
e2df1d2
Merge branch 'main' into rac-submenu-2
reidbarber Jan 24, 2024
c4bc063
fix homepage example styles
reidbarber Jan 25, 2024
e9fd987
fix docs example dark mode style
reidbarber Jan 25, 2024
4b06860
focus trigger on escape
reidbarber Jan 26, 2024
85c38bf
add test for focus menu trigger after submenu closes via escape
reidbarber Jan 26, 2024
d4d3058
Merge remote-tracking branch 'origin/main' into rac-submenu-2
reidbarber Jan 29, 2024
161a84a
add alpha tag to docs
reidbarber Jan 30, 2024
66e5b97
add JSDoc
reidbarber Jan 31, 2024
3dfab71
fix restoring focus to menu trigger after nested submenu closed via E…
reidbarber Jan 31, 2024
51e34f0
lint
reidbarber Jan 31, 2024
e208c99
Merge branch 'main' into rac-submenu-2
reidbarber Jan 31, 2024
4389c5c
Render popover outside menu item div
devongovett Feb 1, 2024
f85a0b8
support a custom delay prop in hook and RAC
reidbarber Feb 1, 2024
77c5cab
remove from homepage and tailwind starter for now
reidbarber Feb 2, 2024
7c9ac79
Merge branch 'main' into rac-submenu-2
LFDanLu Feb 2, 2024
7174f6d
revert auto-formatting
reidbarber Feb 2, 2024
b8ab586
Merge remote-tracking branch 'origin/main' into rac-submenu-2
reidbarber Feb 2, 2024
31df572
Merge branch 'rac-submenu-2' of https://github.com/adobe/react-spectr…
reidbarber Feb 2, 2024
efc1c46
Merge branch 'main' into rac-submenu-2
reidbarber Feb 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions packages/dev/docs/pages/react-aria/home/ExampleApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {Arrow} from './components';
import {Button} from 'tailwind-starter/Button';
import {Cell, Column, Row, TableHeader} from 'tailwind-starter/Table';
import {Checkbox} from 'tailwind-starter/Checkbox';
import {CloudSun, Dessert, Droplet, Droplets, FilterIcon, MoreHorizontal, PencilIcon, PlusIcon, RefreshCw, SlidersIcon, StarIcon, Sun, SunDim, TrashIcon} from 'lucide-react';
import {ColumnProps, Dialog, DialogTrigger, DropZone, Form, Heading, isFileDropItem, Key, MenuTrigger, ModalOverlay, ModalOverlayProps, Modal as RACModal, ResizableTableContainer, Selection, SortDescriptor, Table, TableBody, Text, ToggleButton, ToggleButtonProps, TooltipTrigger} from 'react-aria-components';
import {CloudSun, Dessert, Droplet, Droplets, FilterIcon, Mail, MoreHorizontal, PencilIcon, PlusIcon, RefreshCw, ShareIcon, SlidersIcon, StarIcon, Sun, SunDim, TrashIcon, Twitter} from 'lucide-react';
import {ColumnProps, Dialog, DialogTrigger, DropZone, Form, Heading, isFileDropItem, Key, MenuTrigger, ModalOverlay, ModalOverlayProps, Modal as RACModal, ResizableTableContainer, Selection, SortDescriptor, SubmenuTrigger, Table, TableBody, Text, ToggleButton, ToggleButtonProps, TooltipTrigger} from 'react-aria-components';
import {ComboBox, ComboBoxItem} from 'tailwind-starter/ComboBox';
import {DatePicker} from 'tailwind-starter/DatePicker';
import {focusRing} from 'tailwind-starter/utils';
Expand Down Expand Up @@ -245,6 +245,18 @@ export function ExampleApp() {
<MenuItem id="favorite"><StarIcon aria-hidden className="w-4 h-4" /> {item.isFavorite ? 'Unfavorite' : 'Favorite'}</MenuItem>
<MenuItem id="edit"><PencilIcon aria-hidden className="w-4 h-4" /> Edit…</MenuItem>
<MenuItem id="delete"><TrashIcon aria-hidden className="w-4 h-4" /> Delete…</MenuItem>
<SubmenuTrigger>
<MenuItem aria-label="Share">
<ShareIcon aria-hidden className="w-4 h-4" />
Share
</MenuItem>
<Popover>
<Menu>
<MenuItem href={`https://twitter.com/intent/tweet?text=${encodeURIComponent(item.common_name)}`} target="blank" rel="noopener noreferrer" aria-label="Twitter"><Twitter aria-hidden className="w-4 h-4" /> Twitter…</MenuItem>
<MenuItem href={`mailto:[email protected]?subject=${encodeURIComponent(item.common_name)}`} target="blank" rel="noopener noreferrer" aria-label="Email"><Mail aria-hidden className="w-4 h-4" /> Email…</MenuItem>
</Menu>
</Popover>
</SubmenuTrigger>
</Menu>
</MenuTrigger>
</div>
Expand Down Expand Up @@ -295,6 +307,18 @@ export function ExampleApp() {
<MenuItem id="favorite"><StarIcon aria-hidden className="w-4 h-4" /> {item.isFavorite ? 'Unfavorite' : 'Favorite'}</MenuItem>
<MenuItem id="edit"><PencilIcon aria-hidden className="w-4 h-4" /> Edit…</MenuItem>
<MenuItem id="delete"><TrashIcon aria-hidden className="w-4 h-4" /> Delete…</MenuItem>
<SubmenuTrigger>
<MenuItem aria-label="Share">
<ShareIcon aria-hidden className="w-4 h-4" />
Share
</MenuItem>
<Popover>
<Menu>
<MenuItem href={`https://twitter.com/intent/tweet?text=${encodeURIComponent(item.common_name)}`} target="blank" rel="noopener noreferrer" aria-label="Twitter"><Twitter aria-hidden className="w-4 h-4" /> Twitter…</MenuItem>
<MenuItem href={`mailto:[email protected]?subject=${encodeURIComponent(item.common_name)}`} target="blank" rel="noopener noreferrer" aria-label="Email"><Mail aria-hidden className="w-4 h-4" /> Email…</MenuItem>
</Menu>
</Popover>
</SubmenuTrigger>
</Menu>
</MenuTrigger>
</Cell>
Expand Down
82 changes: 80 additions & 2 deletions packages/react-aria-components/docs/Menu.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type: component

<HeaderInfo
packageData={packageData}
componentNames={['MenuTrigger', 'Menu']}
componentNames={['MenuTrigger', 'Menu', 'SubmenuTrigger']}
sourceData={[
{type: 'W3C', url: 'https://www.w3.org/WAI/ARIA/apg/patterns/menu/'}
]} />
Expand Down Expand Up @@ -226,7 +226,18 @@ function MyMenuButton<T extends object>({label, children, ...props}: MyMenuButto
}

function MyItem(props: MenuItemProps) {
return <MenuItem {...props} className={({isFocused, isSelected}) => `my-item ${isFocused ? 'focused' : ''}`} />
return (
<MenuItem {...props} className={({isFocused, isSelected, isSubmenuOpen}) => `my-item ${isFocused ? 'focused' : ''} ${isSubmenuOpen ? 'submenu-open' : ''}`}>
{({hasSubmenu}) => (
<>
{props.children}
{hasSubmenu && (
<svg xmlns="http://www.w3.org/2000/svg" width={20} height={20} fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} viewBox="0 0 24 24" style={{position: 'absolute', right: 0, top : 0, height: '100%'}}><path d="m9 18 6-6-6-6" /></svg>
)}
</>
)}
</MenuItem>
);
}

<MyMenuButton label="Edit">
Expand Down Expand Up @@ -254,6 +265,10 @@ function MyItem(props: MenuItemProps) {
background: #e70073;
color: white;
}
&.submenu-open:not(.focused) {
background: #dedede;
color: var(--text-color);
}
}

@media (forced-colors: active) {
Expand Down Expand Up @@ -658,12 +673,63 @@ function Example() {
}
```

## Submenus

Submenus can be implemented by using a `SubmenuTrigger`, where the first child inside is the submenu's trigger `MenuItem`, and the second child is the submenu itself.

```tsx example
import {Menu, Popover, SubmenuTrigger} from 'react-aria-components';

<MyMenuButton label="Actions">
<MyItem>Cut</MyItem>
<MyItem>Copy</MyItem>
<MyItem>Delete</MyItem>
<SubmenuTrigger>
<MyItem aria-label="Share">Share</MyItem>
<Popover>
<Menu>
<MyItem>SMS</MyItem>
<MyItem>Twitter</MyItem>
<SubmenuTrigger>
<MyItem aria-label="Email">Email</MyItem>
<Popover>
<Menu>
<MyItem>Work</MyItem>
<MyItem>Personal</MyItem>
</Menu>
</Popover>
</SubmenuTrigger>
</Menu>
</Popover>
</SubmenuTrigger>
</MyMenuButton>
```

<details>
<summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Show CSS</summary>

```css
.react-aria-Popover[data-trigger=SubmenuTrigger][data-placement="right"] {
margin-left: -5px;
}

.react-aria-Popover[data-trigger=SubmenuTrigger][data-placement="left"] {
margin-right: -5px;
}
```

</details>

## Props

### MenuTrigger

<PropTable component={docs.exports.MenuTrigger} links={docs.links} />

### SubmenuTrigger

<PropTable component={docs.exports.SubmenuTrigger} links={docs.links} />

### Button

A `<Button>` accepts its contents as `children`. Other props such as `onPress` and `isDisabled` will be set by the `MenuTrigger`.
Expand Down Expand Up @@ -812,6 +878,18 @@ Within a MenuTrigger, the popover will have the `data-trigger="MenuTrigger"` att
}
```

Within a SubmenuTrigger, the popover will have the `data-trigger="SubmenuTrigger"` attribute, which can be used to define submenu-specific styles.

```css render=false
.react-aria-Popover[data-trigger=SubmenuTrigger][data-placement="right"] {
transform: translateX(-5px);
}

.react-aria-Popover[data-trigger=SubmenuTrigger][data-placement="left"] {
transform: translateX(5px);
}
```

### Menu

A `Menu` can be targeted with the `.react-aria-Menu` CSS selector, or by overriding with a custom `className`.
Expand Down
21 changes: 21 additions & 0 deletions packages/react-aria-components/example/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ html {
.menu, .group {
padding: 0;
list-style: none;
overflow-y: auto;
max-height: inherit;
}

.item {
Expand Down Expand Up @@ -48,6 +50,11 @@ html {
color: white;
}

.item.submenu-open:not(.focused) {
background: lightslategray;
color: white;
}

.item.item.hovered {
background: lightsalmon;
color: white;
Expand All @@ -58,6 +65,20 @@ html {
color: white;
}

.item[data-has-submenu]::after {
content: '›';
content: '›' / '';
justify-self: end;
}

.popover[data-trigger=SubmenuTrigger][data-placement="right"] {
margin-left: -8px;
}

.popover[data-trigger=SubmenuTrigger][data-placement="left"] {
margin-right: -8px;
}

.wrapper {
display: flex;
flex-direction: column;
Expand Down
2 changes: 2 additions & 0 deletions packages/react-aria-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
"@internationalized/string": "^3.2.0",
"@react-aria/focus": "^3.16.0",
"@react-aria/interactions": "^3.20.1",
"@react-aria/menu": "^3.12.0",
"@react-aria/toolbar": "3.0.0-beta.1",
"@react-aria/utils": "^3.23.0",
"@react-stately/menu": "^3.6.0",
"@react-stately/table": "^3.11.4",
"@react-stately/utils": "^3.9.0",
"@react-types/form": "^3.7.1",
Expand Down
Loading