Skip to content

Commit

Permalink
🐛 fix(tooltip,modal): interaction globale et focus iOS [DS-3460,DS-33…
Browse files Browse the repository at this point in the history
…95] (#691)

- Correctif à la pression de la touche Escape sur la modale : si l'élément actif (focus) est un élément de formulaire ou un média, la modale n'est pas refermée pas pour permettre l'interaction native de l'élément actif
- Correctif iOS de la prise de focus au clic
- Fermeture des tooltips dés au clic sur n'importe quel endroit
- Fermeture des tooltip à la pression sur la touche escape, où que soit le focus
  • Loading branch information
lab9fr authored Jul 11, 2023
1 parent 55a3953 commit 23312d5
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 27 deletions.
2 changes: 0 additions & 2 deletions src/analytics/doc/analytics/installation/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ La configuration doit être placée **avant** les fichiers `patch.module.js`, `d
```javascript
<script>
window.dsfr = {
verbose: true,
analytics: {
domain: ' mon.domainedetracking.com',
// collection: 'manual',
Expand All @@ -19,7 +18,6 @@ La configuration doit être placée **avant** les fichiers `patch.module.js`, `d
// ...
},
site: {
production: 'false',
entity: 'Ministère des armées', // Entity responsible for website
}
}
Expand Down
28 changes: 27 additions & 1 deletion src/component/modal/script/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,33 @@ class Modal extends api.core.Disclosure {
this._isDialog = this.node.tagName === 'DIALOG';
this.isScrolling = false;
this.listenClick();
this.listenKey(api.core.KeyCodes.ESCAPE, this.conceal.bind(this, false, false), true, true);
this.addEmission(api.core.RootEmission.KEYDOWN, this._keydown.bind(this));
}

_keydown (keyCode) {
switch (keyCode) {
case api.core.KeyCodes.ESCAPE:
this._escape();
break;
}
}

// TODO v2 : passer les tagName d'action en constante
_escape () {
const tagName = document.activeElement ? document.activeElement.tagName : undefined;

switch (tagName) {
case 'INPUT':
case 'LABEL':
case 'TEXTAREA':
case 'SELECT':
case 'AUDIO':
case 'VIDEO':
break;

default:
this.conceal();
}
}

retrieved () {
Expand Down
41 changes: 31 additions & 10 deletions src/component/tooltip/script/tooltip/tooltip-referent.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,39 @@ class TooltipReferent extends api.core.PlacementReferent {

init () {
super.init();
this.listen('focusin', this.focusin.bind(this));
this.listen('focusout', this.focusout.bind(this));
this.listen('focusin', this.focusIn.bind(this));
this.listen('focusout', this.focusOut.bind(this));
if (!this.matches(TooltipSelector.BUTTON)) {
this.listen('mouseover', this.mouseover.bind(this));
this.placement.listen('mouseover', this.mouseover.bind(this));
this.listen('mouseout', this.mouseout.bind(this));
this.placement.listen('mouseout', this.mouseout.bind(this));
const mouseover = this.mouseover.bind(this);
this.listen('mouseover', mouseover);
this.placement.listen('mouseover', mouseover);
const mouseout = this.mouseout.bind(this);
this.listen('mouseout', mouseout);
this.placement.listen('mouseout', mouseout);
}
this.listenKey(api.core.KeyCodes.ESCAPE, this.escape.bind(this), true, true);
this.addEmission(api.core.RootEmission.KEYDOWN, this._keydown.bind(this));
this.listen('click', this._click.bind(this));
this.addEmission(api.core.RootEmission.CLICK, this._clickOut.bind(this));
}

escape () {
_click () {
this.focus();
}

_clickOut (target) {
if (!this.node.contains(target)) this.blur();
}

_keydown (keyCode) {
switch (keyCode) {
case api.core.KeyCodes.ESCAPE:
this.blur();
this.close();
break;
}
}

close () {
this.state = 0;
}

Expand All @@ -43,11 +64,11 @@ class TooltipReferent extends api.core.PlacementReferent {
this._state = value;
}

focusin () {
focusIn () {
this.state |= TooltipReferentState.FOCUS;
}

focusout () {
focusOut () {
this.state &= ~TooltipReferentState.FOCUS;
}

Expand Down
4 changes: 3 additions & 1 deletion src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import { Equisized } from './script/equisized/equisized.js';
import { EquisizedsGroup } from './script/equisized/equisizeds-group.js';
import { EquisizedEmission } from './script/equisized/equisized-emission.js';
import { Toggle } from './script/action/toggle/toggle';
import { RootSelector } from './script/api/modules/stage/root.js';
import { RootSelector } from './script/api/modules/stage/root-selector.js';
import { RootEmission } from './script/api/modules/stage/root-emission.js';
import { InjectSvg } from './script/inject/inject-svg';
import { InjectSvgSelector } from './script/inject/inject-svg-selector';
import { Artwork } from './script/artwork/artwork';
Expand Down Expand Up @@ -51,6 +52,7 @@ api.core = {
CollapsesGroup: CollapsesGroup,
CollapseSelector: CollapseSelector,
RootSelector: RootSelector,
RootEmission: RootEmission,
Equisized: Equisized,
EquisizedEmission: EquisizedEmission,
Toggle: Toggle,
Expand Down
5 changes: 5 additions & 0 deletions src/core/script/api/modules/register/instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class Instance {
this.node.dispatchEvent(event);
}

// TODO v2 => listener au niveau des éléments qui redistribuent aux instances.
listen (type, closure, options) {
if (!this._listeners[type]) this._listeners[type] = [];
const listeners = this._listeners[type];
Expand Down Expand Up @@ -435,6 +436,10 @@ class Instance {
this.node.focus();
}

blur () {
this.node.blur();
}

focusClosest () {
const closest = this._focusClosest(this.node.parentNode);
if (closest) closest.focus();
Expand Down
42 changes: 34 additions & 8 deletions src/core/script/api/modules/register/key-codes.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
export const KeyCodes = {
TAB: 9,
ESCAPE: 27,
END: 35,
HOME: 36,
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40
TAB: {
id: 'tab',
value: 9
},
ESCAPE: {
id: 'escape',
value: 27
},
END: {
id: 'end',
value: 35
},
HOME: {
id: 'home',
value: 36
},
LEFT: {
id: 'left',
value: 37
},
UP: {
id: 'up',
value: 38
},
RIGHT: {
id: 'right',
value: 39
},
DOWN: {
id: 'down',
value: 40
}
};

export const getKeyCode = (keyCode) => Object.values(KeyCodes).filter(entry => entry.value === keyCode)[0];
7 changes: 7 additions & 0 deletions src/core/script/api/modules/stage/root-emission.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import ns from '../../utilities/namespace.js';

export const RootEmission = {
CLICK: ns.emission('root', 'click'),
KEYDOWN: ns.emission('root', 'keydown'),
KEYUP: ns.emission('root', 'keyup')
};
3 changes: 3 additions & 0 deletions src/core/script/api/modules/stage/root-selector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const RootSelector = {
ROOT: ':root'
};
28 changes: 23 additions & 5 deletions src/core/script/api/modules/stage/root.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
import { Element } from './element.js';
import ns from '../../utilities/namespace.js';
import { RootEmission } from './root-emission';
import { getKeyCode } from '../register/key-codes';

class Root extends Element {
constructor () {
super(document.documentElement, 'root');
this.node.setAttribute(ns.attr('js'), true);
this.listen();
}

listen () {
// TODO v2 => listener au niveau des éléments qui redistribuent aux instances.
document.documentElement.addEventListener('click', this.click.bind(this), { capture: true });
document.documentElement.addEventListener('keydown', this.keydown.bind(this), { capture: true });
document.documentElement.addEventListener('keyup', this.keyup.bind(this), { capture: true });
}

click (e) {
this.emit(RootEmission.CLICK, e.target);
}
}

const RootSelector = {
ROOT: ':root'
};
keydown (e) {
this.emit(RootEmission.KEYDOWN, getKeyCode(e.keyCode));
}

keyup (e) {
this.emit(RootEmission.KEYUP, getKeyCode(e.keyCode));
}
}

export { Root, RootSelector };
export { Root };

0 comments on commit 23312d5

Please sign in to comment.