RizzyUI

Tabs

A set of layered sections of content—known as tab panels—that are displayed one at a time.

Demo

The main demo showcases a common use case for tabs: organizing user settings into "Account" and "Password" sections within a card.

Source
                        <EditForm Model="_demoModel">
                            <DataAnnotationsValidator />
                            <RzInitialValidator />
	                        <RzTabs DefaultValue="account">
		                        <TabsList>
			                        <TabsTrigger Value="account">Account</TabsTrigger>
			                        <TabsTrigger Value="password">Password</TabsTrigger>
		                        </TabsList>
		                        <TabsContent Value="account">
			                        <RzCard>
				                        <CardHeader>
					                        <CardTitle>Account</CardTitle>
					                        <CardDescription>
						                        Make changes to your account here. Click save when you're done.
					                        </CardDescription>
				                        </CardHeader>
				                        <CardContent>
                                            <RzFieldSet>
                                                <RzFieldGroup>
                                                    <Field>
                                                        <FieldLabel For="@(() => _demoModel.Name)" />
                                                        <RzInputText For="@(() => _demoModel.Name)" />
                                                        <FieldError><RzValidationMessage For="@(() => _demoModel.Name)" /></FieldError>
                                                    </Field>
                                                    <Field>
                                                        <FieldLabel For="@(() => _demoModel.Username)" />
                                                        <RzInputText For="@(() => _demoModel.Username)" />
                                                        <FieldError><RzValidationMessage For="@(() => _demoModel.Username)" /></FieldError>
                                                    </Field>
                                                </RzFieldGroup>
                                            </RzFieldSet>
				                        </CardContent>
				                        <CardFooter>
					                        <RzButton>Save changes</RzButton>
				                        </CardFooter>
			                        </RzCard>
		                        </TabsContent>
		                        <TabsContent Value="password">
			                        <RzCard>
				                        <CardHeader>
					                        <CardTitle>Password</CardTitle>
					                        <CardDescription>
						                        Change your password here. After saving, you'll be logged out.
					                        </CardDescription>
				                        </CardHeader>
				                        <CardContent>
                                            <RzFieldSet>
                                                <RzFieldGroup>
                                                    <Field>
                                                        <FieldLabel For="@(() => _demoModel.CurrentPassword)" />
                                                        <RzInputText For="@(() => _demoModel.CurrentPassword)" Role="
" />
                                                        <FieldError><RzValidationMessage For="@(() => _demoModel.CurrentPassword)" /></FieldError>
                                                    </Field>
                                                    <Field>
                                                        <FieldLabel For="@(() => _demoModel.NewPassword)" />
                                                        <RzInputText For="@(() => _demoModel.NewPassword)" Role="
" />
                                                        <FieldError><RzValidationMessage For="@(() => _demoModel.NewPassword)" /></FieldError>
                                                    </Field>
                                                </RzFieldGroup>
                                            </RzFieldSet>
				                        </CardContent>
				                        <CardFooter>
					                        <RzButton>Save password</RzButton>
				                        </CardFooter>
			                        </RzCard>
		                        </TabsContent>
	                        </RzTabs>
                        </EditForm>

Usage

Here is the basic structure for creating a set of tabs.

Source
<RzTabs DefaultValue="account" class="w-[400px]">
  <TabsList>
    <TabsTrigger Value="account">Account</TabsTrigger>
    <TabsTrigger Value="password">Password</TabsTrigger>
  </TabsList>
  <TabsContent Value="account">Make changes to your account here.</TabsContent>
  <TabsContent Value="password">Change your password here.</TabsContent>
</RzTabs>

Accessibility

RzTabs follows the WAI-ARIA Authoring Practices Guide Tabs pattern with automatic activation. A TabsList renders the tablist, each TabsTrigger renders a tab, and each TabsContent renders the associated tabpanel.

Tabs are best for switching between related panels without leaving the current page. Keep tab labels short, unique, and descriptive so assistive technology users can understand the available panels before activating them.

