diff --git a/docs/components/tab.md b/docs/components/tab.md
index 0a4db0a13..796004f4c 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
Tab
Active
+Closable
Disabled
```
diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md
index 981975bb0..940f2841b 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 632f36c4b..db418df28 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) => 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 65560bab0..5e6ddf357 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 62d66de0f..3c90ca07d 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'}
>
+ {this.closable && (
+
+ )}
);