Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Fix various a11y issues with focus and aria labels (develop) #33

Merged
merged 5 commits into from
Sep 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nls/kappnav.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

kappnav = Kubernetes Application Navigator
a11y.editor.escape = You are about to enter a code editor, to escape the editor, press Control + Shift + Q.
a11y.editor.escape.win = You are about to enter a code editor, to escape the editor, press Alt + Shift + Q.
annotation = Annotation
expand = Expand
collapse = Collapse
Expand Down
18 changes: 11 additions & 7 deletions src-web/actions/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -399,17 +399,18 @@ export const getOverflowMenu = (componentData, actionMap, staticResourceData, ap
var hasCmdActions = cmdActions && cmdActions.length && cmdActions.length>0

if(hasStaticActions || hasUrlActions || hasCmdActions) {
return (
<OverflowMenu floatingMenu flipped iconDescription={msgs.get('svg.description.overflowMenu')}>
var menu = <OverflowMenu floatingMenu flipped iconDescription={msgs.get('svg.description.overflowMenu')}>
{(() => {
if(hasStaticActions)
return staticResourceData.actions.map(action => (
if(hasStaticActions) {
return staticResourceData.actions.map((action, staticindex) => (
<OverflowMenuItem key={itemId + action}
primaryFocus={staticindex === 0}
itemText={msgs.get('table.actions.'+action)}
onClick={openModal.bind(this, action, cloneData)}
onFocus={(e) => {e.target.title = msgs.get('table.actions.'+action)}}
onMouseEnter={(e) => {e.target.title = msgs.get('table.actions.'+action)}} />
))
}
})()}
{(() => {
if(urlActions) {
Expand All @@ -420,10 +421,11 @@ export const getOverflowMenu = (componentData, actionMap, staticResourceData, ap
performUrlAction(action['url-pattern'], action['open-window'], kind, name, namespace, undefined, false)
})

return urlActions.map(action => {
return urlActions.map((action, urlindex) => {
let actionLabel = action['text.nls'] ? msgs.get(action['text.nls']) : action.text
let actionDesc = action['description.nls'] ? msgs.get(action['description.nls']) : action.description
return <OverflowMenuItem key={action.name}
primaryFocus={urlindex === 0 && !hasStaticActions}
itemText={actionLabel}
onClick={performUrlAction.bind(this, action['url-pattern'], action['open-window'], componentData && componentData.kind, componentData && componentData.metadata && componentData.metadata.name, componentData && componentData.metadata && componentData.metadata.namespace, undefined, true)}
onFocus={(e) => {
Expand All @@ -437,8 +439,9 @@ export const getOverflowMenu = (componentData, actionMap, staticResourceData, ap
})()}
{(() => {
if(cmdActions) {
return cmdActions.map(action => (
return cmdActions.map((action, cmdindex) => (
<OverflowMenuItem key={action.name}
primaryFocus={cmdindex === 0 && !hasUrlActions && !hasStaticActions}
itemText={action.text ? action.text : action.description ? action.description : action.name}
onClick={openModal.bind(this, "action", cloneData, applicationName, applicationNamespace, action, cmdInputs)}
onFocus={(e) => {if(action.description) e.target.title = action.description}}
Expand All @@ -447,6 +450,7 @@ export const getOverflowMenu = (componentData, actionMap, staticResourceData, ap
}
})()}
</OverflowMenu>
)

return menu
}
}
20 changes: 10 additions & 10 deletions src-web/components/kappnav/common/ModalFormItems.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const General = ({ form, onChange, children, error, labelName, labelContent }, c
id='name'
hideLabel
className='bx--text-input-override'
labelText={labelName || msgs.get('formfield.name')}
labelText={labelName || msgs.get('formfield.name') + ' ' + msgs.get('formtip.common.name')}
value={form.name}
onChange={transform.bind(null, 'name', onChange)}
invalid={error && error.name}
Expand All @@ -73,7 +73,7 @@ const Label = ({ id, item, onModify, onRemove }, context) =>
value={item.name}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.label')}
labelText={msgs.get('formfield.label') + ' ' + msgs.get('formtip.common.label.label')}
onChange={onModify.bind(null, 'name')} />
</FieldWrapper>
<FieldWrapper labelText={msgs.get('formfield.value')} content={msgs.get('formtip.common.label.value')}>
Expand All @@ -82,7 +82,7 @@ const Label = ({ id, item, onModify, onRemove }, context) =>
value={item.value}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.value')}
labelText={msgs.get('formfield.value') + ' ' + msgs.get('formtip.common.label.value')}
onChange={onModify.bind(null, 'value')} />
</FieldWrapper>
<RemoveIcon id={`labels-remove-${id}`} onRemove={onRemove} />
Expand All @@ -96,7 +96,7 @@ const MatchLabel = ({ id, item, onModify, onRemove }, context) =>
value={item.name}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.label')}
labelText={msgs.get('formfield.label') + ' ' + msgs.get('formtip.common.matchLabel')}
onChange={onModify.bind(null, 'name')} />
</FieldWrapper>
<FieldWrapper labelText={msgs.get('formfield.value')} content={msgs.get('formtip.common.matchLabel')}>
Expand All @@ -105,7 +105,7 @@ const MatchLabel = ({ id, item, onModify, onRemove }, context) =>
value={item.value}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.value')}
labelText={msgs.get('formtip.common.matchLabel')}
onChange={onModify.bind(null, 'value')} />
</FieldWrapper>
<RemoveIcon id={`labels-remove-${id}`} onRemove={onRemove} />
Expand Down Expand Up @@ -141,7 +141,7 @@ const NamespaceSelect = ({ form, namespaces, onChange, labelName, labelContent }
value={item.key}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.key')}
labelText={msgs.get('formfield.key') + ' ' + msgs.get('formtip.selectors.matchExpression.key')}
onChange={onModify.bind(null, 'key')} />
</FieldWrapper>
<FieldWrapper labelText={msgs.get('formfield.operator')} content={msgs.get('formtip.selectors.matchExpression.operator', ['<br/>'])}>
Expand All @@ -150,7 +150,7 @@ const NamespaceSelect = ({ form, namespaces, onChange, labelName, labelContent }
value={item.operator}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.operator')}
labelText={msgs.get('formfield.operator') + ' ' + msgs.get('formtip.selectors.matchExpression.operator', ['<br/>'])}
onChange={onModify.bind(null, 'operator')} />
</FieldWrapper>
<FieldWrapper labelText={msgs.get('formfield.values')} content={msgs.get('formtip.selectors.matchExpression.value')}>
Expand All @@ -159,7 +159,7 @@ const NamespaceSelect = ({ form, namespaces, onChange, labelName, labelContent }
value={item.values}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.values')}
labelText={msgs.get('formfield.values') + ' ' + msgs.get('formtip.selectors.matchExpression.value')}
onChange={onModify.bind(null, 'values')} />
</FieldWrapper>
<RemoveIcon id={`match-expression-remove-${id}`} onRemove={onRemove} />
Expand All @@ -173,7 +173,7 @@ const NamespaceSelect = ({ form, namespaces, onChange, labelName, labelContent }
value={item.group}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.group')}
labelText={msgs.get('formfield.group') + ' ' + msgs.get('formtip.common.group')}
onChange={onModify.bind(null, 'group')} />
</FieldWrapper>
<FieldWrapper labelText={msgs.get('formfield.kind')} content={msgs.get('formtip.common.kind')}>
Expand All @@ -182,7 +182,7 @@ const NamespaceSelect = ({ form, namespaces, onChange, labelName, labelContent }
value={item.kind}
hideLabel
className='bx--text-input-override'
labelText={msgs.get('formfield.kind')}
labelText={msgs.get('formfield.kind') + ' ' + msgs.get('formtip.common.kind')}
onChange={onModify.bind(null, 'kind')} />
</FieldWrapper>
<RemoveIcon id={`labels-remove-${id}`} onRemove={onRemove} />
Expand Down
2 changes: 2 additions & 0 deletions src-web/components/kappnav/modals/ActionMessageModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class ActionMessageModal extends React.PureComponent {
className='bx--modal--danger'
id='submit-action-message-dialog'
role='region'
selectorPrimaryFocus='.bx--modal-close'
aria-label={'Label'}
open={open}>
<ModalHeader buttonOnClick={handleClose}>
Expand All @@ -77,6 +78,7 @@ class ActionMessageModal extends React.PureComponent {
<ComposedModal
id='submit-action-message-dialog'
role='region'
selectorPrimaryFocus='.bx--modal-close'
aria-label={'Label'}
open={open}>
<ModalHeader buttonOnClick={handleClose}>
Expand Down
1 change: 1 addition & 0 deletions src-web/components/kappnav/modals/ActionModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class ActionModal extends React.PureComponent {
onRequestSubmit={submitForm}
role='region'
modalAriaLabel={msgs.get(label.heading)}
selectorPrimaryFocus='.bx--modal-close'
aria-label={msgs.get(label.heading)}>
{reqErrorMsg && reqErrorMsg.length > 0 &&
reqErrorMsg.map((err,key) => <InlineNotification key={key} kind='error' title='' subtitle={err} iconDescription={msgs.get('svg.description.error')} />)
Expand Down
2 changes: 1 addition & 1 deletion src-web/components/kappnav/modals/NavModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class NavModal extends React.PureComponent {
{this.props.buttonName}
</Button>
{
open && <ComposedModal id='nav-modal' className='modal nav-modal' role='region' aria-label={this.props.modalHeading} open={open} onClose={() => this.toggleModal(false)}>
open && <ComposedModal id='nav-modal' selectorPrimaryFocus='.bx--modal-close' className='modal nav-modal' role='region' aria-label={this.props.modalHeading} open={open} onClose={() => this.toggleModal(false)}>
<ModalHeader buttonOnClick={this.handleOpen.bind(this, false)} iconDescription={this.props.closeButtonLabel}>
<div>
<p className='bx--modal-header__label'>
Expand Down
1 change: 1 addition & 0 deletions src-web/components/kappnav/modals/RemoveResourceModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class RemoveResourceModal extends React.PureComponent {
<Modal
danger
id='remove-resource-modal'
selectorPrimaryFocus='.bx--modal-close'
iconDescription={msgs.get('modal.button.close.the.modal')}
open={open}
primaryButtonText={msgs.get(label.primaryBtn)}
Expand Down
10 changes: 8 additions & 2 deletions src-web/components/kappnav/modals/ResourceModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class ResourceModal extends React.PureComponent {
escapeEditor(e) {
e.persist()
const button = document.querySelector('.bx--btn--secondary')
e.shiftKey && e.ctrlKey && e.which === 81 && button.focus()
e.shiftKey && (e.ctrlKey || e.altKey) && e.which === 81 && button.focus()
}

onChange(value) {
Expand Down Expand Up @@ -170,14 +170,20 @@ class ResourceModal extends React.PureComponent {
modalHeading = msgs.get(label.heading, [modalLabel])
}

let ariaLabelForEscapingEditor = msgs.get('a11y.editor.escape')
if(navigator.platform.toUpperCase().indexOf('WIN')>=0) {
ariaLabelForEscapingEditor = msgs.get('a11y.editor.escape.win')
}

return (
<div id='resource-modal-container' ref={div => this.resourceModal = div} tabIndex='-1' role='region' onKeyDown={this.escapeEditor} aria-label={msgs.get('a11y.editor.escape')}> {/* eslint-disable-line jsx-a11y/no-noninteractive-element-interactions */}
<div id='resource-modal-container' ref={div => this.resourceModal = div} tabIndex='-1' role='region' onKeyDown={this.escapeEditor} aria-label={ariaLabelForEscapingEditor}> {/* eslint-disable-line jsx-a11y/no-noninteractive-element-interactions */}
{reqCount && reqCount > 0 && <Loading />}
<Modal
id='resource-modal'
iconDescription={msgs.get('modal.button.close.the.modal')}
className='modal'
open={open}
selectorPrimaryFocus='.bx--modal-close'
primaryButtonText={msgs.get(label.primaryBtn)}
secondaryButtonText={msgs.get('modal.button.cancel')}
modalLabel={modalLabel}
Expand Down