MDL-85769 AI: Trap focus within AI drawer on smaller screens
Co-authored-by: Laurent David <[email protected]>
This commit is contained in:
co-authored by
Laurent David
parent
97ed6b7083
commit
c080b4bf58
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -31,6 +31,8 @@ import AIHelper from 'core_ai/helper';
|
||||
import DrawerEvents from 'core/drawer_events';
|
||||
import {subscribe} from 'core/pubsub';
|
||||
import * as MessageDrawerHelper from 'core_message/message_drawer_helper';
|
||||
import * as FocusLock from 'core/local/aria/focuslock';
|
||||
import {isSmall} from "core/pagehelpers";
|
||||
|
||||
const AICourseAssist = class {
|
||||
|
||||
@@ -60,6 +62,7 @@ const AICourseAssist = class {
|
||||
this.jumpToElement = document.querySelector(Selectors.ELEMENTS.JUMPTO);
|
||||
this.summaryActionElement = document.querySelector(Selectors.ACTIONS.SUMMARY);
|
||||
this.aiDrawerCloseElement = this.aiDrawerElement.querySelector(Selectors.ELEMENTS.AIDRAWER_CLOSE);
|
||||
this.isDrawerFocusLocked = false;
|
||||
|
||||
this.registerEventListeners();
|
||||
}
|
||||
@@ -85,6 +88,12 @@ const AICourseAssist = class {
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (this.isAIDrawerOpen() && e.key === 'Escape') {
|
||||
this.closeAIDrawer();
|
||||
}
|
||||
});
|
||||
|
||||
// Close AI drawer if message drawer is shown.
|
||||
subscribe(DrawerEvents.DRAWER_SHOWN, () => {
|
||||
if (this.isAIDrawerOpen()) {
|
||||
@@ -198,12 +207,27 @@ const AICourseAssist = class {
|
||||
}
|
||||
this.jumpToElement.setAttribute('tabindex', 0);
|
||||
this.jumpToElement.focus();
|
||||
|
||||
// If the AI drawer is opened on a small screen, we need to trap the focus tab within the AI drawer.
|
||||
if (isSmall()) {
|
||||
FocusLock.trapFocus(this.aiDrawerElement);
|
||||
this.aiDrawerElement.setAttribute('aria-modal', 'true');
|
||||
this.aiDrawerElement.setAttribute('role', 'dialog');
|
||||
this.isDrawerFocusLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the AI drawer.
|
||||
*/
|
||||
closeAIDrawer() {
|
||||
// Untrap focus if it was locked.
|
||||
if (this.isDrawerFocusLocked) {
|
||||
FocusLock.untrapFocus();
|
||||
this.aiDrawerElement.removeAttribute('aria-modal');
|
||||
this.aiDrawerElement.setAttribute('role', 'region');
|
||||
}
|
||||
|
||||
this.aiDrawerElement.classList.remove('show');
|
||||
this.aiDrawerElement.setAttribute('tabindex', '-1');
|
||||
this.aiDrawerBodyElement.removeAttribute('aria-live');
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['aidrawerlabel'] = 'AI-generated content drawer';
|
||||
$string['aisummary'] = 'AI summary';
|
||||
$string['courseassist:summarise_text'] = 'Summarise text';
|
||||
$string['copy'] = 'Copy';
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"content": "<p>Content to display</p>"
|
||||
}
|
||||
}}
|
||||
<div class="ai-drawer" id="ai-drawer" tabindex="-1">
|
||||
<div class="ai-drawer" id="ai-drawer" aria-label={{#quote}}{{#str}} aidrawerlabel, aiplacement_courseassist {{/str}}{{/quote}} tabindex="-1" role="region">
|
||||
<div class="ai-drawer-header">
|
||||
<button id="ai-drawer-close" class="btn ai-drawer-button" type="button" data-action="course-summarise">
|
||||
{{#pix}} e/cancel, core {{/pix}}
|
||||
|
||||
Reference in New Issue
Block a user