Skip to content

Commit

Permalink
Improve accessibility of the video track editor (#66832)
Browse files Browse the repository at this point in the history
* Do not wrap the track editor form within a navigable menu.

* Improve focus management.

* Make sure to reset the edit track UI.

* Move informative paragraph out of menu.

* Remove unnecessary fragment.

* Improve submit button labeling, position and variant.

* Remove unnecessary space and improve translators comment.

Co-authored-by: afercia <[email protected]>
Co-authored-by: ntsekouras <[email protected]>
  • Loading branch information
3 people authored Nov 20, 2024
1 parent b08c774 commit 41f5eb2
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 139 deletions.
9 changes: 9 additions & 0 deletions packages/block-library/src/video/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
max-width: 240px;
}

.block-library-video-tracks-editor__tracks-informative-message-title,
.block-library-video-tracks-editor__single-track-editor-edit-track-label {
margin-top: $grid-unit-05;
color: $gray-700;
Expand All @@ -56,3 +57,11 @@
padding: 0;
}
}

.block-library-video-tracks-editor__tracks-informative-message {
padding: $grid-unit-10;

&-description {
margin-bottom: 0;
}
}
296 changes: 157 additions & 139 deletions packages/block-library/src/video/tracks-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
} from '@wordpress/block-editor';
import { upload, media } from '@wordpress/icons';
import { useSelect } from '@wordpress/data';
import { useState } from '@wordpress/element';
import { useState, useRef, useEffect } from '@wordpress/element';
import { getFilename } from '@wordpress/url';

const ALLOWED_TYPES = [ 'text/vtt' ];
Expand All @@ -40,39 +40,29 @@ const KIND_OPTIONS = [
];

