diff --git a/docs/data/base/components/menu/UseMenu.js b/docs/data/base/components/menu/UseMenu.js
index f2c4d8f28f2596..d495d627a0b845 100644
--- a/docs/data/base/components/menu/UseMenu.js
+++ b/docs/data/base/components/menu/UseMenu.js
@@ -2,6 +2,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { useMenu, MenuUnstyledContext } from '@mui/base/MenuUnstyled';
import { useMenuItem } from '@mui/base/MenuItemUnstyled';
+import PopperUnstyled from '@mui/base/PopperUnstyled';
import { GlobalStyles } from '@mui/system';
import clsx from 'clsx';
@@ -18,6 +19,15 @@ const grey = {
900: '#24292f',
};
+const blue = {
+ 100: '#DAECFF',
+ 200: '#99CCF3',
+ 400: '#3399FF',
+ 500: '#007FFF',
+ 600: '#0072E5',
+ 900: '#003A75',
+};
+
const styles = `
.menu-root {
font-family: IBM Plex Sans, sans-serif;
@@ -80,10 +90,53 @@ const styles = `
background-color: ${grey[800]};
color: ${grey[300]};
}
+
+ .button {
+ font-family: IBM Plex Sans, sans-serif;
+ font-size: 0.875rem;
+ box-sizing: border-box;
+ min-height: calc(1.5em + 22px);
+ border-radius: 12px;
+ padding: 12px 16px;
+ line-height: 1.5;
+ background: #fff;
+ border: 1px solid ${grey[200]};
+ color: ${grey[900]};
+ cursor: pointer;
+
+ transition-property: all;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ transition-duration: 120ms;
+
+ &:hover {
+ background: ${grey[50]};
+ border-color: ${grey[300]};
+ }
+
+ &:focus {
+ border-color: ${blue[400]};
+ outline: 3px solid ${blue[200]};
+ }
+ }
+
+ .mode-dark .button {
+ background: ${grey[900]};
+ border: 1px solid ${grey[700]};
+ color: ${grey[300]};
+
+ &:hover {
+ background: ${grey[800]};
+ border-color: ${grey[600]};
+ }
+
+ &:focus {
+ outline: 3px solid ${blue[500]}
+ }
+ }
`;
const Menu = React.forwardRef(function Menu(props, ref) {
- const { children, ...other } = props;
+ const { children, onClose, open, ...other } = props;
const {
registerItem,
@@ -93,6 +146,8 @@ const Menu = React.forwardRef(function Menu(props, ref) {
getItemState,
} = useMenu({
listboxRef: ref,
+ onClose,
+ open,
});
const contextValue = {
@@ -114,6 +169,8 @@ const Menu = React.forwardRef(function Menu(props, ref) {
Menu.propTypes = {
children: PropTypes.node,
+ onClose: PropTypes.func.isRequired,
+ open: PropTypes.bool.isRequired,
};
const MenuItem = React.forwardRef(function MenuItem(props, ref) {
@@ -139,14 +196,54 @@ MenuItem.propTypes = {
};
export default function UseMenu() {
+ const [anchorEl, setAnchorEl] = React.useState(null);
+ const preventReopen = React.useRef(false);
+ const buttonRef = React.useRef(null);
+
+ const handleOnClick = (event) => {
+ if (preventReopen.current) {
+ event.preventDefault();
+ preventReopen.current = false;
+ return;
+ }
+
+ setAnchorEl(anchorEl ? null : event.currentTarget);
+ };
+
+ const handleOnClose = () => {
+ setAnchorEl(null);
+ buttonRef.current.focus();
+ };
+
+ const open = Boolean(anchorEl);
+
+ const handleButtonMouseDown = () => {
+ if (open) {
+ // Prevents the menu from reopening right after closing
+ // when clicking the button.
+ preventReopen.current = true;
+ }
+ };
+
return (
-
+
+
+
+
);
}
diff --git a/docs/data/base/components/menu/UseMenu.tsx b/docs/data/base/components/menu/UseMenu.tsx
index bae50a70c799e6..62021d9b0835a1 100644
--- a/docs/data/base/components/menu/UseMenu.tsx
+++ b/docs/data/base/components/menu/UseMenu.tsx
@@ -5,6 +5,7 @@ import {
MenuUnstyledContextType,
} from '@mui/base/MenuUnstyled';
import { useMenuItem } from '@mui/base/MenuItemUnstyled';
+import PopperUnstyled from '@mui/base/PopperUnstyled';
import { GlobalStyles } from '@mui/system';
import clsx from 'clsx';
@@ -20,6 +21,16 @@ const grey = {
800: '#32383f',
900: '#24292f',
};
+
+const blue = {
+ 100: '#DAECFF',
+ 200: '#99CCF3',
+ 400: '#3399FF',
+ 500: '#007FFF',
+ 600: '#0072E5',
+ 900: '#003A75',
+};
+
const styles = `
.menu-root {
font-family: IBM Plex Sans, sans-serif;
@@ -82,13 +93,59 @@ const styles = `
background-color: ${grey[800]};
color: ${grey[300]};
}
+
+ .button {
+ font-family: IBM Plex Sans, sans-serif;
+ font-size: 0.875rem;
+ box-sizing: border-box;
+ min-height: calc(1.5em + 22px);
+ border-radius: 12px;
+ padding: 12px 16px;
+ line-height: 1.5;
+ background: #fff;
+ border: 1px solid ${grey[200]};
+ color: ${grey[900]};
+ cursor: pointer;
+
+ transition-property: all;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ transition-duration: 120ms;
+
+ &:hover {
+ background: ${grey[50]};
+ border-color: ${grey[300]};
+ }
+
+ &:focus {
+ border-color: ${blue[400]};
+ outline: 3px solid ${blue[200]};
+ }
+ }
+
+ .mode-dark .button {
+ background: ${grey[900]};
+ border: 1px solid ${grey[700]};
+ color: ${grey[300]};
+
+ &:hover {
+ background: ${grey[800]};
+ border-color: ${grey[600]};
+ }
+
+ &:focus {
+ outline: 3px solid ${blue[500]}
+ }
+ }
`;
const Menu = React.forwardRef(function Menu(
- props: React.ComponentPropsWithoutRef<'ul'>,
+ props: React.ComponentPropsWithoutRef<'ul'> & {
+ onClose: () => void;
+ open: boolean;
+ },
ref: React.Ref,
) {
- const { children, ...other } = props;
+ const { children, onClose, open, ...other } = props;
const {
registerItem,
@@ -98,6 +155,8 @@ const Menu = React.forwardRef(function Menu(
getItemState,
} = useMenu({
listboxRef: ref,
+ onClose,
+ open,
});
const contextValue: MenuUnstyledContextType = {
@@ -139,14 +198,54 @@ const MenuItem = React.forwardRef(function MenuItem(
});
export default function UseMenu() {
+ const [anchorEl, setAnchorEl] = React.useState(null);
+ const preventReopen = React.useRef(false);
+ const buttonRef = React.useRef(null);
+
+ const handleOnClick = (event: React.MouseEvent) => {
+ if (preventReopen.current) {
+ event.preventDefault();
+ preventReopen.current = false;
+ return;
+ }
+
+ setAnchorEl(anchorEl ? null : event.currentTarget);
+ };
+
+ const handleOnClose = () => {
+ setAnchorEl(null);
+ buttonRef.current!.focus();
+ };
+
+ const open = Boolean(anchorEl);
+
+ const handleButtonMouseDown = () => {
+ if (open) {
+ // Prevents the menu from reopening right after closing
+ // when clicking the button.
+ preventReopen.current = true;
+ }
+ };
+
return (
-
+
+
+
+
);
}
diff --git a/docs/data/base/components/menu/UseMenu.tsx.preview b/docs/data/base/components/menu/UseMenu.tsx.preview
deleted file mode 100644
index eaf8ac1dfb8966..00000000000000
--- a/docs/data/base/components/menu/UseMenu.tsx.preview
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file