Skip to content

Commit

Permalink
feat: implement :focus-visible for close button components with tar…
Browse files Browse the repository at this point in the history
…geted focus style for non-pointer devices
  • Loading branch information
cheton committed Oct 8, 2023
1 parent 85cb1d2 commit 6205a93
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 145 deletions.
31 changes: 25 additions & 6 deletions packages/react/src/alert/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,8 @@ const useAlertCloseButtonStyle = ({
}[variant],
}[colorMode];
const size = '8x';
const _focusBorderColor = 'blue:60';
const _focusBoxShadowBorderColor = 'blue:60';
const _hoverColor = {
const focusVisibleOutlineColor = 'blue:60';
const hoverColor = {
dark: {
solid: 'black:primary',
outline: 'white:emphasis',
Expand All @@ -454,22 +453,42 @@ const useAlertCloseButtonStyle = ({
outline: 'black:primary',
}[variant],
}[colorMode];
const baseStyle = useIconButtonStyle({ color, size, _focusBorderColor, _focusBoxShadowBorderColor, _hoverColor });
const iconButtonStyle = useIconButtonStyle({ color, size });

if (isClosable) {
const parentBorderWidth = sizes['1q'];
const top = `calc(${sizes['1x']} - ${parentBorderWidth})`;
const right = `calc(${sizes['2x']} - ${parentBorderWidth})`;

return {
...baseStyle,
...iconButtonStyle,
_focusVisible: {
outlineColor: focusVisibleOutlineColor,
outlineOffset: '-1h',
outlineStyle: 'solid',
outlineWidth: '1h',
},
_hover: {
color: hoverColor,
},
position: 'absolute',
top,
right,
};
}

return baseStyle;
return {
...iconButtonStyle,
_focusVisible: {
outlineColor: focusVisibleOutlineColor,
outlineOffset: '-1h',
outlineStyle: 'solid',
outlineWidth: '1h',
},
_hover: {
color: hoverColor,
},
};
};

export {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ exports[`Drawer should render correctly 1`] = `
-ms-appearance: none;
appearance: none;
background-color: inherit;
border: var(--tonic-borders-1);
color: rgba(255, 255, 255, .47);
border: none;
color: var(--tonic-colors-white-tertiary);
cursor: pointer;
outline: 0;
padding: 0;
Expand All @@ -123,41 +123,23 @@ exports[`Drawer should render correctly 1`] = `
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
border-color: var(--tonic-colors-transparent);
width: var(--tonic-sizes-8x);
height: var(--tonic-sizes-8x);
-webkit-transition: border-color 200ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1),color 200ms cubic-bezier(0.4, 0, 0.2, 1);
transition: border-color 200ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1),color 200ms cubic-bezier(0.4, 0, 0.2, 1);
position: absolute;
top: calc(.5rem - .0625rem);
right: calc(.5rem - .0625rem);
}
.emotion-12:focus,
.emotion-12[data-focus] {
border-color: #1e5ede;
box-shadow: inset 0 0 0 1px #1e5ede;
color: rgba(255, 255, 255, .47);
.emotion-12:focus-visible {
outline-color: var(--tonic-colors-blue-60);
outline-offset: calc(var(--tonic-space-1h) * -1);
outline-style: solid;
outline-width: var(--tonic-sizes-1h);
}
.emotion-12:hover,
.emotion-12[data-hover] {
color: rgba(255, 255, 255, 1.0);
}
.emotion-12:focus:hover {
color: rgba(255, 255, 255, 1.0);
}
.emotion-12:active,
.emotion-12[data-active] {
color: rgba(255, 255, 255, .47);
}
.emotion-12:focus:active {
border-color: #1e5ede;
box-shadow: inset 0 0 0 1px #1e5ede;
color: rgba(255, 255, 255, .47);
color: var(--tonic-colors-white-emphasis);
}
.emotion-14 {
Expand Down
18 changes: 13 additions & 5 deletions packages/react/src/drawer/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,19 +164,27 @@ const useDrawerCloseButtonStyle = () => {
light: 'black:tertiary',
}[colorMode];
const size = '8x';
const _focusBorderColor = 'blue:60';
const _focusBoxShadowBorderColor = 'blue:60';
const _hoverColor = {
const focusVisibleOutlineColor = 'blue:60';
const hoverColor = {
dark: 'white:emphasis',
light: 'black:primary',
}[colorMode];
const baseStyle = useIconButtonStyle({ color, size, _focusBorderColor, _focusBoxShadowBorderColor, _hoverColor });
const iconButtonStyle = useIconButtonStyle({ color, size });
const parentBorderWidth = sizes['1q'];
const top = `calc(${sizes['2x']} - ${parentBorderWidth})`;
const right = `calc(${sizes['2x']} - ${parentBorderWidth})`;

return {
...baseStyle,
...iconButtonStyle,
_focusVisible: {
outlineColor: focusVisibleOutlineColor,
outlineOffset: '-1h',
outlineStyle: 'solid',
outlineWidth: '1h',
},
_hover: {
color: hoverColor,
},
position: 'absolute',
top,
right,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ exports[`Modal should render correctly 1`] = `
-ms-appearance: none;
appearance: none;
background-color: inherit;
border: var(--tonic-borders-1);
color: rgba(255, 255, 255, .47);
border: none;
color: var(--tonic-colors-white-tertiary);
cursor: pointer;
outline: 0;
padding: 0;
Expand All @@ -123,41 +123,23 @@ exports[`Modal should render correctly 1`] = `
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
border-color: var(--tonic-colors-transparent);
width: var(--tonic-sizes-8x);
height: var(--tonic-sizes-8x);
-webkit-transition: border-color 200ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1),color 200ms cubic-bezier(0.4, 0, 0.2, 1);
transition: border-color 200ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1),color 200ms cubic-bezier(0.4, 0, 0.2, 1);
position: absolute;
top: calc(.5rem - .0625rem);
right: calc(.5rem - .0625rem);
}
.emotion-12:focus,
.emotion-12[data-focus] {
border-color: #1e5ede;
box-shadow: inset 0 0 0 1px #1e5ede;
color: rgba(255, 255, 255, .47);
.emotion-12:focus-visible {
outline-color: var(--tonic-colors-blue-60);
outline-offset: calc(var(--tonic-space-1h) * -1);
outline-style: solid;
outline-width: var(--tonic-sizes-1h);
}
.emotion-12:hover,
.emotion-12[data-hover] {
color: rgba(255, 255, 255, 1.0);
}
.emotion-12:focus:hover {
color: rgba(255, 255, 255, 1.0);
}
.emotion-12:active,
.emotion-12[data-active] {
color: rgba(255, 255, 255, .47);
}
.emotion-12:focus:active {
border-color: #1e5ede;
box-shadow: inset 0 0 0 1px #1e5ede;
color: rgba(255, 255, 255, .47);
color: var(--tonic-colors-white-emphasis);
}
.emotion-14 {
Expand Down
18 changes: 13 additions & 5 deletions packages/react/src/modal/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,19 +142,27 @@ const useModalCloseButtonStyle = () => {
light: 'black:tertiary',
}[colorMode];
const size = '8x';
const _focusBorderColor = 'blue:60';
const _focusBoxShadowBorderColor = 'blue:60';
const _hoverColor = {
const focusVisibleOutlineColor = 'blue:60';
const hoverColor = {
dark: 'white:emphasis',
light: 'black:primary',
}[colorMode];
const baseStyle = useIconButtonStyle({ color, size, _focusBorderColor, _focusBoxShadowBorderColor, _hoverColor });
const iconButtonStyle = useIconButtonStyle({ color, size });
const parentBorderWidth = sizes['1q'];
const top = `calc(${sizes['2x']} - ${parentBorderWidth})`;
const right = `calc(${sizes['2x']} - ${parentBorderWidth})`;

return {
...baseStyle,
...iconButtonStyle,
_focusVisible: {
outlineColor: focusVisibleOutlineColor,
outlineOffset: '-1h',
outlineStyle: 'solid',
outlineWidth: '1h',
},
_hover: {
color: hoverColor,
},
position: 'absolute',
top,
right,
Expand Down
42 changes: 2 additions & 40 deletions packages/react/src/shared/styles.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,14 @@
import { createTransitionStyle } from '@tonic-ui/utils';
import { useTheme } from '../theme';

const useIconButtonStyle = ({
color: colorProp,
color,
size = '8x',
_focusBorderColor: focusBorderColorProp,
_focusBoxShadowBorderColor: focusBoxShadowBorderColorProp,
_hoverColor: hoverColorProp,
}) => {
const { colors } = useTheme();
const color = colors?.[colorProp] ?? colorProp;
const activeColor = color;
const hoverColor = colors?.[hoverColorProp] ?? hoverColorProp;
const focusColor = color;
const focusHoverColor = hoverColor;
const focusActiveColor = activeColor;
const focusBorderColor = colors?.[focusBorderColorProp] ?? focusBorderColorProp;
const focusBoxShadowBorderColor = colors?.[focusBoxShadowBorderColorProp] ?? focusBoxShadowBorderColorProp;

return {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: 1,
borderColor: 'transparent',
color,
color: color,
width: size,
height: size,
transition: createTransitionStyle(['border-color', 'box-shadow', 'color'], { duration: 200 }),
_hover: {
color: hoverColor,
},
_active: {
color: activeColor,
},
_focus: {
borderColor: focusBorderColor,
boxShadow: focusBoxShadowBorderColor ? `inset 0 0 0 1px ${focusBoxShadowBorderColor}` : undefined,
color: focusColor,
},
_focusHover: {
color: focusHoverColor,
},
_focusActive: {
borderColor: focusBorderColor,
boxShadow: focusBoxShadowBorderColor ? `inset 0 0 0 1px ${focusBoxShadowBorderColor}` : undefined,
color: focusActiveColor,
},
};
};

Expand Down
56 changes: 25 additions & 31 deletions packages/react/src/tag/styles.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createTransitionStyle } from '@tonic-ui/utils';
import { useColorMode } from '../color-mode';
import { useIconButtonStyle } from '../shared/styles';
import { useTheme } from '../theme';

const getSolidTagStyle = ({
Expand Down Expand Up @@ -298,47 +298,41 @@ const useTagCloseButtonStyle = ({
dark: 'white:emphasis',
light: 'black:emphasis',
}[colorMode];
const activeColor = color;
const focusColor = hoverColor;
const disabledColor = color;
const focusOutlineColor = {
const focusVisibleOutlineColor = {
dark: 'blue:60',
light: 'blue:60',
}[colorMode];
const size = '4x';
const baseStyle = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color,
height: size,
width: size,
transition: createTransitionStyle(['color'], { duration: 200 }),
_hover: {
color: hoverColor,
},
_focus: {
color: focusColor,
outline: 1,
outlineColor: focusOutlineColor,
},
_active: {
color: activeColor,
},
_disabled: {
color: disabledColor,
cursor: 'not-allowed',
},
};
const iconButtonStyle = useIconButtonStyle({ color, size });

if (isClosable) {
return {
...baseStyle,
...iconButtonStyle,
_hover: {
color: hoverColor,
},
_focusVisible: {
outlineColor: focusVisibleOutlineColor,
outlineOffset: '-1q',
outlineStyle: 'solid',
outlineWidth: '1q',
},
ml: '2x',
};
}

return baseStyle;
return {
...iconButtonStyle,
_hover: {
color: hoverColor,
},
_focusVisible: {
outlineColor: focusVisibleOutlineColor,
outlineOffset: '-1q',
outlineStyle: 'solid',
outlineWidth: '1q',
},
};
};

export {
Expand Down
Loading

0 comments on commit 6205a93

Please sign in to comment.