diff --git a/.changeset/pink-students-compare.md b/.changeset/pink-students-compare.md new file mode 100644 index 00000000000..833071dfca1 --- /dev/null +++ b/.changeset/pink-students-compare.md @@ -0,0 +1,5 @@ +--- +'@shopify/polaris': minor +--- + +Update focus states to be present on :focus-visible rather than :focus diff --git a/polaris-react/src/components/ActionList/ActionList.scss b/polaris-react/src/components/ActionList/ActionList.scss index 72eb147df58..285353fe160 100644 --- a/polaris-react/src/components/ActionList/ActionList.scss +++ b/polaris-react/src/components/ActionList/ActionList.scss @@ -81,7 +81,7 @@ background-color: var(--p-surface-pressed); } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); outline: var(--p-border-width-3) solid transparent; diff --git a/polaris-react/src/components/Autocomplete/components/MappedAction/MappedAction.scss b/polaris-react/src/components/Autocomplete/components/MappedAction/MappedAction.scss index 96acec99543..08b3139e592 100644 --- a/polaris-react/src/components/Autocomplete/components/MappedAction/MappedAction.scss +++ b/polaris-react/src/components/Autocomplete/components/MappedAction/MappedAction.scss @@ -59,7 +59,7 @@ background-color: var(--p-surface-pressed); } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Banner/Banner.scss b/polaris-react/src/components/Banner/Banner.scss index c8f7376a83f..2d7f183d1db 100644 --- a/polaris-react/src/components/Banner/Banner.scss +++ b/polaris-react/src/components/Banner/Banner.scss @@ -236,7 +236,7 @@ text-decoration: underline; } - &:focus > .Text { + &:focus-visible > .Text { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include plain-button-backdrop; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @@ -269,7 +269,7 @@ letter-spacing: initial; color: var(--p-text); - &:focus { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Breadcrumbs/Breadcrumbs.scss b/polaris-react/src/components/Breadcrumbs/Breadcrumbs.scss index a49d280bcea..e8a56262e29 100644 --- a/polaris-react/src/components/Breadcrumbs/Breadcrumbs.scss +++ b/polaris-react/src/components/Breadcrumbs/Breadcrumbs.scss @@ -43,11 +43,11 @@ } } - &:focus { + &:focus-visible { outline: none; } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Button/Button.scss b/polaris-react/src/components/Button/Button.scss index 0e2064949a1..897d93cc02a 100644 --- a/polaris-react/src/components/Button/Button.scss +++ b/polaris-react/src/components/Button/Button.scss @@ -291,7 +291,7 @@ box-shadow: none; } - &:focus { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include no-focus-ring; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @@ -303,7 +303,7 @@ } } - &:focus:not(:active) { + &:focus-visible:not(:active) { > .Content { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); @@ -574,7 +574,7 @@ } } - &:focus { + &:focus-visible { box-shadow: 0 0 0 var(--p-border-width-1) currentColor; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); diff --git a/polaris-react/src/components/Checkbox/Checkbox.scss b/polaris-react/src/components/Checkbox/Checkbox.scss index fdb2b1a6c4b..ce6b74451e6 100644 --- a/polaris-react/src/components/Checkbox/Checkbox.scss +++ b/polaris-react/src/components/Checkbox/Checkbox.scss @@ -12,7 +12,7 @@ // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include visually-hidden; - &.keyFocused { + &:focus-visible { + .Backdrop { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); diff --git a/polaris-react/src/components/Checkbox/Checkbox.tsx b/polaris-react/src/components/Checkbox/Checkbox.tsx index 433eeb8491b..9536074a7d6 100644 --- a/polaris-react/src/components/Checkbox/Checkbox.tsx +++ b/polaris-react/src/components/Checkbox/Checkbox.tsx @@ -2,7 +2,6 @@ import React, { forwardRef, useRef, useImperativeHandle, - useState, useContext, } from 'react'; import {MinusMinor, TickSmallMinor} from '@shopify/polaris-icons'; @@ -13,7 +12,7 @@ import {useUniqueId} from '../../utilities/unique-id'; import {Choice, helpTextID} from '../Choice'; import {errorTextID} from '../InlineError'; import {Icon} from '../Icon'; -import {Error, CheckboxHandles, Key} from '../../types'; +import type {Error, CheckboxHandles} from '../../types'; import {WithinListboxContext} from '../../utilities/listbox/context'; import styles from './Checkbox.scss'; @@ -76,7 +75,6 @@ export const Checkbox = forwardRef( setTrue: handleMouseOver, setFalse: handleMouseOut, } = useToggle(false); - const [keyFocused, setKeyFocused] = useState(false); const isWithinListbox = useContext(WithinListboxContext); useImperativeHandle(ref, () => ({ @@ -89,15 +87,6 @@ export const Checkbox = forwardRef( const handleBlur = () => { onBlur && onBlur(); - setKeyFocused(false); - }; - - const handleKeyUp = (event: React.KeyboardEvent) => { - const {keyCode} = event; - - if (keyCode === Key.Space || keyCode === Key.Tab) { - !keyFocused && setKeyFocused(true); - } }; const handleOnClick = () => { @@ -142,7 +131,6 @@ export const Checkbox = forwardRef( const inputClassName = classNames( styles.Input, isIndeterminate && styles['Input-indeterminate'], - keyFocused && styles.keyFocused, ); return ( @@ -170,7 +158,6 @@ export const Checkbox = forwardRef( onChange={noop} onClick={handleOnClick} onFocus={onFocus} - onKeyUp={handleKeyUp} aria-invalid={error != null} aria-controls={ariaControls} aria-describedby={ariaDescribedBy} diff --git a/polaris-react/src/components/Checkbox/tests/Checkbox.test.tsx b/polaris-react/src/components/Checkbox/tests/Checkbox.test.tsx index af8a8bded99..2b4f9e25fd7 100644 --- a/polaris-react/src/components/Checkbox/tests/Checkbox.test.tsx +++ b/polaris-react/src/components/Checkbox/tests/Checkbox.test.tsx @@ -1,7 +1,6 @@ import React, {AllHTMLAttributes} from 'react'; import {mountWithApp} from 'tests/utilities'; -import {Key} from '../../../types'; import {Checkbox} from '../Checkbox'; describe('', () => { @@ -276,31 +275,6 @@ describe('', () => { }); }); }); - - describe('Focus className', () => { - it('on keyUp adds a keyFocused class to the input', () => { - const checkbox = mountWithApp(); - - checkbox.find('input')!.trigger('onKeyUp', { - keyCode: Key.Space, - }); - - expect(checkbox).toContainReactComponent('input', { - className: 'Input keyFocused', - }); - }); - - it('on change does not add a keyFocused class to the input', () => { - const checkbox = mountWithApp(); - const checkboxInput = checkbox.find('input'); - checkboxInput!.trigger('onChange', { - currentTarget: checkboxInput!.domNode as HTMLInputElement, - }); - expect(checkbox).not.toContainReactComponent('input', { - className: 'Input keyFocused', - }); - }); - }); }); function noop() {} diff --git a/polaris-react/src/components/DataTable/DataTable.scss b/polaris-react/src/components/DataTable/DataTable.scss index 56d5851b586..73019bc01b9 100644 --- a/polaris-react/src/components/DataTable/DataTable.scss +++ b/polaris-react/src/components/DataTable/DataTable.scss @@ -245,7 +245,7 @@ } } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); diff --git a/polaris-react/src/components/DatePicker/DatePicker.scss b/polaris-react/src/components/DatePicker/DatePicker.scss index 78118e276b6..adbabae37b4 100644 --- a/polaris-react/src/components/DatePicker/DatePicker.scss +++ b/polaris-react/src/components/DatePicker/DatePicker.scss @@ -77,7 +77,7 @@ // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring; - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Filters/Filters.scss b/polaris-react/src/components/Filters/Filters.scss index fd6c0fbe1a9..dc3498455d7 100644 --- a/polaris-react/src/components/Filters/Filters.scss +++ b/polaris-react/src/components/Filters/Filters.scss @@ -131,7 +131,7 @@ $list-filters-footer-height: 70px; outline: var(--p-border-width-1) solid transparent; } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Modal/components/CloseButton/CloseButton.scss b/polaris-react/src/components/Modal/components/CloseButton/CloseButton.scss index ce19ee9ca2f..2cfbb29fbb3 100644 --- a/polaris-react/src/components/Modal/components/CloseButton/CloseButton.scss +++ b/polaris-react/src/components/Modal/components/CloseButton/CloseButton.scss @@ -21,7 +21,7 @@ background: var(--p-surface-pressed); } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Navigation/Navigation.scss b/polaris-react/src/components/Navigation/Navigation.scss index 10794d750b6..ba511e360e4 100644 --- a/polaris-react/src/components/Navigation/Navigation.scss +++ b/polaris-react/src/components/Navigation/Navigation.scss @@ -141,12 +141,12 @@ $disabled-fade: 0.6; @include focus-ring; &:hover, - &.keyFocused { + &:focus-visible { background-color: var(--p-background-hovered); color: var(--p-text-primary-hovered); } - .keyFocused { + :focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } @@ -394,7 +394,7 @@ $disabled-fade: 0.6; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring; - &:focus { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } @@ -443,8 +443,7 @@ $disabled-fade: 0.6; color: var(--p-text-subdued); } - // stylelint-disable-next-line selector-max-class -- generated by polaris-migrator DO NOT COPY - &.keyFocused { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); color: var(--p-text); @@ -482,8 +481,8 @@ $disabled-fade: 0.6; &:hover { color: var(--p-text-primary-hovered); } - // stylelint-disable-next-line selector-max-class -- generated by polaris-migrator DO NOT COPY - &.keyFocused { + + &:focus-visible { color: var(--p-text-primary); } @@ -610,7 +609,7 @@ $disabled-fade: 0.6; @include recolor-icon($filter-color: var(--p-filter-icon)); } - &:focus { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } @@ -653,7 +652,7 @@ $disabled-fade: 0.6; color: var(--p-text-primary); } - &:focus { + &:focus-visible { outline: none; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); diff --git a/polaris-react/src/components/Navigation/Navigation.stories.tsx b/polaris-react/src/components/Navigation/Navigation.stories.tsx index 19175f8b497..acab6666757 100644 --- a/polaris-react/src/components/Navigation/Navigation.stories.tsx +++ b/polaris-react/src/components/Navigation/Navigation.stories.tsx @@ -719,6 +719,7 @@ export function WithVariousStatesAndSecondaryElements() { { url: '/admin/products', disabled: false, + selected: true, label: 'Selected sub item', }, { diff --git a/polaris-react/src/components/Navigation/_variables.scss b/polaris-react/src/components/Navigation/_variables.scss index 2b208ba1c58..cb8564662b0 100644 --- a/polaris-react/src/components/Navigation/_variables.scss +++ b/polaris-react/src/components/Navigation/_variables.scss @@ -41,7 +41,7 @@ $nav-animation-variables: ( // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring; - &.keyFocused { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); background: var(--p-background-hovered); @@ -127,7 +127,7 @@ $nav-animation-variables: ( } .Item:hover &, - .Item.keyFocused & { + .Item:focus-visible & { // stylelint-disable -- generated by polaris-migrator DO NOT COPY @include recolor-icon( $fill-color: var(--p-icon), @@ -142,7 +142,7 @@ $nav-animation-variables: ( .subNavigationActive:hover &, .Item-child-active &, .Item-child-active:hover &, - .Item-selected.keyFocused & { + .Item-selected:focus-visible & { // stylelint-disable -- generated by polaris-migrator DO NOT COPY @include recolor-icon( $fill-color: var(--p-action-primary), diff --git a/polaris-react/src/components/Navigation/components/Item/Item.tsx b/polaris-react/src/components/Navigation/components/Item/Item.tsx index 2c086b19345..aff77d3cfa7 100644 --- a/polaris-react/src/components/Navigation/components/Item/Item.tsx +++ b/polaris-react/src/components/Navigation/components/Item/Item.tsx @@ -4,7 +4,6 @@ import React, { useState, MouseEvent, ReactNode, - useCallback, useRef, useLayoutEffect, } from 'react'; @@ -13,7 +12,6 @@ import {classNames} from '../../../../utilities/css'; import {NavigationContext} from '../../context'; import {Badge} from '../../../Badge'; import {Icon, IconProps} from '../../../Icon'; -import {Key} from '../../../../types'; import {Indicator} from '../../../Indicator'; import {UnstyledButton} from '../../../UnstyledButton'; import {UnstyledLink} from '../../../UnstyledLink'; @@ -112,7 +110,6 @@ export function Item({ const {isNavigationCollapsed} = useMediaQuery(); const secondaryNavigationId = useUniqueId('SecondaryNavigation'); const {location, onNavigationDismiss} = useContext(NavigationContext); - const [keyFocused, setKeyFocused] = useState(false); const navTextRef = useRef(null); const [isTruncated, setIsTruncated] = useState(false); @@ -129,19 +126,6 @@ export function Item({ } }, [truncateText]); - const handleKeyUp = useCallback( - (event: React.KeyboardEvent) => { - if (event.keyCode === Key.Tab) { - !keyFocused && setKeyFocused(true); - } - }, - [keyFocused], - ); - - const handleBlur = useCallback(() => { - keyFocused && setKeyFocused(false); - }, [keyFocused]); - const tabIndex = disabled ? -1 : 0; const hasNewChild = @@ -200,7 +184,6 @@ export function Item({ const className = classNames( styles.Item, disabled && styles['Item-disabled'], - keyFocused && styles.keyFocused, selectedOverride && styles['Item-selected'], ); @@ -220,8 +203,6 @@ export function Item({ aria-disabled={disabled} aria-label={accessibilityLabel} onClick={getClickHandler(onClick)} - onKeyUp={handleKeyUp} - onBlur={handleBlur} > {iconMarkup} {itemLabelMarkup} @@ -311,7 +292,6 @@ export function Item({ selected && canBeActive && styles['Item-selected'], showExpanded && styles.subNavigationActive, childIsActive && styles['Item-child-active'], - keyFocused && styles.keyFocused, ); let secondaryNavigationMarkup: ReactNode = null; @@ -373,8 +353,6 @@ export function Item({ aria-disabled={disabled} aria-label={accessibilityLabel} onClick={getClickHandler(onClick)} - onKeyUp={handleKeyUp} - onBlur={handleBlur} {...normalizeAriaAttributes( secondaryNavigationId, subNavigationItems.length > 0, diff --git a/polaris-react/src/components/Navigation/components/Item/tests/Item.test.tsx b/polaris-react/src/components/Navigation/components/Item/tests/Item.test.tsx index 33c69c35cbd..151060b69b6 100644 --- a/polaris-react/src/components/Navigation/components/Item/tests/Item.test.tsx +++ b/polaris-react/src/components/Navigation/components/Item/tests/Item.test.tsx @@ -14,7 +14,6 @@ import {NavigationContext} from '../../../context'; import {Item, ItemSecondaryAction, MAX_SECONDARY_ACTIONS} from '../Item'; import type {ItemProps} from '../Item'; import {Secondary} from '../components'; -import {Key} from '../../../../../types'; import {Tooltip} from '../../../../Tooltip'; describe('', () => { @@ -895,48 +894,6 @@ describe('', () => { }); }); }); - - describe('keyFocused', () => { - it('adds and removes a class to button when item was tabbed into focus and then blurred', () => { - const item = mountWithNavigationProvider( - , - ); - - const event = { - keyCode: Key.Tab, - }; - - item.find('button')!.trigger('onKeyUp', event); - expect(item).toContainReactComponent('button', { - className: 'Item keyFocused', - }); - - item.find('button')!.trigger('onBlur'); - expect(item).toContainReactComponent('button', { - className: 'Item', - }); - }); - - it('adds and removes a class to a link when item was tabbed into focus and then blurred', () => { - const item = mountWithNavigationProvider( - , - ); - - const event = { - keyCode: Key.Tab, - }; - - item.find('a')!.trigger('onKeyUp', event); - expect(item).toContainReactComponent('a', { - className: 'Item keyFocused', - }); - - item.find('a')!.trigger('onBlur'); - expect(item).toContainReactComponent('a', { - className: 'Item', - }); - }); - }); }); function noop() {} diff --git a/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.scss b/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.scss index f0f0ec57101..016cd43aafd 100644 --- a/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.scss +++ b/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.scss @@ -18,8 +18,7 @@ // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include visually-hidden; - // stylelint-disable-next-line selector-max-class -- generated by polaris-migrator DO NOT COPY - &.keyFocused + .Backdrop { + &:focus-visible + .Backdrop { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.tsx b/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.tsx index dee2efef98f..2b15e9de595 100644 --- a/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.tsx +++ b/polaris-react/src/components/OptionList/components/Checkbox/Checkbox.tsx @@ -1,4 +1,4 @@ -import React, {useState} from 'react'; +import React from 'react'; import {TickSmallMinor} from '@shopify/polaris-icons'; import {classNames} from '../../../../utilities/css'; @@ -29,22 +29,10 @@ export function Checkbox({ role, }: CheckboxProps) { const id = useUniqueId('Checkbox', idProp); - const [keyFocused, setKeyFocused] = useState(false); const className = classNames(styles.Checkbox, active && styles.active); - const handleBlur = () => { - setKeyFocused(false); - }; - - const handleKeyUp = () => { - !keyFocused && setKeyFocused(true); - }; - - const inputClassName = classNames( - styles.Input, - keyFocused && styles.keyFocused, - ); + const inputClassName = classNames(styles.Input); return (
@@ -58,8 +46,6 @@ export function Checkbox({ className={inputClassName} aria-checked={checked} onChange={onChange} - onBlur={handleBlur} - onKeyUp={handleKeyUp} role={role} />
diff --git a/polaris-react/src/components/OptionList/components/Checkbox/tests/Checkbox.test.tsx b/polaris-react/src/components/OptionList/components/Checkbox/tests/Checkbox.test.tsx index ac467f9eb59..93d22c8c264 100644 --- a/polaris-react/src/components/OptionList/components/Checkbox/tests/Checkbox.test.tsx +++ b/polaris-react/src/components/OptionList/components/Checkbox/tests/Checkbox.test.tsx @@ -1,7 +1,6 @@ import React from 'react'; import {mountWithApp} from 'tests/utilities'; -import {Key} from '../../../../../types'; import {Checkbox, CheckboxProps} from '../Checkbox'; describe('', () => { @@ -31,47 +30,6 @@ describe('', () => { expect(spy).toHaveBeenCalledTimes(1); }); - - describe('Focus className', () => { - it('on keyUp adds a keyFocused class to the input', () => { - const checkbox = mountWithApp(); - - const event = { - keyCode: Key.Space, - }; - checkbox.find('input')!.trigger('onKeyUp', event); - expect(checkbox).toContainReactComponent('input', { - className: 'Input keyFocused', - }); - }); - - it('removes the keyFocused class on blur', () => { - const checkbox = mountWithApp(); - - const event = { - keyCode: Key.Space, - }; - - checkbox.find('input')!.trigger('onKeyUp', event); - checkbox.find('input')!.trigger('onBlur'); - - expect(checkbox).toContainReactComponent('input', { - className: 'Input', - }); - }); - - it('on change does not add a keyFocused class to the input', () => { - const checkbox = mountWithApp(); - const checkboxInput = checkbox.find('input'); - checkboxInput!.trigger('onChange', { - currentTarget: checkboxInput!.domNode as HTMLInputElement, - }); - - expect(checkbox).not.toContainReactComponent('input', { - className: 'Input keyFocused', - }); - }); - }); }); function noop() {} diff --git a/polaris-react/src/components/OptionList/components/Option/Option.scss b/polaris-react/src/components/OptionList/components/Option/Option.scss index 35d87ded1e6..03435a6db86 100644 --- a/polaris-react/src/components/OptionList/components/Option/Option.scss +++ b/polaris-react/src/components/OptionList/components/Option/Option.scss @@ -29,7 +29,8 @@ $control-vertical-adjustment: 2px; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring; - &.focused:not(:active) { + // stylelint-disable-next-line selector-max-specificity -- required for focus-visible support + &.focused:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/RadioButton/RadioButton.scss b/polaris-react/src/components/RadioButton/RadioButton.scss index 66525fb2a33..a0ce5e77ba6 100644 --- a/polaris-react/src/components/RadioButton/RadioButton.scss +++ b/polaris-react/src/components/RadioButton/RadioButton.scss @@ -11,12 +11,11 @@ // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include visually-hidden; - // stylelint-disable-next-line selector-max-class -- generated by polaris-migrator DO NOT COPY - &.keyFocused + .Backdrop { + &:focus-visible + .Backdrop { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); - // stylelint-disable-next-line selector-max-specificity, selector-max-class -- generated by polaris-migrator DO NOT COPY + // stylelint-disable-next-line selector-max-specificity -- generated by polaris-migrator DO NOT COPY &::after { border-radius: var(--p-border-radius-half); } diff --git a/polaris-react/src/components/RadioButton/RadioButton.tsx b/polaris-react/src/components/RadioButton/RadioButton.tsx index f1f3aa75ebf..913354798a2 100644 --- a/polaris-react/src/components/RadioButton/RadioButton.tsx +++ b/polaris-react/src/components/RadioButton/RadioButton.tsx @@ -1,4 +1,4 @@ -import React, {useRef, useState} from 'react'; +import React, {useRef} from 'react'; import {useUniqueId} from '../../utilities/unique-id'; import {useToggle} from '../../utilities/use-toggle'; @@ -51,7 +51,6 @@ export function RadioButton({ const id = useUniqueId('RadioButton', idProp); const name = nameProp || id; const inputNode = useRef(null); - const [keyFocused, setKeyFocused] = useState(false); const { value: mouseOver, @@ -59,13 +58,8 @@ export function RadioButton({ setFalse: handleMouseOut, } = useToggle(false); - const handleKeyUp = () => { - !keyFocused && setKeyFocused(true); - }; - const handleBlur = () => { onBlur && onBlur(); - setKeyFocused(false); }; function handleChange({currentTarget}: React.ChangeEvent) { @@ -83,10 +77,7 @@ export function RadioButton({ ? describedBy.join(' ') : undefined; - const inputClassName = classNames( - styles.Input, - keyFocused && styles.keyFocused, - ); + const inputClassName = classNames(styles.Input); const backdropClassName = classNames( styles.Backdrop, @@ -114,7 +105,6 @@ export function RadioButton({ className={inputClassName} onChange={handleChange} onFocus={onFocus} - onKeyUp={handleKeyUp} onBlur={handleBlur} aria-describedby={ariaDescribedBy} ref={inputNode} diff --git a/polaris-react/src/components/RadioButton/tests/RadioButton.test.tsx b/polaris-react/src/components/RadioButton/tests/RadioButton.test.tsx index ac1aaaed720..f2a99c06289 100644 --- a/polaris-react/src/components/RadioButton/tests/RadioButton.test.tsx +++ b/polaris-react/src/components/RadioButton/tests/RadioButton.test.tsx @@ -76,28 +76,6 @@ describe('', () => { }); }); - describe('Focus className', () => { - it('on keyUp adds a keyFocused class to the input', () => { - const radioButton = mountWithApp(); - - radioButton.find('input')!.trigger('onKeyUp'); - expect(radioButton).toContainReactComponent('input', { - className: 'Input keyFocused', - }); - }); - - it('on change does not add a keyFocused class to the input', () => { - const radioButton = mountWithApp(); - const radioInput = radioButton.find('input'); - radioInput!.trigger('onChange', { - currentTarget: radioInput!.domNode as HTMLInputElement, - }); - expect(radioButton).not.toContainReactComponent('input', { - className: 'Input keyFocused', - }); - }); - }); - describe('onBlur()', () => { it('is called when the input is focused', () => { const spy = jest.fn(); diff --git a/polaris-react/src/components/RangeSlider/components/DualThumb/DualThumb.scss b/polaris-react/src/components/RangeSlider/components/DualThumb/DualThumb.scss index 300ac43269b..6c92922d74d 100644 --- a/polaris-react/src/components/RangeSlider/components/DualThumb/DualThumb.scss +++ b/polaris-react/src/components/RangeSlider/components/DualThumb/DualThumb.scss @@ -121,7 +121,7 @@ $range-wrapper: 28px; transform: scale(1.5); } - &:focus { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); outline: 0; diff --git a/polaris-react/src/components/Select/Select.scss b/polaris-react/src/components/Select/Select.scss index 68fdb34d95a..b318bfed009 100644 --- a/polaris-react/src/components/Select/Select.scss +++ b/polaris-react/src/components/Select/Select.scss @@ -158,13 +158,13 @@ // Need to override the higher specificity of the sibling selector // so that errors still have red borders. // stylelint-disable-next-line selector-max-combinators, selector-max-specificity, selector-max-class -- generated by polaris-migrator DO NOT COPY - .Input:focus ~ .Backdrop { + .Input:focus-visible ~ .Backdrop { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } } -.Input:focus { +.Input:focus-visible { ~ .Backdrop { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); diff --git a/polaris-react/src/components/SelectAllActions/SelectAllActions.scss b/polaris-react/src/components/SelectAllActions/SelectAllActions.scss index eb7f29a8045..c1724726447 100644 --- a/polaris-react/src/components/SelectAllActions/SelectAllActions.scss +++ b/polaris-react/src/components/SelectAllActions/SelectAllActions.scss @@ -60,7 +60,7 @@ @include no-focus-ring; } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Tabs/Tabs.scss b/polaris-react/src/components/Tabs/Tabs.scss index 5a9e20bcaf6..904125fe92b 100644 --- a/polaris-react/src/components/Tabs/Tabs.scss +++ b/polaris-react/src/components/Tabs/Tabs.scss @@ -92,7 +92,7 @@ $item-vertical-padding: $item-min-height * 0.5; } } - &:focus { + &:focus-visible { .Title { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include text-emphasis-normal; @@ -215,7 +215,7 @@ $item-vertical-padding: $item-min-height * 0.5; background-color: var(--p-surface-primary-selected-pressed); } - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } @@ -252,7 +252,7 @@ $item-vertical-padding: $item-min-height * 0.5; @include recolor-icon(var(--p-icon)); } - &:focus .Title { + &:focus-visible .Title { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/Tag/Tag.scss b/polaris-react/src/components/Tag/Tag.scss index e36fe307268..aac428779c3 100644 --- a/polaris-react/src/components/Tag/Tag.scss +++ b/polaris-react/src/components/Tag/Tag.scss @@ -42,7 +42,7 @@ $button-size: 20px; @include focus-ring; // stylelint-disable selector-max-specificity -- generated by polaris-migrator DO NOT COPY - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } @@ -118,7 +118,7 @@ $button-size: 20px; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring; - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } @@ -168,7 +168,7 @@ $button-size: 20px; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring; - &:focus:not(:active) { + &:focus-visible:not(:active) { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); text-decoration: underline; diff --git a/polaris-react/src/components/TextField/TextField.scss b/polaris-react/src/components/TextField/TextField.scss index 586c675a439..97ebe591258 100644 --- a/polaris-react/src/components/TextField/TextField.scss +++ b/polaris-react/src/components/TextField/TextField.scss @@ -42,7 +42,7 @@ $spinner-icon-size: 12px; .focus > .Input, .focus > .VerticalContent, -.Input:focus { +.Input:focus-visible { outline: none; // stylelint-disable-next-line selector-max-class, selector-max-combinators -- generated by polaris-migrator DO NOT COPY @@ -280,7 +280,7 @@ $spinner-icon-size: 12px; z-index: var(--pc-text-field-contents); margin: 0 var(--p-space-3) 0 var(--p-space-1); - &:focus:enabled { + &:focus-visible:enabled { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } diff --git a/polaris-react/src/components/TopBar/TopBar.scss b/polaris-react/src/components/TopBar/TopBar.scss index d71d765b986..432766b98dd 100644 --- a/polaris-react/src/components/TopBar/TopBar.scss +++ b/polaris-react/src/components/TopBar/TopBar.scss @@ -125,7 +125,7 @@ $icon-size: 20px; } // stylelint-disable selector-max-specificity -- generated by polaris-migrator DO NOT COPY - &:focus:not(:active) { + &:focus-visible:not(:active) { .IconWrapper { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); diff --git a/polaris-react/src/components/TopBar/components/Menu/Menu.scss b/polaris-react/src/components/TopBar/components/Menu/Menu.scss index 2cd03cae5e8..4ac893ab0f9 100644 --- a/polaris-react/src/components/TopBar/components/Menu/Menu.scss +++ b/polaris-react/src/components/TopBar/components/Menu/Menu.scss @@ -41,13 +41,16 @@ $activator-variables: ( border-radius: var(--p-border-radius-base); &:focus { - // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY - @include focus-ring($style: 'focused'); // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY background-color: var(--pc-top-bar-background-lighter); outline: none; } + &:focus-visible { + // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY + @include focus-ring($style: 'focused'); + } + &:hover { // stylelint-disable -- generated by polaris-migrator DO NOT COPY background-color: var( diff --git a/polaris-react/src/components/TopBar/components/SearchField/SearchField.scss b/polaris-react/src/components/TopBar/components/SearchField/SearchField.scss index 9cb676598b0..0044e28d3b5 100644 --- a/polaris-react/src/components/TopBar/components/SearchField/SearchField.scss +++ b/polaris-react/src/components/TopBar/components/SearchField/SearchField.scss @@ -42,7 +42,7 @@ $search-icon-width: calc(#{$icon-size} + var(--p-space-4)); } } -.Input:focus { +.Input:focus-visible { ~ .Backdrop { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); @@ -140,7 +140,7 @@ $search-icon-width: calc(#{$icon-size} + var(--p-space-4)); outline: none; } - &:focus { + &:focus-visible { // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($size: 'wide', $style: 'focused'); } diff --git a/polaris-react/src/styles/shared/_buttons.scss b/polaris-react/src/styles/shared/_buttons.scss index 61077c67eef..53c83137ad0 100644 --- a/polaris-react/src/styles/shared/_buttons.scss +++ b/polaris-react/src/styles/shared/_buttons.scss @@ -44,10 +44,9 @@ outline: var(--p-border-width-1) solid transparent; } - &:focus { + &:focus-visible { box-shadow: var(--p-shadow-button); outline: 0; - // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused'); } @@ -148,7 +147,7 @@ background: var(--p-surface-hovered); } - &:focus { + &:focus-visible { border: var(--p-border-width-1) solid var(--p-border); box-shadow: none; // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @@ -193,7 +192,7 @@ background: var(--p-surface-critical-subdued); } - &:focus { + &:focus-visible { border: var(--p-border-width-1) solid var(--p-border-critical); // stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY @include focus-ring($style: 'focused');