From b84bd8e3cffacafb12fcfa1ad080ef14c1ac7a49 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 11:33:22 -0500 Subject: [PATCH 01/17] backport SL-2221 --- src/components/select/select.test.ts | 23 +++++++++++++++++++++++ src/components/select/select.ts | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/components/select/select.test.ts b/src/components/select/select.test.ts index 70ee423d1..f39d528ea 100644 --- a/src/components/select/select.test.ts +++ b/src/components/select/select.test.ts @@ -217,6 +217,29 @@ describe('', () => { }); }); + // This can happen in on Microsoft Edge auto-filling an associated input element in the same form + // https://github.com/shoelace-style/shoelace/issues/2117 + it('should not throw on incomplete events', async () => { + const el = await fixture(html` + + Option 1 + + `); + + const event = new KeyboardEvent('keydown'); + Object.defineProperty(event, 'target', { writable: false, value: el }); + Object.defineProperty(event, 'key', { writable: false, value: undefined }); + + /** + * If Edge does autofill, it creates a broken KeyboardEvent + * which is missing the key value. + * Using the normal dispatch mechanism does not allow to do this + * Thus passing the event directly to the private method for testing + * + * @ts-expect-error - private property */ + el.handleDocumentKeyDown(event); + }); + it('should open the listbox when any letter key is pressed with wa-select is on focus', async () => { const el = await fixture(html` diff --git a/src/components/select/select.ts b/src/components/select/select.ts index 346177bef..64a9aeb0d 100644 --- a/src/components/select/select.ts +++ b/src/components/select/select.ts @@ -417,7 +417,7 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement { } // All other "printable" keys trigger type to select - if (event.key.length === 1 || event.key === 'Backspace') { + if (event.key?.length === 1 || event.key === 'Backspace') { const allOptions = this.getAllOptions(); // Don't block important key combos like CMD+R From 6cc030fa0672f94c26a2425894d5a9967d87614b Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 11:38:18 -0500 Subject: [PATCH 02/17] backport SL-2220 --- src/components/carousel/carousel.ts | 54 ++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/components/carousel/carousel.ts b/src/components/carousel/carousel.ts index 048bcb491..18efc9a78 100644 --- a/src/components/carousel/carousel.ts +++ b/src/components/carousel/carousel.ts @@ -102,6 +102,7 @@ export default class WaCarousel extends WebAwesomeElement { private dragStartPosition: [number, number] = [-1, -1]; private readonly localize = new LocalizeController(this); private mutationObserver: MutationObserver; + private pendingSlideChange = false; connectedCallback(): void { super.connectedCallback(); @@ -285,6 +286,9 @@ export default class WaCarousel extends WebAwesomeElement { @eventOptions({ passive: true }) private handleScroll() { this.scrolling = true; + if (!this.pendingSlideChange) { + this.synchronizeSlides(); + } } /** @internal Synchronizes the slides with the IntersectionObserver API. */ @@ -302,18 +306,29 @@ export default class WaCarousel extends WebAwesomeElement { const firstIntersecting = entries.find(entry => entry.isIntersecting); - if (firstIntersecting) { - if (this.loop && firstIntersecting.target.hasAttribute('data-clone')) { - const clonePosition = Number(firstIntersecting.target.getAttribute('data-clone')); - // Scrolls to the original slide without animating, so the user won't notice that the position has changed - this.goToSlide(clonePosition, 'instant'); - } else { - const slides = this.getSlides(); + if (!firstIntersecting) { + return; + } - // Update the current index based on the first visible slide - const slideIndex = slides.indexOf(firstIntersecting.target as WaCarouselItem); - // Set the index to the first "snappable" slide - this.activeSlide = Math.ceil(slideIndex / this.slidesPerMove) * this.slidesPerMove; + const slidesWithClones = this.getSlides({ excludeClones: false }); + const slidesCount = this.getSlides().length; + + // Update the current index based on the first visible slide + const slideIndex = slidesWithClones.indexOf(firstIntersecting.target as WaCarouselItem); + // Normalize the index to ignore clones + const normalizedIndex = this.loop ? slideIndex - this.slidesPerPage : slideIndex; + + if (firstIntersecting) { + // Set the index to the closest "snappable" slide + this.activeSlide = + (Math.ceil(normalizedIndex / this.slidesPerMove) * this.slidesPerMove + slidesCount) % slidesCount; + + if (!this.scrolling) { + if (this.loop && firstIntersecting.target.hasAttribute('data-clone')) { + const clonePosition = Number(firstIntersecting.target.getAttribute('data-clone')); + // Scrolls to the original slide without animating, so the user won't notice that the position has changed + this.goToSlide(clonePosition, 'instant'); + } } } }, @@ -334,6 +349,8 @@ export default class WaCarousel extends WebAwesomeElement { this.synchronizeSlides(); this.scrolling = false; + this.pendingSlideChange = false; + this.synchronizeSlides(); } private isCarouselItem(node: Node): node is WaCarouselItem { @@ -403,7 +420,7 @@ export default class WaCarousel extends WebAwesomeElement { } @watch('activeSlide') - handelSlideChange() { + handleSlideChange() { const slides = this.getSlides(); slides.forEach((slide, i) => { slide.classList.toggle('--is-active', i === this.activeSlide); @@ -508,11 +525,14 @@ export default class WaCarousel extends WebAwesomeElement { const nextLeft = nextSlideRect.left - scrollContainerRect.left; const nextTop = nextSlideRect.top - scrollContainerRect.top; - scrollContainer.scrollTo({ - left: nextLeft + scrollContainer.scrollLeft, - top: nextTop + scrollContainer.scrollTop, - behavior - }); + if (nextLeft || nextTop) { + this.pendingSlideChange = true; + scrollContainer.scrollTo({ + left: nextLeft + scrollContainer.scrollLeft, + top: nextTop + scrollContainer.scrollTop, + behavior + }); + } } render() { From 678e3bd108f0c66709966e1cbe3d0f292ff96368 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 11:39:12 -0500 Subject: [PATCH 03/17] backport SL-2272 --- docs/docs/resources/changelog.md | 1 + src/components/rating/rating.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 70144e6ec..5d0cf4974 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -18,6 +18,7 @@ During the alpha period, things might break! We take breaking changes very serio - Added more resilient support for lazy loaded options in `` - Added support for vertical button groups - Fixed a bug in `` when using `precision` +- Fixed a bug in `` that allowed tabbing into the rating when readonly - Fixed a bug in `` where the title attribute would show with redundant info - Fixed a bug in `` that caused a memory leak in disconnected elements - Fixed a bug in `` that prevented label changes in `` from updating the controller diff --git a/src/components/rating/rating.ts b/src/components/rating/rating.ts index 152dc24f9..e2ac7974b 100644 --- a/src/components/rating/rating.ts +++ b/src/components/rating/rating.ts @@ -240,7 +240,7 @@ export default class WaRating extends WebAwesomeElement { aria-valuenow=${this.value} aria-valuemin=${0} aria-valuemax=${this.max} - tabindex=${this.disabled ? '-1' : '0'} + tabindex=${this.disabled || this.readonly ? '-1' : '0'} @click=${this.handleClick} @keydown=${this.handleKeyDown} @mouseenter=${this.handleMouseEnter} From b16821495257ef13ff8064ae089bde2111fdf97b Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 11:45:27 -0500 Subject: [PATCH 04/17] backport SL-2270 --- docs/docs/resources/changelog.md | 1 + src/translations/uk.ts | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/translations/uk.ts diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 5d0cf4974..7b59be0a6 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -14,6 +14,7 @@ During the alpha period, things might break! We take breaking changes very serio ## Next +- Added the Ukrainian translation - Added support for Enter to `` to align with ARIA APG's [window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/) - Added more resilient support for lazy loaded options in `` - Added support for vertical button groups diff --git a/src/translations/uk.ts b/src/translations/uk.ts new file mode 100644 index 000000000..5a106d53f --- /dev/null +++ b/src/translations/uk.ts @@ -0,0 +1,41 @@ +import { registerTranslation } from '../utilities/localize.js'; +import type { Translation } from '../utilities/localize.js'; + +const translation: Translation = { + $code: 'uk', + $name: 'Українська', + $dir: 'ltr', + + carousel: 'Карусель', + clearEntry: 'Очистити поле', + close: 'Закрити', + copied: 'Скопійовано', + copy: 'Скопіювати', + currentValue: 'Поточне значення', + error: 'Збій', + goToSlide: (slide, count) => `Перейти до слайда №${slide} з ${count}`, + hidePassword: 'Приховати пароль', + loading: 'Завантаження', + nextSlide: 'Наступний слайд', + numOptionsSelected: num => { + const n = num % 10; + if (n === 0) return 'не вибрано варіантів'; + if (n === 1) return 'вибрано 1 варіант'; + if (n === 2 || n === 3 || n === 4) return `вибрано ${num} варіанти`; + return `вибрано ${num} варіантів`; + }, + previousSlide: 'Попередній слайд', + progress: 'Поступ', + remove: 'Видалити', + resize: 'Змінити розмір', + scrollToEnd: 'Прокрутити в кінець', + scrollToStart: 'Прокрутити на початок', + selectAColorFromTheScreen: 'Виберіть колір на екрані', + showPassword: 'Показати пароль', + slideNum: slide => `Слайд ${slide}`, + toggleColorFormat: 'Переключити кольорову модель' +}; + +registerTranslation(translation); + +export default translation; From 2089065499bf058f3f13ee112252131c65cc711b Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 11:45:38 -0500 Subject: [PATCH 05/17] add missing translations from shoelace --- docs/docs/localization.md | 6 +++++ docs/docs/resources/changelog.md | 2 ++ src/translations/fi.ts | 39 ++++++++++++++++++++++++++++++++ src/translations/it.ts | 39 ++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 src/translations/fi.ts create mode 100644 src/translations/it.ts diff --git a/docs/docs/localization.md b/docs/docs/localization.md index 9e9f32e0c..2327b5d63 100644 --- a/docs/docs/localization.md +++ b/docs/docs/localization.md @@ -29,6 +29,7 @@ Available translations include:
- ar +- cs - da - de-ch - de @@ -36,19 +37,24 @@ Available translations include: - en - es - fa +- fi - fr - he - hr - hu - id +- it - ja +- nb - nl +- nn - pl - pt - ru - sl - sv - tr +- uk - zh-cn - zh-tw diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 7b59be0a6..49cc58e81 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -14,6 +14,8 @@ During the alpha period, things might break! We take breaking changes very serio ## Next +- Added the Finnish translation +- Added the Italian translation - Added the Ukrainian translation - Added support for Enter to `` to align with ARIA APG's [window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/) - Added more resilient support for lazy loaded options in `` diff --git a/src/translations/fi.ts b/src/translations/fi.ts new file mode 100644 index 000000000..e35468e84 --- /dev/null +++ b/src/translations/fi.ts @@ -0,0 +1,39 @@ +import { registerTranslation } from '@shoelace-style/localize'; +import type { Translation } from '../utilities/localize.js'; + +const translation: Translation = { + $code: 'fi', + $name: 'Suomi', + $dir: 'ltr', + + carousel: 'Karuselli', + clearEntry: 'Poista merkintä', + close: 'Sulje', + copied: 'Kopioitu', + copy: 'Kopioi', + currentValue: 'Nykyinen arvo', + error: 'Virhe', + goToSlide: (slide, count) => `Siirry diaan ${slide} / ${count}`, + hidePassword: 'Piilota salasana', + loading: 'Ladataan', + nextSlide: 'Seuraava dia', + numOptionsSelected: num => { + if (num === 0) return 'Ei valittuja vaihtoehtoja'; + if (num === 1) return 'Yksi vaihtoehto valittu'; + return `${num} vaihtoehtoa valittu`; + }, + previousSlide: 'Edellinen dia', + progress: 'Edistyminen', + remove: 'Poista', + resize: 'Muuta kokoa', + scrollToEnd: 'Vieritä loppuun', + scrollToStart: 'Vieritä alkuun', + selectAColorFromTheScreen: 'Valitse väri näytöltä', + showPassword: 'Näytä salasana', + slideNum: slide => `Dia ${slide}`, + toggleColorFormat: 'Vaihda väriformaattia' +}; + +registerTranslation(translation); + +export default translation; diff --git a/src/translations/it.ts b/src/translations/it.ts new file mode 100644 index 000000000..1d1bb3962 --- /dev/null +++ b/src/translations/it.ts @@ -0,0 +1,39 @@ +import { registerTranslation } from '@shoelace-style/localize'; +import type { Translation } from '../utilities/localize.js'; + +const translation: Translation = { + $code: 'it', + $name: 'Italian', + $dir: 'ltr', + + carousel: 'Carosello', + clearEntry: 'Cancella inserimento', + close: 'Chiudi', + copied: 'Copiato', + copy: 'Copia', + currentValue: 'Valore attuale', + error: 'Errore', + goToSlide: (slide, count) => `Vai alla diapositiva ${slide} di ${count}`, + hidePassword: 'Nascondi password', + loading: 'In caricamento', + nextSlide: 'Prossima diapositiva', + numOptionsSelected: num => { + if (num === 0) return 'Nessuna opzione selezionata'; + if (num === 1) return '1 opzione selezionata'; + return `${num} opzioni selezionate`; + }, + previousSlide: 'Diapositiva precedente', + progress: 'Avanzamento', + remove: 'Rimuovi', + resize: 'Ridimensiona', + scrollToEnd: 'Scorri alla fine', + scrollToStart: "Scorri all'inizio", + selectAColorFromTheScreen: 'Seleziona un colore dalla schermo', + showPassword: 'Mostra password', + slideNum: slide => `Diapositiva ${slide}`, + toggleColorFormat: 'Cambia formato colore' +}; + +registerTranslation(translation); + +export default translation; From 17fb0ef94e66e0860327248debfd054508189b1d Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 11:52:09 -0500 Subject: [PATCH 06/17] backport SL-2293 --- cspell.json | 2 ++ docs/_includes/base.njk | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index 9c65c5fbe..364836bd5 100644 --- a/cspell.json +++ b/cspell.json @@ -108,6 +108,7 @@ "multiselectable", "nextjs", "nocheck", + "noindex", "noopener", "noreferrer", "novalidate", @@ -120,6 +121,7 @@ "peta", "petabit", "Preact", + "preconnect", "prismjs", "progressbar", "radiogroup", diff --git a/docs/_includes/base.njk b/docs/_includes/base.njk index c9b0e53fb..a86627fe5 100644 --- a/docs/_includes/base.njk +++ b/docs/_includes/base.njk @@ -17,7 +17,7 @@ - + From c097b214430b1805ae3a3d3dd71b4c6b1474a869 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:03:49 -0500 Subject: [PATCH 07/17] backport SL-2274 --- src/components/popup/popup.test.ts | 23 +++++++++++++++++++++++ src/components/popup/popup.ts | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/components/popup/popup.test.ts b/src/components/popup/popup.test.ts index 8980635e0..e8bc38d31 100644 --- a/src/components/popup/popup.test.ts +++ b/src/components/popup/popup.test.ts @@ -1,8 +1,11 @@ import { expect } from '@open-wc/testing'; import { fixtures } from '../../internal/test/fixture.js'; import { html } from 'lit'; +import type WaPopup from './popup.js'; describe('', () => { + let element: WaPopup; + for (const fixture of fixtures) { describe(`with "${fixture.type}" rendering`, () => { it('should render a component', async () => { @@ -10,6 +13,26 @@ describe('', () => { expect(el).to.exist; }); + + it('should properly handle positioning when active changes', async () => { + element = await fixture(html``); + + element.active = true; + await element.updateComplete; + + // SImulate a scroll event + const event = new Event('scroll'); + window.dispatchEvent(event); + + element.active = false; + await element.updateComplete; + + // The component should not throw an error when the window is scrolled + expect(() => { + element.active = true; + window.dispatchEvent(event); + }).not.to.throw(); + }); }); } }); diff --git a/src/components/popup/popup.ts b/src/components/popup/popup.ts index 08a482cfd..33b74693b 100644 --- a/src/components/popup/popup.ts +++ b/src/components/popup/popup.ts @@ -276,7 +276,7 @@ export default class WaPopup extends WebAwesomeElement { private start() { // We can't start the positioner without an anchor - if (!this.anchorEl) { + if (!this.anchorEl || !this.active) { return; } From 5ddc832e9d4c488fcfe1a790286a8e56a5b3b31e Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:09:17 -0500 Subject: [PATCH 08/17] backport SL-2292 --- docs/docs/resources/changelog.md | 1 + src/components/select/select.styles.ts | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 49cc58e81..4d009ae4d 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -23,6 +23,7 @@ During the alpha period, things might break! We take breaking changes very serio - Fixed a bug in `` when using `precision` - Fixed a bug in `` that allowed tabbing into the rating when readonly - Fixed a bug in `` where the title attribute would show with redundant info +- Fixed a bug in `` that caused the placeholder to display incorrectly when using placeholder and multiple - Fixed a bug in `` that caused a memory leak in disconnected elements - Fixed a bug in `` that prevented label changes in `` from updating the controller - Fixed a bug in `` that caused interactive elements to be activated when dragging diff --git a/src/components/select/select.styles.ts b/src/components/select/select.styles.ts index e7f9c1575..344d3a2f5 100644 --- a/src/components/select/select.styles.ts +++ b/src/components/select/select.styles.ts @@ -164,7 +164,7 @@ export default css` margin-inline-end: var(--wa-space-s); } - .select--small.select--multiple .select__prefix::slotted(*) { + .select--small.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) { margin-inline-start: var(--wa-space-s); } @@ -192,7 +192,7 @@ export default css` margin-inline-end: var(--wa-space-m); } - .select--medium.select--multiple .select__prefix::slotted(*) { + .select--medium.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) { margin-inline-start: var(--wa-space-m); } @@ -220,7 +220,7 @@ export default css` margin-inline-end: var(--wa-space-l); } - .select--large.select--multiple .select__prefix::slotted(*) { + .select--large.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) { margin-inline-start: var(--wa-space-l); } From 73ca47b608de1c3790e751c7e1594fc82dee965b Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:12:14 -0500 Subject: [PATCH 09/17] who --- cspell.json | 1 + 1 file changed, 1 insertion(+) diff --git a/cspell.json b/cspell.json index 364836bd5..bd723e2f5 100644 --- a/cspell.json +++ b/cspell.json @@ -83,6 +83,7 @@ "jsfiddle", "keydown", "keyframes", + "Konnor", "Kool", "labelledby", "Laravel", From abedd14caca0ac58e61f4a91203ff184910039c6 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:18:17 -0500 Subject: [PATCH 10/17] backport SL-2299 --- docs/docs/components/tab-group.md | 2 +- docs/docs/resources/changelog.md | 1 + src/components/tab-group/tab-group.test.ts | 25 ++++++++++++++++++++++ src/components/tab-group/tab-group.ts | 10 +++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/docs/components/tab-group.md b/docs/docs/components/tab-group.md index 64d98462e..fb2f8ba6d 100644 --- a/docs/docs/components/tab-group.md +++ b/docs/docs/components/tab-group.md @@ -123,7 +123,7 @@ You can make a tab closable by adding a close button next to the tab and inside const tabGroup = document.querySelector('.tabs-closable'); const generalTab = tabGroup.querySelectorAll('wa-tab')[0]; const closableTab = tabGroup.querySelectorAll('wa-tab')[1]; - const closeButton = tabGroup.querySelector('wa-icon-button[slot="nav"]'); + const closeButton = tabGroup.querySelector('wa-icon-button'); const restoreButton = tabGroup.nextElementSibling.nextElementSibling; // Remove the tab when the close button is clicked diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 4d009ae4d..54007dcf6 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -27,6 +27,7 @@ During the alpha period, things might break! We take breaking changes very serio - Fixed a bug in `` that caused a memory leak in disconnected elements - Fixed a bug in `` that prevented label changes in `` from updating the controller - Fixed a bug in `` that caused interactive elements to be activated when dragging +- Fixed a bug in `` that prevented changing tabs by setting `active` on `` elements - Improved alignment of the play icon in `` - Improved behavior of link buttons to not set `noreferrer noopener` by default diff --git a/src/components/tab-group/tab-group.test.ts b/src/components/tab-group/tab-group.test.ts index 59935db59..3f1f12570 100644 --- a/src/components/tab-group/tab-group.test.ts +++ b/src/components/tab-group/tab-group.test.ts @@ -361,6 +361,31 @@ describe('', () => { return expectCustomTabToBeActiveAfter(tabGroup, () => clickOnElement(customHeader!)); }); + it('selects a tab by changing it via active property', async () => { + const tabGroup = await fixture(html` + + General + Custom + This is the general tab panel. + This is the custom tab panel. + + `); + + const customHeader = queryByTestId(tabGroup, 'custom-header')!; + const generalHeader = await waitForHeaderToBeActive(tabGroup, 'general-header'); + generalHeader.focus(); + + expect(customHeader).not.to.have.attribute('active'); + + const showEventPromise = oneEvent(tabGroup, 'wa-tab-show') as Promise; + customHeader.active = true; + + await tabGroup.updateComplete; + expect(customHeader).to.have.attribute('active'); + await expectPromiseToHaveName(showEventPromise, 'custom'); + return expectOnlyOneTabPanelToBeActive(tabGroup, 'custom-tab-content'); + }); + it('does not change if the active tab is reselected', async () => { const tabGroup = await fixture(html` diff --git a/src/components/tab-group/tab-group.ts b/src/components/tab-group/tab-group.ts index 7bbd9ace4..cc3d1709c 100644 --- a/src/components/tab-group/tab-group.ts +++ b/src/components/tab-group/tab-group.ts @@ -96,6 +96,16 @@ export default class WaTabGroup extends WebAwesomeElement { // Sync tabs when disabled states change if (mutations.some(m => m.attributeName === 'disabled')) { this.syncTabsAndPanels(); + // sync tabs when active state on tab changes + } else if (mutations.some(m => m.attributeName === 'active')) { + const tabs = mutations + .filter(m => m.attributeName === 'active' && (m.target as HTMLElement).tagName.toLowerCase() === 'wa-tab') + .map(m => m.target as WaTab); + const newActiveTab = tabs.find(tab => tab.active); + + if (newActiveTab) { + this.setActiveTab(newActiveTab); + } } }); From 58ac1c920d34e7d5dbdb7fe88e1c5eb0cb3ec8a7 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:19:49 -0500 Subject: [PATCH 11/17] fix prefixes --- docs/docs/resources/changelog.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 54007dcf6..3247b4502 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -17,17 +17,17 @@ During the alpha period, things might break! We take breaking changes very serio - Added the Finnish translation - Added the Italian translation - Added the Ukrainian translation -- Added support for Enter to `` to align with ARIA APG's [window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/) +- Added support for Enter to `` to align with ARIA APG's [window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/) - Added more resilient support for lazy loaded options in `` - Added support for vertical button groups - Fixed a bug in `` when using `precision` -- Fixed a bug in `` that allowed tabbing into the rating when readonly +- Fixed a bug in `` that allowed tabbing into the rating when readonly - Fixed a bug in `` where the title attribute would show with redundant info -- Fixed a bug in `` that caused the placeholder to display incorrectly when using placeholder and multiple +- Fixed a bug in `` that caused the placeholder to display incorrectly when using placeholder and multiple - Fixed a bug in `` that caused a memory leak in disconnected elements - Fixed a bug in `` that prevented label changes in `` from updating the controller - Fixed a bug in `` that caused interactive elements to be activated when dragging -- Fixed a bug in `` that prevented changing tabs by setting `active` on `` elements +- Fixed a bug in `` that prevented changing tabs by setting `active` on `` elements - Improved alignment of the play icon in `` - Improved behavior of link buttons to not set `noreferrer noopener` by default From 2f4379716ab8efcc97661c264910bf8ee90a3fb2 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:26:30 -0500 Subject: [PATCH 12/17] backport SL-2182 --- docs/docs/resources/changelog.md | 1 + src/components/textarea/textarea.styles.ts | 14 ++++++++++++-- src/components/textarea/textarea.ts | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 3247b4502..55bc8c0c1 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -28,6 +28,7 @@ During the alpha period, things might break! We take breaking changes very serio - Fixed a bug in `` that prevented label changes in `` from updating the controller - Fixed a bug in `` that caused interactive elements to be activated when dragging - Fixed a bug in `` that prevented changing tabs by setting `active` on `` elements +- Fixed a bug in `` causing scroll jumping when using `resize="auto"` - Improved alignment of the play icon in `` - Improved behavior of link buttons to not set `noreferrer noopener` by default diff --git a/src/components/textarea/textarea.styles.ts b/src/components/textarea/textarea.styles.ts index 174cbdc21..d96b5ccf1 100644 --- a/src/components/textarea/textarea.styles.ts +++ b/src/components/textarea/textarea.styles.ts @@ -24,7 +24,7 @@ export default css` border-style: var(--border-style); border-width: var(--border-width); box-shadow: var(--box-shadow); - display: flex; + display: grid; align-items: center; position: relative; width: 100%; @@ -38,6 +38,17 @@ export default css` cursor: text; } + .textarea__control, + .textarea__size-adjuster { + grid-area: 1 / 1 / 2 / 2; + } + + .textarea__size-adjuster { + visibility: hidden; + pointer-events: none; + opacity: 0; + } + /* Standard textareas */ .textarea--standard.textarea--focused:not(.textarea--disabled) { outline: var(--wa-focus-ring); @@ -62,7 +73,6 @@ export default css` } .textarea__control { - flex: 1 1 auto; font: inherit; line-height: var(--wa-line-height-expanded); color: var(--wa-form-control-value-color); diff --git a/src/components/textarea/textarea.ts b/src/components/textarea/textarea.ts index a752db722..33adf15c0 100644 --- a/src/components/textarea/textarea.ts +++ b/src/components/textarea/textarea.ts @@ -57,6 +57,7 @@ export default class WaTextarea extends WebAwesomeFormAssociatedElement { private resizeObserver: ResizeObserver; @query('.textarea__control') input: HTMLTextAreaElement; + @query('.textarea__size-adjuster') sizeAdjuster: HTMLTextAreaElement; @state() private hasFocus = false; @property() title = ''; // make reactive to pass through @@ -225,6 +226,8 @@ export default class WaTextarea extends WebAwesomeFormAssociatedElement { private setTextareaHeight() { if (this.resize === 'auto') { + // This prevents layout shifts. We use `clientHeight` instead of `scrollHeight` to account for if the ` + + +
From 6dd31748e9a13578170db10cfbcc8a4a7a8a77aa Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:29:23 -0500 Subject: [PATCH 13/17] backport SL-2210 --- docs/docs/resources/changelog.md | 1 + package.json | 3 +++ 2 files changed, 4 insertions(+) diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index 55bc8c0c1..db5eb7cd0 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -29,6 +29,7 @@ During the alpha period, things might break! We take breaking changes very serio - Fixed a bug in `` that caused interactive elements to be activated when dragging - Fixed a bug in `` that prevented changing tabs by setting `active` on `` elements - Fixed a bug in `` causing scroll jumping when using `resize="auto"` +- Fixed a bug with certain bundlers when using dynamic imports - Improved alignment of the play icon in `` - Improved behavior of link buttons to not set `noreferrer noopener` by default diff --git a/package.json b/package.json index 9b19e749b..05570fdce 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,13 @@ "./dist/custom-elements.json": "./dist/custom-elements.json", "./dist/webawesome.js": "./dist/webawesome.js", "./dist/webawesome.loader.js": "./dist/webawesome.loader.js", + "./dist/themes": "./dist/themes", "./dist/themes/*": "./dist/themes/*", + "./dist/components": "./dist/components", "./dist/components/*": "./dist/components/*", "./dist/react": "./dist/react/index.js", "./dist/react/*": "./dist/react/*", + "./dist/translations": "./dist/translations", "./dist/translations/*": "./dist/translations/*" }, "files": [ From 56dc07e30dfb899c64fe54cf447c5aee02864cd6 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 4 Dec 2024 12:39:03 -0500 Subject: [PATCH 14/17] backport SL-2189 --- docs/docs/resources/changelog.md | 1 + src/components/carousel/carousel.ts | 6 +++--- src/components/details/details.ts | 8 +++++--- src/components/image-comparer/image-comparer.ts | 9 ++++++--- src/components/menu-item/menu-item.ts | 4 +++- src/components/menu-item/submenu-controller.ts | 4 ++-- src/components/popup/popup.ts | 4 +++- src/components/range/range.ts | 2 +- src/components/rating/rating.ts | 9 ++++++--- src/components/split-panel/split-panel.ts | 4 ++-- src/components/tab-group/tab-group.ts | 7 +++---- src/components/tree-item/tree-item.ts | 2 +- src/components/tree/tree.ts | 4 +++- 13 files changed, 39 insertions(+), 25 deletions(-) diff --git a/docs/docs/resources/changelog.md b/docs/docs/resources/changelog.md index db5eb7cd0..f4662d9d8 100644 --- a/docs/docs/resources/changelog.md +++ b/docs/docs/resources/changelog.md @@ -32,6 +32,7 @@ During the alpha period, things might break! We take breaking changes very serio - Fixed a bug with certain bundlers when using dynamic imports - Improved alignment of the play icon in `` - Improved behavior of link buttons to not set `noreferrer noopener` by default +- Updated all checks for directionality to use `this.localize.dir()` instead of `el.matches(:dir(rtl))` so older browsers don't error out ## 3.0.0-alpha.3 diff --git a/src/components/carousel/carousel.ts b/src/components/carousel/carousel.ts index 18efc9a78..48e363441 100644 --- a/src/components/carousel/carousel.ts +++ b/src/components/carousel/carousel.ts @@ -176,7 +176,7 @@ export default class WaCarousel extends WebAwesomeElement { private handleKeyDown(event: KeyboardEvent) { if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) { const target = event.target as HTMLElement; - const isRtl = this.matches(':dir(rtl)'); + const isRtl = this.localize.dir() === 'rtl'; const isFocusInPagination = target.closest('[part~="pagination-item"]') !== null; const isNext = event.key === 'ArrowDown' || (!isRtl && event.key === 'ArrowRight') || (isRtl && event.key === 'ArrowLeft'); @@ -501,7 +501,7 @@ export default class WaCarousel extends WebAwesomeElement { : clamp(index, 0, slides.length - slidesPerPage); this.activeSlide = newActiveSlide; - const isRtl = this.matches(':dir(rtl)'); + const isRtl = this.localize.dir() === 'rtl'; // Get the index of the next slide. For looping carousel it adds `slidesPerPage` // to normalize the starting index in order to ignore the first nth clones. @@ -552,7 +552,7 @@ export default class WaCarousel extends WebAwesomeElement { } // We can't rely on `this.matches()` on the server. - const isRTL = isServer ? this.dir === 'rtl' : this.matches(':dir(rtl)'); + const isRTL = isServer ? this.dir === 'rtl' : this.localize.dir() === 'rtl'; return html`