This repository has no description
1<script module lang="ts">
2 import type { Component } from "svelte";
3 import type { SvelteHTMLElements } from "svelte/elements";
4
5 export interface TabDef {
6 id: string;
7 label: string;
8 href: string;
9 icon?: Component<SvelteHTMLElements["svg"]>;
10 count?: number;
11 }
12</script>
13
14<script lang="ts">
15 import { resolve } from "$app/paths";
16
17 interface Props {
18 tabs: TabDef[];
19 active: string;
20 label?: string;
21 }
22
23 let { tabs, active, label }: Props = $props();
24</script>
25
26<nav class="flex w-full overflow-x-auto overflow-y-hidden pl-4" aria-label={label}>
27 {#each tabs as tab (tab.id)}
28 {@const isActive = active === tab.id}
29 {@const Glyph = tab.icon}
30 <a
31 href={tab.href.startsWith("/") ? resolve(tab.href as "/") : tab.href}
32 aria-current={isActive ? "page" : undefined}
33 class={`relative mr-1 flex items-center rounded-t px-4 py-1 whitespace-nowrap text-foreground-default no-underline hover:no-underline ${
34 isActive
35 ? "-mb-px bg-background-default [-webkit-text-stroke:0.3px_currentColor]"
36 : "hover:bg-background-inset"
37 }`}
38 >
39 {#if Glyph}
40 <Glyph class="mr-2 h-4 w-4" aria-hidden="true" />
41 {/if}
42 <span class="flex flex-col">
43 {tab.label}
44 <span aria-hidden="true" class="invisible h-0 overflow-hidden font-medium select-none"
45 >{tab.label}</span
46 >
47 </span>
48 {#if tab.count}
49 <span class="ml-1 rounded bg-background-inset px-1 text-sm">{tab.count}</span>
50 {/if}
51 </a>
52 {/each}
53</nav>