Skip to content

Commit

Permalink
Improve accessibility of the video track editor (WordPress#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 <afercia@git.wordpress.org>
Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>
  • 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

0 comments on commit 41f5eb2

Please sign in to comment.