function TrackList( { tracks, onEditPress } ) {
let content;
if ( tracks.length === 0 ) {
content = (
<p className="block-library-video-tracks-editor__tracks-informative-message">
{ __(
'Tracks can be subtitles, captions, chapters, or descriptions. They help make your content more accessible to a wider range of users.'
) }
</p>
);
} else {
content = tracks.map( ( track, index ) => {
return (
<HStack
key={ index }
className="block-library-video-tracks-editor__track-list-track"
const content = tracks.map( ( track, index ) => {
return (
<HStack
key={ index }
className="block-library-video-tracks-editor__track-list-track"
>
<span>{ track.label }</span>
<Button
__next40pxDefaultSize
variant="tertiary"
onClick={ () => onEditPress( index ) }
aria-label={ sprintf(
/* translators: %s: Label of the video text track e.g: "French subtitles". */
_x( 'Edit %s', 'text tracks' ),
track.label
) }
>
<span>{ track.label } </span>
<Button
__next40pxDefaultSize
variant="tertiary"
onClick={ () => onEditPress( index ) }
aria-label={ sprintf(
/* translators: %s: Label of the video text track e.g: "French subtitles" */
_x( 'Edit %s', 'text tracks' ),
track.label
) }
>
{ __( 'Edit' ) }
</Button>
</HStack>
);
} );
}
{ __( 'Edit' ) }
</Button>
</HStack>
);
} );

return (
<MenuGroup
label={ __( 'Text tracks' ) }
Expand All @@ -87,105 +77,100 @@ function SingleTrackEditor( { track, onChange, onClose, onRemove } ) {
const { src = '', label = '', srcLang = '', kind = DEFAULT_KIND } = track;
const fileName = src.startsWith( 'blob:' ) ? '' : getFilename( src ) || '';
return (
<NavigableMenu>
<VStack
className="block-library-video-tracks-editor__single-track-editor"
spacing="4"
>
<span className="block-library-video-tracks-editor__single-track-editor-edit-track-label">
{ __( 'Edit track' ) }
</span>
<span>
{ __( 'File' ) }: <b>{ fileName }</b>
</span>
<Grid columns={ 2 } gap={ 4 }>
<TextControl
__next40pxDefaultSize
__nextHasNoMarginBottom
/* eslint-disable jsx-a11y/no-autofocus */
autoFocus
/* eslint-enable jsx-a11y/no-autofocus */
onChange={ ( newLabel ) =>
onChange( {
...track,
label: newLabel,
} )
}
label={ __( 'Label' ) }
value={ label }
help={ __( 'Title of track' ) }
/>
<TextControl
<VStack
className="block-library-video-tracks-editor__single-track-editor"
spacing="4"
>
<span className="block-library-video-tracks-editor__single-track-editor-edit-track-label">
{ __( 'Edit track' ) }
</span>
<span>
{ __( 'File' ) }: <b>{ fileName }</b>
</span>
<Grid columns={ 2 } gap={ 4 }>
<TextControl
__next40pxDefaultSize
__nextHasNoMarginBottom
onChange={ ( newLabel ) =>
onChange( {
...track,
label: newLabel,
} )
}
label={ __( 'Label' ) }
value={ label }
help={ __( 'Title of track' ) }
/>
<TextControl
__next40pxDefaultSize
__nextHasNoMarginBottom
onChange={ ( newSrcLang ) =>
onChange( {
...track,
srcLang: newSrcLang,
} )
}
label={ __( 'Source language' ) }
value={ srcLang }
help={ __( 'Language tag (en, fr, etc.)' ) }
/>
</Grid>
<VStack spacing="8">
<SelectControl
__next40pxDefaultSize
__nextHasNoMarginBottom
className="block-library-video-tracks-editor__single-track-editor-kind-select"
options={ KIND_OPTIONS }
value={ kind }
label={ __( 'Kind' ) }
onChange={ ( newKind ) => {
onChange( {
...track,
kind: newKind,
} );
} }
/>
<HStack className="block-library-video-tracks-editor__single-track-editor-buttons-container">
<Button
__next40pxDefaultSize
__nextHasNoMarginBottom
onChange={ ( newSrcLang ) =>
onChange( {
...track,
srcLang: newSrcLang,
} )
}
label={ __( 'Source language' ) }
value={ srcLang }
help={ __( 'Language tag (en, fr, etc.)' ) }
/>
</Grid>
<VStack spacing="8">
<SelectControl
isDestructive
variant="link"
onClick={ onRemove }
>
{ __( 'Remove track' ) }
</Button>
<Button
__next40pxDefaultSize
__nextHasNoMarginBottom
className="block-library-video-tracks-editor__single-track-editor-kind-select"
options={ KIND_OPTIONS }
value={ kind }
label={ __( 'Kind' ) }
onChange={ ( newKind ) => {
onChange( {
...track,
kind: newKind,
} );
variant="primary"
onClick={ () => {
const changes = {};
let hasChanges = false;
if ( label === '' ) {
changes.label = __( 'English' );
hasChanges = true;
}
if ( srcLang === '' ) {
changes.srcLang = 'en';
hasChanges = true;
}
if ( track.kind === undefined ) {
changes.kind = DEFAULT_KIND;
hasChanges = true;
}
if ( hasChanges ) {
onChange( {
...track,
...changes,
} );
}
onClose();
} }
/>
<HStack className="block-library-video-tracks-editor__single-track-editor-buttons-container">
<Button
__next40pxDefaultSize
variant="secondary"
onClick={ () => {
const changes = {};
let hasChanges = false;
if ( label === '' ) {
changes.label = __( 'English' );
hasChanges = true;
}
if ( srcLang === '' ) {
changes.srcLang = 'en';
hasChanges = true;
}
if ( track.kind === undefined ) {
changes.kind = DEFAULT_KIND;
hasChanges = true;
}
if ( hasChanges ) {
onChange( {
...track,
...changes,
} );
}
onClose();
} }
>
{ __( 'Close' ) }
</Button>
<Button
__next40pxDefaultSize
isDestructive
variant="link"
onClick={ onRemove }
>
{ __( 'Remove track' ) }
</Button>
</HStack>
</VStack>
>
{ __( 'Apply' ) }
</Button>
</HStack>
</VStack>
</NavigableMenu>
</VStack>
);
}

Expand All @@ -194,24 +179,44 @@ export default function TracksEditor( { tracks = [], onChange } ) {
return select( blockEditorStore ).getSettings().mediaUpload;
}, [] );
const [ trackBeingEdited, setTrackBeingEdited ] = useState( null );
const dropdownPopoverRef = useRef();

useEffect( () => {
dropdownPopoverRef.current?.focus();
}, [ trackBeingEdited ] );

if ( ! mediaUpload ) {
return null;
}
return (
<Dropdown
contentClassName="block-library-video-tracks-editor"
renderToggle={ ( { isOpen, onToggle } ) => (
<ToolbarGroup>
<ToolbarButton
aria-expanded={ isOpen }
aria-haspopup="true"
onClick={ onToggle }
>
{ __( 'Text tracks' ) }
</ToolbarButton>
</ToolbarGroup>
) }
focusOnMount
popoverProps={ {
ref: dropdownPopoverRef,
} }
renderToggle={ ( { isOpen, onToggle } ) => {
const handleOnToggle = () => {
if ( ! isOpen ) {
// When the Popover opens make sure the initial view is
// always the track list rather than the edit track UI.
setTrackBeingEdited( null );
}
onToggle();
};

return (
<ToolbarGroup>
<ToolbarButton
aria-expanded={ isOpen }
aria-haspopup="true"
onClick={ handleOnToggle }
>
{ __( 'Text tracks' ) }
</ToolbarButton>
</ToolbarGroup>
);
} }
renderContent={ () => {
if ( trackBeingEdited !== null ) {
return (
Expand All @@ -235,8 +240,21 @@ export default function TracksEditor( { tracks = [], onChange } ) {
/>
);
}

return (
<>
{ tracks.length === 0 && (
<div className="block-library-video-tracks-editor__tracks-informative-message">
<h2 className="block-library-video-tracks-editor__tracks-informative-message-title">
{ __( 'Text tracks' ) }
</h2>
<p className="block-library-video-tracks-editor__tracks-informative-message-description">
{ __(
'Tracks can be subtitles, captions, chapters, or descriptions. They help make your content more accessible to a wider range of users.'
) }
</p>
</div>
) }
<NavigableMenu>
<TrackList
tracks={ tracks }
Expand Down

1 comment on commit 41f5eb2

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 41f5eb2.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/11930771273
📝 Reported issues:

Please sign in to comment.