Files
arcadia-admin/app/components
jules 5dfceeff94 Settings/LLM: unified panel with per-row active toggle, edit, spend
Reworks the LLM settings surface based on UX feedback. Drops the
separate "Active LLM (this session)" card — its functionality is now
inline on each saved config as a star toggle (writes the same
localStorage key the Assistant reads via @crema/llm-providers-ui's
saveSettings, so the existing assistant code picks the change up
without any plumbing).

Per-row controls now include:
- Star: make this config active for the current browser
- Switch: enable/disable server-side
- Pencil: edit (modal, not inline-expand)
- Trash: delete (with confirm)
- Spend (30d): cost + request count, sourced from
  /api/v1/ai/llm/usage/by-model and matched on (provider, model)

Other improvements:
- Add wizard moved to a Dialog modal instead of pushing the list
  around. Same form handles edit.
- Empty state: "Seed from catalog" button creates a curated starter
  set (GPT-4o mini/4o, Sonnet 4.6, Haiku 4.5, DeepSeek V4 Flash, LM
  Studio) so first-time operators don't face a blank panel.
- Catalog dropdown picks now auto-fill input/output costs as you
  switch models, so the rates always reflect the chosen model unless
  manually overridden.
- The lib's full settings card (system prompt, transport, context
  budget) is still reachable for advanced cases — collapsed into a
  <details> below the panel.

Adds llm-configs.ts: getUsageByModel + findSpend helper for the
per-row spend lookup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:47:45 +10:00
..

components/

Component layers in this project.

ui/          shadcn primitives — token-driven, reskinnable per design system
forms/       composed form widgets
data/        data display (tables, filters, empty states)
layout/      app shell, page chrome, navigation wrappers
marketing/   landing and marketing blocks
[system]/    design-system-specific components (e.g. m3/, apple/)

The one rule

Custom components import from ui/, never the reverse.

ui/ is the primitive layer. It must stay reskinnable by swapping tokens in app/themes/*.css alone. If a component can't be expressed that way (M3 ripple, Apple segmented control, etc.), it belongs in a system-specific folder — not ui/ and not the shared folders above.

Tokens, not values

Every custom component should reference semantic tokens:

  • Colors: bg-primary, text-muted-foreground, border-border
  • Radius: rounded-md, rounded-lg
  • Fonts: font-sans, font-heading

Hardcoded hex, oklch, or px values are a bug — they break theming.