Skip to content

Commit

Permalink
🐛 fix(tab): écoute des événements de clavier déplacé sur la liste d'o…
Browse files Browse the repository at this point in the history
…nglets [DS-2550] (#531)

L'écoute des événements de clavier se faisant sur le composant, il est impossible d'interagir avec des éléments de formulaire dans le contenu de l'onglet -> l'écoute est déplacée au niveau de la liste des onglets, ce qui en exclut le contenu
  • Loading branch information
lab9fr authored Jun 16, 2023
1 parent 68d562c commit 070e816
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 42 deletions.
4 changes: 3 additions & 1 deletion src/component/tab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { TabButton } from './script/tab/tab-button.js';
import { TabsGroup } from './script/tab/tabs-group.js';
import { TabsList } from './script/tab/tabs-list.js';
import { TabSelector } from './script/tab/tab-selector.js';
import { TabEmission } from './script/tab/tab-emission.js';

api.tab = {
TabPanel: TabPanel,
TabButton: TabButton,
TabsGroup: TabsGroup,
TabsList: TabsList,
TabSelector: TabSelector
TabSelector: TabSelector,
TabEmission: TabEmission
};

export default api;
6 changes: 6 additions & 0 deletions src/component/tab/script/tab/tab-emission.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import api from '../../api.js';

export const TabEmission = {
PRESS_KEY: api.internals.ns.emission('tab', 'press_key'),
LIST_HEIGHT: api.internals.ns.emission('tab', 'list_height')
};
6 changes: 6 additions & 0 deletions src/component/tab/script/tab/tab-keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const TabKeys = {
LEFT: 'tab_keys_left',
RIGHT: 'tab_keys_right',
HOME: 'tab_keys_home',
END: 'tab_keys_end'
};
38 changes: 27 additions & 11 deletions src/component/tab/script/tab/tabs-group.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import api from '../../api.js';
import { TabPanelDirection } from './tab-panel-direction.js';
import { TabKeys } from './tab-keys';
import { TabEmission } from './tab-emission';

/**
* TabGroup est la classe étendue de DiscosuresGroup
Expand All @@ -17,17 +19,13 @@ class TabsGroup extends api.core.DisclosuresGroup {
init () {
super.init();
this.listen('transitionend', this.transitionend.bind(this));
this.listenKey(api.core.KeyCodes.RIGHT, this.pressRight.bind(this), true, true);
this.listenKey(api.core.KeyCodes.LEFT, this.pressLeft.bind(this), true, true);
this.listenKey(api.core.KeyCodes.HOME, this.pressHome.bind(this), true, true);
this.listenKey(api.core.KeyCodes.END, this.pressEnd.bind(this), true, true);
this.addAscent(TabEmission.PRESS_KEY, this.pressKey.bind(this));
this.addAscent(TabEmission.LIST_HEIGHT, this.setListHeight.bind(this));
this.isRendering = true;

if (this.list) this.list.apply();
}

get list () {
return this.element.getDescendantInstances('TabsList', 'TabsGroup', true)[0];
setListHeight (value) {
this.listHeight = value;
}

transitionend (e) {
Expand All @@ -38,6 +36,26 @@ class TabsGroup extends api.core.DisclosuresGroup {
return this.members.some(member => member.buttonHasFocus);
}

pressKey (key) {
switch (key) {
case TabKeys.LEFT:
this.pressLeft();
break;

case TabKeys.RIGHT:
this.pressRight();
break;

case TabKeys.HOME:
this.pressHome();
break;

case TabKeys.END:
this.pressEnd();
break;
}
}

/**
* Selectionne l'element suivant de la liste si on est sur un bouton
* Si on est à la fin on retourne au début
Expand Down Expand Up @@ -119,9 +137,7 @@ class TabsGroup extends api.core.DisclosuresGroup {
const paneHeight = Math.round(this.current.node.offsetHeight);
if (this.panelHeight === paneHeight) return;
this.panelHeight = paneHeight;
let listHeight = 0;
if (this.list) listHeight = this.list.node.offsetHeight;
this.style.setProperty('--tabs-height', (this.panelHeight + listHeight) + 'px');
this.style.setProperty('--tabs-height', (this.panelHeight + this.listHeight) + 'px');
}
}

Expand Down
33 changes: 18 additions & 15 deletions src/component/tab/script/tab/tabs-list.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import api from '../../api.js';
import { TabSelector } from './tab-selector';
import { TabKeys } from './tab-keys';
import { TabEmission } from './tab-emission';
import { TableEmission } from '../../../table/script/table/table-emission';

const FOCALIZE_OFFSET = 16;
const SCROLL_OFFSET = 16; // valeur en px du scroll avant laquelle le shadow s'active ou se desactive
Expand All @@ -11,13 +14,13 @@ class TabsList extends api.core.Instance {

init () {
this.listen('scroll', this.scroll.bind(this));
this.listenKey(api.core.KeyCodes.RIGHT, this.ascend.bind(this, TabEmission.PRESS_KEY, TabKeys.RIGHT), true, true);
this.listenKey(api.core.KeyCodes.LEFT, this.ascend.bind(this, TabEmission.PRESS_KEY, TabKeys.LEFT), true, true);
this.listenKey(api.core.KeyCodes.HOME, this.ascend.bind(this, TabEmission.PRESS_KEY, TabKeys.HOME), true, true);
this.listenKey(api.core.KeyCodes.END, this.ascend.bind(this, TabEmission.PRESS_KEY, TabKeys.END), true, true);
this.isResizing = true;
}

get group () {
return this.element.getAscendantInstance('TabsGroup', 'TabsList');
}

focalize (btn) {
const btnRect = btn.getRect();
const listRect = this.getRect();
Expand All @@ -37,20 +40,18 @@ class TabsList extends api.core.Instance {
}

apply () {
if (!this.group) return;
if (this._isScrolling) {
this.group.addClass(TabSelector.SHADOW);
this.addClass(TabSelector.SHADOW);
this.scroll();
} else {
this.group.removeClass(TabSelector.SHADOW_RIGHT);
this.group.removeClass(TabSelector.SHADOW_LEFT);
this.group.removeClass(TabSelector.SHADOW);
this.removeClass(TabSelector.SHADOW_RIGHT);
this.removeClass(TabSelector.SHADOW_LEFT);
this.removeClass(TabSelector.SHADOW);
}
}

/* ajoute la classe fr-table__shadow-left ou fr-table__shadow-right sur fr-table en fonction d'une valeur de scroll et du sens (right, left) */
scroll () {
if (!this.group) return;
const scrollLeft = this.node.scrollLeft;
const isMin = scrollLeft <= SCROLL_OFFSET;
const max = this.node.scrollWidth - this.node.clientWidth - SCROLL_OFFSET;
Expand All @@ -61,21 +62,23 @@ class TabsList extends api.core.Instance {
const maxSelector = isRtl ? TabSelector.SHADOW_LEFT : TabSelector.SHADOW_RIGHT;

if (isMin) {
this.group.removeClass(minSelector);
this.removeClass(minSelector);
} else {
this.group.addClass(minSelector);
this.addClass(minSelector);
}

if (isMax) {
this.group.removeClass(maxSelector);
this.removeClass(maxSelector);
} else {
this.group.addClass(maxSelector);
this.addClass(maxSelector);
}
}

resize () {
this.isScrolling = this.node.scrollWidth > this.node.clientWidth + SCROLL_OFFSET;
this.setProperty('--tab-list-height', `${this.getRect().height}px`);
const height = this.getRect().height;
this.setProperty('--tabs-list-height', `${height}px`);
this.ascend(TabEmission.LIST_HEIGHT, height);
}

dispose () {
Expand Down
28 changes: 13 additions & 15 deletions src/component/tab/style/module/_shadow.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,22 @@
* Ombres ajoutées en Js si le contenu est plus grand que le conteneur
*/
#{ns(tabs__shadow)} {
--tab-list-height: #{space(12v)};
--tabs-list-height: #{space(12v)};

& > #{ns(tabs__list)} {
@include before('', block) {
@include absolute(4px, 0, null, 0);
@include z-index(above);
@include _tabs-scroll-shadow(false, false);
@include height(calc(var(--tab-list-height) - 8px));
opacity: 0.8;
pointer-events: none;
transition: box-shadow 0.3s;
}
@include before('', block) {
@include absolute(4px, 0, null, 0);
@include z-index(above);
@include _tabs-scroll-shadow(false, false);
@include height(calc(var(--tabs-list-height) - 8px));
opacity: 0.8;
pointer-events: none;
transition: box-shadow 0.3s;
}

/**
* Modifier ombre à gauche
**/
&--left > #{ns(tabs__list)} {
&--left {
@include before {
@include _tabs-scroll-shadow(true, false); // @TODO: à implementer dans la mixin shadow
}
Expand All @@ -35,7 +33,7 @@
/**
* Modifier ombre à droite
**/
&--right > #{ns(tabs__list)} {
&--right {
@include before {
@include _tabs-scroll-shadow(false, true); // @TODO: à implementer dans la mixin shadow
}
Expand All @@ -44,15 +42,15 @@
/**
* Modifier combinaison ombre à gauche et ombre à droite
**/
&--left#{&}--right > #{ns(tabs__list)} {
&--left#{&}--right {
@include before {
@include _tabs-scroll-shadow(true, true); // @TODO: à implementer dans la mixin shadow
}
}
}

@include selector.theme(dark) {
#{ns(tabs__shadow)} > #{ns(tabs__list)} {
#{ns(tabs__shadow)} {
@include before {
opacity: 1;
}
Expand Down

0 comments on commit 070e816

Please sign in to comment.