TabsContent
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Identifier pairing it with a tab; required |
class | string | — | Classes appended to the panel |
On my first day at the new school I met a girl on the roof holding an old camera.
<script setup lang="ts">
import { Stack, Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@hina-ui/vue'
</script>
<template>
<Tabs default-value="intro" class="w-full max-w-md">
<TabsList label="Work details">
<TabsTrigger value="intro">Synopsis</TabsTrigger>
<TabsTrigger value="volumes">Volumes</TabsTrigger>
<TabsTrigger value="staff">Staff</TabsTrigger>
</TabsList>
<TabsContent value="intro">
<Stack gap="xs" class="pt-4">
<Text tone="muted" size="sm">
On my first day at the new school I met a girl on the roof holding an old camera.
</Text>
</Stack>
</TabsContent>
<TabsContent value="volumes">
<Stack gap="xs" class="pt-4">
<Text tone="muted" size="sm">Seven volumes so far, with the eighth due this winter.</Text>
</Stack>
</TabsContent>
<TabsContent value="staff">
<Stack gap="xs" class="pt-4">
<Text tone="muted" size="sm">Written by Isuna Hasekura, illustrated by Jyuu Ayakura.</Text>
</Stack>
</TabsContent>
</Tabs>
</template>
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@hina-ui/vue'
Four parts: Tabs holds the current selection, TabsList is the row the tabs sit in, TabsTrigger is a single tab, and TabsContent is the panel that belongs to it. Triggers and panels are paired by value.
Three works in progress.
<script setup lang="ts">
import { Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@hina-ui/vue'
</script>
<template>
<Tabs default-value="reading" class="w-full max-w-md">
<TabsList label="Shelf">
<TabsTrigger value="reading">Reading</TabsTrigger>
<TabsTrigger value="planned">Want to read</TabsTrigger>
<TabsTrigger value="finished">Read</TabsTrigger>
</TabsList>
<TabsContent value="reading">
<Text tone="muted" size="sm" class="block pt-4">Three works in progress.</Text>
</TabsContent>
<TabsContent value="planned">
<Text tone="muted" size="sm" class="block pt-4">Twelve works saved for later.</Text>
</TabsContent>
<TabsContent value="finished">
<Text tone="muted" size="sm" class="block pt-4">Forty-eight works finished.</Text>
</TabsContent>
</Tabs>
</template>
Tabs switch between sets of content that stand side by side, in no particular order. When the content needs to be visible at once, use section headings instead; when it is a sequence of steps, use Stepper.
underline is the default: a rounded line marks the selected tab, which suits content grouped at the width of the body text. In soft the selection is a raised block, which suits toolbars and compact switches.
A rounded line marks the selected tab.
A raised block marks the selected tab.
<script setup lang="ts">
import { Stack, Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@hina-ui/vue'
</script>
<template>
<Stack gap="lg" class="w-full max-w-md">
<Tabs default-value="a" variant="underline">
<TabsList label="Underline shape">
<TabsTrigger value="a">underline</TabsTrigger>
<TabsTrigger value="b">The default</TabsTrigger>
</TabsList>
<TabsContent value="a">
<Text tone="muted" size="sm" class="block pt-3">
A rounded line marks the selected tab.
</Text>
</TabsContent>
<TabsContent value="b">
<Text tone="muted" size="sm" class="block pt-3">
Suits content grouped at the width of the body text.
</Text>
</TabsContent>
</Tabs>
<Tabs default-value="a" variant="soft">
<TabsList label="Block shape">
<TabsTrigger value="a">soft</TabsTrigger>
<TabsTrigger value="b">The block shape</TabsTrigger>
</TabsList>
<TabsContent value="a">
<Text tone="muted" size="sm" class="block pt-3">
A raised block marks the selected tab.
</Text>
</TabsContent>
<TabsContent value="b">
<Text tone="muted" size="sm" class="block pt-3">Suits toolbars and compact switches.</Text>
</TabsContent>
</Tabs>
</Stack>
</template>
The line or block travels and resizes as the selection moves, rather than jumping.
size changes how dense the row is: sm for toolbars and compact interfaces, md as the default, and lg where the row needs more presence, such as the top of a page.
The type size stays the same across all three. Tabs are interface chrome, so their visual weight comes from height, padding and the selection marker.
sm
md
lg
<script setup lang="ts">
import { Stack, Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@hina-ui/vue'
const sizes = ['sm', 'md', 'lg'] as const
</script>
<template>
<Stack gap="lg" class="w-full max-w-md">
<Stack v-for="size in sizes" :key="size" gap="xs">
<Text tone="muted" size="sm">{{ size }}</Text>
<Tabs default-value="a" :size="size">
<TabsList :label="`Size ${size}`">
<TabsTrigger value="a">Synopsis</TabsTrigger>
<TabsTrigger value="b">Volumes</TabsTrigger>
</TabsList>
<TabsContent value="a" />
<TabsContent value="b" />
</Tabs>
</Stack>
</Stack>
</template>
Set orientation to vertical and the tabs stack into a column beside the content, with the arrow keys switching to up and down.
Username, email address and password.
<script setup lang="ts">
import { Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@hina-ui/vue'
</script>
<template>
<Tabs default-value="account" orientation="vertical" class="w-full max-w-md">
<TabsList label="Settings sections">
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="reading">Reading</TabsTrigger>
<TabsTrigger value="notice">Notifications</TabsTrigger>
</TabsList>
<TabsContent value="account">
<Text tone="muted" size="sm">Username, email address and password.</Text>
</TabsContent>
<TabsContent value="reading">
<Text tone="muted" size="sm">Type size, line height and page direction.</Text>
</TabsContent>
<TabsContent value="notice">
<Text tone="muted" size="sm">Update alerts and site messages.</Text>
</TabsContent>
</Tabs>
</template>
Once the tabs overflow their container the row scrolls sideways without showing a scrollbar: edge shadows indicate the scroll position, the mouse wheel scrolls the row directly, and the keyboard cycles through the tabs with the arrow keys.
Works tagged Sci-fi.
<script setup lang="ts">
import { Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@hina-ui/vue'
const genres = [
'Sci-fi',
'Mystery',
'Slice of life',
'School',
'Healing',
'Fantasy',
'Detective',
'Romance',
'Historical',
'War',
]
</script>
<template>
<Tabs default-value="Sci-fi" class="w-full max-w-sm">
<TabsList label="Genre">
<TabsTrigger v-for="genre in genres" :key="genre" :value="genre">{{ genre }}</TabsTrigger>
</TabsList>
<TabsContent v-for="genre in genres" :key="genre" :value="genre">
<Text tone="muted" size="sm" class="block pt-4">Works tagged {{ genre }}.</Text>
</TabsContent>
</Tabs>
</template>
disabled on a TabsTrigger makes that tab unselectable, and the arrow keys skip over it.
Anyone can see this list.
<script setup lang="ts">
import { Tabs, TabsContent, TabsList, TabsTrigger, Text } from '@hina-ui/vue'
</script>
<template>
<Tabs default-value="public" class="w-full max-w-md">
<TabsList label="Visibility">
<TabsTrigger value="public">Public</TabsTrigger>
<TabsTrigger value="friends">Followers only</TabsTrigger>
<TabsTrigger value="private" disabled>Private (sign in required)</TabsTrigger>
</TabsList>
<TabsContent value="public">
<Text tone="muted" size="sm" class="block pt-4">Anyone can see this list.</Text>
</TabsContent>
<TabsContent value="friends">
<Text tone="muted" size="sm" class="block pt-4">Only people who follow you can see it.</Text>
</TabsContent>
<TabsContent value="private">
<Text tone="muted" size="sm" class="block pt-4">Only you can see it.</Text>
</TabsContent>
</Tabs>
</template>
TabsList a label describing what this set of tabs switches between.Home and End jump to the ends, and the selection follows the focus.| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | — | The selected tab, takes v-model |
defaultValue | string | — | The initially selected tab |
variant | 'underline' | 'soft' | 'underline' | Shape |
size | 'sm' | 'md' | 'lg' | 'md' | Size |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Direction |
class | string | — | Classes appended to the root |
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | A name for this set of tabs |
class | string | — | Classes appended to the row |
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Identifier pairing it with a panel; required |
disabled | boolean | false | Whether the tab can be selected |
class | string | — | Classes appended to the tab |
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Identifier pairing it with a tab; required |
class | string | — | Classes appended to the panel |