Move through svg icons and add aria labels
This commit is contained in:
parent
8bf4008c51
commit
cee22c3277
28 changed files with 194 additions and 101 deletions
|
@ -228,11 +228,11 @@ class Nav extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<ul className="nav__items-left">
|
<ul className="nav__items-left">
|
||||||
<li className="nav__item-logo">
|
<li className="nav__item-logo">
|
||||||
<LogoIcon title="p5.js Logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__item nav__item--no-icon">
|
<li className="nav__item nav__item--no-icon">
|
||||||
<Link to="/" className="nav__back-link">
|
<Link to="/" className="nav__back-link">
|
||||||
<CaretLeftIcon className="nav__back-icon" />
|
<CaretLeftIcon className="nav__back-icon" focusable="false" aria-hidden="true" />
|
||||||
<span className="nav__item-header">
|
<span className="nav__item-header">
|
||||||
Back to Editor
|
Back to Editor
|
||||||
</span>
|
</span>
|
||||||
|
@ -246,7 +246,7 @@ class Nav extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<ul className="nav__items-left">
|
<ul className="nav__items-left">
|
||||||
<li className="nav__item-logo">
|
<li className="nav__item-logo">
|
||||||
<LogoIcon title="p5.js Logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</li>
|
</li>
|
||||||
<li className={navDropdownState.file}>
|
<li className={navDropdownState.file}>
|
||||||
<button
|
<button
|
||||||
|
@ -260,7 +260,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">File</span>
|
<span className="nav__item-header">File</span>
|
||||||
<TriangleIcon className="nav__item-header-triangle" />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -362,7 +362,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Edit</span>
|
<span className="nav__item-header">Edit</span>
|
||||||
<TriangleIcon className="nav__item-header-triangle" />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown" >
|
<ul className="nav__dropdown" >
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -422,7 +422,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Sketch</span>
|
<span className="nav__item-header">Sketch</span>
|
||||||
<TriangleIcon className="nav__item-header-triangle" />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -497,7 +497,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Help</span>
|
<span className="nav__item-header">Help</span>
|
||||||
<TriangleIcon className="nav__item-header-triangle" />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -574,7 +574,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
My Account
|
My Account
|
||||||
<TriangleIcon className="nav__item-header-triangle" />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
|
|
@ -14,13 +14,13 @@ class NavBasic extends React.PureComponent {
|
||||||
<nav className="nav" title="main-navigation" ref={(node) => { this.node = node; }}>
|
<nav className="nav" title="main-navigation" ref={(node) => { this.node = node; }}>
|
||||||
<ul className="nav__items-left">
|
<ul className="nav__items-left">
|
||||||
<li className="nav__item-logo">
|
<li className="nav__item-logo">
|
||||||
<LogoIcon title="p5.js Logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</li>
|
</li>
|
||||||
{ this.props.onBack && (
|
{ this.props.onBack && (
|
||||||
<li className="nav__item">
|
<li className="nav__item">
|
||||||
<button onClick={this.props.onBack}>
|
<button onClick={this.props.onBack}>
|
||||||
<span className="nav__item-header">
|
<span className="nav__item-header">
|
||||||
<ArrowIcon title="Left arrow" />
|
<ArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
Back to the editor
|
Back to the editor
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -9,15 +9,15 @@ const PreviewNav = ({ owner, project }) => (
|
||||||
<nav className="nav preview-nav">
|
<nav className="nav preview-nav">
|
||||||
<div className="nav__items-left">
|
<div className="nav__items-left">
|
||||||
<div className="nav__item-logo">
|
<div className="nav__item-logo">
|
||||||
<LogoIcon title="p5.js Logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</div>
|
</div>
|
||||||
<Link className="nav__item" to={`/${owner.username}/sketches/${project.id}`}>{project.name}</Link>
|
<Link className="nav__item" to={`/${owner.username}/sketches/${project.id}`}>{project.name}</Link>
|
||||||
<p className="toolbar__project-owner">by</p>
|
<p className="toolbar__project-owner">by</p>
|
||||||
<Link className="nav__item" to={`/${owner.username}/sketches/`}>{owner.username}</Link>
|
<Link className="nav__item" to={`/${owner.username}/sketches/`}>{owner.username}</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="nav__items-right">
|
<div className="nav__items-right">
|
||||||
<Link to={`/${owner.username}/sketches/${project.id}`}>
|
<Link to={`/${owner.username}/sketches/${project.id}`} aria-label="Edit Sketch" >
|
||||||
<CodeIcon className="preview-nav__editor-svg" />
|
<CodeIcon className="preview-nav__editor-svg" focusable="false" aria-hidden="true" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -80,8 +80,8 @@ class Overlay extends React.Component {
|
||||||
<h2 className="overlay__title">{title}</h2>
|
<h2 className="overlay__title">{title}</h2>
|
||||||
<div className="overlay__actions">
|
<div className="overlay__actions">
|
||||||
{actions}
|
{actions}
|
||||||
<button className="overlay__close-button" onClick={this.close} >
|
<button className="overlay__close-button" onClick={this.close} aria-label={`Close ${title} overlay`} >
|
||||||
<ExitIcon title="close overlay" />
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -12,7 +12,7 @@ function About(props) {
|
||||||
<title>p5.js Web Editor | About</title>
|
<title>p5.js Web Editor | About</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="about__content-column">
|
<div className="about__content-column">
|
||||||
<SquareLogoIcon className="about__logo" title="p5.js Square Logo" />
|
<SquareLogoIcon className="about__logo" role="img" aria-label="p5.js Logo" focusable="false" />
|
||||||
{/* Video button to hello p5 video page */}
|
{/* Video button to hello p5 video page */}
|
||||||
{/* <p className="about__play-video">
|
{/* <p className="about__play-video">
|
||||||
<a
|
<a
|
||||||
|
@ -32,7 +32,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<AsteriskIcon className="about__content-column-asterisk" title="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Examples
|
Examples
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -42,7 +42,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<AsteriskIcon className="about__content-column-asterisk" title="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Learn
|
Learn
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -55,7 +55,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<AsteriskIcon className="about__content-column-asterisk" title="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Libraries
|
Libraries
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -65,7 +65,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<AsteriskIcon className="about__content-column-asterisk" title="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Reference
|
Reference
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -75,7 +75,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<AsteriskIcon className="about__content-column-asterisk" title="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Forum
|
Forum
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -85,8 +85,9 @@ class AssetListRowBase extends React.Component {
|
||||||
onClick={this.toggleOptions}
|
onClick={this.toggleOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
|
aria-label="Toggle Open/Close Asset Options"
|
||||||
>
|
>
|
||||||
<DownFilledTriangleIcon title="Menu" />
|
<DownFilledTriangleIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
{optionsOpen &&
|
{optionsOpen &&
|
||||||
<ul
|
<ul
|
||||||
|
|
|
@ -82,21 +82,43 @@ class CollectionList extends React.Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getButtonLabel = (fieldName, displayName) => {
|
||||||
|
const { field, direction } = this.props.sorting;
|
||||||
|
let buttonLabel;
|
||||||
|
if (field !== fieldName) {
|
||||||
|
if (field === 'name') {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
}
|
||||||
|
} else if (direction === SortingActions.DIRECTION.ASC) {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
}
|
||||||
|
return buttonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
_renderFieldHeader = (fieldName, displayName) => {
|
_renderFieldHeader = (fieldName, displayName) => {
|
||||||
const { field, direction } = this.props.sorting;
|
const { field, direction } = this.props.sorting;
|
||||||
const headerClass = classNames({
|
const headerClass = classNames({
|
||||||
'sketches-table__header': true,
|
'sketches-table__header': true,
|
||||||
'sketches-table__header--selected': field === fieldName
|
'sketches-table__header--selected': field === fieldName
|
||||||
});
|
});
|
||||||
|
const buttonLabel = this._getButtonLabel(fieldName, displayName);
|
||||||
return (
|
return (
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
<button className="sketch-list__sort-button" onClick={() => this.props.toggleDirectionForField(fieldName)}>
|
<button
|
||||||
|
className="sketch-list__sort-button"
|
||||||
|
onClick={() => this.props.toggleDirectionForField(fieldName)}
|
||||||
|
aria-label={buttonLabel}
|
||||||
|
>
|
||||||
<span className={headerClass}>{displayName}</span>
|
<span className={headerClass}>{displayName}</span>
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
||||||
<ArrowUpIcon />
|
<ArrowUpIcon role="img" aria-label="Ascending" focusable="false" />
|
||||||
}
|
}
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
||||||
<ArrowDownIcon />
|
<ArrowDownIcon role="img" aria-label="Descending" focusable="false" />
|
||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
|
|
|
@ -128,6 +128,7 @@ class CollectionListRowBase extends React.Component {
|
||||||
onClick={this.toggleOptions}
|
onClick={this.toggleOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
|
aria-label="Toggle Open/Close collection options"
|
||||||
>
|
>
|
||||||
<DownFilledTriangleIcon title="Menu" />
|
<DownFilledTriangleIcon title="Menu" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -90,18 +90,18 @@ class Console extends React.Component {
|
||||||
<div className="preview-console__header">
|
<div className="preview-console__header">
|
||||||
<h2 className="preview-console__header-title">Console</h2>
|
<h2 className="preview-console__header-title">Console</h2>
|
||||||
<div className="preview-console__header-buttons">
|
<div className="preview-console__header-buttons">
|
||||||
<button className="preview-console__clear" onClick={this.props.clearConsole} aria-label="clear console">
|
<button className="preview-console__clear" onClick={this.props.clearConsole} aria-label="Clear console">
|
||||||
Clear
|
Clear
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="preview-console__collapse"
|
className="preview-console__collapse"
|
||||||
onClick={this.props.collapseConsole}
|
onClick={this.props.collapseConsole}
|
||||||
aria-label="collapse console"
|
aria-label="Close console"
|
||||||
>
|
>
|
||||||
<DownArrowIcon />
|
<DownArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button className="preview-console__expand" onClick={this.props.expandConsole} aria-label="expand console">
|
<button className="preview-console__expand" onClick={this.props.expandConsole} aria-label="Open console" >
|
||||||
<UpArrowIcon />
|
<UpArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -69,8 +69,9 @@ class CopyableInput extends React.Component {
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
href={value}
|
href={value}
|
||||||
className="copyable-input__preview"
|
className="copyable-input__preview"
|
||||||
|
aria-label={`Open ${label} view in new tab`}
|
||||||
>
|
>
|
||||||
<ShareIcon title={`open ${label} view in new tab`} />
|
<ShareIcon focusable="false" aria-hidden="true" />
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||||
|
|
||||||
import EditIcon from '../../../images/pencil.svg';
|
import EditIcon from '../../../images/pencil.svg';
|
||||||
|
|
||||||
|
// TODO I think this needs a description prop so that it's accessible
|
||||||
function EditableInput({
|
function EditableInput({
|
||||||
validate, value, emptyPlaceholder, InputComponent, inputProps, onChange
|
validate, value, emptyPlaceholder, InputComponent, inputProps, onChange
|
||||||
}) {
|
}) {
|
||||||
|
@ -47,9 +48,13 @@ function EditableInput({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={classes}>
|
<span className={classes}>
|
||||||
<button className="editable-input__label" onClick={beginEditing}>
|
<button
|
||||||
|
className="editable-input__label"
|
||||||
|
onClick={beginEditing}
|
||||||
|
aria-label={`Edit ${displayValue} value`}
|
||||||
|
>
|
||||||
<span>{displayValue}</span>
|
<span>{displayValue}</span>
|
||||||
<EditIcon className="editable-input__icon" />
|
<EditIcon className="editable-input__icon" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<InputComponent
|
<InputComponent
|
||||||
|
|
|
@ -320,24 +320,26 @@ class Editor extends React.Component {
|
||||||
>
|
>
|
||||||
<header className="editor__header">
|
<header className="editor__header">
|
||||||
<button
|
<button
|
||||||
aria-label="collapse file navigation"
|
aria-label="Open Sketch files navigation"
|
||||||
className="sidebar__contract"
|
className="sidebar__contract"
|
||||||
onClick={this.props.collapseSidebar}
|
onClick={this.props.collapseSidebar}
|
||||||
>
|
>
|
||||||
<LeftArrowIcon />
|
<LeftArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-label="expand file navigation"
|
aria-label="Close sketch files navigation"
|
||||||
className="sidebar__expand"
|
className="sidebar__expand"
|
||||||
onClick={this.props.expandSidebar}
|
onClick={this.props.expandSidebar}
|
||||||
>
|
>
|
||||||
<RightArrowIcon />
|
<RightArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<div className="editor__file-name">
|
<div className="editor__file-name">
|
||||||
<span>
|
<span>
|
||||||
{this.props.file.name}
|
{this.props.file.name}
|
||||||
<span className="editor__unsaved-changes">
|
<span className="editor__unsaved-changes">
|
||||||
{this.props.unsavedChanges ? <UnsavedChangesDotIcon /> : null}
|
{this.props.unsavedChanges ?
|
||||||
|
<UnsavedChangesDotIcon role="img" aria-label="Sketch has unsaved changes" focusable="false" /> :
|
||||||
|
null}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<Timer
|
<Timer
|
||||||
|
|
|
@ -23,7 +23,7 @@ function Feedback(props) {
|
||||||
className="feedback__github-link"
|
className="feedback__github-link"
|
||||||
>
|
>
|
||||||
Go to Github
|
Go to Github
|
||||||
<GitHubLogo className="feedback__github-logo" />
|
<GitHubLogo className="feedback__github-logo" focusable="false" aria-hidden="true" />
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -184,7 +184,7 @@ export class FileNode extends React.Component {
|
||||||
<span className="file-item__spacer"></span>
|
<span className="file-item__spacer"></span>
|
||||||
{ isFile &&
|
{ isFile &&
|
||||||
<span className="sidebar__file-item-icon">
|
<span className="sidebar__file-item-icon">
|
||||||
<FileIcon />
|
<FileIcon focusable="false" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
{ isFolder &&
|
{ isFolder &&
|
||||||
|
@ -192,14 +192,16 @@ export class FileNode extends React.Component {
|
||||||
<button
|
<button
|
||||||
className="sidebar__file-item-closed"
|
className="sidebar__file-item-closed"
|
||||||
onClick={this.showFolderChildren}
|
onClick={this.showFolderChildren}
|
||||||
|
aria-label="Open folder contents"
|
||||||
>
|
>
|
||||||
<FolderRightIcon className="folder-right" />
|
<FolderRightIcon className="folder-right" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="sidebar__file-item-open"
|
className="sidebar__file-item-open"
|
||||||
onClick={this.hideFolderChildren}
|
onClick={this.hideFolderChildren}
|
||||||
|
aria-label="Close file contents"
|
||||||
>
|
>
|
||||||
<FolderDownIcon className="folder-down" />
|
<FolderDownIcon className="folder-down" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -221,14 +223,14 @@ export class FileNode extends React.Component {
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="sidebar__file-item-show-options"
|
className="sidebar__file-item-show-options"
|
||||||
aria-label="view file options"
|
aria-label="Toggle open/close file options"
|
||||||
ref={(element) => { this[`fileOptions-${this.props.id}`] = element; }}
|
ref={(element) => { this[`fileOptions-${this.props.id}`] = element; }}
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
onClick={this.toggleFileOptions}
|
onClick={this.toggleFileOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
>
|
>
|
||||||
<DownArrowIcon />
|
<DownArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<div className="sidebar__file-item-options">
|
<div className="sidebar__file-item-options">
|
||||||
<ul title="file options">
|
<ul title="file options">
|
||||||
|
|
|
@ -34,8 +34,12 @@ class NewFileModal extends React.Component {
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<h2 className="modal__title">Create File</h2>
|
<h2 className="modal__title">Create File</h2>
|
||||||
<button className="modal__exit-button" onClick={this.props.closeNewFileModal}>
|
<button
|
||||||
<ExitIcon title="Close New File Modal" />
|
className="modal__exit-button"
|
||||||
|
onClick={this.props.closeNewFileModal}
|
||||||
|
aria-label="Close New File Modal"
|
||||||
|
>
|
||||||
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<NewFileForm
|
<NewFileForm
|
||||||
|
|
|
@ -16,8 +16,12 @@ class NewFolderModal extends React.Component {
|
||||||
<div className="modal-content-folder">
|
<div className="modal-content-folder">
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<h2 className="modal__title">Create Folder</h2>
|
<h2 className="modal__title">Create Folder</h2>
|
||||||
<button className="modal__exit-button" onClick={this.props.closeModal}>
|
<button
|
||||||
<ExitIcon title="Close New Folder Modal" />
|
className="modal__exit-button"
|
||||||
|
onClick={this.props.closeModal}
|
||||||
|
aria-label="Close New Folder Modal"
|
||||||
|
>
|
||||||
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<NewFolderForm {...this.props} />
|
<NewFolderForm {...this.props} />
|
||||||
|
|
|
@ -149,7 +149,7 @@ class Preferences extends React.Component {
|
||||||
aria-label="decrease font size"
|
aria-label="decrease font size"
|
||||||
disabled={this.state.fontSize <= 8}
|
disabled={this.state.fontSize <= 8}
|
||||||
>
|
>
|
||||||
<MinusIcon title="Decrease Font Size" />
|
<MinusIcon focusable="false" aria-hidden="true" />
|
||||||
<h6 className="preference__label">Decrease</h6>
|
<h6 className="preference__label">Decrease</h6>
|
||||||
</button>
|
</button>
|
||||||
<form onSubmit={this.onFontInputSubmit}>
|
<form onSubmit={this.onFontInputSubmit}>
|
||||||
|
@ -170,7 +170,7 @@ class Preferences extends React.Component {
|
||||||
aria-label="increase font size"
|
aria-label="increase font size"
|
||||||
disabled={this.state.fontSize >= 36}
|
disabled={this.state.fontSize >= 36}
|
||||||
>
|
>
|
||||||
<PlusIcon title="Increase Font Size" />
|
<PlusIcon focusable="false" aria-hidden="true" />
|
||||||
<h6 className="preference__label">Increase</h6>
|
<h6 className="preference__label">Increase</h6>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,9 +12,9 @@ const Icons = ({ isAdded }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<CloseIcon className="quick-add__remove-icon" title="Remove from collection" />
|
<CloseIcon className="quick-add__remove-icon" role="img" aria-label="Descending" focusable="false" />
|
||||||
<CheckIcon className="quick-add__in-icon" title="In collection" />
|
<CheckIcon className="quick-add__in-icon" role="img" aria-label="Descending" focusable="false" />
|
||||||
<CloseIcon className="quick-add__add-icon" title="Add to collection" />
|
<CloseIcon className="quick-add__add-icon" role="img" aria-label="Descending" focusable="false" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,9 +6,11 @@ import Icons from './Icons';
|
||||||
|
|
||||||
const Item = ({
|
const Item = ({
|
||||||
isAdded, onSelect, name, url
|
isAdded, onSelect, name, url
|
||||||
}) => (
|
}) => {
|
||||||
|
const buttonLabel = isAdded ? 'Remove from collection' : 'Add to collection';
|
||||||
|
return (
|
||||||
<li className="quick-add__item" onClick={onSelect}> { /* eslint-disable-line */ }
|
<li className="quick-add__item" onClick={onSelect}> { /* eslint-disable-line */ }
|
||||||
<button className="quick-add__item-toggle" onClick={onSelect}>
|
<button className="quick-add__item-toggle" onClick={onSelect} aria-label={buttonLabel}>
|
||||||
<Icons isAdded={isAdded} />
|
<Icons isAdded={isAdded} />
|
||||||
</button>
|
</button>
|
||||||
<span className="quick-add__item-name">{name}</span>
|
<span className="quick-add__item-name">{name}</span>
|
||||||
|
@ -22,6 +24,7 @@ const Item = ({
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const ItemType = PropTypes.shape({
|
const ItemType = PropTypes.shape({
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Searchbar extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className={`searchbar ${searchValue === '' ? 'searchbar--is-empty' : ''}`}>
|
<div className={`searchbar ${searchValue === '' ? 'searchbar--is-empty' : ''}`}>
|
||||||
<div className="searchbar__button">
|
<div className="searchbar__button">
|
||||||
<SearchIcon className="searchbar__icon" />
|
<SearchIcon className="searchbar__icon" focusable="false" aria-hidden="true" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
className="searchbar__input"
|
className="searchbar__input"
|
||||||
|
|
|
@ -75,7 +75,7 @@ class Sidebar extends React.Component {
|
||||||
</h3>
|
</h3>
|
||||||
<div className="sidebar__icons">
|
<div className="sidebar__icons">
|
||||||
<button
|
<button
|
||||||
aria-label="add file or folder"
|
aria-label="Toggle open/close sketch file options"
|
||||||
className="sidebar__add"
|
className="sidebar__add"
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
ref={(element) => { this.sidebarOptions = element; }}
|
ref={(element) => { this.sidebarOptions = element; }}
|
||||||
|
@ -83,7 +83,7 @@ class Sidebar extends React.Component {
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
>
|
>
|
||||||
<DownArrowIcon />
|
<DownArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="sidebar__project-options">
|
<ul className="sidebar__project-options">
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -167,8 +167,9 @@ class SketchListRowBase extends React.Component {
|
||||||
onClick={this.toggleOptions}
|
onClick={this.toggleOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
|
aria-label="Toggle Open/Close Sketch Options"
|
||||||
>
|
>
|
||||||
<DownFilledTriangleIcon title="Menu" />
|
<DownFilledTriangleIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
{optionsOpen &&
|
{optionsOpen &&
|
||||||
<ul
|
<ul
|
||||||
|
@ -325,7 +326,6 @@ class SketchList extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
this.props.getProjects(this.props.username);
|
this.props.getProjects(this.props.username);
|
||||||
this.props.resetSorting();
|
this.props.resetSorting();
|
||||||
this._renderFieldHeader = this._renderFieldHeader.bind(this);
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isInitialDataLoad: true,
|
isInitialDataLoad: true,
|
||||||
|
@ -368,21 +368,43 @@ class SketchList extends React.Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderFieldHeader(fieldName, displayName) {
|
_getButtonLabel = (fieldName, displayName) => {
|
||||||
|
const { field, direction } = this.props.sorting;
|
||||||
|
let buttonLabel;
|
||||||
|
if (field !== fieldName) {
|
||||||
|
if (field === 'name') {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
}
|
||||||
|
} else if (direction === SortingActions.DIRECTION.ASC) {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
}
|
||||||
|
return buttonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderFieldHeader = (fieldName, displayName) => {
|
||||||
const { field, direction } = this.props.sorting;
|
const { field, direction } = this.props.sorting;
|
||||||
const headerClass = classNames({
|
const headerClass = classNames({
|
||||||
'sketches-table__header': true,
|
'sketches-table__header': true,
|
||||||
'sketches-table__header--selected': field === fieldName
|
'sketches-table__header--selected': field === fieldName
|
||||||
});
|
});
|
||||||
|
const buttonLabel = this._getButtonLabel(fieldName, displayName);
|
||||||
return (
|
return (
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
<button className="sketch-list__sort-button" onClick={() => this.props.toggleDirectionForField(fieldName)}>
|
<button
|
||||||
|
className="sketch-list__sort-button"
|
||||||
|
onClick={() => this.props.toggleDirectionForField(fieldName)}
|
||||||
|
aria-label={buttonLabel}
|
||||||
|
>
|
||||||
<span className={headerClass}>{displayName}</span>
|
<span className={headerClass}>{displayName}</span>
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
||||||
<ArrowUpIcon />
|
<ArrowUpIcon role="img" aria-label="Ascending" focusable="false" />
|
||||||
}
|
}
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
||||||
<ArrowDownIcon />
|
<ArrowDownIcon role="img" aria-label="Descending" focusable="false" />
|
||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
|
|
|
@ -12,8 +12,8 @@ function Toast(props) {
|
||||||
<p>
|
<p>
|
||||||
{props.text}
|
{props.text}
|
||||||
</p>
|
</p>
|
||||||
<button className="toast__close" onClick={props.hideToast}>
|
<button className="toast__close" onClick={props.hideToast} aria-label="Close Alert" >
|
||||||
<ExitIcon title="Close Keyboard Shortcuts Overlay" />
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -59,6 +59,8 @@ class Toolbar extends React.Component {
|
||||||
'toolbar__project-name-container--editing': this.props.project.isEditingName
|
'toolbar__project-name-container--editing': this.props.project.isEditingName
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const canEditProjectName = this.canEditProjectName();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="toolbar">
|
<div className="toolbar">
|
||||||
<button
|
<button
|
||||||
|
@ -68,25 +70,25 @@ class Toolbar extends React.Component {
|
||||||
this.props.setTextOutput(true);
|
this.props.setTextOutput(true);
|
||||||
this.props.setGridOutput(true);
|
this.props.setGridOutput(true);
|
||||||
}}
|
}}
|
||||||
aria-label="play sketch"
|
aria-label="Play sketch"
|
||||||
disabled={this.props.infiniteLoop}
|
disabled={this.props.infiniteLoop}
|
||||||
>
|
>
|
||||||
<PlayIcon title="Play Sketch" />
|
<PlayIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={playButtonClass}
|
className={playButtonClass}
|
||||||
onClick={this.props.startSketch}
|
onClick={this.props.startSketch}
|
||||||
aria-label="play only visual sketch"
|
aria-label="Play only visual sketch"
|
||||||
disabled={this.props.infiniteLoop}
|
disabled={this.props.infiniteLoop}
|
||||||
>
|
>
|
||||||
<PlayIcon title="Play only visual Sketch" />
|
<PlayIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={stopButtonClass}
|
className={stopButtonClass}
|
||||||
onClick={this.props.stopSketch}
|
onClick={this.props.stopSketch}
|
||||||
aria-label="stop sketch"
|
aria-label="Stop sketch"
|
||||||
>
|
>
|
||||||
<StopIcon alt="Stop Sketch" />
|
<StopIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<div className="toolbar__autorefresh">
|
<div className="toolbar__autorefresh">
|
||||||
<input
|
<input
|
||||||
|
@ -102,24 +104,28 @@ class Toolbar extends React.Component {
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={nameContainerClass}>
|
<div className={nameContainerClass}>
|
||||||
<a
|
<button
|
||||||
className="toolbar__project-name"
|
className="toolbar__project-name"
|
||||||
href={this.props.owner ? `/${this.props.owner.username}/sketches/${this.props.project.id}` : ''}
|
onClick={() => {
|
||||||
onClick={(e) => {
|
if (canEditProjectName) {
|
||||||
if (this.canEditProjectName()) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.originalProjectName = this.props.project.name;
|
this.originalProjectName = this.props.project.name;
|
||||||
this.props.showEditProjectName();
|
this.props.showEditProjectName();
|
||||||
setTimeout(() => this.projectNameInput.focus(), 0);
|
setTimeout(() => this.projectNameInput.focus(), 0);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
disabled={!canEditProjectName}
|
||||||
|
aria-label="Edit sketch name"
|
||||||
>
|
>
|
||||||
<span>{this.props.project.name}</span>
|
<span>{this.props.project.name}</span>
|
||||||
{
|
{
|
||||||
this.canEditProjectName() &&
|
canEditProjectName &&
|
||||||
<EditProjectNameIcon className="toolbar__edit-name-button" title="Edit Project Name" />
|
<EditProjectNameIcon
|
||||||
|
className="toolbar__edit-name-button"
|
||||||
|
focusable="false"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</a>
|
</button>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
maxLength="128"
|
maxLength="128"
|
||||||
|
@ -149,9 +155,9 @@ class Toolbar extends React.Component {
|
||||||
<button
|
<button
|
||||||
className={preferencesButtonClass}
|
className={preferencesButtonClass}
|
||||||
onClick={this.props.openPreferences}
|
onClick={this.props.openPreferences}
|
||||||
aria-label="preferences"
|
aria-label="Open Preferences"
|
||||||
>
|
>
|
||||||
<PreferencesIcon role="img" />
|
<PreferencesIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,8 +32,12 @@ class UploadFileModal extends React.Component {
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<h2 className="modal__title">Upload File</h2>
|
<h2 className="modal__title">Upload File</h2>
|
||||||
<button className="modal__exit-button" onClick={this.props.closeModal}>
|
<button
|
||||||
<ExitIcon title="Close New File Modal" />
|
className="modal__exit-button"
|
||||||
|
onClick={this.props.closeModal}
|
||||||
|
aria-label="Close upload file modal"
|
||||||
|
>
|
||||||
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{ this.props.reachedTotalSizeLimit &&
|
{ this.props.reachedTotalSizeLimit &&
|
||||||
|
|
|
@ -85,7 +85,7 @@ class APIKeyForm extends React.Component {
|
||||||
disabled={this.state.keyLabel === ''}
|
disabled={this.state.keyLabel === ''}
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
<PlusIcon className="api-key-form__create-icon" />
|
<PlusIcon className="api-key-form__create-icon" focusable="false" aria-hidden="true" />
|
||||||
Create
|
Create
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -31,8 +31,12 @@ function APIKeyList({ apiKeys, onRemove }) {
|
||||||
<td>{format(new Date(key.createdAt), 'MMM D, YYYY h:mm A')}</td>
|
<td>{format(new Date(key.createdAt), 'MMM D, YYYY h:mm A')}</td>
|
||||||
<td>{lastUsed}</td>
|
<td>{lastUsed}</td>
|
||||||
<td className="api-key-list__action">
|
<td className="api-key-list__action">
|
||||||
<button className="api-key-list__delete-button" onClick={() => onRemove(key)}>
|
<button
|
||||||
<TrashCanIcon title="Delete Key" />
|
className="api-key-list__delete-button"
|
||||||
|
onClick={() => onRemove(key)}
|
||||||
|
aria-label="Delete API Key"
|
||||||
|
>
|
||||||
|
<TrashCanIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -96,3 +96,15 @@ textarea:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 0 1px $outline-color;
|
box-shadow: 0 0 0 1px $outline-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// screen reader only class
|
||||||
|
// from https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html#hiding-content-visually
|
||||||
|
.sr-only:not(:focus):not(:active) {
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
clip-path: inset(50%);
|
||||||
|
height: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue