diff --git a/components/filter/filter.js b/components/filter/filter.js index eec6969673d..3bd1cc2dda7 100644 --- a/components/filter/filter.js +++ b/components/filter/filter.js @@ -19,6 +19,7 @@ import '../menu/menu-item.js'; import '../paging/pager-load-more.js'; import '../selection/selection-select-all.js'; import '../selection/selection-summary.js'; +import '../tooltip/tooltip.js'; import { bodyCompactStyles, bodySmallStyles, bodyStandardStyles, heading4Styles } from '../typography/styles.js'; import { css, html, LitElement, nothing } from 'lit'; @@ -37,6 +38,26 @@ const ESCAPE_KEY_CODE = 27; const FILTER_CONTENT_CLASS = 'd2l-filter-dropdown-content'; const SET_DIMENSION_ID_PREFIX = 'list-'; +let hasDisplayedKeyboardTooltip = false; + +export function resetHasDisplayedKeyboardTooltip() { + hasDisplayedKeyboardTooltip = false; +} +let spacePressed = false; +let spaceListenerAdded = false; +function addSpaceListener() { + if (spaceListenerAdded) return; + spaceListenerAdded = true; + document.addEventListener('keydown', e => { + if (e.keyCode !== 32) return; + spacePressed = true; + }); + document.addEventListener('keyup', e => { + if (e.keyCode !== 32) return; + spacePressed = false; + }); +} + /** * A filter component that contains one or more dimensions a user can filter by. * This component is in charge of all rendering. @@ -68,6 +89,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) { text: { type: String }, _activeDimensionKey: { type: String, attribute: false }, _dimensions: { type: Array, attribute: false }, + _displayKeyboardTooltip: { state: true }, _minWidth: { type: Number, attribute: false }, _totalAppliedCount: { type: Number, attribute: false } }; @@ -211,6 +233,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) { this.opened = false; this._changeEventsToDispatch = new Map(); this._dimensions = []; + this._displayKeyboardTooltip = false; this._minWidth = 285; this._openedDimensions = []; this._totalAppliedCount = 0; @@ -226,6 +249,11 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) { return 'd2l-button-subtle'; } + connectedCallback() { + super.connectedCallback(); + addSpaceListener(); + } + firstUpdated(changedProperties) { super.firstUpdated(changedProperties); this.addEventListener('d2l-filter-dimension-data-change', this._handleDimensionDataChange); @@ -590,8 +618,11 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) { } _createSetDimensionItem(item) { + const itemId = `list-item-${item.key}`; return html` + ${item.additionalContent && item.selected && this._displayKeyboardTooltip + ? html`${this.localizeHTML('components.filter.additionalContentTooltip')}` + : nothing} `; } @@ -856,6 +890,12 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) { parentListItem.classList.remove('expanding-content'); } + _handleListItemSelelcted() { + if (hasDisplayedKeyboardTooltip || !spacePressed) return; + this._displayKeyboardTooltip = true; + hasDisplayedKeyboardTooltip = true; + } + _handleSearch(e) { const dimension = this._getActiveDimension(); const searchValue = e.detail.value.trim(); @@ -903,6 +943,11 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) { this._activeFiltersSubscribers.updateSubscribers(); } + _handleTooltipHide() { + this._displayKeyboardTooltip = false; + hasDisplayedKeyboardTooltip = true; + } + _isDimensionEmpty(dimension) { switch (dimension.type) { case 'd2l-filter-dimension-set': diff --git a/components/filter/test/filter.vdiff.js b/components/filter/test/filter.vdiff.js index 9d7c30a7e52..883a6d137a1 100644 --- a/components/filter/test/filter.vdiff.js +++ b/components/filter/test/filter.vdiff.js @@ -1,12 +1,12 @@ -import '../filter.js'; import '../filter-dimension-set.js'; import '../filter-dimension-set-empty-state.js'; import '../filter-dimension-set-date-text-value.js'; import '../filter-dimension-set-date-time-range-value.js'; import '../filter-dimension-set-value.js'; -import { clickElem, expect, fixture, hoverAt, html, nextFrame, oneEvent, sendKeysElem, waitUntil } from '@brightspace-ui/testing'; +import { aTimeout, clickElem, expect, fixture, focusElem, hoverAt, html, nextFrame, oneEvent, sendKeysElem, waitUntil } from '@brightspace-ui/testing'; import { ifDefined } from 'lit/directives/if-defined.js'; import { nothing } from 'lit'; +import { resetHasDisplayedKeyboardTooltip } from '../filter.js'; function createEmptySingleDim(opts) { const { customEmptyState } = { customEmptyState: false, ...opts }; @@ -105,6 +105,16 @@ function createSingleDimDateCustom(opts) { `; } +function createSingleDimDateCustomSimple(customSelected) { + return html` + + + + + + + `; +} function createEmptyMultipleDims(opts) { const { long, text } = { long: false, ...opts }; @@ -196,6 +206,38 @@ describe('filter', () => { await expect(elem).to.be.golden(); }); + it('dates-custom-tooltip', async() => { + resetHasDisplayedKeyboardTooltip(); + const elem = await fixture(createSingleDimDateCustomSimple()); + focusElem(elem.shadowRoot.querySelector('d2l-list-item')); + sendKeysElem(elem, 'press', 'Tab+Space'); + await oneEvent(elem, 'd2l-tooltip-show'); + await nextFrame(); + await expect(document).to.be.golden(); + }); + + it('dates-custom-tooltip-selected-default', async() => { + resetHasDisplayedKeyboardTooltip(); + const elem = await fixture(createSingleDimDateCustomSimple(true)); + const listItem = elem.shadowRoot.querySelector('d2l-list-item'); + focusElem(listItem); + sendKeysElem(listItem, 'press', 'ArrowDown'); + await aTimeout(200); // make sure tooltip does not appear + await expect(document).to.be.golden(); + }); + + it('dates-custom-tooltip-selected-default-deselected-selected', async() => { + resetHasDisplayedKeyboardTooltip(); + const elem = await fixture(createSingleDimDateCustomSimple(true)); + const listItem = elem.shadowRoot.querySelector('d2l-list-item'); + focusElem(listItem); + sendKeysElem(listItem, 'press', 'ArrowDown'); + sendKeysElem(listItem, 'press', 'ArrowUp+Space'); + await oneEvent(elem, 'd2l-tooltip-show'); + await nextFrame(); + await expect(document).to.be.golden(); + }); + describe('searched', () => { [ { name: 'single-selection', search: 'empty', template: createSingleDimSingleSelection() }, diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip-selected-default-deselected-selected.png b/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip-selected-default-deselected-selected.png new file mode 100644 index 00000000000..b75647fc5c7 Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip-selected-default-deselected-selected.png differ diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip-selected-default.png b/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip-selected-default.png new file mode 100644 index 00000000000..ea74b7abe83 Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip-selected-default.png differ diff --git a/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip.png b/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip.png new file mode 100644 index 00000000000..b75647fc5c7 Binary files /dev/null and b/components/filter/test/golden/filter/chromium/single-set-dates-custom-tooltip.png differ diff --git a/lang/ar.js b/lang/ar.js index dfacb077069..a47c8facc95 100644 --- a/lang/ar.js +++ b/lang/ar.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "مهم!", "components.dropdown.close": "إغلاق", "components.filter.activeFilters": "عوامل تصفية نشطة:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "مسح", "components.filter.clearAll": "مسح الكل", "components.filter.clearAllAnnounce": "جارٍ مسح كل عوامل التصفية", diff --git a/lang/cy.js b/lang/cy.js index 1f265ad442d..8b5aaa248a4 100644 --- a/lang/cy.js +++ b/lang/cy.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Critigol!", "components.dropdown.close": "Cau", "components.filter.activeFilters": "Dim Hidlwyr Gweithredol:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Clirio", "components.filter.clearAll": "Clirio’r Cyfan", "components.filter.clearAllAnnounce": "Wrthi’n clirio’r holl hidlwyr", diff --git a/lang/da.js b/lang/da.js index d676ad14fd1..3426a2a5ee9 100644 --- a/lang/da.js +++ b/lang/da.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Kritisk!", "components.dropdown.close": "Luk", "components.filter.activeFilters": "Aktive filtre:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Ryd", "components.filter.clearAll": "Ryd alle", "components.filter.clearAllAnnounce": "Rydder alle filtre", diff --git a/lang/de.js b/lang/de.js index 9c25bc806df..43739ac8776 100644 --- a/lang/de.js +++ b/lang/de.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Kritisch!", "components.dropdown.close": "Schließen", "components.filter.activeFilters": "Aktive Filter:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Löschen", "components.filter.clearAll": "Alle löschen", "components.filter.clearAllAnnounce": "Alle Filter werden gelöscht", diff --git a/lang/en-gb.js b/lang/en-gb.js index c5f7b6e1211..d07d85c524d 100644 --- a/lang/en-gb.js +++ b/lang/en-gb.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Critical!", "components.dropdown.close": "Close", "components.filter.activeFilters": "Active Filters:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Clear", "components.filter.clearAll": "Clear All", "components.filter.clearAllAnnounce": "Clearing all filters", diff --git a/lang/en.js b/lang/en.js index deb561c60f7..bb57e998fde 100644 --- a/lang/en.js +++ b/lang/en.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Critical!", "components.dropdown.close": "Close", "components.filter.activeFilters": "Active Filters:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Clear", "components.filter.clearAll": "Clear All", "components.filter.clearAllAnnounce": "Clearing all filters", diff --git a/lang/es-es.js b/lang/es-es.js index 193015e287d..c436dc12bbb 100644 --- a/lang/es-es.js +++ b/lang/es-es.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "¡Crítico!", "components.dropdown.close": "Cerrar", "components.filter.activeFilters": "Filtros activos:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Borrar", "components.filter.clearAll": "Borrar todo", "components.filter.clearAllAnnounce": "Borrando todos los filtros", diff --git a/lang/es.js b/lang/es.js index b67ccbb690e..0f7b97c10f0 100644 --- a/lang/es.js +++ b/lang/es.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "¡Crucial!", "components.dropdown.close": "Cerrar", "components.filter.activeFilters": "Filtros activos:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Borrar", "components.filter.clearAll": "Borrar todo", "components.filter.clearAllAnnounce": "Borrando todos los filtros", diff --git a/lang/fr-fr.js b/lang/fr-fr.js index c25547ecbe5..8e9f4d20e0f 100644 --- a/lang/fr-fr.js +++ b/lang/fr-fr.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Critique !", "components.dropdown.close": "Fermer", "components.filter.activeFilters": "Filtres actifs :", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Effacer", "components.filter.clearAll": "Tout effacer", "components.filter.clearAllAnnounce": "Suppression de tous les filtres", diff --git a/lang/fr.js b/lang/fr.js index ea08d27f71f..6b42e3da1a4 100644 --- a/lang/fr.js +++ b/lang/fr.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Essentiel!", "components.dropdown.close": "Fermer", "components.filter.activeFilters": "Filtres actifs :", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Effacer", "components.filter.clearAll": "Effacer tout", "components.filter.clearAllAnnounce": "Effacement de tous les filtres en cours", diff --git a/lang/hi.js b/lang/hi.js index 1a1f2dcbfe4..2c820b975e7 100644 --- a/lang/hi.js +++ b/lang/hi.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "महत्वपूर्ण!", "components.dropdown.close": "बंद करें", "components.filter.activeFilters": "सक्रिय फ़िल्टर्स:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "साफ़ करें", "components.filter.clearAll": "सभी साफ़ करें", "components.filter.clearAllAnnounce": "सभी फिल्टर साफ़ किए जा रहे हैं", diff --git a/lang/ja.js b/lang/ja.js index 094305b931a..143982a9160 100644 --- a/lang/ja.js +++ b/lang/ja.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "重大です!", "components.dropdown.close": "閉じる", "components.filter.activeFilters": "アクティブフィルタ:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "クリア", "components.filter.clearAll": "すべてをクリア", "components.filter.clearAllAnnounce": "すべてのフィルタのクリア", diff --git a/lang/ko.js b/lang/ko.js index bdfcc5cf119..c8584e93956 100644 --- a/lang/ko.js +++ b/lang/ko.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "중요!", "components.dropdown.close": "닫기", "components.filter.activeFilters": "활성 필터:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "지우기", "components.filter.clearAll": "모두 지우기", "components.filter.clearAllAnnounce": "모든 필터 지우기", diff --git a/lang/nl.js b/lang/nl.js index 0d30c049796..75ca553c508 100644 --- a/lang/nl.js +++ b/lang/nl.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Kritiek!", "components.dropdown.close": "Sluiten", "components.filter.activeFilters": "Actieve filters:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Wissen", "components.filter.clearAll": "Alles wissen", "components.filter.clearAllAnnounce": "Alle filters wissen", diff --git a/lang/pt.js b/lang/pt.js index 2d11d1a26e2..d7af921db6a 100644 --- a/lang/pt.js +++ b/lang/pt.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Crítico!", "components.dropdown.close": "Fechar", "components.filter.activeFilters": "Filtros ativos:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Limpar", "components.filter.clearAll": "Limpar tudo", "components.filter.clearAllAnnounce": "Limpando todos os filtros", diff --git a/lang/sv.js b/lang/sv.js index 02118eed012..9d7f5d27674 100644 --- a/lang/sv.js +++ b/lang/sv.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Viktigt!", "components.dropdown.close": "Stäng", "components.filter.activeFilters": "Aktiva filter:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Rensa", "components.filter.clearAll": "Rensa alla", "components.filter.clearAllAnnounce": "Rensar alla filter", diff --git a/lang/tr.js b/lang/tr.js index 70f98a77853..b8a007fb721 100644 --- a/lang/tr.js +++ b/lang/tr.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "Kritik!", "components.dropdown.close": "Kapat", "components.filter.activeFilters": "Etkin Filtreler:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "Temizle", "components.filter.clearAll": "Tümünü Temizle", "components.filter.clearAllAnnounce": "Tüm filtreler temizleniyor", diff --git a/lang/zh-cn.js b/lang/zh-cn.js index d54f6ac8933..c328b1d8da5 100644 --- a/lang/zh-cn.js +++ b/lang/zh-cn.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "严重问题!", "components.dropdown.close": "关闭", "components.filter.activeFilters": "活动筛选器:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "清除", "components.filter.clearAll": "全部清除", "components.filter.clearAllAnnounce": "清除所有筛选器", diff --git a/lang/zh-tw.js b/lang/zh-tw.js index d2af9a12209..d324eb7f7c9 100644 --- a/lang/zh-tw.js +++ b/lang/zh-tw.js @@ -10,6 +10,7 @@ export default { "components.dialog.critical": "重大!", "components.dropdown.close": "關閉", "components.filter.activeFilters": "啟用中的篩選器:", + "components.filter.additionalContentTooltip": "Use left/right arrow keys to move focus inside this list item", "components.filter.clear": "清除", "components.filter.clearAll": "全部清除", "components.filter.clearAllAnnounce": "正在清除所有篩選器",