Redesign UI with new token system, primitives, and motion
Restraint-first design language: neutral gray surfaces + one blue accent (cyan/amber/red reserved for state), 8pt spacing, softer radii, one ambient + one raised shadow, standardized motion tokens. Alfa Slab One demoted to BrandMark only; Inter carries all page copy. New primitives (Button, Card, Badge, Stat, SectionHeader, Skeleton, EmptyState, Tabs, Breadcrumbs, StatusPip, Field, Input, Select, Textarea) plus motion utilities (tweenNumber, viewTransition) and a global toast system. All eight route surfaces rewritten on top: Fleet gains an overview hero, Server detail restructures into tabs, Deployments gets a collapsible drift summary + per-server pipeline visual, and the scripts/configs/plugins/betas flows adopt the new form primitives. Sticky translucent nav with backdrop blur, view-transition cross-fades between routes, staggered card entrance on Fleet, breathing status pip halo, tabular-numeric player counts. Gmail-style g-key nav shortcuts. Mobile stacks below 720px; prefers-reduced-motion neutralizes durations. Legacy tokens preserved as aliases so any un-migrated code still renders.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
type Variant = 'neutral' | 'online' | 'warning' | 'danger' | 'info' | 'accent';
|
||||
type Size = 'sm' | 'md';
|
||||
|
||||
interface Props {
|
||||
variant?: Variant;
|
||||
size?: Size;
|
||||
uppercase?: boolean;
|
||||
mono?: boolean;
|
||||
title?: string;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let {
|
||||
variant = 'neutral',
|
||||
size = 'sm',
|
||||
uppercase = false,
|
||||
mono = false,
|
||||
title,
|
||||
children
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<span
|
||||
class="badge v-{variant} s-{size}"
|
||||
class:uppercase
|
||||
class:mono
|
||||
{title}
|
||||
>
|
||||
{@render children?.()}
|
||||
</span>
|
||||
|
||||
<style>
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
border-radius: var(--radius-pill);
|
||||
font-family: var(--font-body);
|
||||
font-weight: var(--weight-medium);
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
font-variant-numeric: tabular-nums;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: var(--tracking-label);
|
||||
font-weight: var(--weight-semibold);
|
||||
}
|
||||
.mono {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.s-sm { padding: 3px 8px; font-size: var(--text-xs); }
|
||||
.s-md { padding: 5px 12px; font-size: var(--text-sm); }
|
||||
|
||||
.v-neutral {
|
||||
background: var(--surface-raised);
|
||||
color: var(--text-secondary);
|
||||
border-color: var(--border-subtle);
|
||||
}
|
||||
.v-online {
|
||||
background: rgba(124, 212, 255, 0.10);
|
||||
color: var(--state-online);
|
||||
border-color: rgba(124, 212, 255, 0.25);
|
||||
}
|
||||
.v-warning {
|
||||
background: rgba(255, 176, 32, 0.10);
|
||||
color: var(--state-warning);
|
||||
border-color: rgba(255, 176, 32, 0.28);
|
||||
}
|
||||
.v-danger {
|
||||
background: rgba(255, 86, 112, 0.10);
|
||||
color: var(--state-danger);
|
||||
border-color: rgba(255, 86, 112, 0.28);
|
||||
}
|
||||
.v-info {
|
||||
background: rgba(124, 192, 245, 0.10);
|
||||
color: var(--blue-300);
|
||||
border-color: rgba(124, 192, 245, 0.28);
|
||||
}
|
||||
.v-accent {
|
||||
background: var(--accent-primary);
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user