Tabs

Keep related content in a single container that is shown and hidden through navigation.

# Features

  • Follows the ARIA pattern for tabs, semantically linking tabs and their associated tab panels.
  • Full keyboard navigation & focus management for improved accessibility.
  • Supports horizontal/vertical orientation.
  • Supports automatic/manual activation.
  • Support for disabled tabs.

# Anatomy

Typically, the tabs consists of:

  • Root: The root container for the trigger and content elements.
    • List: The container for the trigger elements.
      • Trigger: The button that activates a tab panel.
    • Content: The element that holds the content of the tab.
<script>
	import { createTabs } from '@grail-ui/svelte';

	const { useTabs, rootAttrs, listAttrs, triggerAttrs, contentAttrs } = createTabs();

	const data = [
		{ key: "item-1", title: "Item 1", content: "Content for one." },
		{ key: "item-2", title: "Item 2", content: "Content for two." },
		{ key: "item-3", title: "Item 3", content: "Content for three." },
	];
</script>

<div use:useTabs {...$rootAttrs}>
	<div {...$listAttrs}>
		{#each data as item}
			<button {...$triggerAttrs(item.key)}>{item.title}</button>
		{/each}
	</div>
	{#each data as item}
		<div {...$contentAttrs(item.key)}>{item.content}</div>
	{/each}
</div>

# Examples

# Selected by default

Use the value prop to define the selected tab by default.

createTabs({
value: 'item-1',
})

# Changing the orientation

The default orientation of the tabs is horizontal. To change the orientation, set the orientation property in the factory function to "vertical".

createTabs({
orientation: "vertical",
})

# Disabling specific tabs

To disable a specific tab, pass their respective keys to the factory function.

When a tab is disabled, it is skipped from keyboard navigation and can't be interacted with.

createTabs({
disabled: ['item-1'],
})

You can also disable the entire tabs by passing disabled: true.

createTabs({
disabled: true,
})

You can always modify the disabled tabs using the returned disabled writable store.

# Manual tab activation

By default, the tab can be selected when it receives focus from either the keyboard or pointer interaction. This is called "automatic tab activation". The other approach is "manual tab activation" which means the tab is selected with the Enter key or by clicking on the tab.

createTabs({
activationMode: "manual",
})

# Listening to tab selection

Pass onValueChange to the createTabs function to perform some custom logic when a tab is selected. This callback is invoked with the id of the tab.

createTabs({
onValueChange(value) {
console.log(value);
},
})

# Value type safety

The createTabs function accepts any string as a valid value by default.

However, you can specify a set of specific values to be accepted by using a generic. For example:

createTabs<'a' | 'b' | 'c'>()

To illustrate this in a more comprehensive manner, consider the following code:

type TabsKey = 'recent' | 'popular' | 'trending';
const {...} = createTabs<TabsKey>({ value: 'recent' });
const data: { key: TabsKey, ... }[] = [
...
]

# Accessibility

Tabs follow the recommendations of the WAI-ARIA Authoring Practices for tabs.

# Keyboard Interactions

Key description
Space Enter
When focus is on a triggerAttrs element, activates the tab.
Tab
When focus moves onto the tabs, focuses the active triggerAttrs element. When a trigger is focused, moves focus to the active contentAttrs element.
When orientation is vertical, moves focus to the next triggerAttrs element and activates its associated content.
When orientation is vertical, moves focus to the next triggerAttrs element and activates its associated content.
◀︎
When orientation is horizontal, moves focus to the previous triggerAttrs element and activates its associated content.
▶︎
When orientation is horizontal, moves focus to the next triggerAttrs element and activates its associated content.
Home
Moves focus to the first triggerAttrs element and activates its associated content.
End
Moves focus to the last triggerAttrs element and activates its associated content.

# API

# TabsConfig

Property Description Default
value?
Partial<T>
Initial value (controls active state of tabs).
orientation?
vertical | horizontal
The tabs orientation. Affects arrow navigation.
horizontal
activationMode?
automatic | manual
When automatic, tabs are activated when they receive focus. When manual, tabs are activated when clicked.
automatic
disabled?
boolean | Partial<T> | Partial<T>[]
The disabled tabs. Pass to true to disable all the tabs.
false
onValueChange?
(value: undefined | Partial) => void
Event handler called when the active state of the tabs changes.

# TabsReturn

Property Description
activate
(value: T) => void
Activates tab.
active
Readable<undefined | Partial<T>>
The active tab.
disabled
Writable<boolean | Partial<T> | Partial<T>[]>
The disabled keys of the tabs.
useTabs
Action<HTMLElement, void, Record<never, any>>
Action for the tabs root element.
rootAttrs
Readable<Record<string, string>>
HTML attributes for the element that contains the trigger and content elements.
listAttrs
Readable<Record<string, string>>
HTML attributes for the element that contains the triggers.
triggerAttrs
Readable<Function>
HTML attributes for the trigger element.
contentAttrs
Readable<Function>
HTML attributes for the content element.