diff --git a/.changeset/fresh-kings-slide.md b/.changeset/fresh-kings-slide.md new file mode 100644 index 00000000000..096395e8bde --- /dev/null +++ b/.changeset/fresh-kings-slide.md @@ -0,0 +1,47 @@ +--- +"@spectrum-css/tabs": major +--- + +Tab has now been migrated to Spectrum 2. This migration brings with it several major changes: + +- Emphasized variant has been removed +- The divider line has been removed and all variants now resemble what was formerly the quiet variant +- Removal of t-shirt sizes (only one size is available) +- Updated high contrast styles +- The focus indicator's size has changed to accommodate the selection indicator inside of the focus outline + +Overflow and vertical variants, aside from what applies from the notes above, remain mostly unchanged and currently are not fully supported in S2. One exception: a bug fix was made to allow density variants to be visible in the overflow variant (previously, the overflow variant was identical for both densities). + +A full list of added and removed mods can be found below. However, please note the following mod name changes: + +- --mod-tabs-divider-size is now --mod-tabs-selection-indicator-thickness +- --mod-tabs-divider-border-radius is now --mod-tabs-selection-indicator-border-radius + +Removed mods + +- "--mod-tabs-color-hover-emphasized" +- "--mod-tabs-color-key-focus-emphasized" +- "--mod-tabs-color-selected-emphasized" +- "--mod-tabs-divider-background-color" +- "--mod-tabs-divider-border-radius" +- "--mod-tabs-divider-size" +- "--mod-tabs-item-vertical-spacing" +- "--mod-tabs-list-background-direction" +- "--mod-tabs-list-background-direction-vertical" +- "--mod-tabs-list-background-direction-vertical-right" +- "--mod-tabs-selection-indicator-color-emphasized" +- "--mod-tabs-start-to-item-quiet" + +Added mods + +- "--mod-tabs-color-selected-hover" +- "--mod-tabs-color-selected-key-focus" +- "--mod-tabs-item-border-radius" +- "--mod-tabs-item-horizontal-spacing-compact" +- "--mod-tabs-label-to-selection-indicator" +- "--mod-tabs-label-to-selection-indicator-compact" +- "--mod-tabs-selection-indicator-border-radius" +- "--mod-tabs-selection-indicator-color-disabled" +- "--mod-tabs-selection-indicator-thickness" +- "--mod-tabs-side-to-icon" +- "--mod-tabs-side-to-icon-compact" diff --git a/.changeset/ripe-toys-invent.md b/.changeset/ripe-toys-invent.md new file mode 100644 index 00000000000..5bf3e004a2b --- /dev/null +++ b/.changeset/ripe-toys-invent.md @@ -0,0 +1,5 @@ +--- +"@spectrum-css/tokens": minor +--- + +Adds custom tokens for Tabs in Spectrum 2. This is intended to be a temporary change until the tokens have been added to the spectrum-tokens package. diff --git a/components/tabs/dist/metadata.json b/components/tabs/dist/metadata.json index 37e3c7b1a37..879d8bd7440 100644 --- a/components/tabs/dist/metadata.json +++ b/components/tabs/dist/metadata.json @@ -2,38 +2,33 @@ "sourceFile": "index.css", "selectors": [ ".spectrum-Tabs", - ".spectrum-Tabs .is-selected:before", - ".spectrum-Tabs .is-selected:focus", - ".spectrum-Tabs .is-selected:focus-visible", - ".spectrum-Tabs .spectrum-Tabs-item .spectrum-Icon", - ".spectrum-Tabs .spectrum-Tabs-item .spectrum-Tabs-itemLabel", + ".spectrum-Tabs .spectrum-Picker-button", + ".spectrum-Tabs .spectrum-Tabs-item.is-selected", + ".spectrum-Tabs .spectrum-Tabs-item.is-selected .spectrum-Icon", + ".spectrum-Tabs .spectrum-Tabs-item.is-selected.is-disabled .spectrum-Icon", + ".spectrum-Tabs .spectrum-Tabs-item.is-selected.is-disabled .spectrum-Tabs-selectionIndicator", ".spectrum-Tabs--horizontal", ".spectrum-Tabs--horizontal .spectrum-Tabs-item", - ".spectrum-Tabs--horizontal .spectrum-Tabs-item + :not(.spectrum-Tabs-selectionIndicator)", ".spectrum-Tabs--horizontal .spectrum-Tabs-selectionIndicator", ".spectrum-Tabs--horizontal.spectrum-Tabs--compact", - ".spectrum-Tabs--quiet", - ".spectrum-Tabs--quiet .spectrum-Tabs-selectionIndicator", ".spectrum-Tabs--vertical", ".spectrum-Tabs--vertical .spectrum-Icon", ".spectrum-Tabs--vertical .spectrum-Tabs-item", - ".spectrum-Tabs--vertical .spectrum-Tabs-item:before", ".spectrum-Tabs--vertical .spectrum-Tabs-selectionIndicator", ".spectrum-Tabs--vertical-right", ".spectrum-Tabs--vertical-right .spectrum-Icon", ".spectrum-Tabs--vertical-right .spectrum-Tabs-item", - ".spectrum-Tabs--vertical-right .spectrum-Tabs-item:before", ".spectrum-Tabs--vertical-right .spectrum-Tabs-selectionIndicator", - ".spectrum-Tabs--vertical-right.spectrum-Tabs--quiet", - ".spectrum-Tabs--vertical-right:dir(rtl)", - ".spectrum-Tabs--vertical.spectrum-Tabs--quiet", - ".spectrum-Tabs--vertical:dir(rtl)", ".spectrum-Tabs-item", ".spectrum-Tabs-item .spectrum-Icon", ".spectrum-Tabs-item .spectrum-Icon + .spectrum-Tabs-itemLabel", ".spectrum-Tabs-item.is-disabled", ".spectrum-Tabs-item.is-disabled .spectrum-Tabs-itemLabel", + ".spectrum-Tabs-item.is-disabled .spectrum-Tabs-selectionIndicator", ".spectrum-Tabs-item.is-selected", + ".spectrum-Tabs-item.is-selected.is-disabled", + ".spectrum-Tabs-item.is-selected:focus-visible", + ".spectrum-Tabs-item.is-selected:hover", ".spectrum-Tabs-item:before", ".spectrum-Tabs-item:focus-visible", ".spectrum-Tabs-item:focus-visible:before", @@ -41,18 +36,7 @@ ".spectrum-Tabs-itemLabel", ".spectrum-Tabs-itemLabel:empty", ".spectrum-Tabs-selectionIndicator", - ".spectrum-Tabs.spectrum-Tabs--compact", - ".spectrum-Tabs.spectrum-Tabs--compact.spectrum-Tabs--sizeL", - ".spectrum-Tabs.spectrum-Tabs--compact.spectrum-Tabs--sizeS", - ".spectrum-Tabs.spectrum-Tabs--compact.spectrum-Tabs--sizeXL", - ".spectrum-Tabs.spectrum-Tabs--emphasized", - ".spectrum-Tabs.spectrum-Tabs--quiet", - ".spectrum-Tabs.spectrum-Tabs--sizeL", - ".spectrum-Tabs.spectrum-Tabs--sizeS", - ".spectrum-Tabs.spectrum-Tabs--sizeXL", - ".spectrum-Tabs.spectrum-Tabs--vertical.spectrum-Tabs--compact .spectrum-Tabs-item:before", - "[dir=\"rtl\"] .spectrum-Tabs--vertical", - "[dir=\"rtl\"] .spectrum-Tabs--vertical-right" + ".spectrum-Tabs.spectrum-Tabs--compact" ], "modifiers": [ "--mod-tabs-animation-duration", @@ -62,14 +46,10 @@ "--mod-tabs-color", "--mod-tabs-color-disabled", "--mod-tabs-color-hover", - "--mod-tabs-color-hover-emphasized", "--mod-tabs-color-key-focus", - "--mod-tabs-color-key-focus-emphasized", "--mod-tabs-color-selected", - "--mod-tabs-color-selected-emphasized", - "--mod-tabs-divider-background-color", - "--mod-tabs-divider-border-radius", - "--mod-tabs-divider-size", + "--mod-tabs-color-selected-hover", + "--mod-tabs-color-selected-key-focus", "--mod-tabs-focus-indicator-border-radius", "--mod-tabs-focus-indicator-color", "--mod-tabs-focus-indicator-gap", @@ -80,24 +60,28 @@ "--mod-tabs-font-weight", "--mod-tabs-icon-size", "--mod-tabs-icon-to-text", + "--mod-tabs-item-border-radius", "--mod-tabs-item-height", "--mod-tabs-item-height-compact", "--mod-tabs-item-horizontal-spacing", - "--mod-tabs-item-vertical-spacing", + "--mod-tabs-item-horizontal-spacing-compact", + "--mod-tabs-label-to-selection-indicator", + "--mod-tabs-label-to-selection-indicator-compact", "--mod-tabs-line-height", - "--mod-tabs-list-background-direction", - "--mod-tabs-list-background-direction-vertical", - "--mod-tabs-list-background-direction-vertical-right", + "--mod-tabs-selection-indicator-border-radius", "--mod-tabs-selection-indicator-color", - "--mod-tabs-selection-indicator-color-emphasized", + "--mod-tabs-selection-indicator-color-disabled", + "--mod-tabs-selection-indicator-thickness", + "--mod-tabs-side-to-icon", + "--mod-tabs-side-to-icon-compact", "--mod-tabs-start-to-edge", - "--mod-tabs-start-to-item-quiet", "--mod-tabs-top-to-icon", "--mod-tabs-top-to-icon-compact", "--mod-tabs-top-to-text", "--mod-tabs-top-to-text-compact" ], "component": [ + "--spectrum-tab-selection-indicator-thickness", "--spectrum-tabs-animation-duration", "--spectrum-tabs-animation-ease", "--spectrum-tabs-bottom-to-text", @@ -106,9 +90,8 @@ "--spectrum-tabs-color-hover", "--spectrum-tabs-color-key-focus", "--spectrum-tabs-color-selected", - "--spectrum-tabs-divider-background-color", - "--spectrum-tabs-divider-border-radius", - "--spectrum-tabs-divider-size", + "--spectrum-tabs-color-selected-hover", + "--spectrum-tabs-color-selected-key-focus", "--spectrum-tabs-focus-indicator-border-radius", "--spectrum-tabs-focus-indicator-color", "--spectrum-tabs-focus-indicator-gap", @@ -119,103 +102,73 @@ "--spectrum-tabs-font-weight", "--spectrum-tabs-icon-size", "--spectrum-tabs-icon-to-text", + "--spectrum-tabs-item-border-radius", "--spectrum-tabs-item-height", "--spectrum-tabs-item-horizontal-spacing", - "--spectrum-tabs-item-vertical-spacing", + "--spectrum-tabs-label-to-selection-indicator", "--spectrum-tabs-line-height", - "--spectrum-tabs-list-background-direction", + "--spectrum-tabs-selection-indicator-border-radius", "--spectrum-tabs-selection-indicator-color", + "--spectrum-tabs-selection-indicator-color-disabled", + "--spectrum-tabs-selection-indicator-thickness", + "--spectrum-tabs-side-to-icon", "--spectrum-tabs-start-to-edge", "--spectrum-tabs-top-to-icon", "--spectrum-tabs-top-to-text" ], "global": [ - "--spectrum-accent-content-color-default", - "--spectrum-accent-content-color-hover", - "--spectrum-accent-content-color-key-focus", "--spectrum-animation-duration-100", "--spectrum-animation-ease-in-out", - "--spectrum-border-width-200", + "--spectrum-corner-radius-0", "--spectrum-corner-radius-100", + "--spectrum-corner-radius-full", "--spectrum-default-font-style", + "--spectrum-disabled-border-color", + "--spectrum-disabled-content-color", "--spectrum-focus-indicator-color", + "--spectrum-focus-indicator-gap", "--spectrum-focus-indicator-thickness", "--spectrum-font-size-100", - "--spectrum-font-size-200", - "--spectrum-font-size-300", - "--spectrum-font-size-75", - "--spectrum-gray-200", - "--spectrum-gray-500", "--spectrum-line-height-100", + "--spectrum-neutral-content-color-default", + "--spectrum-neutral-content-color-hover", + "--spectrum-neutral-content-color-key-focus", "--spectrum-neutral-subdued-content-color-default", "--spectrum-neutral-subdued-content-color-down", "--spectrum-neutral-subdued-content-color-hover", "--spectrum-neutral-subdued-content-color-key-focus", "--spectrum-regular-font-weight", "--spectrum-sans-font-family-stack", - "--spectrum-tab-item-bottom-to-text-extra-large", - "--spectrum-tab-item-bottom-to-text-large", + "--spectrum-spacing-200", + "--spectrum-spacing-75", + "--spectrum-tab-item-bottom-to-text-compact-medium", "--spectrum-tab-item-bottom-to-text-medium", - "--spectrum-tab-item-bottom-to-text-small", - "--spectrum-tab-item-compact-height-extra-large", - "--spectrum-tab-item-compact-height-large", "--spectrum-tab-item-compact-height-medium", - "--spectrum-tab-item-compact-height-small", - "--spectrum-tab-item-focus-indicator-gap-extra-large", - "--spectrum-tab-item-focus-indicator-gap-large", - "--spectrum-tab-item-focus-indicator-gap-medium", - "--spectrum-tab-item-focus-indicator-gap-small", - "--spectrum-tab-item-height-extra-large", - "--spectrum-tab-item-height-large", "--spectrum-tab-item-height-medium", - "--spectrum-tab-item-height-small", - "--spectrum-tab-item-start-to-edge-extra-large", - "--spectrum-tab-item-start-to-edge-large", + "--spectrum-tab-item-side-to-workflow-icon-compact-medium", + "--spectrum-tab-item-side-to-workflow-icon-medium", "--spectrum-tab-item-start-to-edge-medium", - "--spectrum-tab-item-start-to-edge-small", - "--spectrum-tab-item-to-tab-item-horizontal-extra-large", - "--spectrum-tab-item-to-tab-item-horizontal-large", + "--spectrum-tab-item-to-tab-item-compact-horizontal-medium", "--spectrum-tab-item-to-tab-item-horizontal-medium", - "--spectrum-tab-item-to-tab-item-horizontal-small", - "--spectrum-tab-item-to-tab-item-vertical-extra-large", - "--spectrum-tab-item-to-tab-item-vertical-large", - "--spectrum-tab-item-to-tab-item-vertical-medium", - "--spectrum-tab-item-to-tab-item-vertical-small", - "--spectrum-tab-item-top-to-text-compact-extra-large", - "--spectrum-tab-item-top-to-text-compact-large", "--spectrum-tab-item-top-to-text-compact-medium", - "--spectrum-tab-item-top-to-text-compact-small", - "--spectrum-tab-item-top-to-text-extra-large", - "--spectrum-tab-item-top-to-text-large", "--spectrum-tab-item-top-to-text-medium", - "--spectrum-tab-item-top-to-text-small", - "--spectrum-tab-item-top-to-workflow-icon-compact-extra-large", - "--spectrum-tab-item-top-to-workflow-icon-compact-large", "--spectrum-tab-item-top-to-workflow-icon-compact-medium", - "--spectrum-tab-item-top-to-workflow-icon-compact-small", - "--spectrum-tab-item-top-to-workflow-icon-extra-large", - "--spectrum-tab-item-top-to-workflow-icon-large", "--spectrum-tab-item-top-to-workflow-icon-medium", - "--spectrum-tab-item-top-to-workflow-icon-small", "--spectrum-text-to-visual-100", - "--spectrum-text-to-visual-200", - "--spectrum-text-to-visual-300", - "--spectrum-text-to-visual-75", - "--spectrum-workflow-icon-size-100", - "--spectrum-workflow-icon-size-200", - "--spectrum-workflow-icon-size-50", - "--spectrum-workflow-icon-size-75" + "--spectrum-workflow-icon-size-100" ], - "passthroughs": [], + "passthroughs": ["--mod-picker-block-size"], "high-contrast": [ + "--highcontrast-tabs-background-color-selected", "--highcontrast-tabs-color", "--highcontrast-tabs-color-disabled", "--highcontrast-tabs-color-hover", "--highcontrast-tabs-color-key-focus", "--highcontrast-tabs-color-selected", - "--highcontrast-tabs-divider-background-color", - "--highcontrast-tabs-focus-indicator-background-color", + "--highcontrast-tabs-color-selected-hover", + "--highcontrast-tabs-color-selected-key-focus", "--highcontrast-tabs-focus-indicator-color", - "--highcontrast-tabs-selection-indicator-color" + "--highcontrast-tabs-selection-indicator-color", + "--highcontrast-tabs-selection-indicator-color-disabled" ] } diff --git a/components/tabs/index.css b/components/tabs/index.css index c2a430f3d7c..6587e03e31c 100644 --- a/components/tabs/index.css +++ b/components/tabs/index.css @@ -1,5 +1,5 @@ /*! - * Copyright 2024 Adobe. All rights reserved. + * Copyright 2025 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 @@ -12,149 +12,66 @@ */ .spectrum-Tabs { - --spectrum-tabs-font-weight: var(--spectrum-regular-font-weight); - --spectrum-tabs-divider-background-color: var(--spectrum-gray-200); - - /* Default is Medium sizing */ - --spectrum-tabs-item-height: var(--spectrum-tab-item-height-medium); - --spectrum-tabs-item-horizontal-spacing: var(--spectrum-tab-item-to-tab-item-horizontal-medium); - --spectrum-tabs-item-vertical-spacing: var(--spectrum-tab-item-to-tab-item-vertical-medium); - --spectrum-tabs-start-to-edge: var(--spectrum-tab-item-start-to-edge-medium); - --spectrum-tabs-top-to-text: var(--spectrum-tab-item-top-to-text-medium); - --spectrum-tabs-bottom-to-text: var(--spectrum-tab-item-bottom-to-text-medium); - - --spectrum-tabs-icon-size: var(--spectrum-workflow-icon-size-75); - --spectrum-tabs-icon-to-text: var(--spectrum-text-to-visual-100); - --spectrum-tabs-top-to-icon: var(--spectrum-tab-item-top-to-workflow-icon-medium); - - --spectrum-tabs-color: var(--spectrum-neutral-subdued-content-color-default); - --spectrum-tabs-color-selected: var(--spectrum-neutral-subdued-content-color-down); - --spectrum-tabs-color-hover: var(--spectrum-neutral-subdued-content-color-hover); - --spectrum-tabs-color-key-focus: var(--spectrum-neutral-subdued-content-color-key-focus); - --spectrum-tabs-color-disabled: var(--spectrum-gray-500); - - --spectrum-tabs-font-family: var(--spectrum-sans-font-family-stack); - --spectrum-tabs-font-style: var(--spectrum-default-font-style); - --spectrum-tabs-font-size: var(--spectrum-font-size-100); - --spectrum-tabs-line-height: var(--spectrum-line-height-100); - - /* Focus Indicator */ - --spectrum-tabs-focus-indicator-width: var(--spectrum-focus-indicator-thickness); - --spectrum-tabs-focus-indicator-border-radius: var(--spectrum-corner-radius-100); - --spectrum-tabs-focus-indicator-gap: var(--spectrum-tab-item-focus-indicator-gap-medium); - --spectrum-tabs-focus-indicator-color: var(--spectrum-focus-indicator-color); - --spectrum-tabs-selection-indicator-color: var(--spectrum-neutral-subdued-content-color-down); - - --spectrum-tabs-list-background-direction: top; - --spectrum-tabs-divider-size: var(--spectrum-border-width-200); - --spectrum-tabs-divider-border-radius: 1px; - - --spectrum-tabs-animation-duration: var(--spectrum-animation-duration-100); - --spectrum-tabs-animation-ease: var(--spectrum-animation-ease-in-out); - - &.spectrum-Tabs--sizeS { - --spectrum-tabs-item-height: var(--spectrum-tab-item-height-small); - --spectrum-tabs-item-horizontal-spacing: var(--spectrum-tab-item-to-tab-item-horizontal-small); - --spectrum-tabs-item-vertical-spacing: var(--spectrum-tab-item-to-tab-item-vertical-small); - --spectrum-tabs-start-to-edge: var(--spectrum-tab-item-start-to-edge-small); - --spectrum-tabs-top-to-text: var(--spectrum-tab-item-top-to-text-small); - --spectrum-tabs-bottom-to-text: var(--spectrum-tab-item-bottom-to-text-small); - - --spectrum-tabs-icon-size: var(--spectrum-workflow-icon-size-50); - --spectrum-tabs-icon-to-text: var(--spectrum-text-to-visual-75); - --spectrum-tabs-top-to-icon: var(--spectrum-tab-item-top-to-workflow-icon-small); - - --spectrum-tabs-focus-indicator-gap: var(--spectrum-tab-item-focus-indicator-gap-small); - --spectrum-tabs-font-size: var(--spectrum-font-size-75); - } - - &.spectrum-Tabs--sizeL { - --spectrum-tabs-item-height: var(--spectrum-tab-item-height-large); - --spectrum-tabs-item-horizontal-spacing: var(--spectrum-tab-item-to-tab-item-horizontal-large); - --spectrum-tabs-item-vertical-spacing: var(--spectrum-tab-item-to-tab-item-vertical-large); - --spectrum-tabs-start-to-edge: var(--spectrum-tab-item-start-to-edge-large); - --spectrum-tabs-top-to-text: var(--spectrum-tab-item-top-to-text-large); - --spectrum-tabs-bottom-to-text: var(--spectrum-tab-item-bottom-to-text-large); - - --spectrum-tabs-icon-size: var(--spectrum-workflow-icon-size-100); - --spectrum-tabs-icon-to-text: var(--spectrum-text-to-visual-200); - --spectrum-tabs-top-to-icon: var(--spectrum-tab-item-top-to-workflow-icon-large); - - --spectrum-tabs-focus-indicator-gap: var(--spectrum-tab-item-focus-indicator-gap-large); - --spectrum-tabs-font-size: var(--spectrum-font-size-200); - } - - &.spectrum-Tabs--sizeXL { - --spectrum-tabs-item-height: var(--spectrum-tab-item-height-extra-large); - --spectrum-tabs-item-horizontal-spacing: var(--spectrum-tab-item-to-tab-item-horizontal-extra-large); - --spectrum-tabs-item-vertical-spacing: var(--spectrum-tab-item-to-tab-item-vertical-extra-large); - --spectrum-tabs-start-to-edge: var(--spectrum-tab-item-start-to-edge-extra-large); - --spectrum-tabs-top-to-text: var(--spectrum-tab-item-top-to-text-extra-large); - --spectrum-tabs-bottom-to-text: var(--spectrum-tab-item-bottom-to-text-extra-large); - - --spectrum-tabs-icon-size: var(--spectrum-workflow-icon-size-200); - --spectrum-tabs-icon-to-text: var(--spectrum-text-to-visual-300); - --spectrum-tabs-top-to-icon: var(--spectrum-tab-item-top-to-workflow-icon-extra-large); - - --spectrum-tabs-focus-indicator-gap: var(--spectrum-tab-item-focus-indicator-gap-extra-large); - --spectrum-tabs-font-size: var(--spectrum-font-size-300); - } - - &.spectrum-Tabs--emphasized { - --mod-tabs-color-selected: var(--mod-tabs-color-selected-emphasized, var(--spectrum-accent-content-color-default)); - --mod-tabs-color-hover: var(--mod-tabs-color-hover-emphasized, var(--spectrum-accent-content-color-hover)); - --mod-tabs-color-key-focus: var(--mod-tabs-color-key-focus-emphasized, var(--spectrum-accent-content-color-key-focus)); - - --mod-tabs-selection-indicator-color: var(--mod-tabs-selection-indicator-color-emphasized, var(--spectrum-accent-content-color-default)); - } -} - -.spectrum-Tabs--vertical { - --mod-tabs-list-background-direction: var(--mod-tabs-list-background-direction-vertical, right); -} - -.spectrum-Tabs--vertical-right { - --mod-tabs-list-background-direction: var(--mod-tabs-list-background-direction-vertical-right, left); -} - -.spectrum-Tabs--vertical:dir(rtl) { - --mod-tabs-list-background-direction: var(--mod-tabs-list-background-direction-vertical, left); -} - -.spectrum-Tabs--vertical-right:dir(rtl) { - --mod-tabs-list-background-direction: var(--mod-tabs-list-background-direction-vertical, right); + --spectrum-tabs-item-height: var(--mod-tabs-item-height, var(--spectrum-tab-item-height-medium)); + --spectrum-tabs-start-to-edge: var(--mod-tabs-start-to-edge, var(--spectrum-tab-item-start-to-edge-medium)); + --spectrum-tabs-top-to-text: var(--mod-tabs-top-to-text, var(--spectrum-tab-item-top-to-text-medium)); + --spectrum-tabs-bottom-to-text: var(--mod-tabs-bottom-to-text, var(--spectrum-tab-item-bottom-to-text-medium)); + --spectrum-tabs-label-to-selection-indicator: var(--mod-tabs-label-to-selection-indicator, var(--spectrum-spacing-200)); + --spectrum-tabs-item-horizontal-spacing: var(--mod-tabs-item-horizontal-spacing, var(--spectrum-tab-item-to-tab-item-horizontal-medium)); + + --spectrum-tabs-icon-size: var(--mod-tabs-icon-size, var(--spectrum-workflow-icon-size-100)); + --spectrum-tabs-icon-to-text: var(--mod-tabs-icon-to-text, var(--spectrum-text-to-visual-100)); + --spectrum-tabs-top-to-icon: var(--mod-tabs-top-to-icon, var(--spectrum-tab-item-top-to-workflow-icon-medium)); + --spectrum-tabs-side-to-icon: var(--mod-tabs-side-to-icon, var(--spectrum-tab-item-side-to-workflow-icon-medium)); + + --spectrum-tabs-item-border-radius: var(--mod-tabs-item-border-radius, var(--spectrum-corner-radius-0)); + + --spectrum-tabs-color: var(--highcontrast-tabs-color, var(--mod-tabs-color, var(--spectrum-neutral-subdued-content-color-default))); + --spectrum-tabs-color-hover: var(--highcontrast-tabs-color-hover, var(--mod-tabs-color-hover, var(--spectrum-neutral-subdued-content-color-hover))); + --spectrum-tabs-color-key-focus: var(--highcontrast-tabs-color-key-focus, var(--mod-tabs-color-key-focus, var(--spectrum-neutral-subdued-content-color-key-focus))); + --spectrum-tabs-color-selected: var(--highcontrast-tabs-color-selected, var(--mod-tabs-color-selected, var(--spectrum-neutral-content-color-default))); + --spectrum-tabs-color-selected-hover: var(--highcontrast-tabs-color-selected-hover, var(--mod-tabs-color-selected-hover, var(--spectrum-neutral-content-color-hover))); + --spectrum-tabs-color-selected-key-focus: var(--highcontrast-tabs-color-selected-key-focus, var(--mod-tabs-color-selected-key-focus, var(--spectrum-neutral-content-color-key-focus))); + --spectrum-tabs-color-disabled: var(--highcontrast-tabs-color-disabled, var(--mod-tabs-color-disabled, var(--spectrum-disabled-content-color))); + --spectrum-tabs-selection-indicator-color-disabled: var(--highcontrast-tabs-selection-indicator-color-disabled, var(--mod-tabs-selection-indicator-color-disabled, var(--spectrum-disabled-border-color))); + + --spectrum-tabs-font-weight: var(--mod-tabs-font-weight, var(--spectrum-regular-font-weight)); + --spectrum-tabs-font-family: var(--mod-tabs-font-family, var(--spectrum-sans-font-family-stack)); + --spectrum-tabs-font-style: var(--mod-tabs-font-style, var(--spectrum-default-font-style)); + --spectrum-tabs-font-size: var(--mod-tabs-font-size, var(--spectrum-font-size-100)); + --spectrum-tabs-line-height: var(--mod-tabs-line-height, var(--spectrum-line-height-100)); + + --spectrum-tabs-focus-indicator-width: var(--mod-tabs-focus-indicator-width, var(--spectrum-focus-indicator-thickness)); + --spectrum-tabs-focus-indicator-border-radius: var(--mod-tabs-focus-indicator-border-radius, var(--spectrum-corner-radius-100)); /* component rounding + focus indicator thickness + focus indicator gap = 0 + 2px + 2px = 4px */ + --spectrum-tabs-focus-indicator-gap: var(--mod-tabs-focus-indicator-gap, var(--spectrum-focus-indicator-gap)); + --spectrum-tabs-focus-indicator-color: var(--highcontrast-tabs-focus-indicator-color, var(--mod-tabs-focus-indicator-color, var(--spectrum-focus-indicator-color))); + + --spectrum-tabs-selection-indicator-color: var(--highcontrast-tabs-selection-indicator-color, var(--mod-tabs-selection-indicator-color, var(--spectrum-neutral-subdued-content-color-down))); + --spectrum-tabs-selection-indicator-thickness: var(--mod-tabs-selection-indicator-thickness, var(--spectrum-tab-selection-indicator-thickness)); + --spectrum-tabs-selection-indicator-border-radius: var(--mod-tabs-selection-indicator-border-radius, var(--spectrum-corner-radius-full)); + + --spectrum-tabs-animation-duration: var(--mod-tabs-animation-duration, var(--spectrum-animation-duration-100)); + --spectrum-tabs-animation-ease: var(--mod-tabs-animation-ease, var(--spectrum-animation-ease-in-out)); } .spectrum-Tabs.spectrum-Tabs--compact { - --mod-tabs-item-height: var(--mod-tabs-item-height-compact, var(--spectrum-tab-item-compact-height-medium)); - --mod-tabs-top-to-text: var(--mod-tabs-top-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-medium)); - --mod-tabs-bottom-to-text: var(--mod-tabs-bottom-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-medium)); - --mod-tabs-top-to-icon: var(--mod-tabs-top-to-icon-compact, var(--spectrum-tab-item-top-to-workflow-icon-compact-medium)); - - &.spectrum-Tabs--sizeS { - --mod-tabs-item-height: var(--mod-tabs-item-height-compact, var(--spectrum-tab-item-compact-height-small)); - --mod-tabs-top-to-text: var(--mod-tabs-top-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-small)); - --mod-tabs-bottom-to-text: var(--mod-tabs-bottom-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-small)); - --mod-tabs-top-to-icon: var(--mod-tabs-top-to-icon-compact, var(--spectrum-tab-item-top-to-workflow-icon-compact-small)); - } - - &.spectrum-Tabs--sizeL { - --mod-tabs-item-height: var(--mod-tabs-item-height-compact, var(--spectrum-tab-item-compact-height-large)); - --mod-tabs-top-to-text: var(--mod-tabs-top-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-large)); - --mod-tabs-bottom-to-text: var(--mod-tabs-bottom-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-large)); - --mod-tabs-top-to-icon: var(--mod-tabs-top-to-icon-compact, var(--spectrum-tab-item-top-to-workflow-icon-compact-large)); - } + --spectrum-tabs-item-height: var(--mod-tabs-item-height-compact, var(--spectrum-tab-item-compact-height-medium)); + --spectrum-tabs-top-to-text: var(--mod-tabs-top-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-medium)); + --spectrum-tabs-bottom-to-text: var(--mod-tabs-bottom-to-text-compact, var(--spectrum-tab-item-bottom-to-text-compact-medium)); + --spectrum-tabs-label-to-selection-indicator: var(--mod-tabs-label-to-selection-indicator-compact, var(--spectrum-spacing-75)); + --spectrum-tabs-item-horizontal-spacing: var(--mod-tabs-item-horizontal-spacing-compact, var(--spectrum-tab-item-to-tab-item-compact-horizontal-medium)); + --spectrum-tabs-top-to-icon: var(--mod-tabs-top-to-icon-compact, var(--spectrum-tab-item-top-to-workflow-icon-compact-medium)); + --spectrum-tabs-side-to-icon: var(--mod-tabs-side-to-icon-compact, var(--spectrum-tab-item-side-to-workflow-icon-compact-medium)); +} - &.spectrum-Tabs--sizeXL { - --mod-tabs-item-height: var(--mod-tabs-item-height-compact, var(--spectrum-tab-item-compact-height-extra-large)); - --mod-tabs-top-to-text: var(--mod-tabs-top-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-extra-large)); - --mod-tabs-bottom-to-text: var(--mod-tabs-bottom-to-text-compact, var(--spectrum-tab-item-top-to-text-compact-extra-large)); - --mod-tabs-top-to-icon: var(--mod-tabs-top-to-icon-compact, var(--spectrum-tab-item-top-to-workflow-icon-compact-extra-large)); - } +/* @passthrough -- picker styling for overflow tabs */ +.spectrum-Tabs .spectrum-Picker-button { + --mod-picker-block-size: var(--spectrum-tabs-item-height); } .spectrum-Tabs { display: flex; + gap: var(--spectrum-tabs-item-horizontal-spacing); /* Contain the selection indicator */ position: relative; @@ -165,8 +82,6 @@ /* Friends should align to the top of the tabs */ vertical-align: top; - - background: linear-gradient(to var(--mod-tabs-list-background-direction, var(--spectrum-tabs-list-background-direction)), var(--highcontrast-tabs-divider-background-color, var(--mod-tabs-divider-background-color, var(--spectrum-tabs-divider-background-color))) 0 var(--mod-tabs-divider-size, var(--spectrum-tabs-divider-size)), transparent var(--mod-tabs-divider-size, var(--spectrum-tabs-divider-size))); } .spectrum-Tabs-item { @@ -174,7 +89,7 @@ position: relative; box-sizing: border-box; - block-size: calc(var(--mod-tabs-item-height, var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size, var(--spectrum-tabs-divider-size))); + block-size: var(--spectrum-tabs-item-height); /* Float above the tab line */ z-index: 1; @@ -182,64 +97,78 @@ text-decoration: none; white-space: nowrap; - color: var(--highcontrast-tabs-color, var(--mod-tabs-color, var(--spectrum-tabs-color))); + color: var(--spectrum-tabs-color); - transition: color var(--mod-tabs-animation-duration, var(--spectrum-tabs-animation-duration)) ease-out; + transition: color var(--spectrum-tabs-animation-duration) ease-out; cursor: pointer; outline: none; + border-radius: var(--spectrum-tabs-item-border-radius); .spectrum-Icon { /* Vertical centering */ - block-size: var(--mod-tabs-icon-size, var(--spectrum-tabs-icon-size)); - inline-size: var(--mod-tabs-icon-size, var(--spectrum-tabs-icon-size)); - margin-block-start: var(--mod-tabs-top-to-icon, var(--spectrum-tabs-top-to-icon)); + block-size: var(--spectrum-tabs-icon-size); + inline-size: var(--spectrum-tabs-icon-size); + margin-block-start: var(--spectrum-tabs-top-to-icon); + margin-inline: var(--spectrum-tabs-side-to-icon); & + .spectrum-Tabs-itemLabel { - margin-inline-start: var(--mod-tabs-icon-to-text, var(--spectrum-tabs-icon-to-text)); + margin-inline-start: calc(var(--spectrum-tabs-icon-to-text) - var(--spectrum-tabs-side-to-icon)); } } &::before { content: ""; position: absolute; - box-sizing: border-box; - block-size: calc(100% - var(--mod-tabs-top-to-text, var(--spectrum-tabs-top-to-text))); - inline-size: calc(100% + var(--mod-tabs-focus-indicator-gap, var(--spectrum-tabs-focus-indicator-gap)) * 2); + block-size: calc(100% + var(--spectrum-tabs-focus-indicator-gap) * 2 + var(--spectrum-tabs-focus-indicator-width) * 2); + inline-size: calc(100% + var(--spectrum-tabs-focus-indicator-gap) * 2 + var(--spectrum-tabs-focus-indicator-width) * 2); + margin: calc(-1 * (var(--spectrum-tabs-focus-indicator-gap) + var(--spectrum-tabs-focus-indicator-width))); - inset-block-start: calc(var(--mod-tabs-top-to-text, var(--spectrum-tabs-top-to-text)) / 2); - inset-inline-start: calc(-1 * var(--mod-tabs-focus-indicator-gap, var(--spectrum-tabs-focus-indicator-gap))); - inset-inline-end: calc(-1 * var(--mod-tabs-focus-indicator-gap, var(--spectrum-tabs-focus-indicator-gap))); - - border: var(--mod-tabs-focus-indicator-width, var(--spectrum-tabs-focus-indicator-width)) solid transparent; - border-radius: var(--mod-tabs-focus-indicator-border-radius, var(--spectrum-tabs-focus-indicator-border-radius)); + border: var(--spectrum-tabs-focus-indicator-width) solid transparent; + border-radius: var(--spectrum-tabs-focus-indicator-border-radius); pointer-events: none; } &:hover { - color: var(--highcontrast-tabs-color-hover, var(--mod-tabs-color-hover, var(--spectrum-tabs-color-hover))); + color: var(--spectrum-tabs-color-hover); } &.is-selected { - color: var(--highcontrast-tabs-color-selected, var(--mod-tabs-color-selected, var(--spectrum-tabs-color-selected))); + color: var(--spectrum-tabs-color-selected); + + &:hover { + color: var(--spectrum-tabs-color-selected-hover); + } + + &:focus-visible { + color: var(--spectrum-tabs-color-selected-key-focus); + } + + &.is-disabled { + color: var(--spectrum-tabs-color-disabled); + } } &.is-disabled { cursor: default; - color: var(--highcontrast-tabs-color-disabled, var(--mod-tabs-color-disabled, var(--spectrum-tabs-color-disabled))); + color: var(--spectrum-tabs-color-disabled); .spectrum-Tabs-itemLabel { cursor: default; } + + .spectrum-Tabs-selectionIndicator { + background-color: var(--spectrum-tabs-selection-indicator-color-disabled); + } } &:focus-visible { - color: var(--highcontrast-tabs-color-key-focus, var(--mod-tabs-color-key-focus, var(--spectrum-tabs-color-key-focus))); + color: var(--spectrum-tabs-color-key-focus); &::before { - border-color: var(--highcontrast-tabs-focus-indicator-color, var(--mod-tabs-focus-indicator-color, var(--spectrum-tabs-focus-indicator-color))); + border-color: var(--spectrum-tabs-focus-indicator-color); } } } @@ -249,13 +178,13 @@ display: inline-block; vertical-align: top; - font-family: var(--mod-tabs-font-family, var(--spectrum-tabs-font-family)); - font-style: var(--mod-tabs-font-style, var(--spectrum-tabs-font-style)); - font-size: var(--mod-tabs-font-size, var(--spectrum-tabs-font-size)); - font-weight: var(--mod-tabs-font-weight, var(--spectrum-tabs-font-weight)); - line-height: var(--mod-tabs-line-height, var(--spectrum-tabs-line-height)); - margin-block-start: var(--mod-tabs-top-to-text, var(--spectrum-tabs-top-to-text)); - margin-block-end: var(--mod-tabs-bottom-to-text, var(--spectrum-tabs-bottom-to-text)); + font-family: var(--spectrum-tabs-font-family); + font-style: var(--spectrum-tabs-font-style); + font-size: var(--spectrum-tabs-font-size); + font-weight: var(--spectrum-tabs-font-weight); + line-height: var(--spectrum-tabs-line-height); + margin-block-start: var(--spectrum-tabs-top-to-text); + margin-block-end: var(--spectrum-tabs-bottom-to-text); /* support links */ text-decoration: none; @@ -269,15 +198,16 @@ .spectrum-Tabs-selectionIndicator { position: absolute; inset-inline-start: 0; - background-color: var(--highcontrast-tabs-selection-indicator-color, var(--mod-tabs-selection-indicator-color, var(--spectrum-tabs-selection-indicator-color))); + background-color: var(--spectrum-tabs-selection-indicator-color); /* Be below the tab */ z-index: 0; - transition: transform var(--mod-tabs-animation-duration, var(--spectrum-tabs-animation-duration)) var(--mod-tabs-animation-ease, var(--spectrum-tabs-animation-ease)); + /* @todo: set transition: none for initial positioning */ + transition: transform var(--spectrum-tabs-animation-duration) var(--spectrum-tabs-animation-ease); transform-origin: top left; - border-radius: var(--mod-tabs-divider-border-radius, var(--spectrum-tabs-divider-border-radius)); + border-radius: var(--spectrum-tabs-selection-indicator-border-radius); } .spectrum-Tabs--horizontal { @@ -285,128 +215,90 @@ .spectrum-Tabs-item { vertical-align: top; - - /* Target anything since React likes to add lots of happy
s around all things */ - & + *:not(.spectrum-Tabs-selectionIndicator) { - margin-inline-start: var(--mod-tabs-item-horizontal-spacing, var(--spectrum-tabs-item-horizontal-spacing)); - } } .spectrum-Tabs-selectionIndicator { position: absolute; inset-block-end: 0; - block-size: var(--mod-tabs-divider-size, var(--spectrum-tabs-divider-size)); + inline-size: 100%; + block-size: var(--spectrum-tabs-selection-indicator-thickness); + margin-block-start: var(--spectrum-tabs-label-to-selection-indicator); } &.spectrum-Tabs--compact { - /* The ActionButton is taller than the tabs, so don't push tabs around */ + /* The overflow ActionButton is taller than the tabs, so don't push tabs around */ box-sizing: content-box; align-items: end; } } -/* Quiet tabs should not extend all the way across the screen as their line doesn't */ -.spectrum-Tabs--quiet { - display: inline-flex; - background: none; - border-color: transparent; - - .spectrum-Tabs-selectionIndicator { - padding-inline-start: var(--mod-tabs-start-to-item-quiet); - } -} - .spectrum-Tabs--vertical, .spectrum-Tabs--vertical-right { display: inline-flex; flex-direction: column; padding: 0; - &.spectrum-Tabs--quiet { - border-color: transparent; - } - .spectrum-Tabs-item { - block-size: var(--mod-tabs-item-height, var(--spectrum-tabs-item-height)); - line-height: var(--mod-tabs-item-height, var(--spectrum-tabs-item-height)); + block-size: var(--spectrum-tabs-item-height); + line-height: var(--spectrum-tabs-item-height); padding-block: 0; - margin-block-end: var(--mod-tabs-item-vertical-spacing, var(--spectrum-tabs-item-vertical-spacing)); - margin-inline-start: var(--mod-tabs-start-to-edge, var(--spectrum-tabs-start-to-edge)); - margin-inline-end: var(--mod-tabs-start-to-edge, var(--spectrum-tabs-start-to-edge)); - - &::before { - inset-inline-start: calc(-1 * var(--mod-tabs-focus-indicator-gap, var(--spectrum-tabs-focus-indicator-gap))); - } + margin-inline-start: var(--spectrum-tabs-start-to-edge); + margin-inline-end: var(--spectrum-tabs-start-to-edge); } .spectrum-Icon { - line-height: var(--mod-tabs-item-height, var(--spectrum-tabs-item-height)); + line-height: var(--spectrum-tabs-item-height); } .spectrum-Tabs-selectionIndicator { position: absolute; - inset-inline-start: 0; + inset-inline-start: calc(-1 * var(--spectrum-tabs-start-to-edge)); inset-block-start: 0; - inline-size: var(--mod-tabs-divider-size, var(--spectrum-tabs-divider-size)); + inline-size: var(--spectrum-tabs-selection-indicator-thickness); + block-size: 100%; } } .spectrum-Tabs--vertical-right { .spectrum-Tabs-selectionIndicator { - inset-inline: auto 0; + inset-inline: auto calc(-1 * var(--spectrum-tabs-start-to-edge)); } } @media (forced-colors: active) { .spectrum-Tabs { - --highcontrast-tabs-divider-background-color: var(--spectrum-gray-500); - --highcontrast-tabs-selection-indicator-color: Highlight; - --highcontrast-tabs-focus-indicator-color: CanvasText; - --highcontrast-tabs-focus-indicator-background-color: Highlight; - + --highcontrast-tabs-background-color-selected: SelectedItem; + --highcontrast-tabs-color-selected: SelectedItemText; + --highcontrast-tabs-color-selected-key-focus: SelectedItemText; + --highcontrast-tabs-color-selected-hover: SelectedItemText; + --highcontrast-tabs-selection-indicator-color: CanvasText; + --highcontrast-tabs-focus-indicator-color: Highlight; --highcontrast-tabs-color: ButtonText; --highcontrast-tabs-color-hover: ButtonText; - --highcontrast-tabs-color-selected: HighlightText; --highcontrast-tabs-color-key-focus: ButtonText; --highcontrast-tabs-color-disabled: GrayText; + --highcontrast-tabs-selection-indicator-color-disabled: GrayText; - /* Prevents black box behind text on Highlight background */ + /* Prevents black box behind text on SelectedItem background */ forced-color-adjust: none; - .spectrum-Tabs-item { - .spectrum-Icon { - z-index: 1; - position: relative; - } - - .spectrum-Tabs-itemLabel { - position: relative; - z-index: 1; - } - } + .spectrum-Tabs-item.is-selected { + background-color: var(--highcontrast-tabs-background-color-selected); - .is-selected { - &::before { - background-color: var(--highcontrast-tabs-focus-indicator-background-color); - } - - &:focus, - &:focus-visible { + .spectrum-Icon { color: var(--highcontrast-tabs-color-selected); } - } - &.spectrum-Tabs--vertical.spectrum-Tabs--compact .spectrum-Tabs-item { - &::before { - block-size: 100%; - inset-block-start: 0; - } - } + &.is-disabled { + .spectrum-Icon { + color: var(--highcontrast-tabs-color-disabled); + } - /* Quiet tabs get a bottom border in WHCM */ - &.spectrum-Tabs--quiet { - background: linear-gradient(to var(--mod-tabs-list-background-direction, var(--spectrum-tabs-list-background-direction)), var(--highcontrast-tabs-divider-background-color, var(--mod-tabs-divider-background-color, var(--spectrum-tabs-divider-background-color))) 0 var(--mod-tabs-divider-size, var(--spectrum-tabs-divider-size)), transparent var(--mod-tabs-divider-size, var(--spectrum-tabs-divider-size))); + .spectrum-Tabs-selectionIndicator { + background-color: var(--highcontrast-tabs-selection-indicator-color-disabled); + } + } } } } diff --git a/components/tabs/stories/tabs.stories.js b/components/tabs/stories/tabs.stories.js index 1b26856e13f..93bff87afbf 100644 --- a/components/tabs/stories/tabs.stories.js +++ b/components/tabs/stories/tabs.stories.js @@ -1,10 +1,8 @@ -import { Sizes } from "@spectrum-css/preview/decorators"; import { disableDefaultModes } from "@spectrum-css/preview/modes"; -import { isEmphasized, isQuiet, size } from "@spectrum-css/preview/types"; import metadata from "../dist/metadata.json"; import packageJson from "../package.json"; import { TabsGroups } from "./tabs.test.js"; -import { CompactGroup, OverflowGroup, QuietGroup, Template, VerticalGroup } from "./template.js"; +import { CompactGroup, OverflowGroup, Template, VerticalGroup } from "./template.js"; /** * Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit. Tabs can be either horizontal or vertical. @@ -12,11 +10,13 @@ import { CompactGroup, OverflowGroup, QuietGroup, Template, VerticalGroup } from * ## Usage notes * * ### Use icons consistently - * Icons are optional, but don’t mix the use of icons in tabs if they are utilized. Navigation controls require a clear spacial relationship to one another, and mixing the use of icons can dramatically impact the visual balance and presence for each tab item. + * Icons are optional, but don't mix the use of icons in tabs if they are utilized. Navigation controls require a clear spacial relationship to one another, and mixing the use of icons can dramatically impact the visual balance and presence for each tab item. * * ### Setting the selected tab item - * Only one tab item can be selected at any given time. The selected tab item is designated by the `is-selected` class. A selection indicator line is shown under or next to the selected tab item. + * Only one tab item can be selected at any given time. The selected tab item is designated by the `.is-selected` class. A selection indicator line is shown under or next to the selected tab item. * + * ### Quiet tabs + * The quiet variant has been deprecated for Spectrum 2. By default, all tabs look similar to what was formerly the quiet variant, with no divider spanning across all tab items. */ export default { @@ -24,7 +24,6 @@ export default { component: "Tabs", argTypes: { content: { table: { disable: true } }, - size: size(["s", "m", "l", "xl"]), orientation: { name: "Orientation", type: { name: "string", required: true }, @@ -37,8 +36,6 @@ export default { control: "select", default: "horizontal", }, - isQuiet, - isEmphasized, hasRightAlignedTabs: { name: "Right-aligned tabs", type: { name: "boolean" }, @@ -63,14 +60,12 @@ export default { }, isCompact: { name: "Compact", - description: "Compact tabs should never be used without the quiet styles.", type: { name: "boolean" }, table: { type: { summary: "boolean" }, category: "State", }, control: "boolean", - if: { arg: "isQuiet", truthy: true }, }, iconOnly: { name: "Icon only", @@ -81,14 +76,21 @@ export default { }, control: "boolean", }, + labelOnly: { + name: "Label only", + type: { name: "boolean" }, + table: { + type: { summary: "boolean" }, + category: "Component", + }, + control: "boolean", + }, }, args: { rootClass: "spectrum-Tabs", - isQuiet: false, - isEmphasized: false, isCompact: false, iconOnly: false, - size: "m", + labelOnly: false, orientation: "horizontal", hasRightAlignedTabs: false, useAnchors: false, @@ -104,7 +106,7 @@ export default { }, { label: "Tab 3", - icon: "Document", + icon: "File", isDisabled: true, }, ], @@ -119,29 +121,32 @@ export default { }, packageJson, metadata, + status: { + type: "migrated", + }, }, + tags: ["migrated"], }; /** - * Basic, default tab items should have a label for accessibility. If a label isn’t present, it must include an icon and becomes an icon-only tab item. - * - * By default, tabs have a divider that spans across all tab items. This style works as a way to anchor them to the page. These types of tabs are best used at the top of a page, as a top-level navigation. - * - * Tabs are horizontal by default and should be used when horizontal space is limited. + * #### Labels + * Basic, default tab items should have a label for accessibility. If a label isn't present, it must include an icon and becomes an icon-only tab item. * + * #### Icons + * Icons can be displayed in tab items. Icons should only be used in a tab item when absolutely necessary: when adding essential value and having a strong association with the label. Icons should not be used just as decoration. If the tab item does not have a visible label, it must still have a tooltip to disclose the label. */ export const Default = TabsGroups.bind({}); Default.args = {}; // ********* DOCS ONLY ********* // /** - * Vertical tabs should be used when horizontal space is more generous and when the list of sections is greater than can be presented to the user in a horizontal format. + * Vertical tabs should be used when horizontal space is more limited and when the list of sections is greater than can be presented to the user in a horizontal format. */ export const Vertical = VerticalGroup.bind({}); Vertical.args = { orientation: "vertical", }; -Vertical.tags = ["!dev"]; +Vertical.tags = ["!dev", "!autodocs"]; // TODO: remove "!autodocs" when vertical tabs are supported in S2 Vertical.parameters = { chromatic: { disableSnapshot: true }, }; @@ -152,7 +157,7 @@ VerticalRight.args = { hasRightAlignedTabs: true, }; VerticalRight.storyName = "Vertical right"; -VerticalRight.tags = ["!dev"]; +VerticalRight.tags = ["!dev", "!autodocs"]; // TODO: remove "!autodocs" when vertical tabs are supported in S2 VerticalRight.parameters = { chromatic: { disableSnapshot: true }, }; @@ -166,45 +171,18 @@ export const Overflow = OverflowGroup.bind({}); Overflow.args = { orientation: "overflow", }; -Overflow.tags = ["!dev"]; +Overflow.tags = ["!dev", "!autodocs"]; // TODO: remove "!autodocs" when overflow tabs are supported in S2 Overflow.parameters = { chromatic: { disableSnapshot: true }, }; /** - * The medium size is the default and most frequently used option. Use the other sizes sparingly; they should be used to create a hierarchy of importance within the page. - */ -export const Sizing = (args, context) => Sizes({ - Template, - withHeading: false, - withBorder: false, - ...args, -}, context); -Sizing.args = Default.args; -Sizing.tags = ["!dev"]; -Sizing.parameters = { - chromatic: { disableSnapshot: true }, -}; - -/** - * Quiet tabs have no visible divider across the tab items apart from the one that shows the selected tab item. These should be used as sub-level navigation or for containers. - */ -export const Quiet = QuietGroup.bind({}); -Quiet.args = { - isQuiet: true, -}; -Quiet.tags = ["!dev"]; -Quiet.parameters = { - chromatic: { disableSnapshot: true }, -}; - -/** - * Compact tabs should never be used without the quiet variation. + * In addition to the default, regular density, tabs also come in a compact density which has tighter spacing. */ export const Compact = CompactGroup.bind({}); +Compact.storyName = "Density: compact"; Compact.args = { isCompact: true, - isQuiet: true, }; Compact.tags = ["!dev"]; Compact.parameters = { @@ -238,18 +216,6 @@ Disabled.parameters = { chromatic: { disableSnapshot: true }, }; -/** - * Emphasized tabs have blue text for the selected state for visual prominence and to draw more attention to them. This is optimal for when the selection should call attention, such as the main navigation for a website. - */ -export const Emphasized = Template.bind({}); -Emphasized.args = { - isEmphasized: true, -}; -Emphasized.tags = ["!dev"]; -Emphasized.parameters = { - chromatic: { disableSnapshot: true }, -}; - /** * Tab items can alternatively be anchor tags (``) instead of `div` elements to allow for navigation to on-page anchors. Do not use horizontal tabs for this adaptation. */ diff --git a/components/tabs/stories/tabs.test.js b/components/tabs/stories/tabs.test.js index e0d6fa07578..87a5d965b64 100644 --- a/components/tabs/stories/tabs.test.js +++ b/components/tabs/stories/tabs.test.js @@ -1,22 +1,9 @@ import { Variants } from "@spectrum-css/preview/decorators"; import { Template } from "./template.js"; -const ExampleLabelOnlyTabContent = [ - { - label: "Selected", - isSelected: true, - }, - { - label: "Disabled", - isDisabled: true, - }, - { - label: "Tab 3", - }, -]; - export const TabsGroups = Variants({ Template, + withSizes: false, wrapperStyles: { "column-gap": "80px", }, @@ -24,44 +11,18 @@ export const TabsGroups = Variants({ { testHeading: "Default", }, - { - testHeading: "Emphasized", - isEmphasized: true, - }, - { - testHeading: "Quiet", - isQuiet: true, - }, - { - testHeading: "Quiet emphasized", - isQuiet: true, - isEmphasized: true, - }, { testHeading: "Compact", isCompact: true, - isQuiet: true, - }, - { - testHeading: "Compact emphasized", - isCompact: true, - isQuiet: true, - isEmphasized: true, }, { testHeading: "Vertical tabs", orientation: "vertical", }, - { - testHeading: "Emphasized vertical tabs", - orientation: "vertical", - isEmphasized: true, - }, { testHeading: "Compact vertical tabs", orientation: "vertical", isCompact: true, - isQuiet: true, }, { testHeading: "Right vertical tabs", @@ -76,7 +37,49 @@ export const TabsGroups = Variants({ testHeading: "Compact overflow", orientation: "overflow", isCompact: true, - isQuiet: true, + }, + { + testHeading: "Hover colors", + withStates: false, + content: [ + { + label: "Hovered unselected tab", + icon: "Folder", + isHovered: true, + }, + { + label: "Hovered selected tab", + icon: "Image", + isSelected: true, + isHovered: true, + }, + { + label: "Unhovered unselected tab", + icon: "File", + }, + { + label: "Disabled tab", + icon: "Archive", + isDisabled: true, + } + ] + }, + { + testHeading: "Disabled tabs", + withStates: false, + content: [ + { + label: "Selected tab", + icon: "Archive", + isSelected: true, + isDisabled: true, + }, + { + label: "Unselected tab", + icon: "File", + isDisabled: true, + } + ] }, { testHeading: "With anchor tags", @@ -86,11 +89,31 @@ export const TabsGroups = Variants({ stateData: [ { testHeading: "Label only", - content: ExampleLabelOnlyTabContent, + labelOnly: true, }, { testHeading: "Icon only", - iconOnly: true + iconOnly: true, }, + { + testHeading: "Selected tab focused", + content: [ + { + label: "Tab 1", + icon: "Folder", + }, + { + label: "Selected focused tab", + icon: "Image", + isSelected: true, + isFocused: true, + }, + { + label: "Tab 3", + icon: "File", + } + ], + ignore: ["Overflow", "Compact overflow"], + } ] }); diff --git a/components/tabs/stories/template.js b/components/tabs/stories/template.js index 387683f1ae9..b977dd2fc31 100644 --- a/components/tabs/stories/template.js +++ b/components/tabs/stories/template.js @@ -14,13 +14,11 @@ import "../index.css"; export const Template = ({ rootClass = "spectrum-Tabs", customClasses = [], - size = "m", orientation = "horizontal", - isQuiet = false, isOpen = false, - isEmphasized = false, isCompact = false, iconOnly = false, + labelOnly = false, hasRightAlignedTabs = false, useAnchors = false, id = getRandomId("tabs"), @@ -40,39 +38,19 @@ export const Template = ({ // Note: Lit must use the 'literal' function for dynamic tags to work. const tabMarkup = useAnchors ? literal`a` : literal`div`; - const selectionIndicator = (isSelected) => when( - isSelected, - () => html` -
` - ); - return html`
({ ...a, [c]: true }), {}), })} style=${styleMap(customStyles)} id=${ifDefined(id)} + role="tablist" > ${when(!isOverflow, () => repeat( content, @@ -85,23 +63,32 @@ export const Template = ({ [`${rootClass}-item`]: true, "is-selected": item?.isSelected ?? false, "is-disabled": item?.isDisabled ?? false, + "is-focus-visible": item?.isFocused ?? false, + "is-hover": item?.isHovered ?? false, })} - tabindex="0" + tabindex=${item?.isDisabled ? "-1" : "0"} id=${getRandomId("tab-item")} + role="tab" + aria-selected=${item?.isSelected ?? false} + aria-disabled=${item?.isDisabled ?? false} > - ${when(item.icon, () => + ${when(item.icon && !labelOnly, () => Icon({ iconName: item.icon, setName: "workflow", - size, }, context) )} ${when(item.label && !iconOnly, () => html` - + ${item.label} `)} - ${selectionIndicator(item.isSelected)} + ${when(item.isSelected, () => html` +
+ `)} `; } @@ -112,12 +99,10 @@ export const Template = ({ ), () => html` ${Picker({ isQuiet: true, - size, isOpen, placeholder: !iconOnly ? content?.[0].label : Icon({ iconName: content?.[0].icon, setName: "workflow", - size, }, context), name: content?.[0].label, id: "tab-selector", @@ -127,7 +112,6 @@ export const Template = ({ popoverContent: [ () => Menu({ selectionMode: "none", - size, role: "listbox", subrole: "option", customStyles: { minWidth: "max-content" }, @@ -142,7 +126,7 @@ export const Template = ({ }, context), ] }, context)} - ${selectionIndicator(true)} +
`)}
`; @@ -180,7 +164,7 @@ export const OverflowGroup = (args, context) => Container({ withBorder: false, heading: "Compact overflow", containerStyles: { "gap": "8px", }, - content: Template({...args, isCompact: true, isQuiet: true}, context), + content: Template({...args, isCompact: true}, context), }, context)} ` }, context); @@ -196,86 +180,23 @@ export const VerticalGroup = (args, context) => Container({ containerStyles: {"gap": "8px"}, content: Template(args, context), }, context)} - ${Container({ - withBorder: false, - heading: "Emphasized, with label and icon", - containerStyles: {"gap": "8px"}, - content: Template({...args, isEmphasized: true, }, context), - }, context)} ${Container({ withBorder: false, heading: "Label only", containerStyles: {"gap": "8px"}, content: Template({...args, content: LabelOnlyTabsContent, }, context), }, context)} - ${Container({ - withBorder: false, - heading: "Emphasized, with label only", - containerStyles: {"gap": "8px"}, - content: Template({...args, isEmphasized: true, content: LabelOnlyTabsContent, }, context), - }, context)} ${Container({ withBorder: false, heading: "Compact, with label and icon", containerStyles: {"gap": "8px"}, - content: Template({...args, isCompact: true, isQuiet: true, }, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Compact, emphasized, with label and icon", - containerStyles: {"gap": "8px"}, - content: Template({...args, isEmphasized: true, isCompact: true, isQuiet: true, }, context), + content: Template({...args, isCompact: true, }, context), }, context)} ${Container({ withBorder: false, heading: "Compact, label only", containerStyles: {"gap": "8px"}, - content: Template({...args, content: LabelOnlyTabsContent, isCompact: true, isQuiet: true, }, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Compact, emphasized label only", - containerStyles: {"gap": "8px"}, - content: Template({...args, isEmphasized: true, content: LabelOnlyTabsContent, isCompact: true, isQuiet: true, }, context), - }, context)} - ` -}, context); - -/* Shows variants of quiet story in a single group. */ -export const QuietGroup = (args, context) => Container({ - direction: "column", - withBorder: false, - withHeading: false, - content: html` - ${Container({ - withBorder: false, - heading: "Label and icon", - content: Template(args, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Emphasized, with label and icon", - content: Template({...args, isEmphasized: true, }, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Label only", - content: Template({...args, content: LabelOnlyTabsContent, }, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Emphasized, with label only", - content: Template({...args, isEmphasized: true, content: LabelOnlyTabsContent, }, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Icon only", - content: Template({...args, iconOnly: true, }, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Emphasized, icon-only", - content: Template({...args, isEmphasized: true, iconOnly: true, }, context), + content: Template({...args, content: LabelOnlyTabsContent, isCompact: true, }, context), }, context)} ` }, context); @@ -288,14 +209,9 @@ export const CompactGroup = (args, context) => Container({ content: html` ${Container({ withBorder: false, - heading: "Label and icon (quiet)", + heading: "Label and icon", content: Template(args, context), }, context)} - ${Container({ - withBorder: false, - heading: "Emphasized, with label and icon (quiet)", - content: Template({...args, isEmphasized: true, }, context), - }, context)} ${Container({ withBorder: false, heading: "Label only", @@ -303,18 +219,8 @@ export const CompactGroup = (args, context) => Container({ }, context)} ${Container({ withBorder: false, - heading: "Emphasized, with label only (quiet)", - content: Template({...args, isEmphasized: true, content: LabelOnlyTabsContent, }, context), - }, context)} - ${Container({ - withBorder: false, - heading: "Icon only (quiet)", + heading: "Icon only", content: Template({...args, iconOnly: true, }, context), }, context)} - ${Container({ - withBorder: false, - heading: "Emphasized, icon-only (quiet)", - content: Template({...args, isEmphasized: true, iconOnly: true, }, context), - }, context)} ` }, context); diff --git a/tokens/custom/large-vars.css b/tokens/custom/large-vars.css index d1573c98a11..57f2e0d1e62 100644 --- a/tokens/custom/large-vars.css +++ b/tokens/custom/large-vars.css @@ -107,6 +107,16 @@ --spectrum-takeover-dialog-spacing-header-gap: var(--spectrum-spacing-300); --spectrum-takeover-dialog-spacing-title-to-body: var(--spectrum-spacing-400); + /* @todo: remove when tabs tokens are updated */ + --spectrum-tab-item-top-to-workflow-icon-medium: 18px; + --spectrum-tab-item-side-to-workflow-icon-medium: 6px; + --spectrum-tab-item-bottom-to-text-medium: 21px; + --spectrum-tab-item-to-tab-item-horizontal-medium: 30px; + --spectrum-tab-selection-indicator-thickness: 2px; + --spectrum-tab-item-top-to-workflow-icon-compact-medium: 7px; + --spectrum-tab-item-side-to-workflow-icon-compact-medium: 6px; + --spectrum-tab-item-to-tab-item-compact-horizontal-medium: 30px; + --spectrum-treeview-item-indentation-medium: 20px; --spectrum-treeview-item-indentation-small: 15px; --spectrum-treeview-item-indentation-large: 25px; diff --git a/tokens/custom/medium-vars.css b/tokens/custom/medium-vars.css index d9f08666d34..f11ba26213a 100644 --- a/tokens/custom/medium-vars.css +++ b/tokens/custom/medium-vars.css @@ -105,6 +105,16 @@ --spectrum-takeover-dialog-spacing-header-gap: var(--spectrum-spacing-400); --spectrum-takeover-dialog-spacing-title-to-body: var(--spectrum-spacing-500); + /* @todo: remove when tabs tokens are updated */ + --spectrum-tab-item-top-to-workflow-icon-medium: 14px; + --spectrum-tab-item-side-to-workflow-icon-medium: 6px; + --spectrum-tab-item-bottom-to-text-medium: 16px; + --spectrum-tab-item-to-tab-item-horizontal-medium: 32px; + --spectrum-tab-selection-indicator-thickness: 2px; + --spectrum-tab-item-top-to-workflow-icon-compact-medium: 6px; + --spectrum-tab-item-side-to-workflow-icon-compact-medium: 6px; + --spectrum-tab-item-to-tab-item-compact-horizontal-medium: 24px; + --spectrum-treeview-indicator-inset-block-start: 5px; --spectrum-treeview-item-indentation-small: var(--spectrum-spacing-200); --spectrum-treeview-item-indentation-medium: var(--spectrum-spacing-300);