CI / changes (push) Successful in 7s
CI / openapi (push) Has been skipped
CI / web (push) Successful in 29s
CI / go (push) Has been skipped
CI / docker-web (push) Successful in 1m22s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-go (push) Has been skipped
- Standardized formatting in various Svelte components for better readability. - Updated README.md and .prettierrc for consistent styling and improved documentation. - Refactored class attributes in UI components to enhance clarity and maintainability. - Adjusted layout files to ensure proper alignment and spacing in the application interface.
97 lines
2.7 KiB
Svelte
97 lines
2.7 KiB
Svelte
<script lang="ts">
|
|
import { resolve } from '$app/paths';
|
|
import { page } from '$app/state';
|
|
import { cn } from '$lib/utils.js';
|
|
import { buttonVariants } from '$lib/ui/core/button/index.js';
|
|
import { Separator } from '$lib/ui/core/separator/index.js';
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from '$lib/ui/core/tooltip/index.js';
|
|
import { bottomNav, mainNav } from './nav.js';
|
|
|
|
type Props = {
|
|
collapsed?: boolean;
|
|
onNavigate?: () => void;
|
|
};
|
|
|
|
let { collapsed = false, onNavigate }: Props = $props();
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const navHref = (href: string) => resolve(href as any);
|
|
|
|
function isActive(href: string) {
|
|
const pathname = page.url.pathname;
|
|
if (href === '/') return pathname === '/';
|
|
return pathname === href || pathname.startsWith(href + '/');
|
|
}
|
|
|
|
function linkClass(active: boolean, iconOnly: boolean) {
|
|
return cn(
|
|
buttonVariants({
|
|
variant: active ? 'secondary' : 'ghost',
|
|
size: iconOnly ? 'icon-sm' : 'sm'
|
|
}),
|
|
iconOnly
|
|
? 'flex w-full items-center justify-center no-underline'
|
|
: 'flex w-full items-center justify-start gap-2 no-underline',
|
|
active &&
|
|
(iconOnly
|
|
? 'ring-sidebar-primary/50 bg-sidebar-accent/90 text-sidebar-accent-foreground ring-1'
|
|
: 'border-l-sidebar-primary bg-sidebar-accent/80 text-sidebar-accent-foreground border-l-2 shadow-sm')
|
|
);
|
|
}
|
|
</script>
|
|
|
|
<nav class="flex flex-1 flex-col gap-0.5 overflow-y-auto p-2">
|
|
{#each mainNav as item (item.href)}
|
|
{@const Icon = item.icon}
|
|
{@const active = isActive(item.href)}
|
|
{#if collapsed}
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<a
|
|
href={navHref(item.href)}
|
|
class={linkClass(active, true)}
|
|
aria-current={active ? 'page' : undefined}
|
|
onclick={onNavigate}
|
|
>
|
|
<Icon class="size-4" />
|
|
</a>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="right">{item.label}</TooltipContent>
|
|
</Tooltip>
|
|
{:else}
|
|
<a
|
|
href={navHref(item.href)}
|
|
class={linkClass(active, false)}
|
|
aria-current={active ? 'page' : undefined}
|
|
onclick={onNavigate}
|
|
>
|
|
<Icon class="size-4" />
|
|
{item.label}
|
|
</a>
|
|
{/if}
|
|
{/each}
|
|
</nav>
|
|
|
|
<div class="flex flex-col gap-0.5 p-2">
|
|
<Separator class="mb-2" />
|
|
{#each bottomNav as item (item.href)}
|
|
{@const Icon = item.icon}
|
|
{@const active = isActive(item.href)}
|
|
{#if collapsed}
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<a href={navHref(item.href)} class={linkClass(active, true)} onclick={onNavigate}>
|
|
<Icon class="size-4" />
|
|
</a>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="right">{item.label}</TooltipContent>
|
|
</Tooltip>
|
|
{:else}
|
|
<a href={navHref(item.href)} class={linkClass(active, false)} onclick={onNavigate}>
|
|
<Icon class="size-4" />
|
|
{item.label}
|
|
</a>
|
|
{/if}
|
|
{/each}
|
|
</div>
|