-
Notifications
You must be signed in to change notification settings - Fork 122
[UEPR-445] Ensure topbar is navigable via tab navigation #403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
a2f0390
06d2d62
34b18df
1c05d24
9914e61
328b234
0c20327
6f3a80d
05fb1da
333f1f8
f1ea8f6
2ce4eac
fdac2f4
77f2ac6
3f518b5
83bdad7
5640a76
4f92988
287e1a5
19fef13
d2fd053
016f46f
d75933d
e186ba9
37c9974
fa75484
8626a1a
965434b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| import React, {useRef} from 'react'; | ||
| import styles from './menu-bar.css'; | ||
| import classNames from 'classnames'; | ||
| import PropTypes from 'prop-types'; | ||
| import {connect} from 'react-redux'; | ||
|
|
||
| import editIcon from './icon--edit.svg'; | ||
| import {FormattedMessage, defineMessage} from 'react-intl'; | ||
| import MenuBarMenu from './menu-bar-menu.jsx'; | ||
| import {MenuItem, MenuSection} from '../menu/menu.jsx'; | ||
| import useMenuNavigation from '../../hooks/use-menu-navigation.jsx'; | ||
| import dropdownCaret from './dropdown-caret.svg'; | ||
| import DeletionRestorer from '../../containers/deletion-restorer.jsx'; | ||
| import TurboMode from '../../containers/turbo-mode.jsx'; | ||
| import intlShape from '../../lib/intlShape.js'; | ||
| import propTypes from '../../lib/prop-types.js'; | ||
|
|
||
| const editMenu = defineMessage({ | ||
| id: 'gui.aria.editMenu', | ||
| defaultMessage: 'Edit menu', | ||
| description: 'ARIA label for edit menu' | ||
| }); | ||
|
|
||
| const EditMenu = props => { | ||
| const { | ||
| menuRef, | ||
| intl, | ||
| isRtl, | ||
| onRestoreOption, | ||
| restoreOptionMessage | ||
| } = props; | ||
|
|
||
| const restoreRef = useRef(null); | ||
| const turboRef = useRef(null); | ||
|
|
||
| const itemRefs = [restoreRef, turboRef]; | ||
|
|
||
| const { | ||
| isExpanded, | ||
| handleKeyPress, | ||
| handleKeyPressOpenMenu, | ||
| handleOnOpen, | ||
| handleOnClose | ||
| } = useMenuNavigation({ | ||
| menuRef, | ||
| itemRefs, | ||
| depth: 1 | ||
| }); | ||
|
|
||
| return ( | ||
| <div | ||
| className={classNames(styles.menuBarItem, styles.hoverable, { | ||
| [styles.active]: isExpanded() | ||
| })} | ||
| onClick={handleOnOpen} | ||
| role="button" | ||
| aria-label={intl.formatMessage(editMenu)} | ||
| aria-expanded={isExpanded()} | ||
| tabIndex={0} | ||
| onKeyDown={handleKeyPress} | ||
| ref={menuRef} | ||
| > | ||
| <img src={editIcon} /> | ||
| <span className={styles.collapsibleLabel}> | ||
| <FormattedMessage | ||
| defaultMessage="Edit" | ||
| description="Text for edit dropdown menu" | ||
| id="gui.menuBar.edit" | ||
| /> | ||
| </span> | ||
| <img src={dropdownCaret} /> | ||
| <MenuBarMenu | ||
| className={classNames(styles.menuBarMenu)} | ||
| open={isExpanded()} | ||
| place={isRtl ? 'left' : 'right'} | ||
| onRequestClose={handleOnClose} | ||
| > | ||
| <DeletionRestorer>{(handleRestore, {restorable, deletedItem}) => ( | ||
| <MenuItem | ||
| className={classNames({[styles.disabled]: !restorable})} | ||
| onClick={onRestoreOption(handleRestore)} | ||
| itemRef={restoreRef} | ||
| onParentKeyPress={handleKeyPressOpenMenu} | ||
| isDisabled={!restorable} | ||
| > | ||
| {restoreOptionMessage(deletedItem)} | ||
| </MenuItem> | ||
| )}</DeletionRestorer> | ||
| <MenuSection> | ||
| <TurboMode>{(toggleTurboMode, {turboMode}) => ( | ||
| <MenuItem | ||
| onClick={toggleTurboMode} | ||
| itemRef={turboRef} | ||
| onParentKeyPress={handleKeyPressOpenMenu} | ||
| > | ||
| {turboMode ? ( | ||
| <FormattedMessage | ||
| defaultMessage="Turn off Turbo Mode" | ||
| description="Menu bar item for turning off turbo mode" | ||
| id="gui.menuBar.turboModeOff" | ||
| /> | ||
| ) : ( | ||
| <FormattedMessage | ||
| defaultMessage="Turn on Turbo Mode" | ||
| description="Menu bar item for turning on turbo mode" | ||
| id="gui.menuBar.turboModeOn" | ||
| /> | ||
| )} | ||
| </MenuItem> | ||
| )}</TurboMode> | ||
| </MenuSection> | ||
| </MenuBarMenu> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| EditMenu.propTypes = { | ||
| intl: intlShape.isRequired, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to use Same comment for the other menus where Edit: I just noticed that you're passing it from the MenuBar component. I still think it's better to inject it here rather than passing it from the parent. By the way, if we switch to function components we can use |
||
| menuRef: propTypes.ref.isRequired, | ||
| isRtl: PropTypes.bool, | ||
| restoreOptionMessage: PropTypes.func.isRequired, | ||
| onRestoreOption: PropTypes.func.isRequired | ||
| }; | ||
|
|
||
| const mapStateToProps = state => ({ | ||
| isRtl: state.locales.isRtl | ||
| }); | ||
|
|
||
| export default connect( | ||
| mapStateToProps | ||
| )(EditMenu); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we only need to manage menu refs on the Menu Bar level? If there are other cases where we'll be managing menu refs outside of here, we'd want to move this to an outer level - otherwise it's fine to stay as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose I should have done it here but I do move it in my next task. Although it is illogical in the long term, I think it's fine to stay there in this PR.