Semantics

  • TabsList renders role="tablist" with an accessible name from AriaLabel.
  • TabsList exposes aria-orientation as horizontal or vertical.
  • Each TabsTrigger renders role="tab", stable id, aria-controls, aria-selected, tabindex, and data-state.
  • Each TabsContent renders role="tabpanel", stable id, and aria-labelledby pointing back to its tab.
  • Inactive panels are hidden with hidden and aria-hidden="true"; the active panel removes those hidden states.
  • Disabled tabs expose aria-disabled="true" and are skipped by keyboard activation.

Keyboard interaction

KeyWhen focus is onBehavior
TabTabsTriggerLeaves the tablist and moves to the next focusable element in page order. Focus is not trapped.
Shift + TabTabsTriggerMoves to the previous focusable element in page order.
ArrowRightHorizontal TabsListMoves focus to and automatically activates the next enabled tab, wrapping to the first enabled tab.
ArrowLeftHorizontal TabsListMoves focus to and automatically activates the previous enabled tab, wrapping to the last enabled tab.
ArrowDownVertical TabsListMoves focus to and automatically activates the next enabled tab, wrapping to the first enabled tab.
ArrowUpVertical TabsListMoves focus to and automatically activates the previous enabled tab, wrapping to the last enabled tab.
HomeTabsTriggerMoves focus to and automatically activates the first enabled tab.
EndTabsTriggerMoves focus to and automatically activates the last enabled tab.
Enter or SpaceTabsTriggerActivates the focused native button tab. The current API uses automatic activation, so these keys are not required after arrow navigation.

Activation and focus

  • RzTabs uses automatic activation: arrow navigation changes the active panel immediately and moves focus to the newly active tab.
  • Only one enabled tab participates in sequential keyboard navigation with tabindex="0"; inactive and disabled tabs use tabindex="-1".
  • DefaultValue selects the initial tab when it matches an enabled trigger. If it is missing or disabled, the first enabled trigger is selected.
  • Focus is never trapped. Users can tab out of the tablist into active panel content or the rest of the page.
  • Panels remain associated with tabs by stable IDs generated from the parent RzTabs ID and each tab Value.

Screen-reader behavior

  • Screen readers can announce the tablist name, each tab label, selected state, disabled state, and the currently active panel relationship.
  • RzTabs does not use live-region announcements for normal tab changes because aria-selected, focus movement, and the labelled panel communicate the change without extra announcement noise.
  • Authors should provide meaningful panel headings or introductory text inside complex tab panels.

SSR and CSP notes

  • The component renders SSR-safe roles, IDs, and ARIA relationships before Alpine initializes.
  • Alpine updates selection, roving tabindex, hidden states, and rz:tabs-change events on the client without Blazor interactivity.
  • The runtime is registered through the core-common bundle and works with the default and CSP runtime entrypoints.

Component Parameters

The following tables summarize the main parameters for each component in the Tabs family.

RzTabs

PropertyTypeDefaultDescription
DefaultValuestring?First tabThe value of the tab that should be active on initial render.
ChildContentRenderFragmentRequiredThe content, which should include a TabsList and TabsContent components.

TabsList

PropertyTypeDefaultDescription
ChildContentRenderFragmentRequiredThe content, which should be a series of TabsTrigger components.
AriaLabelstring?"Tabs"The accessible name for the tab list.
OrientationOrientationHorizontalThe orientation of the tab list, affecting keyboard navigation.

TabsTrigger

PropertyTypeDefaultDescription
ValuestringRequiredA unique value that associates the trigger with a TabsContent.
DisabledboolfalseIf true, the trigger is disabled and cannot be selected.
AsChildboolfalseMerges behavior into a single child element instead of rendering a button.

TabsContent

PropertyTypeDefaultDescription
ValuestringRequiredA unique value that associates the content with a TabsTrigger.

Alpine API

This page uses the rzTabs Alpine x-data component. The runtime keeps tab selection, roving tabindex, panel visibility, and keyboard focus in sync after server rendering.

MethodParametersDescription
refreshTriggersRefreshes trigger registrations when tab markup changes.
activateTriggertrigger, focusTriggerSelects an enabled trigger, optionally moves focus, and dispatches rz:tabs-change when the value changes.
onListKeydownKeyboardEventHandles orientation-aware arrow navigation, Home, and End for automatic activation.