Tabbed section layout: tabs on desktop, nav cards on phones.
One real route per tab, under a layout that renders the section. The live demo below is the code on this page: on desktop it opens the first tab, on phones it lists the tabs as cards.
Open the demo sectionUsage
<script lang="ts">
import { resolve } from "$app/paths";
import TabSection from "@orochibraru/ui/blocks/tab-section";
import { tabs } from "./tabs.js";
const { children } = $props();
</script>
<TabSection
title="Section"
indexHref={resolve("/section")}
backHref={resolve("/[group]/[slug]", {
group: "blocks",
slug: "tab-section",
})}
{tabs}
>
{@render children()}
</TabSection>
<script lang="ts">
import NavCards from "@orochibraru/ui/blocks/nav-cards";
import { tabs } from "./tabs.js";
</script>
<NavCards {tabs} />
<script lang="ts">
import ThemePicker from "@orochibraru/ui/blocks/theme-picker";
</script>
<ThemePicker />
<script lang="ts">
import * as Field from "@orochibraru/ui/field";
import { Input } from "@orochibraru/ui/input";
</script>
<Field.Group>
<Field.Field>
<Field.Label for="name">Name</Field.Label>
<Input id="name" value="Alex" />
</Field.Field>
<Field.Field>
<Field.Label for="profile-email">Email</Field.Label>
<Input id="profile-email" type="email" value="alex@example.com" />
</Field.Field>
</Field.Group>
import { resolve } from "$app/paths";
import PaletteIcon from "@lucide/svelte/icons/palette";
import UserRoundIcon from "@lucide/svelte/icons/user-round";
import type { SectionTab } from "@orochibraru/ui/blocks/nav-cards";
export const tabs: SectionTab[] = [
{
href: resolve("/section/profile"),
label: "Profile",
description: "Your name and the email you sign in with.",
icon: UserRoundIcon,
},
{
href: resolve("/section/appearance"),
label: "Appearance",
description: "Light, dark, or whatever the device says.",
icon: PaletteIcon,
},
];