From a24c55e43c7311324607c98503938f596915a829 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:37:45 -0300 Subject: [PATCH 1/3] update the focus ring/slider demo --- .../accessibility/FocusRing.js | 51 +++++++++++-------- .../accessibility/FocusRing.tsx | 51 +++++++++++-------- 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/docs/data/base/getting-started/accessibility/FocusRing.js b/docs/data/base/getting-started/accessibility/FocusRing.js index 3028ebd46a0c02..674862e8f46443 100644 --- a/docs/data/base/getting-started/accessibility/FocusRing.js +++ b/docs/data/base/getting-started/accessibility/FocusRing.js @@ -26,59 +26,70 @@ const Slider = styled(BaseSlider)( height: 6px; width: 100%; padding: 16px 0; - display: inline-block; + display: inline-flex; + align-items: center; position: relative; cursor: pointer; touch-action: none; -webkit-tap-highlight-color: transparent; - &:hover { - opacity: 1; - } - & .${sliderClasses.rail} { display: block; position: absolute; width: 100%; height: 4px; - border-radius: 2px; + border-radius: 6px; background-color: currentColor; - opacity: 0.4; + opacity: 0.3; } & .${sliderClasses.track} { display: block; position: absolute; height: 4px; - border-radius: 2px; + border-radius: 6px; background-color: currentColor; } & .${sliderClasses.thumb} { + display: flex; + align-items: center; + justify-content: center; position: absolute; - width: 16px; - height: 16px; margin-left: -6px; - margin-top: -6px; + width: 20px; + height: 20px; box-sizing: border-box; border-radius: 50%; outline: 0; - border: 3px solid currentColor; - background-color: #fff; + background-color: ${theme.palette.mode === 'light' ? blue[500] : blue[400]}; + transition-property: box-shadow, transform; + transition-timing-function: ease; + transition-duration: 120ms; + transform-origin: center; + + &:hover { + box-shadow: 0 0 0 6px ${alpha( + theme.palette.mode === 'light' ? blue[200] : blue[300], + 0.3, + )}; + } - :hover, &.${sliderClasses.focusVisible} { - box-shadow: 0 0 0 0.25rem ${alpha( - theme.palette.mode === 'light' ? blue[400] : blue[300], - 0.15, + box-shadow: 0 0 0 8px ${alpha( + theme.palette.mode === 'light' ? blue[200] : blue[400], + 0.5, )}; + outline: none; } &.${sliderClasses.active} { - box-shadow: 0 0 0 0.25rem ${alpha( - theme.palette.mode === 'light' ? blue[200] : blue[300], - 0.3, + box-shadow: 0 0 0 8px ${alpha( + theme.palette.mode === 'light' ? blue[200] : blue[400], + 0.5, )}; + outline: none; + transform: scale(1.2); } } `, diff --git a/docs/data/base/getting-started/accessibility/FocusRing.tsx b/docs/data/base/getting-started/accessibility/FocusRing.tsx index 3028ebd46a0c02..674862e8f46443 100644 --- a/docs/data/base/getting-started/accessibility/FocusRing.tsx +++ b/docs/data/base/getting-started/accessibility/FocusRing.tsx @@ -26,59 +26,70 @@ const Slider = styled(BaseSlider)( height: 6px; width: 100%; padding: 16px 0; - display: inline-block; + display: inline-flex; + align-items: center; position: relative; cursor: pointer; touch-action: none; -webkit-tap-highlight-color: transparent; - &:hover { - opacity: 1; - } - & .${sliderClasses.rail} { display: block; position: absolute; width: 100%; height: 4px; - border-radius: 2px; + border-radius: 6px; background-color: currentColor; - opacity: 0.4; + opacity: 0.3; } & .${sliderClasses.track} { display: block; position: absolute; height: 4px; - border-radius: 2px; + border-radius: 6px; background-color: currentColor; } & .${sliderClasses.thumb} { + display: flex; + align-items: center; + justify-content: center; position: absolute; - width: 16px; - height: 16px; margin-left: -6px; - margin-top: -6px; + width: 20px; + height: 20px; box-sizing: border-box; border-radius: 50%; outline: 0; - border: 3px solid currentColor; - background-color: #fff; + background-color: ${theme.palette.mode === 'light' ? blue[500] : blue[400]}; + transition-property: box-shadow, transform; + transition-timing-function: ease; + transition-duration: 120ms; + transform-origin: center; + + &:hover { + box-shadow: 0 0 0 6px ${alpha( + theme.palette.mode === 'light' ? blue[200] : blue[300], + 0.3, + )}; + } - :hover, &.${sliderClasses.focusVisible} { - box-shadow: 0 0 0 0.25rem ${alpha( - theme.palette.mode === 'light' ? blue[400] : blue[300], - 0.15, + box-shadow: 0 0 0 8px ${alpha( + theme.palette.mode === 'light' ? blue[200] : blue[400], + 0.5, )}; + outline: none; } &.${sliderClasses.active} { - box-shadow: 0 0 0 0.25rem ${alpha( - theme.palette.mode === 'light' ? blue[200] : blue[300], - 0.3, + box-shadow: 0 0 0 8px ${alpha( + theme.palette.mode === 'light' ? blue[200] : blue[400], + 0.5, )}; + outline: none; + transform: scale(1.2); } } `, From cb19d5b9c4e4d0151b1cdfeade92c285be7bc34b Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:39:31 -0300 Subject: [PATCH 2/3] update the keyboard nav/menu/select demo --- .../accessibility/KeyboardNavigation.js | 83 ++++++++++------- .../accessibility/KeyboardNavigation.tsx | 90 ++++++++++++------- 2 files changed, 106 insertions(+), 67 deletions(-) diff --git a/docs/data/base/getting-started/accessibility/KeyboardNavigation.js b/docs/data/base/getting-started/accessibility/KeyboardNavigation.js index 5375b3b562ef0f..f6c6484fd2582a 100644 --- a/docs/data/base/getting-started/accessibility/KeyboardNavigation.js +++ b/docs/data/base/getting-started/accessibility/KeyboardNavigation.js @@ -1,11 +1,13 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { Select as BaseSelect, selectClasses } from '@mui/base/Select'; import { Option as BaseOption, optionClasses } from '@mui/base/Option'; import { Dropdown } from '@mui/base/Dropdown'; import { Menu } from '@mui/base/Menu'; import { MenuButton as BaseMenuButton } from '@mui/base/MenuButton'; import { MenuItem as BaseMenuItem, menuItemClasses } from '@mui/base/MenuItem'; -import { styled } from '@mui/system'; +import { styled, alpha } from '@mui/system'; +import UnfoldMoreRoundedIcon from '@mui/icons-material/UnfoldMoreRounded'; export default function KeyboardNavigation() { return ( @@ -23,7 +25,7 @@ export default function KeyboardNavigation() { - Edit + Open menu Cut Copy @@ -36,7 +38,7 @@ export default function KeyboardNavigation() { const Select = React.forwardRef(function Select(props, ref) { const slots = { - root: Button, + root: SelectButton, listbox: Listbox, popup: Popup, ...props.slots, @@ -45,6 +47,21 @@ const Select = React.forwardRef(function Select(props, ref) { return ; }); +const SelectButton = React.forwardRef(function SelectButton(props, ref) { + const { ownerState, ...other } = props; + return ( + + {other.children} + + + ); +}); + +SelectButton.propTypes = { + children: PropTypes.node, + ownerState: PropTypes.object.isRequired, +}; + const blue = { 50: '#F0F7FF', 100: '#DAECFF', @@ -69,8 +86,9 @@ const grey = { 900: '#24292f', }; -const Button = styled('button')( +const StyledSelectButton = styled('button')( ({ theme }) => ` + position: relative; font-family: 'IBM Plex Sans', sans-serif; font-size: 0.875rem; box-sizing: border-box; @@ -79,11 +97,11 @@ const Button = styled('button')( border-radius: 8px; text-align: left; line-height: 1.5; - background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'}; - border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]}; + background: ${theme.palette.mode === 'dark' ? alpha(grey[900], 0.4) : '#fff'}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[900] : grey[200]}; color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; - box-shadow: 0px 4px 6px ${ - theme.palette.mode === 'dark' ? 'rgba(0,0,0, 0.50)' : 'rgba(0,0,0, 0.05)' + box-shadow: 0px 2px 6px ${ + theme.palette.mode === 'dark' ? 'rgba(0,0,0, 0.2)' : 'rgba(0,0,0, 0.1)' }; transition-property: all; @@ -91,24 +109,22 @@ const Button = styled('button')( transition-duration: 120ms; &:hover { - background: ${theme.palette.mode === 'dark' ? grey[800] : grey[50]}; - border-color: ${theme.palette.mode === 'dark' ? grey[600] : grey[300]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border-color: ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; } &.${selectClasses.focusVisible} { + outline: 0; border-color: ${blue[400]}; - outline: 3px solid ${theme.palette.mode === 'dark' ? blue[500] : blue[200]}; - } - - &.${selectClasses.expanded} { - &::after { - content: '▴'; - } + box-shadow: 0 0 0 3px ${theme.palette.mode === 'dark' ? blue[600] : blue[200]}; } - &::after { - content: '▾'; - float: right; + & > svg { + font-size: 1rem; + position: absolute; + height: 100%; + top: 0; + right: 10px; } `, ); @@ -120,14 +136,14 @@ const Listbox = styled('ul')( box-sizing: border-box; padding: 6px; margin: 12px 0; - min-width: 150px; + min-width: 200px; border-radius: 12px; overflow: auto; outline: 0px; background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'}; - border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[200]}; color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; - box-shadow: 0px 4px 6px ${ + box-shadow: 0px 2px 6px ${ theme.palette.mode === 'dark' ? 'rgba(0,0,0, 0.50)' : 'rgba(0,0,0, 0.05)' }; `, @@ -154,15 +170,15 @@ const Option = styled(BaseOption)( color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; } - &:focus-visible { - outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[200]}; - } - &.${optionClasses.highlighted}.${optionClasses.selected} { background-color: ${theme.palette.mode === 'dark' ? blue[900] : blue[100]}; color: ${theme.palette.mode === 'dark' ? blue[100] : blue[900]}; } + &:focus-visible { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[200]}; + } + &.${optionClasses.disabled} { color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; } @@ -212,18 +228,19 @@ const MenuButton = styled(BaseMenuButton)( border-radius: 8px; padding: 8px 16px; line-height: 1.5; - background: transparent; + background: ${ + theme.palette.mode === 'dark' ? alpha(grey[900], 0.5) : alpha(grey[50], 0.5) + }; border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[200]}; - color: ${theme.palette.mode === 'dark' ? blue[300] : blue[500]}; - cursor: pointer; + color: ${theme.palette.mode === 'dark' ? grey[200] : grey[800]}; transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 120ms; &:hover { - background: ${theme.palette.mode === 'dark' ? grey[800] : grey[50]}; - border-color: ${theme.palette.mode === 'dark' ? grey[600] : grey[300]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[300]}; } &:focus-visible { @@ -235,7 +252,7 @@ const MenuButton = styled(BaseMenuButton)( const Container = styled('div')` display: flex; - gap: 10px; + gap: 12px; `; const Popup = styled('div')` diff --git a/docs/data/base/getting-started/accessibility/KeyboardNavigation.tsx b/docs/data/base/getting-started/accessibility/KeyboardNavigation.tsx index 200a76a16f6c1b..917e340d1ea07d 100644 --- a/docs/data/base/getting-started/accessibility/KeyboardNavigation.tsx +++ b/docs/data/base/getting-started/accessibility/KeyboardNavigation.tsx @@ -1,11 +1,17 @@ import * as React from 'react'; -import { Select as BaseSelect, SelectProps, selectClasses } from '@mui/base/Select'; +import { + Select as BaseSelect, + SelectProps, + SelectRootSlotProps, + selectClasses, +} from '@mui/base/Select'; import { Option as BaseOption, optionClasses } from '@mui/base/Option'; import { Dropdown } from '@mui/base/Dropdown'; import { Menu } from '@mui/base/Menu'; import { MenuButton as BaseMenuButton } from '@mui/base/MenuButton'; import { MenuItem as BaseMenuItem, menuItemClasses } from '@mui/base/MenuItem'; -import { styled } from '@mui/system'; +import { styled, alpha } from '@mui/system'; +import UnfoldMoreRoundedIcon from '@mui/icons-material/UnfoldMoreRounded'; export default function KeyboardNavigation() { return ( @@ -23,7 +29,7 @@ export default function KeyboardNavigation() { - Edit + Open menu Cut Copy @@ -39,7 +45,7 @@ const Select = React.forwardRef(function Select< Multiple extends boolean, >(props: SelectProps, ref: React.ForwardedRef) { const slots: SelectProps['slots'] = { - root: Button, + root: SelectButton, listbox: Listbox, popup: Popup, ...props.slots, @@ -50,6 +56,22 @@ const Select = React.forwardRef(function Select< props: SelectProps & React.RefAttributes, ) => JSX.Element; +const SelectButton = React.forwardRef(function SelectButton< + TValue extends {}, + Multiple extends boolean, +>( + props: SelectRootSlotProps, + ref: React.ForwardedRef, +) { + const { ownerState, ...other } = props; + return ( + + {other.children} + + + ); +}); + const blue = { 50: '#F0F7FF', 100: '#DAECFF', @@ -74,8 +96,9 @@ const grey = { 900: '#24292f', }; -const Button = styled('button')( +const StyledSelectButton = styled('button')( ({ theme }) => ` + position: relative; font-family: 'IBM Plex Sans', sans-serif; font-size: 0.875rem; box-sizing: border-box; @@ -84,11 +107,11 @@ const Button = styled('button')( border-radius: 8px; text-align: left; line-height: 1.5; - background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'}; - border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]}; + background: ${theme.palette.mode === 'dark' ? alpha(grey[900], 0.4) : '#fff'}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[900] : grey[200]}; color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; - box-shadow: 0px 4px 6px ${ - theme.palette.mode === 'dark' ? 'rgba(0,0,0, 0.50)' : 'rgba(0,0,0, 0.05)' + box-shadow: 0px 2px 6px ${ + theme.palette.mode === 'dark' ? 'rgba(0,0,0, 0.2)' : 'rgba(0,0,0, 0.1)' }; transition-property: all; @@ -96,24 +119,22 @@ const Button = styled('button')( transition-duration: 120ms; &:hover { - background: ${theme.palette.mode === 'dark' ? grey[800] : grey[50]}; - border-color: ${theme.palette.mode === 'dark' ? grey[600] : grey[300]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border-color: ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; } &.${selectClasses.focusVisible} { + outline: 0; border-color: ${blue[400]}; - outline: 3px solid ${theme.palette.mode === 'dark' ? blue[500] : blue[200]}; + box-shadow: 0 0 0 3px ${theme.palette.mode === 'dark' ? blue[600] : blue[200]}; } - &.${selectClasses.expanded} { - &::after { - content: '▴'; - } - } - - &::after { - content: '▾'; - float: right; + & > svg { + font-size: 1rem; + position: absolute; + height: 100%; + top: 0; + right: 10px; } `, ); @@ -125,14 +146,14 @@ const Listbox = styled('ul')( box-sizing: border-box; padding: 6px; margin: 12px 0; - min-width: 150px; + min-width: 200px; border-radius: 12px; overflow: auto; outline: 0px; background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'}; - border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[200]}; color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; - box-shadow: 0px 4px 6px ${ + box-shadow: 0px 2px 6px ${ theme.palette.mode === 'dark' ? 'rgba(0,0,0, 0.50)' : 'rgba(0,0,0, 0.05)' }; `, @@ -159,15 +180,15 @@ const Option = styled(BaseOption)( color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; } - &:focus-visible { - outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[200]}; - } - &.${optionClasses.highlighted}.${optionClasses.selected} { background-color: ${theme.palette.mode === 'dark' ? blue[900] : blue[100]}; color: ${theme.palette.mode === 'dark' ? blue[100] : blue[900]}; } + &:focus-visible { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[200]}; + } + &.${optionClasses.disabled} { color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; } @@ -217,18 +238,19 @@ const MenuButton = styled(BaseMenuButton)( border-radius: 8px; padding: 8px 16px; line-height: 1.5; - background: transparent; + background: ${ + theme.palette.mode === 'dark' ? alpha(grey[900], 0.5) : alpha(grey[50], 0.5) + }; border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[200]}; - color: ${theme.palette.mode === 'dark' ? blue[300] : blue[500]}; - cursor: pointer; + color: ${theme.palette.mode === 'dark' ? grey[200] : grey[800]}; transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 120ms; &:hover { - background: ${theme.palette.mode === 'dark' ? grey[800] : grey[50]}; - border-color: ${theme.palette.mode === 'dark' ? grey[600] : grey[300]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[300]}; } &:focus-visible { @@ -240,7 +262,7 @@ const MenuButton = styled(BaseMenuButton)( const Container = styled('div')` display: flex; - gap: 10px; + gap: 12px; `; const Popup = styled('div')` From 0d242aee1c1e7527df944c285090087e22f1592d Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:42:40 -0300 Subject: [PATCH 3/3] bonus: fix typo on the Select Tailwind intro demo --- .../select/UnstyledSelectIntroduction/tailwind/index.js | 2 +- .../select/UnstyledSelectIntroduction/tailwind/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.js b/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.js index 373c419fd123ab..a827c78b398922 100644 --- a/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.js +++ b/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.js @@ -162,7 +162,7 @@ const Select = React.forwardRef(function CustomSelect(props, ref) { return { ...resolvedSlotProps, className: clsx( - `${isDarkMode ? 'dark' : ''} z-10x`, + `${isDarkMode ? 'dark' : ''} z-10`, resolvedSlotProps?.className, ), }; diff --git a/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.tsx b/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.tsx index 57b21ad8510cdc..1d5fad07676cde 100644 --- a/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.tsx +++ b/docs/data/base/components/select/UnstyledSelectIntroduction/tailwind/index.tsx @@ -181,7 +181,7 @@ const Select = React.forwardRef(function CustomSelect< return { ...resolvedSlotProps, className: clsx( - `${isDarkMode ? 'dark' : ''} z-10x`, + `${isDarkMode ? 'dark' : ''} z-10`, resolvedSlotProps?.className, ), };