R0: design foundations — reference tokens, motion set, lucide primitives

- globals.css @theme merged with the measured reference system
  (docs/tokens.css): hover/divider/subtle-fg colors, cream + bubble
  tokens, squircle/toggle radii, spec-verbatim shadow set (bubble, card,
  dialog, dock-tile, CTA glow, launcher glow, screen-card ambient, dock
  capsule), marketing light palette, default 0.25s ease-app transition
  tokens. Legacy aliases (--color-accent, --spacing-rail/panel-*)
  retained so existing classes keep working
- motion.css: full app-shell choreography (zoom-in/out from tile origin
  w/ --app-origin-scale, push/pop slides, cross-fade) + messageSlideIn,
  create-claw step/swatch, device-* set — keyframes verbatim from
  docs/motion.md
- lucide-react installed (ISC). New tested primitives: Button (cream/
  coral/ghost/icon/launcher variants per measured states), GradientGlyph
  (per-instance coral linearGradient stroke, the reference glyph
  technique), SegmentedTabs, Card + SectionLabel + GroupedRows,
  SearchPill; Avatar extended (squircle r17, rail/chat/welcome sizes,
  online-dot overlay)

82 unit tests; functional e2e suite green (visual baselines regenerate
in R7).

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-10 18:07:35 -05:00
co-authored by Claude Fable 5
parent 447f7039d8
commit 3ec1d3b829
14 changed files with 566 additions and 29 deletions
+37 -9
View File
@@ -2,26 +2,54 @@ interface AvatarProps {
name: string;
/** Per-agent accent hex; defaults to the brand coral. */
accent?: string;
size?: "sm" | "md" | "lg";
size?: "sm" | "md" | "lg" | "rail" | "chat" | "welcome";
/** Circle (people) or 17px-radius squircle (claws, measured). */
shape?: "circle" | "squircle";
/** Green presence dot overlay (rail + chat headers). */
online?: boolean;
}
const SIZES = { sm: "size-6 text-xxs", md: "size-8 text-xs", lg: "size-16 text-xl" };
const SIZES = {
sm: "size-6 text-xxs",
md: "size-8 text-xs",
lg: "size-16 text-xl",
rail: "size-12 text-base" /* 48px claw rail tile */,
chat: "size-[50px] text-base" /* assistant message avatar */,
welcome: "size-[126px] text-4xl" /* empty-state hero */,
};
/** Initials avatar used until generated art assets land (excluded by spec). */
export function Avatar({ name, accent, size = "md" }: AvatarProps) {
export function Avatar({
name,
accent,
size = "md",
shape = "circle",
online = false,
}: AvatarProps) {
const initials = name
.split(/\s+/)
.filter(Boolean)
.slice(0, 2)
.map((part) => part[0]!.toUpperCase())
.join("");
const radius =
shape === "squircle" ? "rounded-radius-squircle" : "rounded-full";
return (
<span
aria-hidden
className={`inline-flex items-center justify-center rounded-full font-medium text-background ${SIZES[size]}`}
style={{ backgroundColor: accent || "var(--color-accent)" }}
>
{initials}
<span className="relative inline-flex">
<span
aria-hidden
className={`inline-flex items-center justify-center font-medium text-background ${radius} ${SIZES[size]}`}
style={{ backgroundColor: accent || "var(--color-accent)" }}
>
{initials}
</span>
{online && (
<span
data-online-dot
aria-hidden
className="absolute -right-0.5 -bottom-0.5 size-2.5 rounded-full border-2 border-background bg-green-500"
/>
)}
</span>
);
}