Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Menu] Overhaul the component API #468

Merged
merged 122 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from 117 commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
6ca6e15
Move related components under Menu
michaldudak Jun 5, 2024
dc71a04
Rename Menu components and types
michaldudak Jun 5, 2024
98145a4
useMenuRoot
michaldudak Jun 5, 2024
ee3951c
Move hooks under components
michaldudak Jun 6, 2024
3ff79ae
Docs page
michaldudak Jun 6, 2024
d5dea02
Render props
michaldudak Jun 6, 2024
52b7c25
Fix types in tests
michaldudak Jun 6, 2024
2bbe4b3
Create a simple Positioner
michaldudak Jun 6, 2024
3f1e617
Overhaul menu reducers WIP
michaldudak Jun 18, 2024
dde423d
Merge remote-tracking branch 'upstream/master' into menu-on-hooks
michaldudak Jun 18, 2024
6f16604
Refactor listReducer
michaldudak Jun 18, 2024
588fab3
Remove unnecessary ListReducerAction type
michaldudak Jun 18, 2024
3a897d1
Refactor useList
michaldudak Jun 18, 2024
adf7da1
Clean up useControllableReducer
michaldudak Jun 18, 2024
c59b3d4
Make useList tests pass
michaldudak Jun 18, 2024
a04e0d0
Use new conformance tests
michaldudak Jun 19, 2024
8f54897
Move menuReducer logic to dropdownReducer
michaldudak Jun 19, 2024
c4b4b40
Few renames
michaldudak Jun 19, 2024
8fedc16
Refactor MenuRoot and MenuPopup
michaldudak Jun 19, 2024
fc12227
Create MenuPopupContext
michaldudak Jun 19, 2024
e6db65a
Refactor useMenuItem
michaldudak Jun 20, 2024
74b190b
Improve prop merging
michaldudak Jun 20, 2024
0967e20
Fixes
michaldudak Jun 20, 2024
5dce37b
Merge remote-tracking branch 'upstream/master' into menu-on-hooks
michaldudak Jun 20, 2024
f828cff
Fix tests
michaldudak Jun 20, 2024
c07a159
More tests
michaldudak Jun 20, 2024
88a5740
Refactor Tabs to use new patterns
michaldudak Jun 21, 2024
d6086ac
Cleanup
michaldudak Jun 21, 2024
e607ee6
Remove value from list item metadata
michaldudak Jun 24, 2024
67d0f19
Fix tabs
michaldudak Jun 24, 2024
1043f44
Merge remote-tracking branch 'upstream/master' into menu-on-hooks
michaldudak Jun 24, 2024
c6a3a45
Implement positioner
michaldudak Jun 24, 2024
4fabac7
Move more logic to useMenuItem hook
michaldudak Jun 24, 2024
3c3c509
Subitem trigger
michaldudak Jun 25, 2024
90e0fb3
Nested menu using Floating UI
michaldudak Jun 25, 2024
18468db
Merge remote-tracking branch 'upstream/master' into menu-on-hooks
michaldudak Jun 25, 2024
8e6ad6b
Nested menus
michaldudak Jun 26, 2024
9159be7
Tests
michaldudak Jun 26, 2024
cebe629
API docs
michaldudak Jun 26, 2024
9431c7f
Fix a few eslint errors
michaldudak Jun 26, 2024
68b859d
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Jun 27, 2024
417e575
Fix TS errors in legacy components
michaldudak Jun 27, 2024
9c001fe
Remove getItemState from useList
michaldudak Jun 28, 2024
1bf405d
useListNavigation
michaldudak Jun 28, 2024
9880d79
typeahead
michaldudak Jun 28, 2024
11e94f1
Remove unneeded code
michaldudak Jun 28, 2024
681b467
Fix demo outlines
michaldudak Jun 28, 2024
a2995f7
Fix few issues
michaldudak Jul 1, 2024
e2e2ad3
Declutter useMenuRoot types
michaldudak Jul 1, 2024
d0d9bb5
One click interaction
michaldudak Jul 2, 2024
7c7c44b
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Jul 2, 2024
5b055a2
Fix Menu tests
michaldudak Jul 3, 2024
ce729e1
Fixing the tests
michaldudak Jul 3, 2024
64d2d16
Update internal-test-utils
michaldudak Jul 3, 2024
0d0ca30
Remove react-test-renderer
michaldudak Jul 3, 2024
070b3ed
Remove enzyme
michaldudak Jul 3, 2024
e50d71d
Fix skipped tests
michaldudak Jul 3, 2024
4fda285
Merge branch 'test-utils-update' into menu
michaldudak Jul 3, 2024
16d37ce
Fix listreducer tests
michaldudak Jul 3, 2024
8e33a6e
Wrap render in act
michaldudak Jul 3, 2024
6a9ab10
Merge branch 'test-utils-update' into menu
michaldudak Jul 3, 2024
ce02cd8
Fix Menu tests
michaldudak Jul 3, 2024
2da29a7
Focus disabled items, orientation and direction support
michaldudak Jul 3, 2024
3fabe35
Fix type errors in slider
michaldudak Jul 3, 2024
82ee275
Fix Slider
michaldudak Jul 3, 2024
31c83ef
Update MenuRoot tests
michaldudak Jul 3, 2024
27ff988
Unmount the closed menu
michaldudak Jul 4, 2024
79f9403
Close the menu on trigger click
michaldudak Jul 4, 2024
10583f2
Use FloatingList
michaldudak Jul 4, 2024
c6fddff
Remove reducers infra and useCompound
michaldudak Jul 4, 2024
a1f17f2
Fixing tests
michaldudak Jul 4, 2024
8ad7fed
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Jul 5, 2024
52135d9
Remove unrelated changes
michaldudak Jul 5, 2024
8709b1c
Tests
michaldudak Jul 5, 2024
f8d5af1
Unbind event handlers
michaldudak Jul 5, 2024
02bbab6
Fix click and drag
michaldudak Jul 5, 2024
4774791
Fix click and drag on submenus
michaldudak Jul 5, 2024
dd462a3
API docs
michaldudak Jul 5, 2024
80e6eab
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Jul 15, 2024
88b40b7
Fix unit tests
michaldudak Jul 16, 2024
242160f
Fix karma tests
michaldudak Jul 16, 2024
4ec5f60
Make tests more reliable
michaldudak Jul 16, 2024
c035a1a
Lint
michaldudak Jul 16, 2024
8a04dfd
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Jul 16, 2024
680b72d
closeOnClick
michaldudak Jul 16, 2024
c561ecf
Animations
michaldudak Jul 16, 2024
f62484c
Escape key behavior
michaldudak Jul 17, 2024
7a152b9
Docs
michaldudak Jul 17, 2024
15ffd83
Do not block pointer-events in safe polygon
michaldudak Jul 18, 2024
73940d3
Move types to namespaces
michaldudak Jul 17, 2024
32d6d26
Fix disabling animations
michaldudak Jul 17, 2024
25f26ba
Remove duplicated test
michaldudak Jul 18, 2024
648f30e
JSDocs
michaldudak Jul 18, 2024
6fde3c8
Fix tests
michaldudak Jul 18, 2024
3c78d2d
Fix the docs build
michaldudak Jul 18, 2024
7785852
Fix the Tailwind demo
michaldudak Jul 18, 2024
2b7de72
Update Floating UI
michaldudak Jul 22, 2024
8add1da
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Jul 22, 2024
522c92d
keepMounted
michaldudak Jul 22, 2024
00f60d7
openOnHover
michaldudak Jul 23, 2024
0b71d35
Merge branch 'master' into menu
michaldudak Jul 23, 2024
c82a571
Fixes
michaldudak Jul 23, 2024
3fccaaa
escapeClosesParents -> closeParentOnEscape
michaldudak Jul 24, 2024
ec4aac7
Fix focus restoration when keepMounted=true
michaldudak Jul 24, 2024
02939f8
Fixes to fixes
michaldudak Jul 24, 2024
82d5d26
Demo styles
michaldudak Jul 24, 2024
8a18f82
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Jul 25, 2024
7b2ecb1
Fix flaky tests
michaldudak Jul 25, 2024
b793644
Merge branch 'master' into menu
michaldudak Jul 25, 2024
25a0517
Merge branch 'master' into menu
michaldudak Jul 25, 2024
efc877e
Fix subbomponents in trigger causing the menu to close immediately
michaldudak Jul 25, 2024
8c3c643
closeParentOnEscape -> closeParentOnEsc
michaldudak Jul 25, 2024
e37432a
Add MenuArrow
michaldudak Jul 25, 2024
c46f384
loop prop
michaldudak Jul 26, 2024
1be33b4
Arrow docs
michaldudak Jul 26, 2024
2b4bcda
Update animation docs
michaldudak Jul 26, 2024
d79f4b8
Fix submenu not reopening
michaldudak Jul 26, 2024
e83d9c2
Olivier's feedback
michaldudak Jul 26, 2024
625b366
data-state -> data-menu
michaldudak Jul 31, 2024
b3b8235
Merge remote-tracking branch 'upstream/master' into menu
michaldudak Aug 1, 2024
0472563
Fix types
michaldudak Aug 1, 2024
c66dcb1
Merge branch 'master' into menu
michaldudak Aug 2, 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
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module.exports = {
...baseline.rules,
// TODO move to @mui/monorepo, codebase is moving away from default exports https://github.com/mui/material-ui/issues/21862
'import/prefer-default-export': 'off',
'import/export': 'off', // Mostly handled by Typescript itself. ESLint produces false positives with declaration merging.
'no-restricted-imports': [
'error',
{
Expand All @@ -43,6 +44,7 @@ module.exports = {
],
},
],
'@typescript-eslint/no-redeclare': 'off',
},
overrides: [
...baseline.overrides,
Expand Down
174 changes: 174 additions & 0 deletions docs/data/base/components/menu/MenuIntroduction/css/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import * as React from 'react';
import * as Menu from '@base_ui/react/Menu';
import { useTheme } from '@mui/system';

export default function MenuIntroduction() {
const createHandleMenuClick = (menuItem) => {
return () => {
console.log(`Clicked on ${menuItem}`);
};
};

return (
<Menu.Root>
<Menu.Trigger className="TriggerButtonIntroduction">My account</Menu.Trigger>

<Menu.Positioner className="CustomMenuIntroduction">
<Menu.Popup className="CustomMenuIntroduction--listbox">
<Menu.Item
className="CustomMenuIntroduction--item"
onClick={createHandleMenuClick('Profile')}
>
Profile
</Menu.Item>
<Menu.Item
className="CustomMenuIntroduction--item"
onClick={createHandleMenuClick('Language settings')}
>
Language settings
</Menu.Item>
<Menu.Item
className="CustomMenuIntroduction--item"
onClick={createHandleMenuClick('Log out')}
>
Log out
</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
<Styles />
</Menu.Root>
);
}

const cyan = {
50: '#E9F8FC',
100: '#BDEBF4',
200: '#99D8E5',
300: '#66BACC',
400: '#1F94AD',
500: '#0D5463',
600: '#094855',
700: '#063C47',
800: '#043039',
900: '#022127',
};

const grey = {
50: '#F3F6F9',
100: '#E5EAF2',
200: '#DAE2ED',
300: '#C7D0DD',
400: '#B0B8C4',
500: '#9DA8B7',
600: '#6B7A90',
700: '#434D5B',
800: '#303740',
900: '#1C2025',
};

function useIsDarkMode() {
const theme = useTheme();
return theme.palette.mode === 'dark';
}

function Styles() {
// Replace this with your app logic for determining dark mode
const isDarkMode = useIsDarkMode();

return (
<style>{`
.CustomMenuIntroduction--listbox {
font-family: 'IBM Plex Sans', sans-serif;
font-size: 0.875rem;
box-sizing: border-box;
padding: 6px;
margin: 12px 0;
min-width: 200px;
border-radius: 12px;
overflow: auto;
outline: 0;
background: ${isDarkMode ? grey[900] : '#fff'};
border: 1px solid ${isDarkMode ? grey[700] : grey[200]};
color: ${isDarkMode ? grey[300] : grey[900]};
box-shadow: 0px 4px 30px ${isDarkMode ? grey[900] : grey[200]};
transform-origin: var(--transform-origin);
&[data-state='closed'] {
opacity: 0;
transform: scale(0.95, 0.8);
transition: opacity 200ms ease-in, transform 200ms ease-in;
}
&[data-state='open'] {
opacity: 1;
transform: scale(1, 1);
transition: opacity 100ms ease-out, transform 100ms cubic-bezier(0.43, 0.29, 0.37, 1.48);
}
}
.CustomMenuIntroduction--item {
list-style: none;
padding: 8px;
border-radius: 8px;
cursor: default;
user-select: none;
}
.CustomMenuIntroduction--item:last-of-type {
border-bottom: none;
}
.CustomMenuIntroduction--item:focus {
outline: 3px solid ${isDarkMode ? cyan[600] : cyan[200]};
background-color: ${isDarkMode ? grey[800] : grey[100]};
color: ${isDarkMode ? grey[300] : grey[900]};
}
.CustomMenuIntroduction--item.[data-disabled] {
color: ${isDarkMode ? grey[700] : grey[400]};
}
.TriggerButtonIntroduction {
font-family: 'IBM Plex Sans', sans-serif;
font-weight: 600;
font-size: 0.875rem;
line-height: 1.5;
padding: 8px 16px;
border-radius: 8px;
color: white;
transition: all 150ms ease;
cursor: pointer;
background: ${isDarkMode ? grey[900] : '#fff'};
border: 1px solid ${isDarkMode ? grey[700] : grey[200]};
color: ${isDarkMode ? grey[200] : grey[900]};
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
&:hover {
background: ${isDarkMode ? grey[800] : grey[50]};
border-color: ${isDarkMode ? grey[600] : grey[300]};
}
&:active {
background: ${isDarkMode ? grey[700] : grey[100]};
}
&:focus-visible {
box-shadow: 0 0 0 4px ${isDarkMode ? cyan[300] : cyan[200]};
outline: none;
}
}
.CustomMenuIntroduction {
z-index: 1;
&:focus-visible {
outline: 0;
}
&[data-state='closed'] {
pointer-events: none;
}
}
`}</style>
);
}
174 changes: 174 additions & 0 deletions docs/data/base/components/menu/MenuIntroduction/css/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import * as React from 'react';
import * as Menu from '@base_ui/react/Menu';
import { useTheme } from '@mui/system';

export default function MenuIntroduction() {
const createHandleMenuClick = (menuItem: string) => {
return () => {
console.log(`Clicked on ${menuItem}`);
};
};

return (
<Menu.Root>
<Menu.Trigger className="TriggerButtonIntroduction">My account</Menu.Trigger>

<Menu.Positioner className="CustomMenuIntroduction">
<Menu.Popup className="CustomMenuIntroduction--listbox">
<Menu.Item
className="CustomMenuIntroduction--item"
onClick={createHandleMenuClick('Profile')}
>
Profile
</Menu.Item>
<Menu.Item
className="CustomMenuIntroduction--item"
onClick={createHandleMenuClick('Language settings')}
>
Language settings
</Menu.Item>
<Menu.Item
className="CustomMenuIntroduction--item"
onClick={createHandleMenuClick('Log out')}
>
Log out
</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
<Styles />
</Menu.Root>
);
}

const cyan = {
50: '#E9F8FC',
100: '#BDEBF4',
200: '#99D8E5',
300: '#66BACC',
400: '#1F94AD',
500: '#0D5463',
600: '#094855',
700: '#063C47',
800: '#043039',
900: '#022127',
};

const grey = {
50: '#F3F6F9',
100: '#E5EAF2',
200: '#DAE2ED',
300: '#C7D0DD',
400: '#B0B8C4',
500: '#9DA8B7',
600: '#6B7A90',
700: '#434D5B',
800: '#303740',
900: '#1C2025',
};

function useIsDarkMode() {
const theme = useTheme();
return theme.palette.mode === 'dark';
}

function Styles() {
// Replace this with your app logic for determining dark mode
const isDarkMode = useIsDarkMode();

return (
<style>{`
.CustomMenuIntroduction--listbox {
font-family: 'IBM Plex Sans', sans-serif;
font-size: 0.875rem;
box-sizing: border-box;
padding: 6px;
margin: 12px 0;
min-width: 200px;
border-radius: 12px;
overflow: auto;
outline: 0;
background: ${isDarkMode ? grey[900] : '#fff'};
border: 1px solid ${isDarkMode ? grey[700] : grey[200]};
color: ${isDarkMode ? grey[300] : grey[900]};
box-shadow: 0px 4px 30px ${isDarkMode ? grey[900] : grey[200]};
transform-origin: var(--transform-origin);
&[data-state='closed'] {
opacity: 0;
transform: scale(0.95, 0.8);
transition: opacity 200ms ease-in, transform 200ms ease-in;
}
&[data-state='open'] {
opacity: 1;
transform: scale(1, 1);
transition: opacity 100ms ease-out, transform 100ms cubic-bezier(0.43, 0.29, 0.37, 1.48);
}
}
.CustomMenuIntroduction--item {
list-style: none;
padding: 8px;
border-radius: 8px;
cursor: default;
user-select: none;
}
.CustomMenuIntroduction--item:last-of-type {
border-bottom: none;
}
.CustomMenuIntroduction--item:focus {
outline: 3px solid ${isDarkMode ? cyan[600] : cyan[200]};
background-color: ${isDarkMode ? grey[800] : grey[100]};
color: ${isDarkMode ? grey[300] : grey[900]};
}
.CustomMenuIntroduction--item.[data-disabled] {
color: ${isDarkMode ? grey[700] : grey[400]};
}
.TriggerButtonIntroduction {
font-family: 'IBM Plex Sans', sans-serif;
font-weight: 600;
font-size: 0.875rem;
line-height: 1.5;
padding: 8px 16px;
border-radius: 8px;
color: white;
transition: all 150ms ease;
cursor: pointer;
background: ${isDarkMode ? grey[900] : '#fff'};
border: 1px solid ${isDarkMode ? grey[700] : grey[200]};
color: ${isDarkMode ? grey[200] : grey[900]};
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
&:hover {
background: ${isDarkMode ? grey[800] : grey[50]};
border-color: ${isDarkMode ? grey[600] : grey[300]};
}
&:active {
background: ${isDarkMode ? grey[700] : grey[100]};
}
&:focus-visible {
box-shadow: 0 0 0 4px ${isDarkMode ? cyan[300] : cyan[200]};
outline: none;
}
}
.CustomMenuIntroduction {
z-index: 1;
&:focus-visible {
outline: 0;
}
&[data-state='closed'] {
pointer-events: none;
}
}
`}</style>
);
}
Loading