Tabs
Allow users to switch between pages, or between panels on the same page
<sa-tab-list>
<sa-tab-link href="#">Flights</sa-tab-link>
<sa-tab-link href="#">Accommodation</sa-tab-link>
<sa-tab-link href="#">Car Rental</sa-tab-link>
</sa-tab-list>Usage
Tabs can be used to either display a set of interactive navigation links, or interactive tabs with panels. Both share the same variants, orientations and icons.
Tabs with navigation links
Use <sa-tab-list> with <sa-tab-link> when you want tabs that navigate the user to different pages.
<sa-tab-list>
<sa-tab-link>...</sa-tab-link>
</sa-tab-list>Interactive tab panels
When you want to use tabs with interactive panels that display different content based on the selected tab, you can use this pattern.
Place <sa-tab-list> inside an <sa-tabs> Tag Helper. Use combinations of <sa-tab> and <sa-tab-panel> for the content. Each tabs's for attribute names the id of its panel. Selecting a tab shows its panel in place, without navigating.
<sa-tabs>
<sa-tab-list>
<sa-tab for="summary">...</sa-tab>
<sa-tab for="orders">...</sa-tab>
</sa-tab-list>
<sa-tab-panel id="summary">...</sa-tab-panel>
<sa-tab-panel id="orders">...</sa-tab-panel>
</sa-tabs>Examples
Variant
Create underline tabs by setting the variant attribute.
<sa-tab-list variant="TabListVariant.Line">
<sa-tab-link href="#">Flights</sa-tab-link>
<sa-tab-link href="#">Accommodation</sa-tab-link>
<sa-tab-link href="#">Car Rental</sa-tab-link>
</sa-tab-list>Orientation
Create vertical tabs by setting the orientation attribute.
<sa-tab-list orientation="TabListOrientation.Vertical" class="w-fit">
<sa-tab-link href="#">Flights</sa-tab-link>
<sa-tab-link href="#">Accommodation</sa-tab-link>
<sa-tab-link href="#">Car Rental</sa-tab-link>
</sa-tab-list>Icons
Use icons along with the text.
<sa-tab-list>
<sa-tab-link href="#">
<sa-icon name="plane"/>
Flights
</sa-tab-link>
<sa-tab-link href="#">
<sa-icon name="bed-double"/>
Accommodation
</sa-tab-link>
<sa-tab-link href="#">
<sa-icon name="car-front"/>
Car Rental
</sa-tab-link>
</sa-tab-list>Icons only
Tabs can contain only an icon. Give each one an accessible name.
<sa-tab-list>
<sa-tab-link href="#">
<sa-icon name="plane"/>
</sa-tab-link>
<sa-tab-link href="#">
<sa-icon name="bed-double"/>
</sa-tab-link>
<sa-tab-link href="#">
<sa-icon name="car-front"/>
</sa-tab-link>
</sa-tab-list>Active item
Set the currently active item using the active attribute.
<sa-tab-list>
<sa-tab-link href="#">Flights</sa-tab-link>
<sa-tab-link active="true" href="#">Accommodation</sa-tab-link>
<sa-tab-link href="#">Car Rental</sa-tab-link>
</sa-tab-list>URL
The URL of <sa-tab-link> can be specified a couple of ways:
- You can use the
hrefproperty to specify any valid URL as per thehrefproperty of the anchor element. - You can use any of the attributes that are valid for specifying the URL for the ASP.NET Core Anchor Tag Helper, such as
asp-controller,asp-action,asp-page, etc. Please refer to the Anchor Tag Helper documentation for more examples.
<sa-tab-list>
<sa-tab-link asp-controller="Search" asp-route-category="flights">
Flights
</sa-tab-link>
<sa-tab-link asp-controller="Search" asp-route-category="accommodation">
Accommodation
</sa-tab-link>
<sa-tab-link asp-controller="Search" asp-route-category="carrental">
Car Rental
</sa-tab-link>
</sa-tab-list>When specifying the URL, StellarAdmin will automatically set the active attribute for the tab link representing the currently active route, so you should not need to specify the active attribute explicitly. However, StellarAdmin can not always determine this correctly - especially if the URL contains query string parameters. In such cases, you can explicitly set the active attribute to either true or false.
Disabled
Disable a tab using the disabled attribute.
<sa-tab-list>
<sa-tab-link href="#">Flights</sa-tab-link>
<sa-tab-link href="#">Accommodation</sa-tab-link>
<sa-tab-link href="#" disabled="true">Car Rental</sa-tab-link>
</sa-tab-list>Panels
Selecting a tab shows its panel and hides the others. The first tab is selected unless <sa-tabs> names another panel. A disabled tab cannot be selected.
<sa-tabs class="w-full max-w-md">
<sa-tab-list>
<sa-tab for="tabs-panels-flights">Flights</sa-tab>
<sa-tab for="tabs-panels-accommodation">Accommodation</sa-tab>
<sa-tab for="tabs-panels-car-rental" disabled="true">Car Rental</sa-tab>
</sa-tab-list>
<sa-tab-panel id="tabs-panels-flights">
<p class="font-medium">Lisbon (LIS) to Reykjavík (KEF)</p>
<p class="text-muted-foreground text-sm">Departs 14 March at 07:40, arrives 10:15. Economy, 1 checked bag.</p>
</sa-tab-panel>
<sa-tab-panel id="tabs-panels-accommodation">
<p class="font-medium">Hotel Borg, Reykjavík</p>
<p class="text-muted-foreground text-sm">3 nights from 14 March. Deluxe double room, breakfast included.</p>
</sa-tab-panel>
<sa-tab-panel id="tabs-panels-car-rental">
<p class="font-medium">No car booked</p>
</sa-tab-panel>
</sa-tabs>Selected panel
Show a panel other than the first by setting the value attribute of <sa-tabs> to its id. Panel tabs take the same variants and icons as link tabs.
<sa-tabs value="tabs-line-itinerary" class="w-full max-w-md">
<sa-tab-list variant="TabListVariant.Line">
<sa-tab for="tabs-line-overview">
<sa-icon name="info"/>
Overview
</sa-tab>
<sa-tab for="tabs-line-itinerary">
<sa-icon name="map"/>
Itinerary
</sa-tab>
<sa-tab for="tabs-line-travellers">
<sa-icon name="users"/>
Travellers
</sa-tab>
</sa-tab-list>
<sa-tab-panel id="tabs-line-overview">
<p class="text-muted-foreground text-sm">Seven days in Iceland's south coast, from Reykjavík to Jökulsárlón.</p>
</sa-tab-panel>
<sa-tab-panel id="tabs-line-itinerary">
<ol class="text-muted-foreground list-decimal space-y-1 ps-5 text-sm">
<li>Arrive in Reykjavík, Golden Circle tour</li>
<li>Seljalandsfoss and Skógafoss waterfalls</li>
<li>Glacier hike at Sólheimajökull</li>
</ol>
</sa-tab-panel>
<sa-tab-panel id="tabs-line-travellers">
<p class="text-muted-foreground text-sm">Priya Raman and Mika Tanaka.</p>
</sa-tab-panel>
</sa-tabs>Vertical panels
With a vertical tab list, the panels sit beside the tabs.
<sa-tabs class="w-full max-w-lg">
<sa-tab-list orientation="TabListOrientation.Vertical">
<sa-tab for="tabs-vertical-profile">Profile</sa-tab>
<sa-tab for="tabs-vertical-preferences">Preferences</sa-tab>
<sa-tab for="tabs-vertical-loyalty">Loyalty</sa-tab>
</sa-tab-list>
<sa-tab-panel id="tabs-vertical-profile">
<p class="font-medium">Priya Raman</p>
<p class="text-muted-foreground text-sm">priya.raman@voyager.travel, travelling from Lisbon.</p>
</sa-tab-panel>
<sa-tab-panel id="tabs-vertical-preferences">
<p class="text-muted-foreground text-sm">Window seat, vegetarian meals, quiet rooms on a high floor.</p>
</sa-tab-panel>
<sa-tab-panel id="tabs-vertical-loyalty">
<p class="text-muted-foreground text-sm">Voyager Gold, 18,400 points. Next tier at 25,000 points.</p>
</sa-tab-panel>
</sa-tabs>Loading a panel when it is shown
Selecting a tab raises a bubbling tabhide event on the panel it hides, then a tabshow event on the panel it shows, once that panel is visible. The event's detail holds the tab and the panel. The panel shown when the page loads raises no event. This example listens for tabshow to fill the Documents panel the first time it opens.
<sa-tabs class="w-full max-w-md">
<sa-tab-list>
<sa-tab for="tabs-load-summary">Summary</sa-tab>
<sa-tab for="tabs-load-documents">Documents</sa-tab>
</sa-tab-list>
<sa-tab-panel id="tabs-load-summary">
<p class="font-medium">Booking VYG-4471-KX</p>
<p class="text-muted-foreground text-sm">Reykjavík, 14 to 17 March. Paid in full.</p>
</sa-tab-panel>
<sa-tab-panel id="tabs-load-documents">
<div class="flex flex-col gap-2">
<sa-skeleton class="h-4 w-48"/>
<sa-skeleton class="h-4 w-40"/>
</div>
</sa-tab-panel>
</sa-tabs>
<script>
(() => {
// With htmx, hx-get="…" hx-trigger="tabshow once" on the panel does the same.
const panel = document.getElementById("tabs-load-documents");
panel.addEventListener("tabshow", async () => {
await new Promise((resolve) => setTimeout(resolve, 800));
panel.innerHTML = `
<ul class="text-muted-foreground list-disc space-y-1 ps-5 text-sm">
<li>E-ticket LIS to KEF</li>
<li>Hotel Borg confirmation</li>
</ul>`;
}, { once: true });
})();
</script>With htmx, put the attributes on the panel itself, where the event fires. The placeholder shows until the response arrives. Drop once to reload the panel every time it is shown.
<sa-tab-panel id="documents"
hx-get="/bookings/VYG-4471-KX/documents"
hx-trigger="tabshow once">
<sa-skeleton class="h-4 w-48"/>
</sa-tab-panel>Accessibility
Link tabs are links. Each <sa-tab-link> renders an <a role="tab"> with aria-selected reflecting the active state, and following it navigates to its URL. Because they are links, each tab is a separate Tab stop and the arrow keys are not used to move between them.
A disabled tab renders aria-disabled="true" and has its href removed so it cannot be followed. Give every tab visible text.
Panel tabs follow the WAI-ARIA tabs pattern. The list renders role="tablist" with aria-orientation, each <sa-tab> renders a <button role="tab"> with aria-selected and aria-controls, and each panel renders role="tabpanel" labelled by its tab. Only the selected tab is a Tab stop. The arrow keys move between the tabs and select the one they move to (Up and Down for a vertical list), Home and End move to the first and last, and disabled tabs are skipped. Pressing Tab from the selected tab moves focus to its panel.
API Reference
<sa-tab-list>
Renders a <div> element wrapping an inner tab list <div>. Inside an <sa-tabs>, the inner list renders role="tablist".
Prop
Type
<sa-tab-link>
Renders an <a> element.
Prop
Type
Routing attributes
The tab link also accepts the same routing attributes as the ASP.NET Core Anchor Tag Helper for generating the href. Supply either an href or these attributes — not both.
Prop
Type
<sa-tabs>
Wraps an <sa-tab-list> of <sa-tab>s and their <sa-tab-panel>s, rendered as a web component that takes the id you give it. It raises the bubbling tabhide and tabshow events on the panels as they are hidden and shown. From JavaScript, call select(tab) on document.getElementById() of that id, passing an <sa-tab>'s button.
Prop
Type
<sa-tab>
Renders a <button> element. Its id defaults to the panel's id followed by -tab.
Prop
Type
<sa-tab-panel>
Renders a <div> element, hidden until its tab is selected. It needs an id, which its tab's for attribute names.