Tabs
A set of layered sections of content, known as tab panels, that display one panel of content at a time.
Manage your account details and preferences.
View source
import * as Tabs from "@danielfrg/solid-ui/tabs"
import styles from "./index.module.css"
export function DemoTabsHero() {
return (
<Tabs.Root defaultValue="account" class={styles.root}>
<Tabs.List class={styles.list}>
<Tabs.Trigger value="account" class={styles.trigger}>
Account
</Tabs.Trigger>
<Tabs.Trigger value="password" class={styles.trigger}>
Password
</Tabs.Trigger>
<Tabs.Trigger value="settings" class={styles.trigger}>
Settings
</Tabs.Trigger>
<Tabs.Indicator class={styles.indicator} />
</Tabs.List>
<Tabs.Content value="account" class={styles.content}>
<p>Manage your account details and preferences.</p>
</Tabs.Content>
<Tabs.Content value="password" class={styles.content}>
<p>Change your password and security settings.</p>
</Tabs.Content>
<Tabs.Content value="settings" class={styles.content}>
<p>Configure your application settings.</p>
</Tabs.Content>
</Tabs.Root>
)
}.root {
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.list {
display: flex;
position: relative;
z-index: 0;
padding-inline: 0.25rem;
gap: 0.25rem;
box-shadow: inset 0 -1px var(--color-gray-200);
}
.trigger {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.5rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.trigger[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.trigger:hover {
color: var(--color-gray-900);
}
}
.trigger[data-highlighted] {
outline: none;
}
.trigger[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.trigger:focus-visible {
position: relative;
}
.trigger:focus-visible::before {
content: "";
position: absolute;
inset: 0.25rem 0;
border-radius: 0.25rem;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}
.indicator {
position: absolute;
z-index: -1;
top: 50%;
margin-top: -0.75rem;
height: 1.5rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, width;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 8rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
.content:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.375rem;
}
.status {
margin: 1rem 0 0;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-gray-600);
}
/* Vertical tabs layout */
.rootVertical {
display: flex;
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.listVertical {
display: flex;
flex-direction: column;
position: relative;
z-index: 0;
padding-block: 0.25rem;
gap: 0.25rem;
box-shadow: inset -1px 0 var(--color-gray-200);
}
.triggerVertical {
display: flex;
align-items: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.75rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.triggerVertical[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.triggerVertical:hover {
color: var(--color-gray-900);
}
}
.triggerVertical[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.triggerVertical:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.25rem;
}
.indicatorVertical {
position: absolute;
z-index: -1;
left: 50%;
margin-left: -2.5rem;
width: 5rem;
height: 2rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, height;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.contentVertical {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
/* Dynamic tabs helpers */
.dynamicWrapper {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
max-width: 400px;
}
.dynamicControls {
display: flex;
gap: 0.5rem;
}
.dynamicButton {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 2rem;
padding: 0 0.75rem;
outline: 0;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
background-color: var(--color-gray-50);
font-family: inherit;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-gray-900);
cursor: pointer;
}
.dynamicButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
@media (hover: hover) {
.dynamicButton:hover:not(:disabled) {
background-color: var(--color-gray-100);
}
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}Examples
Default value
Use defaultValue to set the initially active tab without controlling the state.
Change your password and security settings.
View source
import * as Tabs from "@danielfrg/solid-ui/tabs"
import styles from "./index.module.css"
export function DemoTabsDefaultValue() {
return (
<Tabs.Root defaultValue="password" class={styles.root}>
<Tabs.List class={styles.list}>
<Tabs.Trigger value="account" class={styles.trigger}>
Account
</Tabs.Trigger>
<Tabs.Trigger value="password" class={styles.trigger}>
Password
</Tabs.Trigger>
<Tabs.Trigger value="settings" class={styles.trigger}>
Settings
</Tabs.Trigger>
<Tabs.Indicator class={styles.indicator} />
</Tabs.List>
<Tabs.Content value="account" class={styles.content}>
<p>Manage your account details and preferences.</p>
</Tabs.Content>
<Tabs.Content value="password" class={styles.content}>
<p>Change your password and security settings.</p>
</Tabs.Content>
<Tabs.Content value="settings" class={styles.content}>
<p>Configure your application settings.</p>
</Tabs.Content>
</Tabs.Root>
)
}.root {
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.list {
display: flex;
position: relative;
z-index: 0;
padding-inline: 0.25rem;
gap: 0.25rem;
box-shadow: inset 0 -1px var(--color-gray-200);
}
.trigger {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.5rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.trigger[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.trigger:hover {
color: var(--color-gray-900);
}
}
.trigger[data-highlighted] {
outline: none;
}
.trigger[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.trigger:focus-visible {
position: relative;
}
.trigger:focus-visible::before {
content: "";
position: absolute;
inset: 0.25rem 0;
border-radius: 0.25rem;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}
.indicator {
position: absolute;
z-index: -1;
top: 50%;
margin-top: -0.75rem;
height: 1.5rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, width;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 8rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
.content:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.375rem;
}
.status {
margin: 1rem 0 0;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-gray-600);
}
/* Vertical tabs layout */
.rootVertical {
display: flex;
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.listVertical {
display: flex;
flex-direction: column;
position: relative;
z-index: 0;
padding-block: 0.25rem;
gap: 0.25rem;
box-shadow: inset -1px 0 var(--color-gray-200);
}
.triggerVertical {
display: flex;
align-items: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.75rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.triggerVertical[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.triggerVertical:hover {
color: var(--color-gray-900);
}
}
.triggerVertical[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.triggerVertical:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.25rem;
}
.indicatorVertical {
position: absolute;
z-index: -1;
left: 50%;
margin-left: -2.5rem;
width: 5rem;
height: 2rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, height;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.contentVertical {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
/* Dynamic tabs helpers */
.dynamicWrapper {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
max-width: 400px;
}
.dynamicControls {
display: flex;
gap: 0.5rem;
}
.dynamicButton {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 2rem;
padding: 0 0.75rem;
outline: 0;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
background-color: var(--color-gray-50);
font-family: inherit;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-gray-900);
cursor: pointer;
}
.dynamicButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
@media (hover: hover) {
.dynamicButton:hover:not(:disabled) {
background-color: var(--color-gray-100);
}
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}Controlled
Use value and onChange to control the active tab externally.
Manage your account details and preferences.
Active tab: account
View source
import { createSignal } from "solid-js"
import * as Tabs from "@danielfrg/solid-ui/tabs"
import styles from "./index.module.css"
export function DemoTabsControlled() {
const [tab, setTab] = createSignal("account")
return (
<div>
<Tabs.Root value={tab()} onChange={setTab} class={styles.root}>
<Tabs.List class={styles.list}>
<Tabs.Trigger value="account" class={styles.trigger}>
Account
</Tabs.Trigger>
<Tabs.Trigger value="password" class={styles.trigger}>
Password
</Tabs.Trigger>
<Tabs.Trigger value="settings" class={styles.trigger}>
Settings
</Tabs.Trigger>
<Tabs.Indicator class={styles.indicator} />
</Tabs.List>
<Tabs.Content value="account" class={styles.content}>
<p>Manage your account details and preferences.</p>
</Tabs.Content>
<Tabs.Content value="password" class={styles.content}>
<p>Change your password and security settings.</p>
</Tabs.Content>
<Tabs.Content value="settings" class={styles.content}>
<p>Configure your application settings.</p>
</Tabs.Content>
</Tabs.Root>
<p class={styles.status}>Active tab: {tab()}</p>
</div>
)
}.root {
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.list {
display: flex;
position: relative;
z-index: 0;
padding-inline: 0.25rem;
gap: 0.25rem;
box-shadow: inset 0 -1px var(--color-gray-200);
}
.trigger {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.5rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.trigger[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.trigger:hover {
color: var(--color-gray-900);
}
}
.trigger[data-highlighted] {
outline: none;
}
.trigger[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.trigger:focus-visible {
position: relative;
}
.trigger:focus-visible::before {
content: "";
position: absolute;
inset: 0.25rem 0;
border-radius: 0.25rem;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}
.indicator {
position: absolute;
z-index: -1;
top: 50%;
margin-top: -0.75rem;
height: 1.5rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, width;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 8rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
.content:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.375rem;
}
.status {
margin: 1rem 0 0;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-gray-600);
}
/* Vertical tabs layout */
.rootVertical {
display: flex;
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.listVertical {
display: flex;
flex-direction: column;
position: relative;
z-index: 0;
padding-block: 0.25rem;
gap: 0.25rem;
box-shadow: inset -1px 0 var(--color-gray-200);
}
.triggerVertical {
display: flex;
align-items: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.75rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.triggerVertical[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.triggerVertical:hover {
color: var(--color-gray-900);
}
}
.triggerVertical[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.triggerVertical:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.25rem;
}
.indicatorVertical {
position: absolute;
z-index: -1;
left: 50%;
margin-left: -2.5rem;
width: 5rem;
height: 2rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, height;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.contentVertical {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
/* Dynamic tabs helpers */
.dynamicWrapper {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
max-width: 400px;
}
.dynamicControls {
display: flex;
gap: 0.5rem;
}
.dynamicButton {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 2rem;
padding: 0 0.75rem;
outline: 0;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
background-color: var(--color-gray-50);
font-family: inherit;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-gray-900);
cursor: pointer;
}
.dynamicButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
@media (hover: hover) {
.dynamicButton:hover:not(:disabled) {
background-color: var(--color-gray-100);
}
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}Manual activation
Use activationMode="manual" so keyboard navigation moves focus without activating the tab — the user must press Enter or Space to select.
Manage your account details and preferences.
View source
import * as Tabs from "@danielfrg/solid-ui/tabs"
import styles from "./index.module.css"
export function DemoTabsManualActivation() {
return (
<Tabs.Root defaultValue="account" activationMode="manual" class={styles.root}>
<Tabs.List class={styles.list}>
<Tabs.Trigger value="account" class={styles.trigger}>
Account
</Tabs.Trigger>
<Tabs.Trigger value="password" class={styles.trigger}>
Password
</Tabs.Trigger>
<Tabs.Trigger value="settings" class={styles.trigger}>
Settings
</Tabs.Trigger>
<Tabs.Indicator class={styles.indicator} />
</Tabs.List>
<Tabs.Content value="account" class={styles.content}>
<p>Manage your account details and preferences.</p>
</Tabs.Content>
<Tabs.Content value="password" class={styles.content}>
<p>Change your password and security settings.</p>
</Tabs.Content>
<Tabs.Content value="settings" class={styles.content}>
<p>Configure your application settings.</p>
</Tabs.Content>
</Tabs.Root>
)
}.root {
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.list {
display: flex;
position: relative;
z-index: 0;
padding-inline: 0.25rem;
gap: 0.25rem;
box-shadow: inset 0 -1px var(--color-gray-200);
}
.trigger {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.5rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.trigger[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.trigger:hover {
color: var(--color-gray-900);
}
}
.trigger[data-highlighted] {
outline: none;
}
.trigger[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.trigger:focus-visible {
position: relative;
}
.trigger:focus-visible::before {
content: "";
position: absolute;
inset: 0.25rem 0;
border-radius: 0.25rem;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}
.indicator {
position: absolute;
z-index: -1;
top: 50%;
margin-top: -0.75rem;
height: 1.5rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, width;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 8rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
.content:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.375rem;
}
.status {
margin: 1rem 0 0;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-gray-600);
}
/* Vertical tabs layout */
.rootVertical {
display: flex;
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.listVertical {
display: flex;
flex-direction: column;
position: relative;
z-index: 0;
padding-block: 0.25rem;
gap: 0.25rem;
box-shadow: inset -1px 0 var(--color-gray-200);
}
.triggerVertical {
display: flex;
align-items: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.75rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.triggerVertical[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.triggerVertical:hover {
color: var(--color-gray-900);
}
}
.triggerVertical[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.triggerVertical:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.25rem;
}
.indicatorVertical {
position: absolute;
z-index: -1;
left: 50%;
margin-left: -2.5rem;
width: 5rem;
height: 2rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, height;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.contentVertical {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
/* Dynamic tabs helpers */
.dynamicWrapper {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
max-width: 400px;
}
.dynamicControls {
display: flex;
gap: 0.5rem;
}
.dynamicButton {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 2rem;
padding: 0 0.75rem;
outline: 0;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
background-color: var(--color-gray-50);
font-family: inherit;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-gray-900);
cursor: pointer;
}
.dynamicButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
@media (hover: hover) {
.dynamicButton:hover:not(:disabled) {
background-color: var(--color-gray-100);
}
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}Vertical
Use orientation="vertical" to render tabs in a vertical layout.
Manage your account details and preferences.
View source
import * as Tabs from "@danielfrg/solid-ui/tabs"
import styles from "./index.module.css"
export function DemoTabsVertical() {
return (
<Tabs.Root defaultValue="account" orientation="vertical" class={styles.rootVertical}>
<Tabs.List class={styles.listVertical}>
<Tabs.Trigger value="account" class={styles.triggerVertical}>
Account
</Tabs.Trigger>
<Tabs.Trigger value="password" class={styles.triggerVertical}>
Password
</Tabs.Trigger>
<Tabs.Trigger value="settings" class={styles.triggerVertical}>
Settings
</Tabs.Trigger>
<Tabs.Indicator class={styles.indicatorVertical} />
</Tabs.List>
<Tabs.Content value="account" class={styles.contentVertical}>
<p>Manage your account details and preferences.</p>
</Tabs.Content>
<Tabs.Content value="password" class={styles.contentVertical}>
<p>Change your password and security settings.</p>
</Tabs.Content>
<Tabs.Content value="settings" class={styles.contentVertical}>
<p>Configure your application settings.</p>
</Tabs.Content>
</Tabs.Root>
)
}.root {
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.list {
display: flex;
position: relative;
z-index: 0;
padding-inline: 0.25rem;
gap: 0.25rem;
box-shadow: inset 0 -1px var(--color-gray-200);
}
.trigger {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.5rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.trigger[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.trigger:hover {
color: var(--color-gray-900);
}
}
.trigger[data-highlighted] {
outline: none;
}
.trigger[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.trigger:focus-visible {
position: relative;
}
.trigger:focus-visible::before {
content: "";
position: absolute;
inset: 0.25rem 0;
border-radius: 0.25rem;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}
.indicator {
position: absolute;
z-index: -1;
top: 50%;
margin-top: -0.75rem;
height: 1.5rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, width;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 8rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
.content:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.375rem;
}
.status {
margin: 1rem 0 0;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-gray-600);
}
/* Vertical tabs layout */
.rootVertical {
display: flex;
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.listVertical {
display: flex;
flex-direction: column;
position: relative;
z-index: 0;
padding-block: 0.25rem;
gap: 0.25rem;
box-shadow: inset -1px 0 var(--color-gray-200);
}
.triggerVertical {
display: flex;
align-items: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.75rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.triggerVertical[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.triggerVertical:hover {
color: var(--color-gray-900);
}
}
.triggerVertical[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.triggerVertical:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.25rem;
}
.indicatorVertical {
position: absolute;
z-index: -1;
left: 50%;
margin-left: -2.5rem;
width: 5rem;
height: 2rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, height;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.contentVertical {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
/* Dynamic tabs helpers */
.dynamicWrapper {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
max-width: 400px;
}
.dynamicControls {
display: flex;
gap: 0.5rem;
}
.dynamicButton {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 2rem;
padding: 0 0.75rem;
outline: 0;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
background-color: var(--color-gray-50);
font-family: inherit;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-gray-900);
cursor: pointer;
}
.dynamicButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
@media (hover: hover) {
.dynamicButton:hover:not(:disabled) {
background-color: var(--color-gray-100);
}
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}Disabled tab
Use the disabled prop on an individual Tabs.Trigger to disable it.
Manage your account details and preferences.
View source
import * as Tabs from "@danielfrg/solid-ui/tabs"
import styles from "./index.module.css"
export function DemoTabsDisabled() {
return (
<Tabs.Root defaultValue="account" class={styles.root}>
<Tabs.List class={styles.list}>
<Tabs.Trigger value="account" class={styles.trigger}>
Account
</Tabs.Trigger>
<Tabs.Trigger value="password" class={styles.trigger} disabled>
Password
</Tabs.Trigger>
<Tabs.Trigger value="settings" class={styles.trigger}>
Settings
</Tabs.Trigger>
<Tabs.Indicator class={styles.indicator} />
</Tabs.List>
<Tabs.Content value="account" class={styles.content}>
<p>Manage your account details and preferences.</p>
</Tabs.Content>
<Tabs.Content value="password" class={styles.content}>
<p>Change your password and security settings.</p>
</Tabs.Content>
<Tabs.Content value="settings" class={styles.content}>
<p>Configure your application settings.</p>
</Tabs.Content>
</Tabs.Root>
)
}.root {
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.list {
display: flex;
position: relative;
z-index: 0;
padding-inline: 0.25rem;
gap: 0.25rem;
box-shadow: inset 0 -1px var(--color-gray-200);
}
.trigger {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.5rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.trigger[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.trigger:hover {
color: var(--color-gray-900);
}
}
.trigger[data-highlighted] {
outline: none;
}
.trigger[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.trigger:focus-visible {
position: relative;
}
.trigger:focus-visible::before {
content: "";
position: absolute;
inset: 0.25rem 0;
border-radius: 0.25rem;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}
.indicator {
position: absolute;
z-index: -1;
top: 50%;
margin-top: -0.75rem;
height: 1.5rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, width;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 8rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
.content:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.375rem;
}
.status {
margin: 1rem 0 0;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-gray-600);
}
/* Vertical tabs layout */
.rootVertical {
display: flex;
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.listVertical {
display: flex;
flex-direction: column;
position: relative;
z-index: 0;
padding-block: 0.25rem;
gap: 0.25rem;
box-shadow: inset -1px 0 var(--color-gray-200);
}
.triggerVertical {
display: flex;
align-items: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.75rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.triggerVertical[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.triggerVertical:hover {
color: var(--color-gray-900);
}
}
.triggerVertical[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.triggerVertical:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.25rem;
}
.indicatorVertical {
position: absolute;
z-index: -1;
left: 50%;
margin-left: -2.5rem;
width: 5rem;
height: 2rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, height;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.contentVertical {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
/* Dynamic tabs helpers */
.dynamicWrapper {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
max-width: 400px;
}
.dynamicControls {
display: flex;
gap: 0.5rem;
}
.dynamicButton {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 2rem;
padding: 0 0.75rem;
outline: 0;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
background-color: var(--color-gray-50);
font-family: inherit;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-gray-900);
cursor: pointer;
}
.dynamicButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
@media (hover: hover) {
.dynamicButton:hover:not(:disabled) {
background-color: var(--color-gray-100);
}
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}Dynamic tabs
Drive the list of tabs from a signal to add or remove tabs at runtime.
Content for Account.
View source
import { createSignal, For } from "solid-js"
import * as Tabs from "@danielfrg/solid-ui/tabs"
import styles from "./index.module.css"
export function DemoTabsDynamic() {
const [tabs, setTabs] = createSignal(["Account", "Password", "Settings"])
const [selected, setSelected] = createSignal("Account")
const addTab = () => {
const name = `Tab ${tabs().length + 1}`
setTabs((t) => [...t, name])
setSelected(name)
}
const removeTab = () => {
if (tabs().length <= 1) return
const next = tabs().filter((t) => t !== selected())
setTabs(next)
setSelected(next[next.length - 1])
}
return (
<div class={styles.dynamicWrapper}>
<div class={styles.dynamicControls}>
<button class={styles.dynamicButton} onClick={addTab}>
Add tab
</button>
<button class={styles.dynamicButton} onClick={removeTab} disabled={tabs().length <= 1}>
Remove tab
</button>
</div>
<Tabs.Root value={selected()} onChange={setSelected} class={styles.root}>
<Tabs.List class={styles.list}>
<For each={tabs()}>
{(tab) => (
<Tabs.Trigger value={tab} class={styles.trigger}>
{tab}
</Tabs.Trigger>
)}
</For>
<Tabs.Indicator class={styles.indicator} />
</Tabs.List>
<For each={tabs()}>
{(tab) => (
<Tabs.Content value={tab} class={styles.content}>
<p>Content for {tab}.</p>
</Tabs.Content>
)}
</For>
</Tabs.Root>
</div>
)
}.root {
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.list {
display: flex;
position: relative;
z-index: 0;
padding-inline: 0.25rem;
gap: 0.25rem;
box-shadow: inset 0 -1px var(--color-gray-200);
}
.trigger {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.5rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.trigger[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.trigger:hover {
color: var(--color-gray-900);
}
}
.trigger[data-highlighted] {
outline: none;
}
.trigger[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.trigger:focus-visible {
position: relative;
}
.trigger:focus-visible::before {
content: "";
position: absolute;
inset: 0.25rem 0;
border-radius: 0.25rem;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
}
.indicator {
position: absolute;
z-index: -1;
top: 50%;
margin-top: -0.75rem;
height: 1.5rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, width;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 8rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
.content:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.375rem;
}
.status {
margin: 1rem 0 0;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-gray-600);
}
/* Vertical tabs layout */
.rootVertical {
display: flex;
width: 100%;
max-width: 400px;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
}
.listVertical {
display: flex;
flex-direction: column;
position: relative;
z-index: 0;
padding-block: 0.25rem;
gap: 0.25rem;
box-shadow: inset -1px 0 var(--color-gray-200);
}
.triggerVertical {
display: flex;
align-items: center;
border: 0;
margin: 0;
outline: 0;
background: none;
appearance: none;
color: var(--color-gray-600);
font-family: inherit;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
user-select: none;
white-space: nowrap;
padding-inline: 0.75rem;
padding-block: 0;
height: 2rem;
cursor: pointer;
}
.triggerVertical[data-selected] {
color: var(--color-gray-900);
}
@media (hover: hover) {
.triggerVertical:hover {
color: var(--color-gray-900);
}
}
.triggerVertical[data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
.triggerVertical:focus-visible {
outline: 2px solid var(--color-blue);
outline-offset: -1px;
border-radius: 0.25rem;
}
.indicatorVertical {
position: absolute;
z-index: -1;
left: 50%;
margin-left: -2.5rem;
width: 5rem;
height: 2rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
transition-property: transform, height;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
}
.contentVertical {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
outline: 0;
font-size: 0.875rem;
color: var(--color-gray-600);
line-height: 1.5;
}
/* Dynamic tabs helpers */
.dynamicWrapper {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
max-width: 400px;
}
.dynamicControls {
display: flex;
gap: 0.5rem;
}
.dynamicButton {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 2rem;
padding: 0 0.75rem;
outline: 0;
border: 1px solid var(--color-gray-200);
border-radius: 0.375rem;
background-color: var(--color-gray-50);
font-family: inherit;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-gray-900);
cursor: pointer;
}
.dynamicButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
@media (hover: hover) {
.dynamicButton:hover:not(:disabled) {
background-color: var(--color-gray-100);
}
}:root {
--color-blue: oklch(45% 50% 264deg);
--color-red: oklch(50% 55% 31deg);
--color-gray-50: oklch(98% 0.25% 264deg);
--color-gray-100: oklch(12% 9.5% 264deg / 5%);
--color-gray-200: oklch(12% 9% 264deg / 7%);
--color-gray-300: oklch(12% 8.5% 264deg / 17%);
--color-gray-400: oklch(12% 8% 264deg / 38%);
--color-gray-500: oklch(12% 7.5% 264deg / 50%);
--color-gray-600: oklch(12% 7% 264deg / 67%);
--color-gray-700: oklch(12% 6% 264deg / 77%);
--color-gray-800: oklch(12% 5% 264deg / 85%);
--color-gray-900: oklch(12% 5% 264deg / 90%);
--color-gray-950: oklch(12% 5% 264deg / 95%);
}
@media (prefers-color-scheme: dark) {
:root {
--color-blue: oklch(69% 50% 264deg);
--color-red: oklch(80% 55% 31deg);
--color-gray-50: oklch(17% 0.25% 264deg);
--color-gray-100: oklch(28% 0.75% 264deg / 65%);
--color-gray-200: oklch(29% 0.75% 264deg / 80%);
--color-gray-300: oklch(35% 0.75% 264deg / 80%);
--color-gray-400: oklch(47% 0.875% 264deg / 80%);
--color-gray-500: oklch(64% 1% 264deg / 80%);
--color-gray-600: oklch(82% 1% 264deg / 80%);
--color-gray-700: oklch(92% 1.125% 264deg / 80%);
--color-gray-800: oklch(93% 0.875% 264deg / 85%);
--color-gray-900: oklch(95% 0.5% 264deg / 90%);
--color-gray-950: oklch(94% 0.375% 264deg / 95%);
}
}