Skip to content

Commit

Permalink
Docs and demos
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldudak committed Feb 10, 2022
1 parent 57a6ad9 commit 15dbdc3
Show file tree
Hide file tree
Showing 9 changed files with 472 additions and 7 deletions.
148 changes: 148 additions & 0 deletions docs/data/material/components/menus/UnstyledMenuPopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import MenuUnstyled from '@mui/base/MenuUnstyled';
import MenuItemUnstyled, {
menuItemUnstyledClasses,
} from '@mui/base/MenuItemUnstyled';
import { styled } from '@mui/system';
import { ClickAwayListener, PopperUnstyled } from '@mui/base';

const StyledMenu = styled(MenuUnstyled)`
font-family: IBM Plex Sans, sans-serif;
min-width: 200px;
max-width: 300px;
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
border-radius: 5px;
overflow: hidden;
background-color: #fff;
margin-top: 10px;
.mode-dark & {
border-color: #333;
background-color: #0a1929;
}
`;

const StyledMenuItem = styled(MenuItemUnstyled)`
padding: 6px 20px;
margin: 0;
cursor: default;
display: flex;
gap: 10px;
align-items: center;
&:hover:not(.${menuItemUnstyledClasses.disabled}),
&:focus-visible {
background-color: #16d;
color: #fff;
outline: none;
}
&:active:not(.${menuItemUnstyledClasses.disabled}) {
background-color: #05e;
}
&.${menuItemUnstyledClasses.disabled} {
opacity: 0.5;
}
> svg {
opacity: 0.6;
}
`;

const TriggerButton = styled('button')`
font-family: IBM Plex Sans, sans-serif;
box-sizing: border-box;
background: #fff;
border: 1px solid #ccc;
border-radius: 5px;
margin: 0.5em;
padding: 10px;
text-align: left;
line-height: 1.5;
color: #000;
font-size: 1rem;
.mode-dark & {
color: #fff;
border-color: #333;
background-color: #0a1929;
}
}`;

const Popper = styled(PopperUnstyled)`
z-index: 1;
`;

function MenuWrapper(props) {
const { children, contentRef, label } = props;

const [isOpen, setOpen] = React.useState(false);
const buttonRef = React.useRef(null);

const close = () => setOpen(false);

React.useEffect(() => {
if (isOpen) {
contentRef.current?.focus();
}
}, [isOpen, contentRef]);

return (
<React.Fragment>
<TriggerButton type="button" ref={buttonRef} onClick={() => setOpen(!isOpen)}>
{label}
</TriggerButton>
<Popper
placement="bottom-start"
open={isOpen && buttonRef.current != null}
anchorEl={buttonRef.current}
keepMounted
disablePortal
>
{isOpen && (
<ClickAwayListener onClickAway={() => setOpen(false)}>
{children?.(close)}
</ClickAwayListener>
)}
</Popper>
</React.Fragment>
);
}

MenuWrapper.propTypes = {
children: PropTypes.func.isRequired,
contentRef: PropTypes.shape({
current: function (props, propName) {
if (props[propName] == null) {
return null;
} else if (
typeof props[propName] !== 'object' ||
props[propName].nodeType !== 1
) {
return new Error("Expected prop '" + propName + "' to be of type Element");
}
},
}).isRequired,
label: PropTypes.string,
};

export default function UnstyledMenuPopup() {
const contentRef = React.useRef(null);

return (
<MenuWrapper contentRef={contentRef} label="Language">
{(close) => (
<StyledMenu ref={contentRef}>
<StyledMenuItem onClick={() => close()}>English</StyledMenuItem>
<StyledMenuItem onClick={() => close()}>中文</StyledMenuItem>
<StyledMenuItem onClick={() => close()}>Português</StyledMenuItem>
</StyledMenu>
)}
</MenuWrapper>
);
}
136 changes: 136 additions & 0 deletions docs/data/material/components/menus/UnstyledMenuPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import * as React from 'react';
import MenuUnstyled from '@mui/base/MenuUnstyled';
import MenuItemUnstyled, {
menuItemUnstyledClasses,
} from '@mui/base/MenuItemUnstyled';
import { styled } from '@mui/system';
import { ClickAwayListener, PopperUnstyled } from '@mui/base';

const StyledMenu = styled(MenuUnstyled)`
font-family: IBM Plex Sans, sans-serif;
min-width: 200px;
max-width: 300px;
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
border-radius: 5px;
overflow: hidden;
background-color: #fff;
margin-top: 10px;
.mode-dark & {
border-color: #333;
background-color: #0a1929;
}
`;

