From 527c2f677e4c1e136e6429695cf72ee101016330 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 21 Jun 2026 12:19:51 +0000 Subject: [PATCH] feat(web): drop material gloss, full punktfunk theme for Scalar, center mobile tabs - console: remove @unom/ui's specular "material" gloss (drop UnomProviders + the material.css import) so components render flat like the marketing site; the violet brand + Geist stay. - mobile bottom tab bar: center the labels (w-full text-center, leading-tight) and even out the per-tab layout. - docs /api: roll the punktfunk dark-violet palette across the whole Scalar reference (surfaces/text/sidebar/links/buttons/method colours via the full --scalar-* token set), locked to dark (hideDarkModeToggle). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs-site/src/routes/api/index.tsx | 68 +++++++++++++++++++++++++-- web/README.md | 3 +- web/src/components/app-shell.tsx | 6 +-- web/src/components/unom-providers.tsx | 21 --------- web/src/routes/__root.tsx | 15 +++--- web/src/styles.css | 3 -- 6 files changed, 73 insertions(+), 43 deletions(-) delete mode 100644 web/src/components/unom-providers.tsx diff --git a/docs-site/src/routes/api/index.tsx b/docs-site/src/routes/api/index.tsx index cf17c54..9492d46 100644 --- a/docs-site/src/routes/api/index.tsx +++ b/docs-site/src/routes/api/index.tsx @@ -17,19 +17,75 @@ export const Route = createFileRoute('/api/')({ }), }) -// Brand the Scalar reference to the punktfunk violet + Geist, in both light and -// dark. Scalar ignores unknown custom-property names, so this is forward-safe. +// The full punktfunk theme rolled out onto Scalar — the same dark-violet +// product chrome as the management console (bg #141019 / cards #1c1530, the +// violet lens brand, Geist). Scalar is locked to dark mode below; the palette +// maps every Scalar token (surfaces, text, sidebar, links, buttons, method +// colours). Scalar ignores unknown custom-property names, so this is forward-safe. const SCALAR_CSS = ` -:root { - --scalar-color-accent: #6c5bf3; +.light-mode, +.dark-mode { --scalar-font: 'Geist Variable', ui-sans-serif, system-ui, sans-serif; + --scalar-font-code: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace; + --scalar-radius: 0.5rem; + --scalar-radius-lg: 0.75rem; + --scalar-radius-xl: 0.875rem; } .dark-mode { - --scalar-color-accent: #a79ff8; + /* Surfaces — the violet-tinted app-icon chrome. */ --scalar-background-1: #141019; --scalar-background-2: #1c1530; --scalar-background-3: #221a36; + --scalar-background-accent: #6c5bf32e; --scalar-border-color: #2a2148; + + /* Text. */ + --scalar-color-1: #f4f2fb; + --scalar-color-2: #b7b1c9; + --scalar-color-3: #8a85a0; + --scalar-color-accent: #a79ff8; + + /* Links. */ + --scalar-link-color: #a79ff8; + --scalar-link-color-hover: #c8c0fb; + + /* Primary action button (brand violet). */ + --scalar-button-1: #6c5bf3; + --scalar-button-1-color: #ffffff; + --scalar-button-1-hover: #5d4ee0; + + /* Sidebar. */ + --scalar-sidebar-background-1: #17121f; + --scalar-sidebar-color-1: #e9e6f4; + --scalar-sidebar-color-2: #9a94ad; + --scalar-sidebar-color-active: #c8c0fb; + --scalar-sidebar-item-hover-background: #6c5bf31f; + --scalar-sidebar-item-hover-color: #f4f2fb; + --scalar-sidebar-item-active-background: #6c5bf333; + --scalar-sidebar-border-color: #241c3d; + --scalar-sidebar-search-background: #1c1530; + --scalar-sidebar-search-border-color: #2a2148; + --scalar-sidebar-search-color: #9a94ad; + --scalar-sidebar-indent-border: #2a2148; + --scalar-sidebar-indent-border-active: #6c5bf3; + --scalar-sidebar-indent-border-hover: #463a78; + + /* Header (if shown). */ + --scalar-header-background-1: #141019; + --scalar-header-color-1: #f4f2fb; + --scalar-header-border-color: #2a2148; + + /* Scrollbar. */ + --scalar-scrollbar-color: #2a2148; + --scalar-scrollbar-color-active: #463a78; + + /* HTTP method / status colours — kept distinct, tuned to read on dark. */ + --scalar-color-green: #4ade80; + --scalar-color-red: #f87171; + --scalar-color-yellow: #fbbf24; + --scalar-color-blue: #60a5fa; + --scalar-color-orange: #fb923c; + --scalar-color-purple: #a79ff8; } ` @@ -75,6 +131,8 @@ function ApiReference() { configuration={{ url: '/openapi.json', darkMode: true, + // Lock to the punktfunk dark-violet theme — no light-mode escape hatch. + hideDarkModeToggle: true, metaData: { title: 'punktfunk Management API' }, hideDownloadButton: false, customCss: SCALAR_CSS, diff --git a/web/README.md b/web/README.md index 95c7428..7d3234c 100644 --- a/web/README.md +++ b/web/README.md @@ -7,7 +7,7 @@ clients, the pairing-PIN flow, and session controls. Stack: **TanStack Start** (full SSR) on **Bun** via **Nitro v2** (`bun` preset) · **React Query** through **orval** codegen from the OpenAPI spec · **[`@unom/ui`](https://git.unom.io/unom/ui)** — the shared punktfunk/unom design system the marketing site + docs are built on (Tailwind v4, -animated components + specular "material" gloss, the violet brand on dark chrome) · +animated components on the violet brand over dark chrome) · **Paraglide** i18n (en/de). Package manager + runtime: **Bun**. The `@unom` registry mapping lives in [`.npmrc`](.npmrc); the auth token comes from @@ -98,7 +98,6 @@ src/ components/ app-shell.tsx sidebar nav (brand lens + wordmark) + language switcher brand-mark/wordmark/logo.tsx punktfunk lens mark + wordmark (shared with the site/docs) - unom-providers.tsx @unom/ui Material provider (specular gloss; no sounds, like the site) ui/ @unom/ui-backed primitives (button, input, label, card; badge/table/skeleton) query-state.tsx loading/error wrapper (incl. 401 → "set a token") api/ diff --git a/web/src/components/app-shell.tsx b/web/src/components/app-shell.tsx index 3dae45a..b866a24 100644 --- a/web/src/components/app-shell.tsx +++ b/web/src/components/app-shell.tsx @@ -76,11 +76,11 @@ export function AppShell({ children }: { children: ReactNode }) { key={to} to={to} activeOptions={{ exact: to === '/' }} - className="flex flex-1 flex-col items-center gap-1 py-2 text-[10px] text-muted-foreground transition-colors" + className="flex flex-1 flex-col items-center justify-center gap-1 px-0.5 py-2 text-muted-foreground transition-colors" activeProps={{ className: 'text-[var(--brand-light)]' }} > - - {label()} + + {label()} ))} diff --git a/web/src/components/unom-providers.tsx b/web/src/components/unom-providers.tsx deleted file mode 100644 index 0c53a1d..0000000 --- a/web/src/components/unom-providers.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import type { ReactNode } from 'react' -import { MaterialProvider } from '@unom/ui/material' - -// Turn on @unom/ui's specular "material" gloss for the whole console — the same -// design system the punktfunk marketing site is built on. SSR-safe (material -// gates its effects on a mounted flag). No SoundProvider: like the marketing -// site, the console stays silent (@unom/ui's useSound no-ops without a provider). -const MATERIAL = { - button: { enabled: true }, - card: { enabled: true }, - dialog: { enabled: true }, - tabs: { enabled: true }, - select: { enabled: true }, - input: { enabled: true }, - checkbox: { enabled: true }, - toast: { enabled: true }, -} as const - -export function UnomProviders({ children }: { children: ReactNode }) { - return {children} -} diff --git a/web/src/routes/__root.tsx b/web/src/routes/__root.tsx index 17ee3d4..501cd51 100644 --- a/web/src/routes/__root.tsx +++ b/web/src/routes/__root.tsx @@ -9,7 +9,6 @@ import { import type { QueryClient } from '@tanstack/react-query' import '@fontsource-variable/geist' import { AppShell } from '@/components/app-shell' -import { UnomProviders } from '@/components/unom-providers' import appCss from '@/styles.css?url' export interface RouterContext { @@ -38,15 +37,13 @@ function RootComponent() { - - {isLogin ? ( + {isLogin ? ( + + ) : ( + - ) : ( - - - - )} - + + )} diff --git a/web/src/styles.css b/web/src/styles.css index d1d0c99..8104d04 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -1,9 +1,6 @@ @import 'tailwindcss'; @import 'tw-animate-css'; @import './timing-functions.css'; -/* @unom/ui's specular "material" gloss layer (.material / .material-fx). Colours - derive from --neutral / --neutral-accent via the --mat-* knobs it ships. */ -@import '@unom/ui/styles/material.css'; @custom-variant dark (&:is(.dark *));