diff --git a/docs/components/tab.md b/docs/components/tab.md index 0a4db0a1..796004f4 100644 --- a/docs/components/tab.md +++ b/docs/components/tab.md @@ -7,6 +7,7 @@ Tabs are used inside tab groups to represent tab panels. ```html preview <sl-tab>Tab</sl-tab> <sl-tab active>Active</sl-tab> +<sl-tab closable>Closable</sl-tab> <sl-tab disabled>Disabled</sl-tab> ``` diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md index 981975bb..940f2841 100644 --- a/docs/getting-started/changelog.md +++ b/docs/getting-started/changelog.md @@ -10,6 +10,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis - Added experimental `sl-resize-observer` utility - Added experimental `sl-theme` utility and updated theming documentation +- Added `closable` prop to `sl-tab` - Fixed a bug where `sl-menu-item` wouldn't render properly in the dark theme - Improved placeholder contrast in dark theme - Updated Boostrap Icons to 1.1.0 diff --git a/src/components.d.ts b/src/components.d.ts index 632f36c4..db418df2 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -976,6 +976,10 @@ export namespace Components { * Set to true to draw the tab in an active state. */ "active": boolean; + /** + * When true, the tab will be rendered with a close icon. + */ + "closable": boolean; /** * Set to true to draw the tab in a disabled state. */ @@ -2503,10 +2507,18 @@ declare namespace LocalJSX { * Set to true to draw the tab in an active state. */ "active"?: boolean; + /** + * When true, the tab will be rendered with a close icon. + */ + "closable"?: boolean; /** * Set to true to draw the tab in a disabled state. */ "disabled"?: boolean; + /** + * Emitted when the tab is closable and the close button is activated. + */ + "onSl-close"?: (event: CustomEvent<any>) => void; /** * The name of the tab panel the tab will control. The panel must be located in the same tab group. */ diff --git a/src/components/tab/tab.scss b/src/components/tab/tab.scss index 65560bab..5e6ddf35 100644 --- a/src/components/tab/tab.scss +++ b/src/components/tab/tab.scss @@ -10,6 +10,8 @@ } .tab { + display: inline-flex; + align-items: center; font-family: var(--sl-font-sans); font-size: var(--sl-font-size-small); font-weight: var(--sl-font-weight-semibold); @@ -43,3 +45,13 @@ cursor: not-allowed; } } + +.tab__close-button { + font-size: var(--sl-font-size-large); + margin-left: var(--sl-spacing-xx-small); + margin-right: calc(-1 * var(--sl-spacing-xx-small)); + + &::part(base) { + padding: var(--sl-spacing-xxx-small); + } +} diff --git a/src/components/tab/tab.tsx b/src/components/tab/tab.tsx index 62d66de0..3c90ca07 100644 --- a/src/components/tab/tab.tsx +++ b/src/components/tab/tab.tsx @@ -1,4 +1,4 @@ -import { Component, Element, Host, Method, Prop, h } from '@stencil/core'; +import { Component, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core'; let id = 0; @@ -28,9 +28,19 @@ export class Tab { /** Set to true to draw the tab in an active state. */ @Prop({ reflect: true }) active = false; + /** When true, the tab will be rendered with a close icon. */ + @Prop() closable = false; + /** Set to true to draw the tab in a disabled state. */ @Prop({ reflect: true }) disabled = false; + /** Emitted when the tab is closable and the close button is activated. */ + @Event({ eventName: 'sl-close' }) slClose: EventEmitter; + + connectedCallback() { + this.handleCloseClick = this.handleCloseClick.bind(this); + } + /** Sets focus to the tab. */ @Method() async setFocus() { @@ -43,6 +53,10 @@ export class Tab { this.tab.blur(); } + handleCloseClick() { + this.slClose.emit(); + } + render() { return ( // If the user didn't provide an ID, we'll set one so we can link tabs and tab panels with aria labels @@ -55,6 +69,7 @@ export class Tab { // States 'tab--active': this.active, + 'tab--closable': this.closable, 'tab--disabled': this.disabled }} role="tab" @@ -63,6 +78,15 @@ export class Tab { tabindex={this.disabled || !this.active ? '-1' : '0'} > <slot /> + {this.closable && ( + <sl-icon-button + name="x" + class="tab__close-button" + onClick={this.handleCloseClick} + tabIndex={-1} + aria-hidden="true" + /> + )} </div> </Host> );