const StyledMenuItem = styled(MenuItemUnstyled)`
padding: 6px 20px;
margin: 0;
cursor: default;
display: flex;
gap: 10px;
align-items: center;
&:hover:not(.${menuItemUnstyledClasses.disabled}),
&:focus-visible {
background-color: #16d;
color: #fff;
outline: none;
}
&:active:not(.${menuItemUnstyledClasses.disabled}) {
background-color: #05e;
}
&.${menuItemUnstyledClasses.disabled} {
opacity: 0.5;
}
> svg {
opacity: 0.6;
}
`;

const TriggerButton = styled('button')`
font-family: IBM Plex Sans, sans-serif;
box-sizing: border-box;
background: #fff;
border: 1px solid #ccc;
border-radius: 5px;
margin: 0.5em;
padding: 10px;
text-align: left;
line-height: 1.5;
color: #000;
font-size: 1rem;
.mode-dark & {
color: #fff;
border-color: #333;
background-color: #0a1929;
}
}`;

const Popper = styled(PopperUnstyled)`
z-index: 1;
`;

interface MenuWrapperProps {
contentRef: React.RefObject<HTMLElement>;
children: (close: () => void) => JSX.Element;
label?: string;
}

function MenuWrapper(props: MenuWrapperProps) {
const { children, contentRef, label } = props;

const [isOpen, setOpen] = React.useState(false);
const buttonRef = React.useRef<HTMLButtonElement>(null);

const close = () => setOpen(false);

React.useEffect(() => {
if (isOpen) {
contentRef.current?.focus();
}
}, [isOpen, contentRef]);

return (
<React.Fragment>
<TriggerButton type="button" ref={buttonRef} onClick={() => setOpen(!isOpen)}>
{label}
</TriggerButton>
<Popper
placement="bottom-start"
open={isOpen && buttonRef.current != null}
anchorEl={buttonRef.current}
keepMounted
disablePortal
>
{isOpen && (
<ClickAwayListener onClickAway={() => setOpen(false)}>
{children?.(close)}
</ClickAwayListener>
)}
</Popper>
</React.Fragment>
);
}

export default function UnstyledMenuPopup() {
const contentRef = React.useRef<HTMLElement>(null);

return (
<MenuWrapper contentRef={contentRef} label="Language">
{(close) => (
<StyledMenu ref={contentRef}>
<StyledMenuItem onClick={() => close()}>English</StyledMenuItem>
<StyledMenuItem onClick={() => close()}>中文</StyledMenuItem>
<StyledMenuItem onClick={() => close()}>Português</StyledMenuItem>
</StyledMenu>
)}
</MenuWrapper>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<MenuWrapper contentRef={contentRef} label="Language">
{(close) => (
<StyledMenu ref={contentRef}>
<StyledMenuItem onClick={() => close()}>English</StyledMenuItem>
<StyledMenuItem onClick={() => close()}>中文</StyledMenuItem>
<StyledMenuItem onClick={() => close()}>Português</StyledMenuItem>
</StyledMenu>
)}
</MenuWrapper>
69 changes: 69 additions & 0 deletions docs/data/material/components/menus/UnstyledMenuSimple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as React from 'react';
import MenuUnstyled from '@mui/base/MenuUnstyled';
import MenuItemUnstyled, {
menuItemUnstyledClasses,
} from '@mui/base/MenuItemUnstyled';
import { styled } from '@mui/system';
import ContentCut from '@mui/icons-material/ContentCut';
import ContentCopy from '@mui/icons-material/ContentCopy';
import ContentPaste from '@mui/icons-material/ContentPaste';

const StyledMenu = styled(MenuUnstyled)`
font-family: IBM Plex Sans, sans-serif;
min-width: 200px;
max-width: 300px;
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
border-radius: 5px;
overflow: hidden;
.mode-dark & {
border-color: #333;
}
`;

const StyledMenuItem = styled(MenuItemUnstyled)`
padding: 6px 20px;
margin: 0;
cursor: default;
display: flex;
gap: 10px;
align-items: center;
&:hover:not(.${menuItemUnstyledClasses.disabled}),
&:focus-visible {
background-color: #16d;
color: #fff;
outline: none;
}
&:active:not(.${menuItemUnstyledClasses.disabled}) {
background-color: #05e;
}
&.${menuItemUnstyledClasses.disabled} {
opacity: 0.5;
}
> svg {
opacity: 0.6;
}
`;

export default function UnstyledMenuSimple() {
return (
<StyledMenu>
<StyledMenuItem onClick={() => console.log('Cut')}>
<ContentCut fontSize="small" /> Cut
</StyledMenuItem>
<StyledMenuItem onClick={() => console.log('Copy')}>
<ContentCopy fontSize="small" /> Copy
</StyledMenuItem>
<StyledMenuItem onClick={() => console.log('Paste')} disabled>
<ContentPaste fontSize="small" /> Paste
</StyledMenuItem>
</StyledMenu>
);
}
Loading

0 comments on commit 15dbdc3

Please sign in to comment.