/* * M3's tabs (PrimaryNavigationTabTokens, SecondaryNavigationTabTokens, androidx Compose Material 3, * Apache-2.0): a 48px tablist on the surface over an outline-variant divider (64px when a primary * tab stacks its icon over its label), title-small labels in on-surface-variant, the chosen tab's * in primary (primary tabs) or on-surface (secondary tabs). * * The active indicator is drawn in every tab and shown under the chosen one, so it is right before * Alpine starts and after a morph: 3px with rounded top corners under the content of a primary tab * (at least 24px wide), 2px across the whole of a secondary one. When the choice changes, a view * transition moves it from the old tab to the new (resources/js/tabs.js), as M3's slides. */ @layer components { [data-tabs-bar] { position: relative; display: flex; overflow-x: auto; overscroll-behavior-x: contain; border-bottom: 1px solid var(--md-sys-color-outline-variant); scrollbar-width: thin; } /* A section nav's links sit in list items that share the width. */ [data-tabs-bar] > li { flex: 1 1 0%; } [data-tabs-bar] > li > [data-tab] { flex: 1 1 0%; } [data-tab] { position: relative; display: flex; flex: 1 1 0%; min-width: 5.625rem; height: 3rem; align-items: center; justify-content: center; padding-inline: 1rem; color: var(--md-sys-color-on-surface-variant); cursor: pointer; outline: none; font: var(--md-sys-typescale-title-sm); letter-spacing: var(--md-sys-typescale-title-sm-tracking); white-space: nowrap; transition: color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); } [data-tabs-bar][data-scrollable] [data-tab] { flex: none; } [data-tabs-bar][data-stacked] [data-tab] { height: 4rem; } [data-tab]::before { content: ""; position: absolute; inset: 0; pointer-events: none; transition: background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); } @media (hover: hover) { [data-tab]:hover { color: var(--md-sys-color-on-surface); } [data-tab]:hover::before { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 8%, transparent); } } [data-tab]:focus-visible::before, [data-tab]:active::before { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent); } [data-tab]:focus-visible { color: var(--md-sys-color-on-surface); outline: 3px solid var(--md-sys-color-secondary); outline-offset: -3px; } [data-tab][aria-selected="true"] { color: var(--md-sys-color-primary); } [data-tabs-bar][data-variant="secondary"] [data-tab]:is([aria-selected="true"], [aria-current="page"]) { color: var(--md-sys-color-on-surface); } [data-tab]:disabled { color: color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent); cursor: default; } [data-tab]:disabled::before { background-color: transparent; } [data-tab-content] { position: relative; display: inline-flex; height: 100%; min-width: 1.5rem; align-items: center; justify-content: center; gap: 0.5rem; } [data-tabs-bar][data-stacked] [data-tab-content] { flex-direction: column; gap: 0.125rem; } [data-tab-indicator] { position: absolute; inset-inline: 0; bottom: 0; height: 3px; border-radius: 3px 3px 0 0; background-color: var(--md-sys-color-primary); opacity: 0; pointer-events: none; view-transition-class: material-tab-indicator; } /* A secondary tab's indicator spans the tab, not its content. */ [data-tabs-bar][data-variant="secondary"] [data-tab-content] { position: static; } [data-tabs-bar][data-variant="secondary"] [data-tab-indicator] { height: 2px; border-radius: 0; } [data-tab]:is([aria-selected="true"], [aria-current="page"]) [data-tab-indicator] { opacity: 1; view-transition-name: var(--tabs-indicator); } } ::view-transition-group(*.material-tab-indicator) { animation-duration: var(--md-sys-motion-spatial-default-duration); animation-timing-function: var(--md-sys-motion-spatial-default); }