e0b166ad60
ci / rust (push) Has been cancelled
Browser UI for the host's management REST API (mgmt.rs / docs/api/openapi.json). Stack, exactly as specified: - TanStack Start (Vite, SPA mode) — file-based routes, SSR shell + client hydration. - React Query via orval codegen from the checked-in OpenAPI spec: a custom fetch mutator (src/api/fetcher.ts) centralizes the base URL, the bearer token (Settings → localStorage), JSON, and a throwing ApiError; the query client skips retries on 4xx. orval returns the response body directly (includeHttpResponseReturnType:false) so a query's `.data` is the typed payload; GET→useQuery, POST/DELETE→useMutation by method. - shadcn/ui on Tailwind v4 (CSS-first tokens, dark-first) — button/card/badge/input/label/ table/skeleton primitives hand-authored from the canonical source. - Paraglide i18n (en + de) with a reactive useLocale() hook and a language switcher. Pages: dashboard (live status — video/audio/session/stream, stop-session + request-IDR, 2s polling), host (identity/codecs/ports), clients (paired list + unpair), pairing (PIN submit, polls pin_pending), settings (API token + language). Dev server proxies /api → 127.0.0.1:47990 (same-origin, no CORS; PUNKTFUNK_MGMT_URL to override). Generated code (orval client, paraglide runtime, routeTree) is gitignored and reproduced by `pnpm codegen` (prepare/pre* scripts). Validated live against `serve`: API shapes match, dev proxy works, SSR shell renders the localized nav, build + tsc green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
91 lines
2.8 KiB
CSS
91 lines
2.8 KiB
CSS
@import 'tailwindcss';
|
|
@import 'tw-animate-css';
|
|
|
|
@custom-variant dark (&:is(.dark *));
|
|
|
|
/* shadcn/ui design tokens (neutral base, dark-first to match a streaming console). */
|
|
:root {
|
|
--radius: 0.625rem;
|
|
--background: oklch(1 0 0);
|
|
--foreground: oklch(0.145 0 0);
|
|
--card: oklch(1 0 0);
|
|
--card-foreground: oklch(0.145 0 0);
|
|
--popover: oklch(1 0 0);
|
|
--popover-foreground: oklch(0.145 0 0);
|
|
--primary: oklch(0.205 0 0);
|
|
--primary-foreground: oklch(0.985 0 0);
|
|
--secondary: oklch(0.97 0 0);
|
|
--secondary-foreground: oklch(0.205 0 0);
|
|
--muted: oklch(0.97 0 0);
|
|
--muted-foreground: oklch(0.556 0 0);
|
|
--accent: oklch(0.97 0 0);
|
|
--accent-foreground: oklch(0.205 0 0);
|
|
--destructive: oklch(0.577 0.245 27.325);
|
|
--destructive-foreground: oklch(0.985 0 0);
|
|
--border: oklch(0.922 0 0);
|
|
--input: oklch(0.922 0 0);
|
|
--ring: oklch(0.708 0 0);
|
|
--success: oklch(0.6 0.13 160);
|
|
}
|
|
|
|
.dark {
|
|
--background: oklch(0.145 0 0);
|
|
--foreground: oklch(0.985 0 0);
|
|
--card: oklch(0.205 0 0);
|
|
--card-foreground: oklch(0.985 0 0);
|
|
--popover: oklch(0.205 0 0);
|
|
--popover-foreground: oklch(0.985 0 0);
|
|
--primary: oklch(0.922 0 0);
|
|
--primary-foreground: oklch(0.205 0 0);
|
|
--secondary: oklch(0.269 0 0);
|
|
--secondary-foreground: oklch(0.985 0 0);
|
|
--muted: oklch(0.269 0 0);
|
|
--muted-foreground: oklch(0.708 0 0);
|
|
--accent: oklch(0.269 0 0);
|
|
--accent-foreground: oklch(0.985 0 0);
|
|
--destructive: oklch(0.704 0.191 22.216);
|
|
--destructive-foreground: oklch(0.985 0 0);
|
|
--border: oklch(1 0 0 / 10%);
|
|
--input: oklch(1 0 0 / 15%);
|
|
--ring: oklch(0.556 0 0);
|
|
--success: oklch(0.7 0.15 160);
|
|
}
|
|
|
|
@theme inline {
|
|
--radius-sm: calc(var(--radius) - 4px);
|
|
--radius-md: calc(var(--radius) - 2px);
|
|
--radius-lg: var(--radius);
|
|
--radius-xl: calc(var(--radius) + 4px);
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
--color-card: var(--card);
|
|
--color-card-foreground: var(--card-foreground);
|
|
--color-popover: var(--popover);
|
|
--color-popover-foreground: var(--popover-foreground);
|
|
--color-primary: var(--primary);
|
|
--color-primary-foreground: var(--primary-foreground);
|
|
--color-secondary: var(--secondary);
|
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
--color-muted: var(--muted);
|
|
--color-muted-foreground: var(--muted-foreground);
|
|
--color-accent: var(--accent);
|
|
--color-accent-foreground: var(--accent-foreground);
|
|
--color-destructive: var(--destructive);
|
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
--color-success: var(--success);
|
|
--color-border: var(--border);
|
|
--color-input: var(--input);
|
|
--color-ring: var(--ring);
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
border-color: var(--border);
|
|
}
|
|
body {
|
|
background-color: var(--background);
|
|
color: var(--foreground);
|
|
font-feature-settings: 'rlig' 1, 'calt' 1;
|
|
}
|
|
}
|