Search

Tabs

This page is currently under construction
Lism UI (@lism-css/ui) is still in preparation.

A component for creating tab elements. Only interaction behavior is provided — visual styling is intentionally left for you to customize.

Usage

Provided as Tabs from the @lism-css/ui package.

Import

import { Tabs } from '@lism-css/ui/react';

Props

PropertyDescription
<Tabs.Root>
variant
Outputs the c--tabs--{variant} class.
<Tabs.Root>
tabId
A string ID used as the value for aria-controls to identify each tab.
<Tabs.Root>
defaultIndex
Specifies which tab to open initially.
<Tabs.Root>
listProps
Props passed to the list element (c--tabs_list) wrapping the tab buttons.

Structure

<Tabs.Root>
<Tabs.Item>
<Tabs.Tab>Tab label</Tabs.Tab>
<Tabs.Panel>...Contents...</Tabs.Panel>
</Tabs.Item>
</Tabs.Root>

Only <Tabs.Tab> and <Tabs.Panel> are recognized as children of <Tabs.Item>. Both must always be used together.

Source Code

The source code is available on GitHub.

Examples

Basic example

Example

Tab 01: Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

<Tabs.Root>
<Tabs.Item>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Panel>
<DummyText pre="Tab 01: " />
</Tabs.Panel>
</Tabs.Item>
<Tabs.Item>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Panel>
<DummyText length="l" offset={1} pre="Tab 02: " />
</Tabs.Panel>
</Tabs.Item>
</Tabs.Root>

Specifying the initially open tab

Use defaultIndex on <Tabs.Root> to specify which tab is open by default. (Index numbers start from 1.)

Example

Tab 02: Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.

<Tabs.Root defaultIndex={2}>
<Tabs.Item>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Panel>
<DummyText pre="Tab 01: " />
</Tabs.Panel>
</Tabs.Item>
<Tabs.Item>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Panel>
<DummyText length="l" offset={1} pre="Tab 02: " />
</Tabs.Panel>
</Tabs.Item>
</Tabs.Root>

Side-by-side tab layout

Setting grid-template: 'list panel' auto / auto 1fr; on <Tabs.Root> (c--tabs) places the tab list and content side by side.

At the same time, changing the tab list (c--tabs_list) buttons to stack vertically (flex-direction: column;) achieves the following layout.

Example: side-by-side layout on @sm and above

Tab 01: Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

Resize
<Tabs.Root gt={[null, '"list panel" auto / auto 1fr']} listProps={{ fxd: [null, 'column'] }}>
<Tabs.Item>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Panel>
<DummyText pre="Tab 01: " />
</Tabs.Panel>
</Tabs.Item>
<Tabs.Item>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Panel>
<DummyText length="l" offset={1} pre="Tab 02: " />
</Tabs.Panel>
</Tabs.Item>
</Tabs.Root>

Opt-in

Style variation examples

c--tabs_tab exposes --_isSelected and --_notSelected variables, which are handy for styling. (They can be used in the same way as --_isHov and --_notHov from set--var:hov.)

Here are a few styling examples.

c--tabs--line

Required additional CSS
@layer lism-component {
  .c--tabs--line > .c--tabs_list {
    /* Memo: ov-x='auto' の時に margin がネガティブだと崩れるので、box-shadowで表現する。 */
    box-shadow: inset 0 -2px 0 var(--divider);
  }
  .c--tabs--line .c--tabs_tab {
    font-size: var(--fz--s);
    background-color: transparent;
    box-shadow: var(--_isSelected, inset 0 -2px 0 0 currentColor);
  }
}
variant='line'

Tab 01: Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

<Tabs.Root variant="line">
<Tabs.Item>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Panel>
<DummyText pre="Tab 01: " />
</Tabs.Panel>
</Tabs.Item>
<Tabs.Item>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Panel>
<DummyText length="l" offset={1} pre="Tab 02: " />
</Tabs.Panel>
</Tabs.Item>
</Tabs.Root>

c--tabs--emboss

Required additional CSS
@layer lism-component {
  .c--tabs--emboss > .c--tabs_list {
    justify-self: center;
    padding: 4px;
    font-size: var(--fz--s);
    background-color: var(--base-2);
    border-radius: var(--bdrs--20);
  }
  .c--tabs--emboss .c--tabs_tab {
    padding: 0.25em 0.75em;
    border-radius: calc(var(--bdrs--20) - 2px); /* 親の bdrs - (親のpadding / 2) */
    background-color: var(--_isSelected, var(--base));
    box-shadow: var(--_isSelected, var(--bxsh--10));
  }
}
variant='emboss'

Tab 01: Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

<Tabs.Root variant="emboss">
<Tabs.Item>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Panel>
<DummyText pre="Tab 01: " />
</Tabs.Panel>
</Tabs.Item>
<Tabs.Item>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Panel>
<DummyText length="l" offset={1} pre="Tab 02: " />
</Tabs.Panel>
</Tabs.Item>
</Tabs.Root>

Fixed height

An example of how to fix the overall tabs height to match the tallest content panel.

Required additional CSS
@layer lism-component {
  [data-tabs-keep-height] > [aria-hidden='true'] {
    display: block;
    visibility: hidden;
    opacity: 0;
  }
}
Example (height is fixed to Tab 2)

Tab 01: Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

<Tabs.Root data-tabs-keep-height g="15">
<Tabs.Item>
<Tabs.Tab px="10">Tab 1</Tabs.Tab>
<Tabs.Panel>
<DummyText pre="Tab 01: " />
</Tabs.Panel>
</Tabs.Item>
<Tabs.Item>
<Tabs.Tab px="10">Tab 2</Tabs.Tab>
<Tabs.Panel>
<DummyText length="xl" offset={1} pre="Tab 02: " />
</Tabs.Panel>
</Tabs.Item>
</Tabs.Root>

© Lism CSS. All rights reserved.