Skip to content
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

Fix: CSS to animate popups, dialog for accessibility (fixes #600) #601

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 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
13 changes: 12 additions & 1 deletion js/a11y/popup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Adapt from 'core/js/adapt';
import logging from '../logging';

/**
* Tabindex and aria-hidden manager for popups.
Expand Down Expand Up @@ -94,6 +95,12 @@ export default class Popup extends Backbone.Controller {
}
this._floorStack.push($popupElement);
this._focusStack.push($(document.activeElement));
if ($popupElement.is('dialog')) {
$popupElement[0].addEventListener('cancel', event => event.preventDefault());
$popupElement[0].showModal();
return;
}
logging.deprecated('a11y/popup opened: Use native dialog tag for', $popupElement);
let $elements = $(config._options._tabbableElements).filter(config._options._tabbableElementsExcludes);
const $branch = $popupElement.add($popupElement.parents());
const $siblings = $branch.siblings().filter(config._options._tabbableElementsExcludes);
Expand Down Expand Up @@ -167,7 +174,11 @@ export default class Popup extends Backbone.Controller {
if (this._floorStack.length <= 1) {
return;
}
this._floorStack.pop();
const $popupElement = this._floorStack.pop();
if ($popupElement.is('dialog')) {
$popupElement[0].close();
return this._focusStack.pop();
}
$(config._options._tabbableElements).filter(config._options._tabbableElementsExcludes).each((index, item) => {
const $item = $(item);
let previousTabIndex = '';
Expand Down
1 change: 1 addition & 0 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'core/js/navigation';
import 'core/js/startController';
import 'core/js/DOMElementModifications';
import 'core/js/tooltips';
import 'core/js/shadow';
import 'plugins';

$('body').append(Handlebars.templates.loading());
Expand Down
1 change: 1 addition & 0 deletions js/drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Drawer extends Backbone.Controller {

onAdaptStart() {
this._drawerView = new DrawerView({ collection: DrawerCollection });
this._drawerView.$el.insertAfter('#shadow');
}

onLanguageChanged() {
Expand Down
37 changes: 37 additions & 0 deletions js/shadow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Backbone from 'backbone';
import Adapt from 'core/js/adapt';
import ShadowView from './views/ShadowView';

class Shadow extends Backbone.Controller {

initialize() {
this.listenTo(Adapt, {
'adapt:start': this.onAdaptStart
});
}

onAdaptStart() {
this._shadowView = new ShadowView();
this._shadowView.$el.prependTo('body');
}

get isOpen() {
return this._shadowView?.isOpen ?? false;
}

async show() {
return this._shadowView?.showShadow();
}

async hide() {
return this._shadowView?.hideShadow();
}

remove() {
this._shadowView?.remove();
this._shadowView = null;
}

}

export default new Shadow();
8 changes: 8 additions & 0 deletions js/transitions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import logging from 'core/js/logging';

/**
* Wait for one requestAnimationFrame to allow classes to settle
* @returns {Promise}
*/
export async function transitionNextFrame() {
return new Promise(resolve => requestAnimationFrame(resolve));
}

/**
* Handler to await completion of active `CSSTransitions`.
* An optional `transition-property` to await can be specified, else all properties will be evaluated.
Expand Down
57 changes: 57 additions & 0 deletions js/views/ShadowView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Adapt from 'core/js/adapt';
import Backbone from 'backbone';
import { transitionNextFrame, transitionsEnded } from '../transitions';

class ShadowView extends Backbone.View {

className() {
return 'shadow js-shadow u-display-none';
}

attributes() {
return {
id: 'shadow'
};
}

initialize() {
this._isOpen = false;
this.disableAnimation = Adapt.config.get('_disableAnimation') ?? false;
this.$el.toggleClass('disable-animation', Boolean(this.disableAnimation));
this.render();
}

render() {
const template = Handlebars.templates.shadow;
this.$el.html(template({ _globals: Adapt.course.get('_globals') }));
return this;
}

get isOpen() {
return this._isOpen;
}

async showShadow() {
this._isOpen = true;
this.$el.addClass('anim-show-before');
await transitionNextFrame();
this.$el.removeClass('u-display-none');
await transitionNextFrame();
this.$el.addClass('anim-show-after');
await transitionsEnded(this.$el);
}

async hideShadow() {
this._isOpen = false;
this.$el.addClass('anim-hide-before');
await transitionNextFrame();
this.$el.addClass('anim-hide-after');
await transitionsEnded(this.$el);
this.$el.addClass('u-display-none');
await transitionNextFrame();
this.$el.removeClass('anim-open-before anim-open-after anim-hide-before anim-hide-after');
}

}

export default ShadowView;
Loading