diff --git a/packages/ilios-common/.lint-todo b/packages/ilios-common/.lint-todo index 2912ff5299..c704b8d52b 100644 --- a/packages/ilios-common/.lint-todo +++ b/packages/ilios-common/.lint-todo @@ -40,8 +40,6 @@ add|ember-template-lint|no-at-ember-render-modifiers|4|2|4|2|23cd787c79c34a628da add|ember-template-lint|no-at-ember-render-modifiers|5|2|5|2|32658810aa13672f5981281c562729112a89788f|1731542400000|1762646400000|1793750400000|addon/components/course/header.hbs add|ember-template-lint|no-at-ember-render-modifiers|4|2|4|2|23cd787c79c34a628dadb6e96dd4004d42eebb79|1731542400000|1762646400000|1793750400000|addon/components/course/objective-list.hbs add|ember-template-lint|no-at-ember-render-modifiers|5|2|5|2|84076f8cf85c554eaf0d9fdec26154bae5bceeb2|1731542400000|1762646400000|1793750400000|addon/components/course/objective-list.hbs -add|ember-template-lint|no-at-ember-render-modifiers|28|6|28|6|1ef231a97c0ec761eaafb3e76093515e5523ff27|1731542400000|1762646400000|1793750400000|addon/components/course/publication-menu.hbs -add|ember-template-lint|no-at-ember-render-modifiers|29|6|29|6|df94e6558ff62dea69f6f656f668f29b56bcc378|1731542400000|1762646400000|1793750400000|addon/components/course/publication-menu.hbs add|ember-template-lint|no-at-ember-render-modifiers|4|2|4|2|2bbf15957242a9a3c1e26e14e5d022c858199fde|1731542400000|1762646400000|1793750400000|addon/components/course/rollover-date-picker.hbs add|ember-template-lint|no-at-ember-render-modifiers|5|2|5|2|167e8d9ede488c7f199cb748e81bc09b97617e71|1731542400000|1762646400000|1793750400000|addon/components/course/rollover-date-picker.hbs add|ember-template-lint|no-at-ember-render-modifiers|3|2|3|2|1009d3843f6aed52099f0e7fbd4eebb52bc176e5|1731542400000|1762646400000|1793750400000|addon/components/course/rollover.hbs @@ -55,5 +53,3 @@ add|ember-template-lint|no-at-ember-render-modifiers|4|2|4|2|23cd787c79c34a628da add|ember-template-lint|no-at-ember-render-modifiers|3|2|3|2|23cd787c79c34a628dadb6e96dd4004d42eebb79|1731542400000|1762646400000|1793750400000|addon/components/dashboard/courses-calendar-filter.hbs add|ember-template-lint|no-at-ember-render-modifiers|4|2|4|2|a90be151f45cd8ab32827e9247a9a9eb7f1baef2|1731542400000|1762646400000|1793750400000|addon/components/dashboard/courses-calendar-filter.hbs add|ember-template-lint|no-at-ember-render-modifiers|24|10|24|10|2ed3ce70b879732dc85047f9f546c5dbd5376dba|1731542400000|1762646400000|1793750400000|addon/components/dashboard/courses-calendar-filter.hbs -add|ember-template-lint|no-at-ember-render-modifiers|28|6|28|6|1ef231a97c0ec761eaafb3e76093515e5523ff27|1731542400000|1762646400000|1793750400000|addon/components/session/publication-menu.hbs -add|ember-template-lint|no-at-ember-render-modifiers|29|6|29|6|df94e6558ff62dea69f6f656f668f29b56bcc378|1731542400000|1762646400000|1793750400000|addon/components/session/publication-menu.hbs diff --git a/packages/ilios-common/addon/components/course/publication-menu.hbs b/packages/ilios-common/addon/components/course/publication-menu.hbs index 5afd59ea65..1eef71f587 100644 --- a/packages/ilios-common/addon/components/course/publication-menu.hbs +++ b/packages/ilios-common/addon/components/course/publication-menu.hbs @@ -1,107 +1,101 @@ - + + + {{this.title}} + + + + {{#if this.isOpen}} + + {{/if}} + +{{/let}} \ No newline at end of file diff --git a/packages/ilios-common/addon/components/course/publication-menu.js b/packages/ilios-common/addon/components/course/publication-menu.js index 71f89bd589..31a5e494ff 100644 --- a/packages/ilios-common/addon/components/course/publication-menu.js +++ b/packages/ilios-common/addon/components/course/publication-menu.js @@ -2,6 +2,7 @@ import Component from '@glimmer/component'; import { service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; +import { task, timeout } from 'ember-concurrency'; export default class CoursePublicationMenuComponent extends Component { @service router; @@ -63,53 +64,67 @@ export default class CoursePublicationMenuComponent extends Component { return 'notpublished'; } - focusOnFirstItem(menuElement) { - menuElement.querySelector('button:first-of-type').focus(); + focusFirstLink = task(async (item) => { + await timeout(1); + item.querySelector('.menu button:first-of-type').focus(); + }); + + handleArrowUp(item) { + if (item?.previousElementSibling) { + item.previousElementSibling.focus(); + } else { + item?.parentElement.lastElementChild.focus(); + } + } + + async handleArrowDown(item) { + if (item.classList.value == 'toggle') { + this.isOpen = true; + await this.focusFirstLink.perform(item.parentElement); + } else { + if (item.nextElementSibling) { + item.nextElementSibling.focus(); + } else { + await this.focusFirstLink.perform(item.parentElement); + } + } } @action - moveFocus({ key, target }) { + async toggleMenu({ target }) { + this.isOpen = !this.isOpen; + + if (this.isOpen) { + await this.focusFirstLink.perform(target.parentElement.parentElement); + } + } + @action + keyUp({ key, target }) { switch (key) { case 'ArrowDown': - if (target.nextElementSibling) { - target.nextElementSibling.focus(); - } else { - this.menuElement.querySelector('button:nth-of-type(1)').focus(); - } + this.handleArrowDown(target); break; case 'ArrowUp': - if (target.previousElementSibling) { - target.previousElementSibling.focus(); - } else { - this.menuElement.querySelector('button:last-of-type').focus(); - } + this.handleArrowUp(target); break; case 'Escape': case 'Tab': case 'ArrowRight': case 'ArrowLeft': - this.isOpen = false; + this.close(); break; } + + return false; } @action - clearFocus() { - const buttons = this.menuElement.querySelectorAll('button'); - buttons.forEach((el) => el.blur()); + clearFocus({ target }) { + const menu = target.parentElement.parentElement; + menu.querySelectorAll('button').forEach((el) => el.blur()); } @action - toggleMenu({ key }) { - switch (key) { - case 'ArrowDown': - this.isOpen = true; - break; - case 'Escape': - case 'Tab': - case 'ArrowRight': - case 'ArrowLeft': - this.isOpen = false; - break; - } + close() { + this.isOpen = false; } @action diff --git a/packages/ilios-common/addon/components/session/publication-menu.hbs b/packages/ilios-common/addon/components/session/publication-menu.hbs index 705fef5540..04fd6fb819 100644 --- a/packages/ilios-common/addon/components/session/publication-menu.hbs +++ b/packages/ilios-common/addon/components/session/publication-menu.hbs @@ -1,107 +1,101 @@ - + + + {{this.title}} + + + + {{#if this.isOpen}} + + {{/if}} + +{{/let}} \ No newline at end of file diff --git a/packages/ilios-common/addon/components/session/publication-menu.js b/packages/ilios-common/addon/components/session/publication-menu.js index 9917ed4e9b..997ee5729e 100644 --- a/packages/ilios-common/addon/components/session/publication-menu.js +++ b/packages/ilios-common/addon/components/session/publication-menu.js @@ -2,6 +2,7 @@ import Component from '@glimmer/component'; import { service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; +import { task, timeout } from 'ember-concurrency'; export default class SessionPublicationMenuComponent extends Component { @service router; @@ -67,53 +68,67 @@ export default class SessionPublicationMenuComponent extends Component { return 'notpublished'; } - focusOnFirstItem(menuElement) { - menuElement.querySelector('button:first-of-type').focus(); + focusFirstLink = task(async (item) => { + await timeout(1); + item.querySelector('.menu button:first-of-type').focus(); + }); + + handleArrowUp(item) { + if (item?.previousElementSibling) { + item.previousElementSibling.focus(); + } else { + item?.parentElement.lastElementChild.focus(); + } + } + + async handleArrowDown(item) { + if (item.classList.value == 'toggle') { + this.isOpen = true; + await this.focusFirstLink.perform(item.parentElement); + } else { + if (item.nextElementSibling) { + item.nextElementSibling.focus(); + } else { + await this.focusFirstLink.perform(item.parentElement); + } + } } @action - moveFocus({ key, target }) { + async toggleMenu({ target }) { + this.isOpen = !this.isOpen; + + if (this.isOpen) { + await this.focusFirstLink.perform(target.parentElement.parentElement); + } + } + @action + keyUp({ key, target }) { switch (key) { case 'ArrowDown': - if (target.nextElementSibling) { - target.nextElementSibling.focus(); - } else { - this.menuElement.querySelector('button:nth-of-type(1)').focus(); - } + this.handleArrowDown(target); break; case 'ArrowUp': - if (target.previousElementSibling) { - target.previousElementSibling.focus(); - } else { - this.menuElement.querySelector('button:last-of-type').focus(); - } + this.handleArrowUp(target); break; case 'Escape': case 'Tab': case 'ArrowRight': case 'ArrowLeft': - this.isOpen = false; + this.close(); break; } + + return true; } @action - clearFocus() { - const buttons = this.menuElement.querySelectorAll('button'); - buttons.forEach((el) => el.blur()); + clearFocus({ target }) { + const menu = target.parentElement.parentElement; + menu.querySelectorAll('button').forEach((el) => el.blur()); } @action - toggleMenu({ key }) { - switch (key) { - case 'ArrowDown': - this.isOpen = true; - break; - case 'Escape': - case 'Tab': - case 'ArrowRight': - case 'ArrowLeft': - this.isOpen = false; - break; - } + close() { + this.isOpen = false; } @action