diff --git a/packages/tabs-overflow/.npmignore b/packages/tabs-overflow/.npmignore new file mode 100644 index 0000000000..c50cbe188c --- /dev/null +++ b/packages/tabs-overflow/.npmignore @@ -0,0 +1,2 @@ +stories +test \ No newline at end of file diff --git a/packages/tabs-overflow/README.md b/packages/tabs-overflow/README.md new file mode 100644 index 0000000000..f3cdef6aca --- /dev/null +++ b/packages/tabs-overflow/README.md @@ -0,0 +1,43 @@ +## Description + +The `` is a decorator component for the `` component that enables scrolling for horizontal tabs when there is not enough width to display all of the tabs. + +### Usage + +[![See it on NPM!](https://img.shields.io/npm/v/@spectrum-web-components/tabs-overflow?style=for-the-badge)](https://www.npmjs.com/package/@spectrum-web-components/tabs-overflow) +[![How big is this package in your project?](https://img.shields.io/bundlephobia/minzip/@spectrum-web-components/tabs-overflow?style=for-the-badge)](https://bundlephobia.com/result?p=@spectrum-web-components/tabs-overflow) + +``` +yarn add @spectrum-web-components/tabs-overflow +``` + +Import the side effectful registration of `` via: + +``` +import '@spectrum-web-components/tabs-overflow/sp-tabs-overflow.js'; +``` + +When looking to leverage the `TabsOverflow` base class as a type and/or for extension purposes, do so via: + +``` +import { TabsOverflow } from '@spectrum-web-components/tabs-overflow'; +``` + +## Example + +To use the `` component, simply wrap it around the `` element as a child element, like so: + +```html + + + + + + + Content for Tab 1 + Content for Tab 2 + Content for Tab 3 + Content for Tab 4 + + +``` diff --git a/packages/tabs-overflow/exports.json b/packages/tabs-overflow/exports.json new file mode 100644 index 0000000000..cd355fd411 --- /dev/null +++ b/packages/tabs-overflow/exports.json @@ -0,0 +1,4 @@ +{ + "./src/*": "./src/*.js", + "./sp-tabs-overflow.js": "./sp-tabs-overflow.js" +} diff --git a/packages/tabs-overflow/package.json b/packages/tabs-overflow/package.json new file mode 100644 index 0000000000..c488c636ce --- /dev/null +++ b/packages/tabs-overflow/package.json @@ -0,0 +1,70 @@ +{ + "name": "@spectrum-web-components/tabs-overflow", + "version": "0.0.1", + "publishConfig": { + "access": "public" + }, + "description": "Web component implementation of a Spectrum design TabsOverflow", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/adobe/spectrum-web-components.git", + "directory": "packages/tabs-overflow" + }, + "author": "", + "homepage": "https://adobe.github.io/spectrum-web-components/components/tabs-overflow", + "bugs": { + "url": "https://github.com/adobe/spectrum-web-components/issues" + }, + "main": "src/index.js", + "module": "src/index.js", + "type": "module", + "exports": { + ".": { + "development": "./src/index.dev.js", + "default": "./src/index.js" + }, + "./package.json": "./package.json", + "./src/TabsOverflow.js": { + "development": "./src/TabsOverflow.dev.js", + "default": "./src/TabsOverflow.js" + }, + "./src/index.js": { + "development": "./src/index.dev.js", + "default": "./src/index.js" + }, + "./src/tabs-overflow.css.js": "./src/tabs-overflow.css.js", + "./sp-tabs-overflow.js": { + "development": "./sp-tabs-overflow.dev.js", + "default": "./sp-tabs-overflow.js" + } + }, + "scripts": { + "test": "echo \"Error: run tests from mono-repo root.\" && exit 1" + }, + "files": [ + "**/*.d.ts", + "**/*.js", + "**/*.js.map", + "custom-elements.json", + "!stories/", + "!test/" + ], + "keywords": [ + "spectrum css", + "web components", + "lit-element", + "lit-html" + ], + "dependencies": { + "@spectrum-web-components/base": "^0.7.2", + "tslib": "^2.0.0" + }, + "types": "./src/index.d.ts", + "customElements": "custom-elements.json", + "sideEffects": [ + "./sp-*.js", + "./**/*.dev.js", + "./**/*.dev.js" + ] +} diff --git a/packages/tabs-overflow/sp-tabs-overflow.ts b/packages/tabs-overflow/sp-tabs-overflow.ts new file mode 100644 index 0000000000..639b7be0ed --- /dev/null +++ b/packages/tabs-overflow/sp-tabs-overflow.ts @@ -0,0 +1,20 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +import { TabsOverflow } from './src/TabsOverflow.js'; + +customElements.define('sp-tabs-overflow', TabsOverflow); + +declare global { + interface HTMLElementTagNameMap { + 'sp-tabs-overflow': TabsOverflow; + } +} diff --git a/packages/tabs-overflow/src/TabsOverflow.ts b/packages/tabs-overflow/src/TabsOverflow.ts new file mode 100644 index 0000000000..182c2ccf1c --- /dev/null +++ b/packages/tabs-overflow/src/TabsOverflow.ts @@ -0,0 +1,153 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +import { + CSSResultArray, + html, + PropertyValues, + SpectrumElement, + TemplateResult, +} from '@spectrum-web-components/base'; +import { + query, + queryAssignedElements, + state, +} from '@spectrum-web-components/base/src/decorators.js'; +import { classMap } from '@spectrum-web-components/base/src/directives.js'; +import { ResizeController } from '@lit-labs/observers/resize_controller.js'; +import { Tabs } from '@spectrum-web-components/tabs'; +import '@spectrum-web-components/action-button/sp-action-button.js'; +import '@spectrum-web-components/icons-workflow/icons/sp-icon-chevron-left.js'; +import '@spectrum-web-components/icons-workflow/icons/sp-icon-chevron-right.js'; + +import styles from './tabs-overflow.css.js'; + +interface TabsOverflowState { + canScrollLeft: boolean; + canScrollRight: boolean; +} +/** + * @element sp-tabs-overflow + */ +export class TabsOverflow extends SpectrumElement { + public static override get styles(): CSSResultArray { + return [styles]; + } + + @state() + private overflowState: TabsOverflowState = { + canScrollLeft: false, + canScrollRight: false, + }; + + @queryAssignedElements({ selector: 'sp-tabs', flatten: true }) + private scrollContent!: Tabs[]; + + @query('.tabs-overflow-container') + private overflowContainer!: HTMLDivElement; + + @state() + private tabsSize = 'm'; + + resizeController!: ResizeController; + + public constructor() { + super(); + this.resizeController = new ResizeController(this, { + target: this, + callback: (): void => { + this._updateScrollState(); + }, + }); + } + + protected override firstUpdated(changes: PropertyValues): void { + super.firstUpdated(changes); + // enable scroll event + this.scrollContent[0]?.setAttribute('enableTabsScroll', ''); + this.tabsSize = this.scrollContent[0]?.getAttribute('size') || 'm'; + this.resizeController.observe(this.overflowContainer); + } + + private async _handleSlotChange(): Promise { + const [tabsElement] = this.scrollContent; + await tabsElement.updateComplete; + this._updateScrollState(); + } + + private _updateScrollState(): void { + const { scrollContent, overflowState } = this; + + if (scrollContent) { + const [tabsElement] = this.scrollContent; + const { canScrollLeft, canScrollRight } = + tabsElement?.scrollState || { + canScrollLeft: false, + canScrollRight: false, + }; + + this.overflowState = { + ...overflowState, + canScrollLeft, + canScrollRight, + }; + } + } + + private _handleScrollClick(event: MouseEvent): void { + const currentTarget = event.currentTarget as HTMLElement; + const [tabsElement] = this.scrollContent; + + const dist = tabsElement.clientWidth * 0.5; + const left = currentTarget?.classList?.contains('left-scroll') + ? -dist + : dist; + tabsElement.scrollTabs(left, 'smooth'); + } + + protected override render(): TemplateResult { + const { canScrollRight, canScrollLeft } = this.overflowState; + return html` +
+ + + + + + + +
+ `; + } +} diff --git a/packages/tabs-overflow/src/index.ts b/packages/tabs-overflow/src/index.ts new file mode 100644 index 0000000000..96d3d09b10 --- /dev/null +++ b/packages/tabs-overflow/src/index.ts @@ -0,0 +1,12 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +export * from './TabsOverflow.js'; diff --git a/packages/tabs-overflow/src/spectrum-config.js b/packages/tabs-overflow/src/spectrum-config.js new file mode 100644 index 0000000000..7692d50b8b --- /dev/null +++ b/packages/tabs-overflow/src/spectrum-config.js @@ -0,0 +1,24 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +const config = { + spectrum: '', + components: [ + { + name: 'tabs-overflow', + host: { + selector: '.spectrum-TabsOverflow', + }, + }, + ], +}; + +export default config; diff --git a/packages/tabs-overflow/src/tabs-overflow.css b/packages/tabs-overflow/src/tabs-overflow.css new file mode 100644 index 0000000000..8240e5a6b3 --- /dev/null +++ b/packages/tabs-overflow/src/tabs-overflow.css @@ -0,0 +1,137 @@ +/* +Copyright 2020 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +:host { + inset: 0; + width: 100%; + + --sp-tabs-overflow-next-button-right: -15px; + --sp-tabs-overflow-previous-button-left: -15px; + --sp-tabs-overflow-button-size: var( + --spectrum-global-dimension-static-size-500 + ); + --sp-tabs-overflow-button-top: 5px; + --sp-tabs-overflow-button-radius: 50px; + --sp-tabs-overflow-icon-color: var(--spectrum-global-color-static-gray-800); + --sp-tabs-overflow-shadow-color: var(--spectrum-global-color-static-white); + --sp-tabs-overflow-shadow-width: 50px; + --sp-tabs-overflow-shadow-border-radius: 0; +} + +sp-action-button { + width: var(--sp-tabs-overflow-button-size); + height: var(--sp-tabs-overflow-button-size); + position: absolute; + inset-block-start: var(--sp-tabs-overflow-button-top); + z-index: 2; + border-radius: var(--sp-tabs-overflow-button-radius); + border: none; + text-align: center; + box-shadow: none; + background: transparent; +} + +sp-action-button.left-scroll { + visibility: hidden; + inset-inline-end: var(--sp-tabs-overflow-previous-button-left); +} + +sp-action-button.right-scroll { + visibility: hidden; + inset-inline-end: var(--sp-tabs-overflow-next-button-right); +} + +sp-action-button.left-scroll.show, +sp-action-button.right-scroll.show { + visibility: visible; +} + +.tabs-overflow-container { + position: relative; +} + +.tabs-overflow-container.s { + --sp-tabs-overflow-button-top: 0px; +} + +.tabs-overflow-container.m { + --sp-tabs-overflow-button-top: 5px; +} + +.tabs-overflow-container.l { + --sp-tabs-overflow-button-top: 8px; +} + +.tabs-overflow-container.xl { + --sp-tabs-overflow-button-top: 12px; +} + +/* styling for shadow behind the left and right buttons */ +.tabs-overflow-container:before, +.tabs-overflow-container:after { + content: ''; + visibility: hidden; + position: absolute; + z-index: 1; + border-radius: var(--sp-tabs-overflow-shadow-border-radius); + height: 100%; + width: var(--sp-tabs-overflow-shadow-width); + pointer-events: none; + inset-block-start: 0; +} + +.tabs-overflow-container.s:before, +.tabs-overflow-container.s:after { + height: 40px; +} + +.tabs-overflow-container.m:before, +.tabs-overflow-container.m:after { + height: 48px; +} + +.tabs-overflow-container.l:before, +.tabs-overflow-container.l:after { + height: 56px; +} + +.tabs-overflow-container.xl:before, +.tabs-overflow-container.xl:after { + height: 64px; +} + +.tabs-overflow-container:before { + background: var(--spectrum-alias-background-color-transparent) + linear-gradient( + 270deg, + var(--spectrum-alias-background-color-transparent), + var(--sp-tabs-overflow-shadow-color) + ) + 0 0 no-repeat padding-box; + inset-inline-start: 0; +} + +.tabs-overflow-container:after { + background: var(--spectrum-alias-background-color-transparent) + linear-gradient( + 90deg, + var(--spectrum-alias-background-color-transparent), + var(--sp-tabs-overflow-shadow-color) + ) + 0 0 no-repeat padding-box; + inset-inline-end: 0; +} + +.tabs-overflow-container.left-shadow:before, +.tabs-overflow-container.right-shadow:after { + visibility: visible; +} diff --git a/packages/tabs-overflow/stories/tabs-overflow.stories.ts b/packages/tabs-overflow/stories/tabs-overflow.stories.ts new file mode 100644 index 0000000000..560c979343 --- /dev/null +++ b/packages/tabs-overflow/stories/tabs-overflow.stories.ts @@ -0,0 +1,97 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +import { html, nothing, TemplateResult } from '@spectrum-web-components/base'; +import { repeat } from '@spectrum-web-components/base/src/directives.js'; + +import '@spectrum-web-components/tabs/sp-tab-panel.js'; +import '@spectrum-web-components/tabs/sp-tab.js'; +import '@spectrum-web-components/tabs/sp-tabs.js'; +import '../sp-tabs-overflow.js'; + +export default { + title: 'Tabs Overflow', + component: 'sp-tabs-overflow', +}; + +const renderTabsOverflowExample = ( + count: number, + size: string, + includeTabPanel: boolean +): TemplateResult => { + return html` + +
+ + + ${repeat( + new Array(count), + (item) => item, + (_item, index) => + html` + + ` + )} + ${includeTabPanel + ? html` + ${repeat( + new Array(count), + (item) => item, + (_item, index) => + html` + + Content for Tab Item ${index + 1} + + ` + )} + ` + : nothing} + + +
+ `; +}; + +export const SpTabsAndTabPanelSizeS = (): TemplateResult => { + return renderTabsOverflowExample(20, 's', true); +}; +export const SpTabsAndTabPanelSizeM = (): TemplateResult => { + return renderTabsOverflowExample(20, 'm', true); +}; +export const SpTabsAndTabPanelSizeL = (): TemplateResult => { + return renderTabsOverflowExample(20, 'l', true); +}; +export const SpTabsAndTabPanelSizeXL = (): TemplateResult => { + return renderTabsOverflowExample(20, 'xl', true); +}; + +export const SpTabsOnlySizeS = (): TemplateResult => { + return renderTabsOverflowExample(20, 's', false); +}; +export const SpTabsOnlySizeM = (): TemplateResult => { + return renderTabsOverflowExample(20, 'm', false); +}; +export const SpTabsOnlySizeL = (): TemplateResult => { + return renderTabsOverflowExample(20, 'l', false); +}; +export const SpTabsOnlySizeXL = (): TemplateResult => { + return renderTabsOverflowExample(20, 'xl', false); +}; diff --git a/packages/tabs-overflow/test/benchmark/basic-test.ts b/packages/tabs-overflow/test/benchmark/basic-test.ts new file mode 100644 index 0000000000..25c16703a0 --- /dev/null +++ b/packages/tabs-overflow/test/benchmark/basic-test.ts @@ -0,0 +1,18 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +import '@spectrum-web-components/tabs-overflow/sp-tabs-overflow.js'; +import { html } from '@spectrum-web-components/base'; +import { measureFixtureCreation } from '../../../../test/benchmark/helpers.js'; + +measureFixtureCreation(html` + +`); diff --git a/packages/tabs-overflow/test/tabs-overflow.test.ts b/packages/tabs-overflow/test/tabs-overflow.test.ts new file mode 100644 index 0000000000..f1316ac77f --- /dev/null +++ b/packages/tabs-overflow/test/tabs-overflow.test.ts @@ -0,0 +1,115 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +import { elementUpdated, expect, fixture } from '@open-wc/testing'; +import { html, nothing } from '@spectrum-web-components/base'; +import { repeat } from 'lit/directives/repeat.js'; + +import { TabsOverflow } from '../src/TabsOverflow'; +import { ActionButton } from '@spectrum-web-components/action-button'; +import '@spectrum-web-components/theme/sp-theme.js'; +import '@spectrum-web-components/theme/scale-medium.js'; +import '@spectrum-web-components/theme/theme-light.js'; +import '../sp-tabs-overflow.js'; + +const renderTabsOverflow = async ( + count: number, + size: string, + includeTabPanel: boolean +): Promise => { + const tabsContainer = await fixture( + html` +
+ + + ${repeat( + new Array(count), + (item) => item, + (_item, index) => + html` + + ` + )} + ${includeTabPanel + ? html` + ${repeat( + new Array(count), + (item) => item, + (_item, index) => + html` + + Content for Tab Item + ${index + 1} + + ` + )} + ` + : nothing} + + +
+ ` + ); + await elementUpdated(tabsContainer); + return tabsContainer; +}; + +describe('TabsOverflow', () => { + it('loads default tabs-overflow accessibly', async () => { + const el = await fixture( + html` + + + + + Tab Content 1 + Tab Content 2 + + + ` + ); + + await elementUpdated(el); + + await expect(el).to.be.accessible(); + }); + + it('show render left and right buttons in shadowDom', async () => { + const el = await renderTabsOverflow(20, 'l', true); + + const spTabsOverflows: TabsOverflow = el.querySelector( + 'sp-tabs-overflow' + ) as TabsOverflow; + const rightButton = spTabsOverflows.shadowRoot.querySelector( + '.right-scroll' + ) as ActionButton; + expect(rightButton).to.exist; + const leftButton = spTabsOverflows.shadowRoot.querySelector( + '.left-scroll' + ) as ActionButton; + expect(leftButton).to.exist; + }); + + it('reflect proper sp-tab size', async () => { + const el = await renderTabsOverflow(20, 'm', true); + + const spTabsOverflows: TabsOverflow = el.querySelector( + 'sp-tabs-overflow' + ) as TabsOverflow; + const overflowContainerEl = spTabsOverflows.shadowRoot.querySelector( + '.tabs-overflow-container' + ) as HTMLDivElement; + expect(overflowContainerEl.classList[1]).to.equal('m'); + }); +}); diff --git a/packages/tabs-overflow/tsconfig.json b/packages/tabs-overflow/tsconfig.json new file mode 100644 index 0000000000..c90873db4c --- /dev/null +++ b/packages/tabs-overflow/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true, + "rootDir": "./" + }, + "include": ["*.ts", "src/*.ts"], + "exclude": ["test/*.ts", "stories/*.ts"], + "references": [{ "path": "../../tools/base" }] +} diff --git a/packages/tabs/src/Tabs.ts b/packages/tabs/src/Tabs.ts index 8ea5c25c7e..17257dd55c 100644 --- a/packages/tabs/src/Tabs.ts +++ b/packages/tabs/src/Tabs.ts @@ -23,7 +23,10 @@ import { property, query, } from '@spectrum-web-components/base/src/decorators.js'; -import { ifDefined } from '@spectrum-web-components/base/src/directives.js'; +import { + classMap, + ifDefined, +} from '@spectrum-web-components/base/src/directives.js'; import { IntersectionController } from '@lit-labs/observers/intersection_controller.js'; import { Tab } from './Tab.js'; import { Focusable } from '@spectrum-web-components/shared'; @@ -101,6 +104,9 @@ export class Tabs extends SizedMixin(Focusable) { @property() public label = ''; + @property({ type: Boolean, reflect: true }) + public enableTabsScroll = false; + /** * The tab list is displayed without a border. */ @@ -193,6 +199,29 @@ export class Tabs extends SizedMixin(Focusable) { return this.rovingTabindexController.focusInElement || this; } + public scrollTabs( + delta: number, + behavior: ScrollBehavior = 'smooth' + ): void { + this.tabList?.scrollBy({ + left: delta, + top: 0, + behavior, + }); + } + + public get scrollState(): Record { + const canScrollLeft = this.tabList?.scrollLeft > 0; + const canScrollRight = + Math.ceil(this.tabList?.scrollLeft) < + this.tabList?.scrollWidth - this.tabList?.clientWidth; + + return { + canScrollLeft, + canScrollRight, + }; + } + protected override manageAutoFocus(): void { const tabs = [...this.children] as Tab[]; const tabUpdateCompletes = tabs.map((tab) => { @@ -222,10 +251,12 @@ export class Tabs extends SizedMixin(Focusable) { protected override render(): TemplateResult { return html`
{ + this.dispatchEvent( + new Event('sp-tabs-scroll', { + bubbles: true, + composed: true, + }) + ); + }; + private onClick = (event: Event): void => { if (this.disabled) { return; diff --git a/packages/tabs/src/tabs.css b/packages/tabs/src/tabs.css index e026f2d64b..0082801c12 100644 --- a/packages/tabs/src/tabs.css +++ b/packages/tabs/src/tabs.css @@ -154,14 +154,23 @@ governing permissions and limitations under the License. :host([dir='ltr'][direction='vertical-right']) ::slotted(:not([slot])) { margin-left: 0; - margin-right: calc( - var(--spectrum-tabs-vertical-textonly-tabitem-gap) / 2 - ); /* [dir=ltr] .spectrum-Tabs--vertical .spectrum-Tabs-item */ + margin-right: calc(var(--spectrum-tabs-vertical-textonly-tabitem-gap) / 2); + + /* [dir=ltr] .spectrum-Tabs--vertical .spectrum-Tabs-item */ } :host([dir='rtl'][direction='vertical-right']) ::slotted(:not([slot])) { margin-right: 0; - margin-left: calc( - var(--spectrum-tabs-vertical-textonly-tabitem-gap) / 2 - ); /* [dir=rtl] .spectrum-Tabs--vertical .spectrum-Tabs-item */ + margin-left: calc(var(--spectrum-tabs-vertical-textonly-tabitem-gap) / 2); + + /* [dir=rtl] .spectrum-Tabs--vertical .spectrum-Tabs-item */ +} + +:host([dir][direction='horizontal']) #list.scroll { + overflow-x: auto; + scrollbar-width: none; +} + +:host([dir][direction='horizontal']) #list.scroll::-webkit-scrollbar { + display: none; }