diff --git a/src/component/tab/index.js b/src/component/tab/index.js index e6caca659..4cbfe9fdd 100644 --- a/src/component/tab/index.js +++ b/src/component/tab/index.js @@ -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; diff --git a/src/component/tab/script/tab/tab-emission.js b/src/component/tab/script/tab/tab-emission.js new file mode 100644 index 000000000..c818beb2f --- /dev/null +++ b/src/component/tab/script/tab/tab-emission.js @@ -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') +}; diff --git a/src/component/tab/script/tab/tab-keys.js b/src/component/tab/script/tab/tab-keys.js new file mode 100644 index 000000000..b19d57b5a --- /dev/null +++ b/src/component/tab/script/tab/tab-keys.js @@ -0,0 +1,6 @@ +export const TabKeys = { + LEFT: 'tab_keys_left', + RIGHT: 'tab_keys_right', + HOME: 'tab_keys_home', + END: 'tab_keys_end' +}; diff --git a/src/component/tab/script/tab/tabs-group.js b/src/component/tab/script/tab/tabs-group.js index e3e6bd7ec..011453ef8 100644 --- a/src/component/tab/script/tab/tabs-group.js +++ b/src/component/tab/script/tab/tabs-group.js @@ -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 @@ -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) { @@ -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 @@ -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'); } } diff --git a/src/component/tab/script/tab/tabs-list.js b/src/component/tab/script/tab/tabs-list.js index 165437337..ce9cadfbe 100644 --- a/src/component/tab/script/tab/tabs-list.js +++ b/src/component/tab/script/tab/tabs-list.js @@ -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 @@ -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(); @@ -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; @@ -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 () { diff --git a/src/component/tab/style/module/_shadow.scss b/src/component/tab/style/module/_shadow.scss index c473dfab4..8aa611324 100644 --- a/src/component/tab/style/module/_shadow.scss +++ b/src/component/tab/style/module/_shadow.scss @@ -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 } @@ -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 } @@ -44,7 +42,7 @@ /** * 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 } @@ -52,7 +50,7 @@ } @include selector.theme(dark) { - #{ns(tabs__shadow)} > #{ns(tabs__list)} { + #{ns(tabs__shadow)} { @include before { opacity: 1; }