Skip to content

Commit

Permalink
DropdownMenuV2: fix active and focus-visible item glitches (#64942)
Browse files Browse the repository at this point in the history
* Remove previous workaround

* Implement flushSync-based workaround

* Update CHANGELOG

---

Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>
Co-authored-by: diegohaz <hazdiego@git.wordpress.org>
  • Loading branch information
4 people authored Sep 2, 2024
1 parent a342589 commit 52832f5
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 15 deletions.
2 changes: 1 addition & 1 deletion packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

### Internal

- `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873)).
- `DropdownMenu` v2: fix flashing menu item styles when using keyboard ([#64873](https://github.com/WordPress/gutenberg/pull/64873), [#64942](https://github.com/WordPress/gutenberg/pull/64942)).
- `DropdownMenu` v2: refactor to overloaded naming convention ([#64654](https://github.com/WordPress/gutenberg/pull/64654)).
- `DropdownMenu` v2: add `GroupLabel` subcomponent ([#64854](https://github.com/WordPress/gutenberg/pull/64854)).
- `Composite` V2: fix Storybook docgen ([#64682](https://github.com/WordPress/gutenberg/pull/64682)).
Expand Down
6 changes: 5 additions & 1 deletion packages/components/src/dropdown-menu-v2/checkbox-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,24 @@ import type { WordPressComponentProps } from '../context';
import { DropdownMenuContext } from './context';
import type { DropdownMenuCheckboxItemProps } from './types';
import * as Styled from './styles';
import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix';

export const DropdownMenuCheckboxItem = forwardRef<
HTMLDivElement,
WordPressComponentProps< DropdownMenuCheckboxItemProps, 'div', false >
>( function DropdownMenuCheckboxItem(
{ suffix, children, hideOnClick = false, ...props },
{ suffix, children, onBlur, hideOnClick = false, ...props },
ref
) {
// TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed
const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } );
const dropdownMenuContext = useContext( DropdownMenuContext );

return (
<Styled.DropdownMenuCheckboxItem
ref={ ref }
{ ...props }
{ ...focusVisibleFixProps }
accessibleWhenDisabled
hideOnClick={ hideOnClick }
store={ dropdownMenuContext?.store }
Expand Down
6 changes: 5 additions & 1 deletion packages/components/src/dropdown-menu-v2/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,24 @@ import type { WordPressComponentProps } from '../context';
import type { DropdownMenuItemProps } from './types';
import * as Styled from './styles';
import { DropdownMenuContext } from './context';
import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix';

export const DropdownMenuItem = forwardRef<
HTMLDivElement,
WordPressComponentProps< DropdownMenuItemProps, 'div', false >
>( function DropdownMenuItem(
{ prefix, suffix, children, hideOnClick = true, ...props },
{ prefix, suffix, children, onBlur, hideOnClick = true, ...props },
ref
) {
// TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed
const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } );
const dropdownMenuContext = useContext( DropdownMenuContext );

return (
<Styled.DropdownMenuItem
ref={ ref }
{ ...props }
{ ...focusVisibleFixProps }
accessibleWhenDisabled
hideOnClick={ hideOnClick }
store={ dropdownMenuContext?.store }
Expand Down
6 changes: 5 additions & 1 deletion packages/components/src/dropdown-menu-v2/radio-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { DropdownMenuContext } from './context';
import type { DropdownMenuRadioItemProps } from './types';
import * as Styled from './styles';
import { SVG, Circle } from '@wordpress/primitives';
import { useTemporaryFocusVisibleFix } from './use-temporary-focus-visible-fix';

const radioCheck = (
<SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
Expand All @@ -28,15 +29,18 @@ export const DropdownMenuRadioItem = forwardRef<
HTMLDivElement,
WordPressComponentProps< DropdownMenuRadioItemProps, 'div', false >
>( function DropdownMenuRadioItem(
{ suffix, children, hideOnClick = false, ...props },
{ suffix, children, onBlur, hideOnClick = false, ...props },
ref
) {
// TODO: Remove when https://github.com/ariakit/ariakit/issues/4083 is fixed
const focusVisibleFixProps = useTemporaryFocusVisibleFix( { onBlur } );
const dropdownMenuContext = useContext( DropdownMenuContext );

return (
<Styled.DropdownMenuRadioItem
ref={ ref }
{ ...props }
{ ...focusVisibleFixProps }
accessibleWhenDisabled
hideOnClick={ hideOnClick }
store={ dropdownMenuContext?.store }
Expand Down
15 changes: 4 additions & 11 deletions packages/components/src/dropdown-menu-v2/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,23 +171,16 @@ const baseItem = css`
cursor: not-allowed;
}
/* Active item (including hover)
* Note: we should be able to remove :focus-visible once
* https://github.com/ariakit/ariakit/issues/4083 is fixed and released
*/
&[data-active-item]:not( [data-focus-visible] ):not( :focus-visible ):not(
/* Active item (including hover) */
&[data-active-item]:not( [data-focus-visible] ):not(
[aria-disabled='true']
) {
background-color: ${ COLORS.theme.accent };
color: ${ COLORS.white };
}
/* Keyboard focus (focus-visible)
* Note: we should be able to remove :focus-visible once
* https://github.com/ariakit/ariakit/issues/4083 is fixed and released
*/
&[data-focus-visible],
&:focus-visible {
/* Keyboard focus (focus-visible) */
&[data-focus-visible] {
box-shadow: 0 0 0 1.5px ${ COLORS.theme.accent };
/* Only visible in Windows High Contrast mode */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* WordPress dependencies
*/
import { useState, flushSync } from '@wordpress/element';

export function useTemporaryFocusVisibleFix( {
onBlur: onBlurProp,
}: {
onBlur?: React.FocusEventHandler< HTMLDivElement >;
} ) {
const [ focusVisible, setFocusVisible ] = useState( false );
return {
'data-focus-visible': focusVisible || undefined,
onFocusVisible: () => {
flushSync( () => setFocusVisible( true ) );
},
onBlur: ( ( event ) => {
onBlurProp?.( event );
setFocusVisible( false );
} ) as React.FocusEventHandler< HTMLDivElement >,
};
}

0 comments on commit 52832f5

Please sign in to comment.