fix(a11y): fix a11y warning in alert, and other a11y fixes (#3237)

* fix(a11y): fix a11y warning in alert, and other a11y fixes

* chore: correct import

* chore: use `class`
This commit is contained in:
David Wheatley 2021-12-28 21:08:34 +01:00 committed by GitHub
parent 0e9c169e06
commit 993500aae4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 13 deletions

View File

@ -3,6 +3,8 @@ import Button from './Button';
import listItems from '../helpers/listItems'; import listItems from '../helpers/listItems';
import extract from '../utils/extract'; import extract from '../utils/extract';
import type Mithril from 'mithril'; import type Mithril from 'mithril';
import classList from '../utils/classList';
import app from '../app';
export interface AlertAttrs extends ComponentAttrs { export interface AlertAttrs extends ComponentAttrs {
/** The type of alert this is. Will be used to give the alert a class name of `Alert--{type}`. */ /** The type of alert this is. Will be used to give the alert a class name of `Alert--{type}`. */
@ -24,7 +26,7 @@ export default class Alert<T extends AlertAttrs = AlertAttrs> extends Component<
const attrs = Object.assign({}, this.attrs); const attrs = Object.assign({}, this.attrs);
const type = extract(attrs, 'type'); const type = extract(attrs, 'type');
attrs.className = 'Alert Alert--' + type + ' ' + (attrs.className || ''); attrs.className = classList('Alert', `Alert--${type}`, attrs.className);
const content = extract(attrs, 'content') || vnode.children; const content = extract(attrs, 'content') || vnode.children;
const controls = (extract(attrs, 'controls') || []) as Mithril.Vnode[]; const controls = (extract(attrs, 'controls') || []) as Mithril.Vnode[];
@ -37,13 +39,20 @@ export default class Alert<T extends AlertAttrs = AlertAttrs> extends Component<
const dismissControl: Mithril.Vnode[] = []; const dismissControl: Mithril.Vnode[] = [];
if (dismissible || dismissible === undefined) { if (dismissible || dismissible === undefined) {
dismissControl.push(<Button icon="fas fa-times" className="Button Button--link Button--icon Alert-dismiss" onclick={ondismiss} />); dismissControl.push(
<Button
aria-label={app.translator.trans('core.lib.alert.dismiss_a11y_label')}
icon="fas fa-times"
class="Button Button--link Button--icon Alert-dismiss"
onclick={ondismiss}
/>
);
} }
return ( return (
<div {...attrs}> <div {...attrs}>
<span className="Alert-body">{content}</span> <span class="Alert-body">{content}</span>
<ul className="Alert-controls">{listItems(controls.concat(dismissControl))}</ul> <ul class="Alert-controls">{listItems(controls.concat(dismissControl))}</ul>
</div> </div>
); );
} }

View File

@ -1,5 +1,4 @@
import Component from '../Component'; import Component from '../Component';
import Alert from './Alert';
/** /**
* The `AlertManager` component provides an area in which `Alert` components can * The `AlertManager` component provides an area in which `Alert` components can
@ -14,14 +13,18 @@ export default class AlertManager extends Component {
view() { view() {
return ( return (
<div className="AlertManager"> <div class="AlertManager">
{Object.entries(this.state.getActiveAlerts()).map(([key, alert]) => ( {Object.entries(this.state.getActiveAlerts()).map(([key, alert]) => {
<div className="AlertManager-alert"> const urgent = alert.attrs.type === 'error';
<alert.componentClass {...alert.attrs} ondismiss={this.state.dismiss.bind(this.state, key)}>
{alert.children} return (
</alert.componentClass> <div class="AlertManager-alert" role="alert" aria-live={urgent ? 'assertive' : 'polite'}>
</div> <alert.componentClass {...alert.attrs} ondismiss={this.state.dismiss.bind(this.state, key)}>
))} {alert.children}
</alert.componentClass>
</div>
);
})}
</div> </div>
); );
} }

View File

@ -504,6 +504,10 @@ core:
lib: lib:
debug_button: Debug debug_button: Debug
# These translations are used in the Alert component.
alert:
dismiss_a11y_label: Dismiss alert
# These translations are displayed as tooltips for discussion badges. # These translations are displayed as tooltips for discussion badges.
badge: badge:
hidden_tooltip: Hidden hidden_tooltip: Hidden