diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md index 1a3eb182..916207a4 100644 --- a/docs/getting-started/changelog.md +++ b/docs/getting-started/changelog.md @@ -8,6 +8,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis ## Next +- Added `no-scroll-controls` prop to `sl-tab-group` - Fixed a bug where `disabled` could be set when buttons are rendered as links - Fixed a bug where hoisted dropdowns would render in the wrong position when place inside an `sl-dialog` - Improved `sl-dropdown` accessibility by attaching `aria-haspopup` and `aria-expanded` to the slotted trigger diff --git a/src/components.d.ts b/src/components.d.ts index a8b790db..0abcb526 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -992,6 +992,10 @@ export namespace Components { "setFocus": () => Promise; } interface SlTabGroup { + /** + * Disables the scroll arrows that appear when tabs overflow. + */ + "noScrollControls": boolean; /** * The placement of the tabs. */ @@ -2481,6 +2485,10 @@ declare namespace LocalJSX { "panel"?: string; } interface SlTabGroup { + /** + * Disables the scroll arrows that appear when tabs overflow. + */ + "noScrollControls"?: boolean; /** * Emitted when a tab is hidden. */ diff --git a/src/components/tab-group/tab-group.scss b/src/components/tab-group/tab-group.scss index 2f84ef05..0ed267ca 100644 --- a/src/components/tab-group/tab-group.scss +++ b/src/components/tab-group/tab-group.scss @@ -31,7 +31,7 @@ } } -.tab-group--horizontal-scroll .tab-group__nav-container { +.tab-group--has-scroll-controls .tab-group__nav-container { position: relative; padding: 0 var(--sl-spacing-x-large); } diff --git a/src/components/tab-group/tab-group.tsx b/src/components/tab-group/tab-group.tsx index 39efe8cc..d2548a3d 100644 --- a/src/components/tab-group/tab-group.tsx +++ b/src/components/tab-group/tab-group.tsx @@ -35,16 +35,24 @@ export class TabGroup { @Element() host: HTMLSlTabGroupElement; - @State() canScrollHorizontally = false; + @State() hasScrollControls = false; /** The placement of the tabs. */ @Prop() placement: 'top' | 'bottom' | 'left' | 'right' = 'top'; + /** Disables the scroll arrows that appear when tabs overflow. */ + @Prop() noScrollControls = false; + @Watch('placement') handlePlacementChange() { this.syncActiveTabIndicator(); } + @Watch('noScrollControls') + handleNoScrollControlsChange() { + this.updateScrollControls(); + } + /** Emitted when a tab is shown. */ @Event({ eventName: 'sl-tab-show' }) slTabShow: EventEmitter<{ name: string }>; @@ -71,9 +79,9 @@ export class TabGroup { focusVisible.observe(this.tabGroup); - this.resizeObserver = new ResizeObserver(() => this.syncHorizontalScroll()); + this.resizeObserver = new ResizeObserver(() => this.updateScrollControls()); this.resizeObserver.observe(this.nav); - requestAnimationFrame(() => this.syncHorizontalScroll()); + requestAnimationFrame(() => this.updateScrollControls()); // Update aria labels if the DOM changes this.mutationObserver = new MutationObserver(mutations => { @@ -189,6 +197,15 @@ export class TabGroup { }); } + updateScrollControls() { + if (this.noScrollControls) { + this.hasScrollControls = false; + } else { + this.hasScrollControls = + ['top', 'bottom'].includes(this.placement) && this.nav.scrollWidth > this.nav.clientWidth; + } + } + setActiveTab(tab: HTMLSlTabElement, emitEvents = true) { if (tab && tab !== this.activeTab && !tab.disabled) { const previousTab = this.activeTab; @@ -253,11 +270,6 @@ export class TabGroup { } } - syncHorizontalScroll() { - this.canScrollHorizontally = - ['top', 'bottom'].includes(this.placement) && this.nav.scrollWidth > this.nav.clientWidth; - } - render() { return (
- {this.canScrollHorizontally && ( + {this.hasScrollControls && (
- {this.canScrollHorizontally && ( + {this.hasScrollControls && (