Skip to content

Commit

Permalink
Make social icon navigation one arrow keypress (#64883)
Browse files Browse the repository at this point in the history
By moving the blockProps for the social icon from the <li> to the <button>, we get the appropriate behavior of being able to select and create social icons with a clean keyboard behavior.
  • Loading branch information
jeryj authored Nov 18, 2024
1 parent d4d6d4c commit 2027fdb
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 26 deletions.
66 changes: 47 additions & 19 deletions packages/block-library/src/social-link/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import clsx from 'clsx';
/**
* WordPress dependencies
*/
import { DELETE, BACKSPACE } from '@wordpress/keycodes';
import { DELETE, BACKSPACE, ENTER } from '@wordpress/keycodes';
import { useDispatch } from '@wordpress/data';

import {
Expand All @@ -16,14 +16,15 @@ import {
useBlockProps,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { useState } from '@wordpress/element';
import { useState, useRef } from '@wordpress/element';
import {
Button,
PanelBody,
PanelRow,
TextControl,
__experimentalInputControlSuffixWrapper as InputControlSuffixWrapper,
} from '@wordpress/components';
import { useMergeRefs } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import { keyboardReturn } from '@wordpress/icons';

Expand Down Expand Up @@ -112,12 +113,19 @@ const SocialLinkEdit = ( {
iconBackgroundColorValue,
} = context;
const [ showURLPopover, setPopover ] = useState( false );
const classes = clsx( 'wp-social-link', 'wp-social-link-' + service, {
'wp-social-link__is-incomplete': ! url,
[ `has-${ iconColor }-color` ]: iconColor,
[ `has-${ iconBackgroundColor }-background-color` ]:
iconBackgroundColor,
} );
const wrapperClasses = clsx(
'wp-social-link',
// Manually adding this class for backwards compatibility of CSS when moving the
// blockProps from the li to the button: https://github.com/WordPress/gutenberg/pull/64883
'wp-block-social-link',
'wp-social-link-' + service,
{
'wp-social-link__is-incomplete': ! url,
[ `has-${ iconColor }-color` ]: iconColor,
[ `has-${ iconBackgroundColor }-background-color` ]:
iconBackgroundColor,
}
);

// Use internal state instead of a ref to make sure that the component
// re-renders when the popover's anchor updates.
Expand All @@ -131,11 +139,16 @@ const SocialLinkEdit = ( {
// spaces. The PHP render callback fallbacks to the social name as well.
const socialLinkText = label.trim() === '' ? socialLinkName : label;

const ref = useRef();
const blockProps = useBlockProps( {
className: classes,
style: {
color: iconColorValue,
backgroundColor: iconBackgroundColorValue,
className: 'wp-block-social-link-anchor',
ref: useMergeRefs( [ setPopoverAnchor, ref ] ),
onClick: () => setPopover( true ),
onKeyDown: ( event ) => {
if ( event.keyCode === ENTER ) {
event.preventDefault();
setPopover( true );
}
},
} );

Expand Down Expand Up @@ -169,13 +182,27 @@ const SocialLinkEdit = ( {
onChange={ ( value ) => setAttributes( { rel: value } ) }
/>
</InspectorControls>
<li { ...blockProps }>
<button
className="wp-block-social-link-anchor"
ref={ setPopoverAnchor }
onClick={ () => setPopover( true ) }
aria-haspopup="dialog"
>
{ /*
* Because the `<ul>` element has a role=document, the `<li>` is
* not semantically correct, so adding role=presentation is cleaner.
* https://github.com/WordPress/gutenberg/pull/64883#issuecomment-2472874551
*/ }
<li
role="presentation"
className={ wrapperClasses }
style={ {
color: iconColorValue,
backgroundColor: iconBackgroundColorValue,
} }
>
{ /*
* Disable reason: The `button` ARIA role is redundant but
* blockProps has a role of `document` automatically applied
* which breaks the semantics of this button since it removes
* the information about the popover.
*/
/* eslint-disable jsx-a11y/no-redundant-roles */ }
<button aria-haspopup="dialog" { ...blockProps } role="button">
<IconComponent />
<span
className={ clsx( 'wp-block-social-link-label', {
Expand All @@ -185,6 +212,7 @@ const SocialLinkEdit = ( {
{ socialLinkText }
</span>
</button>
{ /* eslint-enable jsx-a11y/no-redundant-roles */ }
{ isSelected && showURLPopover && (
<SocialLinkURLPopover
url={ url }
Expand Down
11 changes: 4 additions & 7 deletions packages/block-library/src/social-link/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@
// This rule is duplicated from the style.scss and needs to be the same as there.
padding: 0.25em;

// Focus styles replicate the `@wordpress/components` button component.
&:focus:not(:disabled) {
border-radius: 2px;
box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);

// Windows High Contrast mode will show this outline, but not the box-shadow.
outline: 3px solid transparent;
// Override the shared `.wp-block-social-link` class used on both the li and button
// due to backwards compatibility from moving the blockProps from the li to the button.
&:hover {
transform: none;
}
}

Expand Down

0 comments on commit 2027fdb

Please sign in to comment.