From bc6d25acbcf2093684066c8f8621f548f91cdfb4 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 5 Aug 2024 08:46:30 -0400 Subject: [PATCH 1/4] optional chain disconnects; fixes #2127 (#2129) --- docs/pages/resources/changelog.md | 4 ++++ src/components/carousel/carousel.component.ts | 2 +- src/components/details/details.component.ts | 2 +- src/components/range/range.component.ts | 2 +- src/components/split-panel/split-panel.component.ts | 2 +- src/components/tab-group/tab-group.component.ts | 4 ++-- src/components/textarea/textarea.component.ts | 2 +- src/components/tree/tree.component.ts | 3 +-- 8 files changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index 1d79ae57..f1df3160 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -12,6 +12,10 @@ Components with the Experimental bad New versions of Shoelace are released as-needed and generally occur when a critical mass of changes have accumulated. At any time, you can see what's coming in the next release by visiting [next.shoelace.style](https://next.shoelace.style). +## Next + +- Fixed a bug that caused errors to show in the console when components disconnect before before `firstUpdated()` executes [#2127] + ## 2.16.0 - Added the Czech translation [#2084] diff --git a/src/components/carousel/carousel.component.ts b/src/components/carousel/carousel.component.ts index e1204736..0d3d7f94 100644 --- a/src/components/carousel/carousel.component.ts +++ b/src/components/carousel/carousel.component.ts @@ -103,7 +103,7 @@ export default class SlCarousel extends ShoelaceElement { disconnectedCallback(): void { super.disconnectedCallback(); - this.mutationObserver.disconnect(); + this.mutationObserver?.disconnect(); } protected firstUpdated(): void { diff --git a/src/components/details/details.component.ts b/src/components/details/details.component.ts index 2a38fd41..ad379b99 100644 --- a/src/components/details/details.component.ts +++ b/src/components/details/details.component.ts @@ -89,7 +89,7 @@ export default class SlDetails extends ShoelaceElement { disconnectedCallback() { super.disconnectedCallback(); - this.detailsObserver.disconnect(); + this.detailsObserver?.disconnect(); } private handleSummaryClick(event: MouseEvent) { diff --git a/src/components/range/range.component.ts b/src/components/range/range.component.ts index b3b38532..853679b7 100644 --- a/src/components/range/range.component.ts +++ b/src/components/range/range.component.ts @@ -132,7 +132,7 @@ export default class SlRange extends ShoelaceElement implements ShoelaceFormCont disconnectedCallback() { super.disconnectedCallback(); - this.resizeObserver.unobserve(this.input); + this.resizeObserver?.unobserve(this.input); } private handleChange() { diff --git a/src/components/split-panel/split-panel.component.ts b/src/components/split-panel/split-panel.component.ts index c61d014a..d2d2411a 100644 --- a/src/components/split-panel/split-panel.component.ts +++ b/src/components/split-panel/split-panel.component.ts @@ -85,7 +85,7 @@ export default class SlSplitPanel extends ShoelaceElement { disconnectedCallback() { super.disconnectedCallback(); - this.resizeObserver.unobserve(this); + this.resizeObserver?.unobserve(this); } private detectSize() { diff --git a/src/components/tab-group/tab-group.component.ts b/src/components/tab-group/tab-group.component.ts index cfbd917f..14e03f0d 100644 --- a/src/components/tab-group/tab-group.component.ts +++ b/src/components/tab-group/tab-group.component.ts @@ -120,8 +120,8 @@ export default class SlTabGroup extends ShoelaceElement { disconnectedCallback() { super.disconnectedCallback(); - this.mutationObserver.disconnect(); - this.resizeObserver.unobserve(this.nav); + this.mutationObserver?.disconnect(); + this.resizeObserver?.unobserve(this.nav); } private getAllTabs() { diff --git a/src/components/textarea/textarea.component.ts b/src/components/textarea/textarea.component.ts index d0dd8d5d..9a176df2 100644 --- a/src/components/textarea/textarea.component.ts +++ b/src/components/textarea/textarea.component.ts @@ -164,7 +164,7 @@ export default class SlTextarea extends ShoelaceElement implements ShoelaceFormC disconnectedCallback() { super.disconnectedCallback(); if (this.input) { - this.resizeObserver.unobserve(this.input); + this.resizeObserver?.unobserve(this.input); } } diff --git a/src/components/tree/tree.component.ts b/src/components/tree/tree.component.ts index 23ac4663..a9bb1a1c 100644 --- a/src/components/tree/tree.component.ts +++ b/src/components/tree/tree.component.ts @@ -111,8 +111,7 @@ export default class SlTree extends ShoelaceElement { disconnectedCallback() { super.disconnectedCallback(); - - this.mutationObserver.disconnect(); + this.mutationObserver?.disconnect(); } // Generates a clone of the expand icon element to use for each tree item From 2704f7269623759deb9e31fa2cdb043bf1a648f9 Mon Sep 17 00:00:00 2001 From: Christian Schilling Date: Mon, 5 Aug 2024 15:19:06 +0200 Subject: [PATCH 2/4] Add support for sl-dropdown in the default slot of sl-breadcrumb-item (#2015) * Add support for dropdowns in the default slot * Make sure to register changes to the href attribute, too * Update src/components/breadcrumb-item/breadcrumb-item.component.ts Co-authored-by: Konnor Rogers * Update src/components/breadcrumb-item/breadcrumb-item.component.ts Co-authored-by: Konnor Rogers * Update src/components/breadcrumb-item/breadcrumb-item.component.ts Co-authored-by: Konnor Rogers * Prettier --------- Co-authored-by: Konnor Rogers --- docs/pages/components/breadcrumb.md | 58 +++++++++++++++++++ docs/pages/resources/changelog.md | 1 + .../breadcrumb-item.component.ts | 56 +++++++++++++++--- .../breadcrumb-item/breadcrumb-item.test.ts | 24 ++++++++ 4 files changed, 131 insertions(+), 8 deletions(-) diff --git a/docs/pages/components/breadcrumb.md b/docs/pages/components/breadcrumb.md index 9f707158..2a3db394 100644 --- a/docs/pages/components/breadcrumb.md +++ b/docs/pages/components/breadcrumb.md @@ -256,3 +256,61 @@ const App = () => ( ); ``` + +### With Dropdowns in default slot + +Dropdown menus can be placed in the default slot to provide additional options. + +```html:preview + + Homepage + + + + + + + Web Design + Web Development + Marketing + + + + Our Services + Digital Media + +``` + +```jsx:react +import { + SlBreadcrumb, + SlBreadcrumbItem, + SlButton, + SlDropdown, + SlIcon, + SlMenu, + SlMenuItem +} from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + + Homepage + + + + + + + + Web Design + + Web Development + Marketing + + + + Our Services + Digital Media + +); +``` diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index f1df3160..ec5b63bb 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -32,6 +32,7 @@ New versions of Shoelace are released as-needed and generally occur when a criti ## 2.15.1 +- Added support for using `` in `` default slot [#2015] - Fixed a bug in `` where if a click did not contain a `` it would show a console error. [#2009] - Fixed a bug in `` that caused it not to recalculate it's position when going from being `display: none;` to its original display value. [#1942] - Fixed a bug in `` where when it showed it would cause a layout shift. [#1967] diff --git a/src/components/breadcrumb-item/breadcrumb-item.component.ts b/src/components/breadcrumb-item/breadcrumb-item.component.ts index 5c81c15b..2afbac1d 100644 --- a/src/components/breadcrumb-item/breadcrumb-item.component.ts +++ b/src/components/breadcrumb-item/breadcrumb-item.component.ts @@ -2,7 +2,8 @@ import { classMap } from 'lit/directives/class-map.js'; import { HasSlotController } from '../../internal/slot.js'; import { html } from 'lit'; import { ifDefined } from 'lit/directives/if-defined.js'; -import { property } from 'lit/decorators.js'; +import { property, query, state } from 'lit/decorators.js'; +import { watch } from '../../internal/watch.js'; import componentStyles from '../../styles/component.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './breadcrumb-item.styles.js'; @@ -31,6 +32,10 @@ export default class SlBreadcrumbItem extends ShoelaceElement { private readonly hasSlotController = new HasSlotController(this, 'prefix', 'suffix'); + @query('slot:not([name])') defaultSlot: HTMLSlotElement; + + @state() private renderType: 'button' | 'link' | 'dropdown' = 'button'; + /** * Optional URL to direct the user to when the breadcrumb item is activated. When set, a link will be rendered * internally. When unset, a button will be rendered instead. @@ -43,9 +48,34 @@ export default class SlBreadcrumbItem extends ShoelaceElement { /** The `rel` attribute to use on the link. Only used when `href` is set. */ @property() rel = 'noreferrer noopener'; - render() { - const isLink = this.href ? true : false; + private setRenderType() { + const hasDropdown = + this.defaultSlot.assignedElements({ flatten: true }).filter(i => i.tagName.toLowerCase() === 'sl-dropdown') + .length > 0; + if (this.href) { + this.renderType = 'link'; + return; + } + + if (hasDropdown) { + this.renderType = 'dropdown'; + return; + } + + this.renderType = 'button'; + } + + @watch('href', { waitUntilFirstUpdate: true }) + hrefChanged() { + this.setRenderType(); + } + + handleSlotChange() { + this.setRenderType(); + } + + render() { return html`
- ${isLink + ${this.renderType === 'link' ? html` - + ` - : html` + : ''} + ${this.renderType === 'button' + ? html` - `} + ` + : ''} + ${this.renderType === 'dropdown' + ? html` + + ` + : ''} diff --git a/src/components/breadcrumb-item/breadcrumb-item.test.ts b/src/components/breadcrumb-item/breadcrumb-item.test.ts index b89964f6..2ec94f3a 100644 --- a/src/components/breadcrumb-item/breadcrumb-item.test.ts +++ b/src/components/breadcrumb-item/breadcrumb-item.test.ts @@ -103,6 +103,30 @@ describe('', () => { }); }); + describe('when rendering a sl-dropdown in the default slot', () => { + it('should not render a link or button tag, but a div wrapper', async () => { + el = await fixture(html` + + + + + + + Web Design + Web Development + Marketing + + + + `); + + await expect(el).to.be.accessible(); + expect(el.shadowRoot!.querySelector('a')).to.be.null; + expect(el.shadowRoot!.querySelector('button')).to.be.null; + expect(el.shadowRoot!.querySelector('div.breadcrumb-item__label--drop-down')).not.to.be.null; + }); + }); + describe('when provided an element in the slot "prefix" to support prefix icons', () => { before(async () => { el = await fixture(html` From c2e0544e4bfd144a38594ecad8f3cbfd0faa2540 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 5 Aug 2024 09:20:01 -0400 Subject: [PATCH 3/4] update changelog --- docs/pages/resources/changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index ec5b63bb..afa61857 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -14,6 +14,7 @@ New versions of Shoelace are released as-needed and generally occur when a criti ## Next +- Added support for using `` in `` default slot [#2015] - Fixed a bug that caused errors to show in the console when components disconnect before before `firstUpdated()` executes [#2127] ## 2.16.0 @@ -32,7 +33,6 @@ New versions of Shoelace are released as-needed and generally occur when a criti ## 2.15.1 -- Added support for using `` in `` default slot [#2015] - Fixed a bug in `` where if a click did not contain a `` it would show a console error. [#2009] - Fixed a bug in `` that caused it not to recalculate it's position when going from being `display: none;` to its original display value. [#1942] - Fixed a bug in `` where when it showed it would cause a layout shift. [#1967] From 5760017ad384e97eba5b66828bbaca72a2cc5179 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Mon, 5 Aug 2024 09:23:58 -0400 Subject: [PATCH 4/4] update docs --- docs/pages/components/breadcrumb.md | 116 ++++++++++++++-------------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/docs/pages/components/breadcrumb.md b/docs/pages/components/breadcrumb.md index 2a3db394..6be8c96f 100644 --- a/docs/pages/components/breadcrumb.md +++ b/docs/pages/components/breadcrumb.md @@ -199,7 +199,63 @@ const App = () => ( ### With Dropdowns -Dropdown menus can be placed in a prefix or suffix slot to provide additional options. +Dropdown menus can be placed in the default slot to provide additional options. + +```html:preview + + Homepage + + + + + + + Web Design + Web Development + Marketing + + + + Our Services + Digital Media + +``` + +```jsx:react +import { + SlBreadcrumb, + SlBreadcrumbItem, + SlButton, + SlDropdown, + SlIcon, + SlMenu, + SlMenuItem +} from '@shoelace-style/shoelace/dist/react'; + +const App = () => ( + + Homepage + + + + + + + + Web Design + + Web Development + Marketing + + + + Our Services + Digital Media + +); +``` + +Alternatively, you can place dropdown menus in a prefix or suffix slot. ```html:preview @@ -256,61 +312,3 @@ const App = () => ( ); ``` - -### With Dropdowns in default slot - -Dropdown menus can be placed in the default slot to provide additional options. - -```html:preview - - Homepage - - - - - - - Web Design - Web Development - Marketing - - - - Our Services - Digital Media - -``` - -```jsx:react -import { - SlBreadcrumb, - SlBreadcrumbItem, - SlButton, - SlDropdown, - SlIcon, - SlMenu, - SlMenuItem -} from '@shoelace-style/shoelace/dist/react'; - -const App = () => ( - - Homepage - - - - - - - - Web Design - - Web Development - Marketing - - - - Our Services - Digital Media - -); -```