Several changes improving accessibility of the dialogs
- Wrapped all the modals inside a react-focus-trap component disabling keyboard navigation outside the modal dialogs - Disabled our custom key handling at dialog level. Cancelling on esc key is now handled via FocusTrap component. - Removed onEnter prop from the BaseDialog component. Dialogs that submit data all now embed a form with onSubmit handler. And since keyboard focus is now managed better via FocusTrap it no longer makes sense for the other dialog types. Fixes https://github.com/vector-im/riot-web/issues/5736 - Set aria-hidden on the matrixChat outer node when showing dialogs to disable navigating outside the modals by using screen reader specific features.
This commit is contained in:
parent
437a440bdf
commit
5ccbcf02e2
8 changed files with 60 additions and 65 deletions
|
@ -33,9 +33,6 @@ export default React.createClass({
|
|||
// onFinished callback to call when Escape is pressed
|
||||
onFinished: React.PropTypes.func.isRequired,
|
||||
|
||||
// callback to call when Enter is pressed
|
||||
onEnterPressed: React.PropTypes.func,
|
||||
|
||||
// CSS class to apply to dialog div
|
||||
className: React.PropTypes.string,
|
||||
|
||||
|
@ -51,17 +48,16 @@ export default React.createClass({
|
|||
contentId: React.PropTypes.string
|
||||
},
|
||||
|
||||
_onKeyDown: function(e) {
|
||||
if (e.keyCode === KeyCode.ESCAPE) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.props.onFinished();
|
||||
} else if (e.keyCode === KeyCode.ENTER) {
|
||||
if (this.props.onEnterPressed) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.props.onEnterPressed(e);
|
||||
}
|
||||
componentDidMount: function() {
|
||||
this.applicationNode = document.getElementById('matrixchat');
|
||||
if (this.applicationNode) {
|
||||
this.applicationNode.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
if (this.applicationNode) {
|
||||
this.applicationNode.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -73,7 +69,7 @@ export default React.createClass({
|
|||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
return (
|
||||
<div onKeyDown={this._onKeyDown} className={this.props.className} role="dialog" aria-labelledby='mx_BaseDialog_title' aria-describedby={this.props.contentId}>
|
||||
<div className={this.props.className} role="dialog" aria-labelledby='mx_BaseDialog_title' aria-describedby={this.props.contentId}>
|
||||
<AccessibleButton onClick={this._onCancelClick}
|
||||
className="mx_Dialog_cancelButton"
|
||||
>
|
||||
|
|
|
@ -116,10 +116,10 @@ export default React.createClass({
|
|||
|
||||
return (
|
||||
<BaseDialog className="mx_ConfirmUserActionDialog" onFinished={this.props.onFinished}
|
||||
onEnterPressed={this.onOk}
|
||||
title={this.props.title}
|
||||
contentId='mx_Dialog_content'
|
||||
>
|
||||
<div className="mx_Dialog_content">
|
||||
<div id="mx_Dialog_content" className="mx_Dialog_content">
|
||||
<div className="mx_ConfirmUserActionDialog_avatar">
|
||||
{ avatar }
|
||||
</div>
|
||||
|
|
|
@ -116,7 +116,6 @@ export default React.createClass({
|
|||
|
||||
return (
|
||||
<BaseDialog className="mx_CreateGroupDialog" onFinished={this.props.onFinished}
|
||||
onEnterPressed={this._onFormSubmit}
|
||||
title={_t('Create Community')}
|
||||
>
|
||||
<form onSubmit={this._onFormSubmit}>
|
||||
|
|
|
@ -43,38 +43,37 @@ export default React.createClass({
|
|||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
return (
|
||||
<BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished}
|
||||
onEnterPressed={this.onOk}
|
||||
title={_t('Create Room')}
|
||||
>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className="mx_CreateRoomDialog_label">
|
||||
<label htmlFor="textinput"> { _t('Room name (optional)') } </label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="textinput" ref="textinput" className="mx_CreateRoomDialog_input" autoFocus={true} size="64" />
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<details className="mx_CreateRoomDialog_details">
|
||||
<summary className="mx_CreateRoomDialog_details_summary">{ _t('Advanced options') }</summary>
|
||||
<div>
|
||||
<input type="checkbox" id="checkbox" ref="checkbox" defaultChecked={this.defaultNoFederate} />
|
||||
<label htmlFor="checkbox">
|
||||
{ _t('Block users on other matrix homeservers from joining this room') }
|
||||
<br />
|
||||
({ _t('This setting cannot be changed later!') })
|
||||
</label>
|
||||
<form onSubmit={this.onOk}>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className="mx_CreateRoomDialog_label">
|
||||
<label htmlFor="textinput"> { _t('Room name (optional)') } </label>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onCancel}>
|
||||
{ _t('Cancel') }
|
||||
</button>
|
||||
<button className="mx_Dialog_primary" onClick={this.onOk}>
|
||||
{ _t('Create Room') }
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<input id="textinput" ref="textinput" className="mx_CreateRoomDialog_input" autoFocus={true} size="64" />
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<details className="mx_CreateRoomDialog_details">
|
||||
<summary className="mx_CreateRoomDialog_details_summary">{ _t('Advanced options') }</summary>
|
||||
<div>
|
||||
<input type="checkbox" id="checkbox" ref="checkbox" defaultChecked={this.defaultNoFederate} />
|
||||
<label htmlFor="checkbox">
|
||||
{ _t('Block users on other matrix homeservers from joining this room') }
|
||||
<br />
|
||||
({ _t('This setting cannot be changed later!') })
|
||||
</label>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onCancel}>
|
||||
{ _t('Cancel') }
|
||||
</button>
|
||||
<input type="submit" className="mx_Dialog_primary" value={ _t('Create Room') }/>
|
||||
</div>
|
||||
</form>
|
||||
</BaseDialog>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -64,7 +64,6 @@ export default React.createClass({
|
|||
});
|
||||
return (
|
||||
<BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished}
|
||||
onEnterPressed={this.onOk}
|
||||
title={this.props.title}
|
||||
contentId='mx_Dialog_content'
|
||||
>
|
||||
|
|
|
@ -60,25 +60,24 @@ export default React.createClass({
|
|||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
return (
|
||||
<BaseDialog className="mx_TextInputDialog" onFinished={this.props.onFinished}
|
||||
onEnterPressed={this.onOk}
|
||||
title={this.props.title}
|
||||
>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className="mx_TextInputDialog_label">
|
||||
<label htmlFor="textinput"> { this.props.description } </label>
|
||||
<form onSubmit={this.onOk}>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className="mx_TextInputDialog_label">
|
||||
<label htmlFor="textinput"> { this.props.description } </label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="textinput" ref="textinput" className="mx_TextInputDialog_input" defaultValue={this.props.value} autoFocus={this.props.focus} size="64" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<input id="textinput" ref="textinput" className="mx_TextInputDialog_input" defaultValue={this.props.value} autoFocus={this.props.focus} size="64" />
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onCancel}>
|
||||
{ _t("Cancel") }
|
||||
</button>
|
||||
<input type="submit" className="mx_Dialog_primary" value={ this.props.button }/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onCancel}>
|
||||
{ _t("Cancel") }
|
||||
</button>
|
||||
<button className="mx_Dialog_primary" onClick={this.onOk}>
|
||||
{ this.props.button }
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</BaseDialog>
|
||||
);
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue