feat: redesign toward shadcn-svelte dashboard-01 (inset sidebar, gradient stat cards)
Problem: requested visual alignment with the shadcn-svelte dashboard-01
reference block (shadcn-svelte.com/blocks#dashboard-01) — the app's
sidebar/header shell and Overview stat cards looked plain by comparison.
Change: pulled the actual reference source (app-sidebar.svelte,
nav-main.svelte, site-header.svelte, section-cards.svelte from
huntabyte/shadcn-svelte) rather than approximating from screenshots.
- App.svelte: Sidebar.Root now uses variant="inset" (the floating,
rounded, shadowed content panel — already fully built into the
existing Sidebar.Inset component via peer-data selectors, just never
enabled). Brand mark is now a proper Sidebar.MenuButton matching the
reference's padding/hover treatment; "New chat" uses the reference's
primary-colored button styling. Header matches the reference exactly:
h-(--header-height) (48px, was 44px), vertical separator after the
sidebar trigger, right-aligned actions group.
- Overview.svelte: stat cards rebuilt to match section-cards.svelte —
gradient background, Card.Action badge, Card.Footer with a bold line
+ muted context line, tabular-nums, responsive @container grid
(1/2/4 columns). Deliberately did NOT copy the reference's fake
trend-percentage badges (Oikos doesn't track historical trends, and
this project's whole thrust has been eliminating dishonest UI state —
see 279549c). Badges instead reflect real current-state signals
(healthy/degraded/down, clear/needs-review) computed from the actual
dashboard summary.
- EntityDetailContent.svelte + Entities/Signals/Ops/Events/Agent/
Audit/Knowledge pages: normalized root padding to p-4 md:p-6 (was a
flat p-6) to match the reference's responsive py-4 md:py-6 convention.
Risk: reversible_low (UI-only, no data or behavior changes).
Verification: npx tsc --noEmit clean (excluding pre-existing unrelated
.svelte type-resolution warnings, same as prior commits). go build/vet
clean (backend untouched, sanity check only). Manually verified in the
browser preview at 1400px: inset sidebar's margin/rounded-corner/shadow
classes confirmed applied via computed styles; Overview cards render
with real live numbers from the now-fixed dashboard summary endpoint;
Signals/Ops pages confirmed visually consistent with the new spacing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
import * as Sheet from '$lib/components/ui/sheet'
|
||||
import { Button } from '$lib/components/ui/button'
|
||||
import { Badge } from '$lib/components/ui/badge'
|
||||
import { Separator } from '$lib/components/ui/separator'
|
||||
import { Toaster } from '$lib/components/ui/sonner'
|
||||
import PlusIcon from '@lucide/svelte/icons/plus'
|
||||
import MessageSquareIcon from '@lucide/svelte/icons/message-square'
|
||||
@@ -76,18 +77,34 @@
|
||||
|
||||
<Toaster />
|
||||
|
||||
<Sidebar.Provider>
|
||||
<Sidebar.Root collapsible="icon">
|
||||
<Sidebar.Provider style="--header-height: calc(var(--spacing) * 12);">
|
||||
<Sidebar.Root collapsible="icon" variant="inset">
|
||||
<Sidebar.Header>
|
||||
<div class="flex items-center px-1">
|
||||
<svg viewBox="0 0 91 100" class="size-5 shrink-0 fill-white" aria-hidden="true" role="img">
|
||||
<title>Oikos</title>
|
||||
<path d="m45.601 1q20.993 0 33.71 15.946 10.799 13.625 10.799 31.287 0 12.414-5.9548 25.131-5.9548 12.717-16.451 19.176-10.395 6.4592-23.213 6.4592-20.892 0-33.205-16.653-10.395-14.029-10.395-31.489 0-12.717 6.2577-25.232 6.3584-12.616 16.653-18.57 10.295-6.0556 21.801-6.0556zm-3.128 6.5605q-5.3492 0-10.799 3.2296-5.3492 3.1287-8.68 11.102-3.3305 7.9735-3.3305 20.488 0 20.185 7.973 34.82 8.0743 14.634 21.195 14.634 9.7896 0 16.149-8.0743 6.3584-8.0743 6.3584-27.755 0-24.627-10.597-38.756-7.1657-9.6888-18.268-9.6888z" />
|
||||
</svg>
|
||||
</div>
|
||||
<Sidebar.Menu>
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton onclick={() => { newChat(); navigate('chat') }} tooltipContent="New chat">
|
||||
<Sidebar.MenuButton
|
||||
class="data-[slot=sidebar-menu-button]:!p-1.5"
|
||||
onclick={() => navigate('overview')}
|
||||
tooltipContent="Oikos"
|
||||
>
|
||||
{#snippet child({ props })}
|
||||
<button {...props}>
|
||||
<svg viewBox="0 0 91 100" class="!size-5 shrink-0 fill-white" aria-hidden="true" role="img">
|
||||
<title>Oikos</title>
|
||||
<path d="m45.601 1q20.993 0 33.71 15.946 10.799 13.625 10.799 31.287 0 12.414-5.9548 25.131-5.9548 12.717-16.451 19.176-10.395 6.4592-23.213 6.4592-20.892 0-33.205-16.653-10.395-14.029-10.395-31.489 0-12.717 6.2577-25.232 6.3584-12.616 16.653-18.57 10.295-6.0556 21.801-6.0556zm-3.128 6.5605q-5.3492 0-10.799 3.2296-5.3492 3.1287-8.68 11.102-3.3305 7.9735-3.3305 20.488 0 20.185 7.973 34.82 8.0743 14.634 21.195 14.634 9.7896 0 16.149-8.0743 6.3584-8.0743 6.3584-27.755 0-24.627-10.597-38.756-7.1657-9.6888-18.268-9.6888z" />
|
||||
</svg>
|
||||
</button>
|
||||
{/snippet}
|
||||
</Sidebar.MenuButton>
|
||||
</Sidebar.MenuItem>
|
||||
</Sidebar.Menu>
|
||||
<Sidebar.Menu>
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton
|
||||
class="bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground min-w-8 duration-200 ease-linear"
|
||||
onclick={() => { newChat(); navigate('chat') }}
|
||||
tooltipContent="New chat"
|
||||
>
|
||||
{#snippet child({ props })}
|
||||
<button {...props}>
|
||||
<PlusIcon />
|
||||
@@ -144,10 +161,11 @@
|
||||
</Sidebar.Root>
|
||||
|
||||
<Sidebar.Inset class="h-svh min-h-0">
|
||||
<header class="flex h-11 shrink-0 items-center gap-3 border-b px-3">
|
||||
<Sidebar.Trigger />
|
||||
<span class="text-sm font-medium capitalize">{page === 'entity' ? routeParam : page}</span>
|
||||
<div class="flex-1"></div>
|
||||
<header class="flex h-(--header-height) shrink-0 items-center gap-1 border-b px-4 lg:gap-2 lg:px-6">
|
||||
<Sidebar.Trigger class="-ms-1" />
|
||||
<Separator orientation="vertical" class="mx-2 data-[orientation=vertical]:h-4" />
|
||||
<span class="text-base font-medium capitalize">{page === 'entity' ? routeParam : page}</span>
|
||||
<div class="ms-auto flex items-center gap-2.5">
|
||||
{#if $summary}
|
||||
<div class="hidden items-center gap-2.5 text-xs text-muted-foreground sm:flex">
|
||||
<span class="flex items-center gap-1" title="healthy"><span class="size-2 rounded-full bg-success"></span>{$summary.health.healthy}</span>
|
||||
@@ -169,6 +187,7 @@
|
||||
class="size-2 rounded-full {$connectionState === 'open' ? 'bg-success' : $connectionState === 'connecting' ? 'animate-pulse bg-warning' : 'bg-destructive'}"
|
||||
title="event stream: {$connectionState}"
|
||||
></span>
|
||||
</div>
|
||||
</header>
|
||||
<main class="min-h-0 flex-1 overflow-hidden">
|
||||
{#if page === 'overview'}
|
||||
|
||||
Reference in New Issue
Block a user