mirror of
https://github.com/shoelace-style/shoelace.git
synced 2026-01-12 02:59:13 +00:00
Merge branch 'next' into auto-hide-tab-group-scroll-buttons
This commit is contained in:
@@ -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
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb-item>Homepage</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>
|
||||
<sl-dropdown>
|
||||
<sl-button slot="trigger" size="small" circle>
|
||||
<sl-icon label="More options" name="three-dots"></sl-icon>
|
||||
</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item type="checkbox" checked>Web Design</sl-menu-item>
|
||||
<sl-menu-item type="checkbox">Web Development</sl-menu-item>
|
||||
<sl-menu-item type="checkbox">Marketing</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Our Services</sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item>Digital Media</sl-breadcrumb-item>
|
||||
</sl-breadcrumb>
|
||||
```
|
||||
|
||||
```jsx:react
|
||||
import {
|
||||
SlBreadcrumb,
|
||||
SlBreadcrumbItem,
|
||||
SlButton,
|
||||
SlDropdown,
|
||||
SlIcon,
|
||||
SlMenu,
|
||||
SlMenuItem
|
||||
} from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => (
|
||||
<SlBreadcrumb>
|
||||
<SlBreadcrumbItem>Homepage</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>
|
||||
<SlDropdown slot="suffix">
|
||||
<SlButton slot="trigger" size="small" circle>
|
||||
<SlIcon label="More options" name="three-dots"></SlIcon>
|
||||
</SlButton>
|
||||
<SlMenu>
|
||||
<SlMenuItem type="checkbox" checked>
|
||||
Web Design
|
||||
</SlMenuItem>
|
||||
<SlMenuItem type="checkbox">Web Development</SlMenuItem>
|
||||
<SlMenuItem type="checkbox">Marketing</SlMenuItem>
|
||||
</SlMenu>
|
||||
</SlDropdown>
|
||||
</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Our Services</SlBreadcrumbItem>
|
||||
<SlBreadcrumbItem>Digital Media</SlBreadcrumbItem>
|
||||
</SlBreadcrumb>
|
||||
);
|
||||
```
|
||||
|
||||
Alternatively, you can place dropdown menus in a prefix or suffix slot.
|
||||
|
||||
```html:preview
|
||||
<sl-breadcrumb>
|
||||
|
||||
@@ -15,6 +15,8 @@ New versions of Shoelace are released as-needed and generally occur when a criti
|
||||
## Next
|
||||
|
||||
- Added ability to auto hide scroll buttons for `<sl-tab-group>` when scroll button is not clickable by adding the `auto-hide-scroll-buttons` attribute. [#2128]
|
||||
- Added support for using `<sl-dropdown>` in `<sl-breadcrumb-item>` 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
|
||||
|
||||
|
||||
@@ -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`
|
||||
<div
|
||||
part="base"
|
||||
@@ -59,7 +89,7 @@ export default class SlBreadcrumbItem extends ShoelaceElement {
|
||||
<slot name="prefix"></slot>
|
||||
</span>
|
||||
|
||||
${isLink
|
||||
${this.renderType === 'link'
|
||||
? html`
|
||||
<a
|
||||
part="label"
|
||||
@@ -68,14 +98,24 @@ export default class SlBreadcrumbItem extends ShoelaceElement {
|
||||
target="${ifDefined(this.target ? this.target : undefined)}"
|
||||
rel=${ifDefined(this.target ? this.rel : undefined)}
|
||||
>
|
||||
<slot></slot>
|
||||
<slot @slotchange=${this.handleSlotChange}></slot>
|
||||
</a>
|
||||
`
|
||||
: html`
|
||||
: ''}
|
||||
${this.renderType === 'button'
|
||||
? html`
|
||||
<button part="label" type="button" class="breadcrumb-item__label breadcrumb-item__label--button">
|
||||
<slot></slot>
|
||||
<slot @slotchange=${this.handleSlotChange}></slot>
|
||||
</button>
|
||||
`}
|
||||
`
|
||||
: ''}
|
||||
${this.renderType === 'dropdown'
|
||||
? html`
|
||||
<div part="label" class="breadcrumb-item__label breadcrumb-item__label--drop-down">
|
||||
<slot @slotchange=${this.handleSlotChange}></slot>
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
|
||||
<span part="suffix" class="breadcrumb-item__suffix">
|
||||
<slot name="suffix"></slot>
|
||||
|
||||
@@ -103,6 +103,30 @@ describe('<sl-breadcrumb-item>', () => {
|
||||
});
|
||||
});
|
||||
|
||||
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<SlBreadcrumbItem>(html`
|
||||
<sl-breadcrumb-item>
|
||||
<sl-dropdown>
|
||||
<sl-button slot="trigger" size="small" circle>
|
||||
<sl-icon label="More options" name="three-dots"></sl-icon>
|
||||
</sl-button>
|
||||
<sl-menu>
|
||||
<sl-menu-item type="checkbox" checked>Web Design</sl-menu-item>
|
||||
<sl-menu-item type="checkbox">Web Development</sl-menu-item>
|
||||
<sl-menu-item type="checkbox">Marketing</sl-menu-item>
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
</sl-breadcrumb-item>
|
||||
`);
|
||||
|
||||
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<SlBreadcrumbItem>(html`
|
||||
|
||||
@@ -103,7 +103,7 @@ export default class SlCarousel extends ShoelaceElement {
|
||||
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this.mutationObserver.disconnect();
|
||||
this.mutationObserver?.disconnect();
|
||||
}
|
||||
|
||||
protected firstUpdated(): void {
|
||||
|
||||
@@ -89,7 +89,7 @@ export default class SlDetails extends ShoelaceElement {
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.detailsObserver.disconnect();
|
||||
this.detailsObserver?.disconnect();
|
||||
}
|
||||
|
||||
private handleSummaryClick(event: MouseEvent) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -85,7 +85,7 @@ export default class SlSplitPanel extends ShoelaceElement {
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.resizeObserver.unobserve(this);
|
||||
this.resizeObserver?.unobserve(this);
|
||||
}
|
||||
|
||||
private detectSize() {
|
||||
|
||||
@@ -127,8 +127,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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user