Fix interface fidelity: invalid Tailwind classes + restore lost HomeScreen

Side-by-side comparison surfaced that several restyle classes silently
generated NO CSS (confirmed against the compiled .next CSS) — invisible
to tests because unit tests assert class strings, not computed styles,
and visual baselines were captured from the broken build.

Root causes fixed:
- rounded-radius-button (51) / rounded-radius-squircle (3) generated
  nothing → every pill/button/chip was border-radius:0. Tailwind v4 maps
  --radius-button to 'rounded-button', not 'rounded-radius-button'.
  Replaced with rounded-full / rounded-[17px].
- duration-normal/fast/slow (58) generated nothing → transitions had
  easing but 0 duration (snapped). Replaced with the token-arbitrary
  form duration-(--duration-normal). (Also fixed an over-replace that
  double-wrapped var(--duration-normal) inside animate-[…] values.)
- HomeScreen.tsx was the OLD emoji version — the R3 rewrite was never
  committed. Restored: brand Chrome/Slack squircle tiles, coral
  GradientGlyph icons, 56px tiles with press-scale, and the frosted
  glass dock (bg-white/[0.07] backdrop-blur-[40px] saturate-150).

Targeted gaps from the feedback:
- raised surface --color-surface-warm-muted #1f1f1f → #1a1a1a (composer,
  chips, tabs)
- welcome chips: max-w-[422px] gap-3 → centered 2×2 grid
- composer input + rail nav labels → 14px
- DeviceSizeToggle: Full/Tablet/Phone text → lucide monitor/tablet/
  smartphone icons (aria-label keeps the radio names)
- SW cache bumped v1→v2 so redeployed clients purge the stale bundle
- LeftRail drawer: ref-during-render → prev-state pattern (lint)

Compiled CSS now emits .rounded-full, transition-duration:var(--duration-
normal), border-radius:17px, and shadow-dock-capsule. Button/Avatar unit
tests updated to the real class names. 83 unit tests green.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-10 21:21:20 -05:00
co-authored by Claude Fable 5
parent 889c65685e
commit 0383d8fd77
33 changed files with 155 additions and 119 deletions
+2 -2
View File
@@ -3,8 +3,8 @@
// /api/** -> NEVER touched (approvals + SSE must be live) // /api/** -> NEVER touched (approvals + SSE must be live)
// /_next/static/** -> cache-first (content-hashed, immutable) // /_next/static/** -> cache-first (content-hashed, immutable)
// navigations -> network-first, cache fallback for offline shell // navigations -> network-first, cache fallback for offline shell
const STATIC_CACHE = "tc-static-v1"; const STATIC_CACHE = "tc-static-v2";
const PAGE_CACHE = "tc-pages-v1"; const PAGE_CACHE = "tc-pages-v2";
self.addEventListener("install", () => { self.addEventListener("install", () => {
self.skipWaiting(); self.skipWaiting();
@@ -82,7 +82,7 @@ export default async function CreditsPage() {
</div> </div>
<a <a
href="mailto:[email protected]" href="mailto:[email protected]"
className="rounded-radius-button border border-border px-4 py-2 text-sm text-foreground transition-colors duration-normal ease-app hover:bg-hover-bg" className="rounded-full border border-border px-4 py-2 text-sm text-foreground transition-colors duration-(--duration-normal) ease-app hover:bg-hover-bg"
> >
Talk to sales Talk to sales
</a> </a>
+1 -1
View File
@@ -12,7 +12,7 @@
--color-card: #0a0a0a; --color-card: #0a0a0a;
--color-popover: #0a0a0a; --color-popover: #0a0a0a;
--color-surface-warm: #141414; /* raised tier 1 */ --color-surface-warm: #141414; /* raised tier 1 */
--color-surface-warm-muted: #1f1f1f; /* raised tier 2 */ --color-surface-warm-muted: #1a1a1a; /* raised tier 2 */
--color-subtle: #141414; --color-subtle: #141414;
--color-hover-bg: #171717; /* generic hover fill */ --color-hover-bg: #171717; /* generic hover fill */
--color-divider-subtle: #1a1a1a; --color-divider-subtle: #1a1a1a;
+3 -3
View File
@@ -40,7 +40,7 @@ export function ChatHeader({
aria-label="Sessions" aria-label="Sessions"
aria-pressed={sessions} aria-pressed={sessions}
onClick={() => setParams({ sessions: !sessions })} onClick={() => setParams({ sessions: !sessions })}
className={`inline-flex size-9 items-center justify-center rounded-radius-button transition-colors duration-normal ease-app ${ className={`inline-flex size-9 items-center justify-center rounded-full transition-colors duration-(--duration-normal) ease-app ${
sessions sessions
? "bg-surface-warm-muted text-foreground" ? "bg-surface-warm-muted text-foreground"
: "text-muted-foreground hover:bg-hover-bg hover:text-foreground" : "text-muted-foreground hover:bg-hover-bg hover:text-foreground"
@@ -52,7 +52,7 @@ export function ChatHeader({
type="button" type="button"
aria-label="New" aria-label="New"
onClick={onNewSession} onClick={onNewSession}
className="inline-flex size-9 items-center justify-center rounded-radius-button text-muted-foreground transition-colors duration-normal ease-app hover:bg-hover-bg hover:text-foreground" className="inline-flex size-9 items-center justify-center rounded-full text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:bg-hover-bg hover:text-foreground"
> >
<SquarePen aria-hidden size={18} /> <SquarePen aria-hidden size={18} />
</button> </button>
@@ -60,7 +60,7 @@ export function ChatHeader({
type="button" type="button"
aria-label="Computer" aria-label="Computer"
onClick={() => setParams({ app: "home" })} onClick={() => setParams({ app: "home" })}
className="inline-flex size-[42px] items-center justify-center rounded-radius-button text-coral shadow-launcher transition-all duration-normal ease-app hover:bg-coral/10 active:scale-95" className="inline-flex size-[42px] items-center justify-center rounded-full text-coral shadow-launcher transition-all duration-(--duration-normal) ease-app hover:bg-coral/10 active:scale-95"
> >
<Monitor aria-hidden size={20} /> <Monitor aria-hidden size={20} />
</button> </button>
+2 -2
View File
@@ -52,12 +52,12 @@ export function Composer({
rows={1} rows={1}
onChange={(e) => setValue(e.target.value)} onChange={(e) => setValue(e.target.value)}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
className="max-h-40 min-h-8 flex-1 resize-none bg-transparent py-1 text-base text-foreground outline-none placeholder:text-subtle-foreground" className="max-h-40 min-h-8 flex-1 resize-none bg-transparent py-1 text-sm text-foreground outline-none placeholder:text-subtle-foreground"
/> />
<button <button
type="submit" type="submit"
disabled={disabled || value.trim() === ""} disabled={disabled || value.trim() === ""}
className="rounded-radius-button bg-cream px-4 py-2 text-sm font-medium text-primary-foreground shadow-cta transition-colors duration-normal ease-app hover:bg-white disabled:opacity-40 disabled:shadow-none" className="rounded-full bg-cream px-4 py-2 text-sm font-medium text-primary-foreground shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-white disabled:opacity-40 disabled:shadow-none"
> >
Send Send
</button> </button>
@@ -35,13 +35,13 @@ export function WelcomeState({
<p className="text-base text-muted-foreground"> <p className="text-base text-muted-foreground">
{agent.job_title} · Shared with your team {agent.job_title} · Shared with your team
</p> </p>
<div className="flex max-w-xl flex-wrap justify-center gap-2 pt-2"> <div className="flex max-w-[422px] flex-wrap justify-center gap-3 pt-2">
{SUGGESTED_PROMPTS.map(({ label, icon: Icon }) => ( {SUGGESTED_PROMPTS.map(({ label, icon: Icon }) => (
<button <button
key={label} key={label}
type="button" type="button"
onClick={() => onPick(label)} onClick={() => onPick(label)}
className="inline-flex h-9 items-center gap-2 rounded-radius-button bg-surface-warm-muted px-3.5 text-xs font-medium text-neutral-200 shadow-bubble ring-1 ring-neutral-700/70 transition-colors duration-normal ease-app ring-inset hover:bg-neutral-700/60 hover:ring-neutral-600" className="inline-flex h-9 items-center gap-2 rounded-full bg-surface-warm-muted px-3.5 text-xs font-medium text-neutral-200 shadow-bubble ring-1 ring-neutral-700/70 transition-colors duration-(--duration-normal) ease-app ring-inset hover:bg-neutral-700/60 hover:ring-neutral-600"
> >
<Icon aria-hidden size={14} className="shrink-0 text-coral" /> <Icon aria-hidden size={14} className="shrink-0 text-coral" />
{label} {label}
@@ -18,7 +18,7 @@ export function StepTrace({ steps }: { steps: UiStep[] }) {
aria-expanded={expanded} aria-expanded={expanded}
aria-controls={regionId} aria-controls={regionId}
onClick={() => setExpanded((v) => !v)} onClick={() => setExpanded((v) => !v)}
className="rounded-radius-button px-2 py-0.5 text-xs text-muted-foreground transition-colors duration-normal ease-app hover:bg-hover-bg hover:text-foreground" className="rounded-full px-2 py-0.5 text-xs text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:bg-hover-bg hover:text-foreground"
> >
{expanded ? "▾" : "▸"} {steps.length}{" "} {expanded ? "▾" : "▸"} {steps.length}{" "}
{steps.length === 1 ? "step" : "steps"} {steps.length === 1 ? "step" : "steps"}
@@ -1,14 +1,18 @@
"use client"; "use client";
import { Monitor, Smartphone, Tablet } from "lucide-react";
import type { LucideIcon } from "lucide-react";
import type { DeviceSize } from "@/lib/url/panel-params"; import type { DeviceSize } from "@/lib/url/panel-params";
const SIZES: { id: DeviceSize; label: string }[] = [ const SIZES: { id: DeviceSize; label: string; icon: LucideIcon }[] = [
{ id: "full", label: "Full" }, { id: "full", label: "Full", icon: Monitor },
{ id: "tablet", label: "Tablet" }, { id: "tablet", label: "Tablet", icon: Tablet },
{ id: "phone", label: "Phone" }, { id: "phone", label: "Phone", icon: Smartphone },
]; ];
/** The §7 size toggle: Full / Tablet / Phone. */ /** The §7 size toggle (measured): three icon buttons (monitor/tablet/
* smartphone); the accessible name stays the size label. */
export function DeviceSizeToggle({ export function DeviceSizeToggle({
value, value,
onChange, onChange,
@@ -23,15 +27,16 @@ export function DeviceSizeToggle({
key={size.id} key={size.id}
type="button" type="button"
role="radio" role="radio"
aria-label={size.label}
aria-checked={value === size.id} aria-checked={value === size.id}
onClick={() => onChange(size.id)} onClick={() => onChange(size.id)}
className={`rounded-(--radius) px-2 py-0.5 text-xxs ${ className={`inline-flex size-6 items-center justify-center rounded-full transition-colors duration-(--duration-normal) ease-app ${
value === size.id value === size.id
? "bg-surface-warm-muted text-foreground" ? "bg-white/15 text-white"
: "text-muted-foreground hover:text-foreground" : "text-white/60 hover:text-white"
}`} }`}
> >
{size.label} <size.icon aria-hidden size={13} />
</button> </button>
))} ))}
</div> </div>
+67 -37
View File
@@ -1,74 +1,104 @@
"use client"; "use client";
import Image from "next/image";
import type { MouseEvent } from "react";
import type { AppId } from "@/lib/url/panel-params"; import type { AppId } from "@/lib/url/panel-params";
import { GradientGlyph } from "@/components/ui/GradientGlyph";
import { APP_ICON, HOME_DOCK, HOME_GRID } from "./appCatalog";
interface HomeScreenProps { interface HomeScreenProps {
agentName: string; agentName: string;
onOpen: (app: AppId) => void; /** Receives the tapped tile's rect so the app window can zoom from it. */
onOpen: (app: AppId, origin: DOMRect) => void;
} }
const GRID: { app: AppId; label: string; glyph: string }[] = [ /* Brand tiles use the official service marks on a white squircle; the
{ app: "browser", label: "Browser", glyph: "🌐" }, rest get the coral-gradient lucide glyph on a glass tile. 56px tile,
{ app: "slack", label: "Slack", glyph: "💬" }, 16px-radius icon container, press scales to 0.92 (measured). */
{ app: "chat", label: "Claw Chat", glyph: "🦀" }, function homeIcon(app: AppId) {
{ app: "apps", label: "Add", glyph: "+" }, if (app === "browser") {
]; return (
<span className="flex size-14 items-center justify-center rounded-2xl bg-white shadow-dock-tile">
const DOCK: { app: AppId; label: string; glyph: string }[] = [ <Image src="/services/chrome.svg" alt="" width={32} height={32} />
{ app: "skills", label: "Skills", glyph: "⚡" }, </span>
{ app: "files", label: "Files", glyph: "📁" }, );
{ app: "routines", label: "Routines", glyph: "🔔" }, }
{ app: "settings", label: "Settings", glyph: "⚙" }, if (app === "slack") {
]; return (
<span className="flex size-14 items-center justify-center rounded-2xl bg-white shadow-dock-tile">
<Image src="/services/slack.svg" alt="" width={30} height={30} />
</span>
);
}
if (app === "apps") {
return (
<span className="flex size-14 items-center justify-center rounded-2xl border border-dashed border-white/40 text-white/65">
<GradientGlyph icon={APP_ICON.apps} size={26} />
</span>
);
}
return (
<span className="flex size-14 items-center justify-center rounded-2xl bg-black/50 shadow-dock-tile backdrop-blur-sm">
<GradientGlyph icon={APP_ICON[app]} size={28} />
</span>
);
}
function Tile({ function Tile({
app,
label, label,
glyph, onOpen,
onClick,
}: { }: {
app: AppId;
label: string; label: string;
glyph: string; onOpen: (app: AppId, origin: DOMRect) => void;
onClick: () => void;
}) { }) {
return ( return (
<button <button
type="button" type="button"
onClick={onClick} aria-label={label}
className="flex flex-col items-center gap-1 rounded-(--radius) px-3 py-2 text-xxs text-foreground/90 hover:bg-white/10" onClick={(e: MouseEvent<HTMLButtonElement>) =>
onOpen(app, e.currentTarget.getBoundingClientRect())
}
className="flex flex-col items-center gap-1.5 transition-transform duration-[0.1s] ease-out-app active:scale-[0.92]"
> >
<span aria-hidden className="text-xl"> {homeIcon(app)}
{glyph} <span className="text-[11px] text-white/80">{label}</span>
</span>
{label}
</button> </button>
); );
} }
/** The §7.0 home screen: app grid over the wallpaper, glassy dock below. */ /** The measured home screen: app grid over the wallpaper, frosted dock. */
export function HomeScreen({ agentName, onOpen }: HomeScreenProps) { export function HomeScreen({ agentName, onOpen }: HomeScreenProps) {
return ( return (
<div className="relative flex flex-1 flex-col justify-between p-4"> <div className="relative flex flex-1 flex-col justify-between p-5">
<div className="grid grid-cols-4 gap-2" aria-label={`${agentName}'s apps`}> <div className="grid grid-cols-4 gap-3" aria-label={`${agentName}'s apps`}>
{GRID.map((tile) => ( {HOME_GRID.map((tile) => (
<Tile <Tile
key={tile.app} key={tile.app}
app={tile.app}
label={tile.label} label={tile.label}
glyph={tile.glyph} onOpen={onOpen}
onClick={() => onOpen(tile.app)}
/> />
))} ))}
</div> </div>
<div <div
aria-label="Dock" aria-label="Dock"
className="mx-auto flex gap-2 rounded-(--radius) border border-white/10 bg-white/5 px-3 py-1.5 shadow-(--shadow-dock-tile) backdrop-blur" className="mx-auto flex gap-5 rounded-3xl bg-white/[0.07] px-6 pt-4 pb-3 shadow-dock-capsule ring-1 ring-white/[0.04] ring-inset backdrop-blur-[40px] backdrop-saturate-150"
> >
{DOCK.map((tile) => ( {HOME_DOCK.map((tile) => (
<Tile <button
key={tile.app} key={tile.app}
label={tile.label} type="button"
glyph={tile.glyph} aria-label={tile.label}
onClick={() => onOpen(tile.app)} onClick={(e) =>
/> onOpen(tile.app, e.currentTarget.getBoundingClientRect())
}
className="flex size-12 items-center justify-center rounded-2xl bg-black shadow-dock-tile transition-transform duration-[0.1s] ease-out-app active:scale-[0.92]"
>
<GradientGlyph icon={APP_ICON[tile.app]} size={22} />
</button>
))} ))}
</div> </div>
</div> </div>
@@ -76,7 +76,7 @@ export default function AddAppsApp({ agent }: { agent: Agent }) {
role="tab" role="tab"
aria-selected={category === entry} aria-selected={category === entry}
onClick={() => setCategory(entry)} onClick={() => setCategory(entry)}
className={`shrink-0 rounded-radius-button px-2.5 py-1 text-xs font-medium transition-colors duration-normal ease-app ${ className={`shrink-0 rounded-full px-2.5 py-1 text-xs font-medium transition-colors duration-(--duration-normal) ease-app ${
category === entry category === entry
? "bg-white text-primary-foreground" ? "bg-white text-primary-foreground"
: "bg-white/10 text-white/80 hover:text-white" : "bg-white/10 text-white/80 hover:text-white"
@@ -99,7 +99,7 @@ export default function AddAppsApp({ agent }: { agent: Agent }) {
<ul aria-label="App directory"> <ul aria-label="App directory">
{apps.map((app) => ( {apps.map((app) => (
<li key={app.id} className="px-1 py-1"> <li key={app.id} className="px-1 py-1">
<div className="flex items-center gap-2 rounded-xl px-2 py-2 transition-colors duration-normal ease-app hover:bg-neutral-800/40"> <div className="flex items-center gap-2 rounded-xl px-2 py-2 transition-colors duration-(--duration-normal) ease-app hover:bg-neutral-800/40">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="text-sm">{app.name}</p> <p className="text-sm">{app.name}</p>
<p className="truncate text-xs text-muted-foreground"> <p className="truncate text-xs text-muted-foreground">
@@ -107,7 +107,7 @@ export default function AddAppsApp({ agent }: { agent: Agent }) {
</p> </p>
</div> </div>
{app.connected ? ( {app.connected ? (
<span className="rounded-radius-button border border-border px-2 py-0.5 text-xxs text-muted-foreground"> <span className="rounded-full border border-border px-2 py-0.5 text-xxs text-muted-foreground">
✓ Connected ✓ Connected
</span> </span>
) : ( ) : (
@@ -117,7 +117,7 @@ export default function AddAppsApp({ agent }: { agent: Agent }) {
onClick={() => onClick={() =>
setConnecting(connecting === app.id ? null : app.id) setConnecting(connecting === app.id ? null : app.id)
} }
className="inline-flex size-7 shrink-0 items-center justify-center rounded-radius-button border border-border text-muted-foreground transition-colors duration-normal ease-app hover:border-coral hover:text-foreground" className="inline-flex size-7 shrink-0 items-center justify-center rounded-full border border-border text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:border-coral hover:text-foreground"
> >
<Plus aria-hidden size={14} /> <Plus aria-hidden size={14} />
</button> </button>
@@ -138,7 +138,7 @@ export default function AddAppsApp({ agent }: { agent: Agent }) {
/> />
<button <button
type="submit" type="submit"
className="rounded-radius-button bg-coral px-3 py-1.5 text-xs font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light" className="rounded-full bg-coral px-3 py-1.5 text-xs font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light"
> >
Connect Connect
</button> </button>
@@ -46,7 +46,7 @@ export default function BrowserApp({ agent }: { agent: Agent }) {
type="button" type="button"
aria-label="Back" aria-label="Back"
disabled disabled
className="inline-flex size-7 items-center justify-center rounded-radius-button text-muted-foreground disabled:opacity-40" className="inline-flex size-7 items-center justify-center rounded-full text-muted-foreground disabled:opacity-40"
> >
<ChevronLeft aria-hidden size={16} /> <ChevronLeft aria-hidden size={16} />
</button> </button>
@@ -54,7 +54,7 @@ export default function BrowserApp({ agent }: { agent: Agent }) {
type="button" type="button"
aria-label="Forward" aria-label="Forward"
disabled disabled
className="inline-flex size-7 items-center justify-center rounded-radius-button text-muted-foreground disabled:opacity-40" className="inline-flex size-7 items-center justify-center rounded-full text-muted-foreground disabled:opacity-40"
> >
<ChevronRight aria-hidden size={16} /> <ChevronRight aria-hidden size={16} />
</button> </button>
@@ -83,7 +83,7 @@ export default function ClawChatApp({ agent }: { agent: Agent }) {
<button <button
type="button" type="button"
onClick={() => setOpenThread(thread)} onClick={() => setOpenThread(thread)}
className="w-full rounded-xl px-2 py-2 text-left transition-colors duration-normal ease-app hover:bg-neutral-800/40" className="w-full rounded-xl px-2 py-2 text-left transition-colors duration-(--duration-normal) ease-app hover:bg-neutral-800/40"
> >
<p className="flex items-center gap-2 text-sm"> <p className="flex items-center gap-2 text-sm">
{thread.subject} {thread.subject}
@@ -42,7 +42,7 @@ export default function FilesApp({ agent }: { agent: Agent }) {
<button <button
type="button" type="button"
onClick={() => setDrive(entry.id)} onClick={() => setDrive(entry.id)}
className="flex h-[45px] w-full items-center gap-3 rounded-xl px-3 text-base transition-colors duration-normal ease-app hover:bg-neutral-800/40" className="flex h-[45px] w-full items-center gap-3 rounded-xl px-3 text-base transition-colors duration-(--duration-normal) ease-app hover:bg-neutral-800/40"
> >
<GradientGlyph icon={Folder} size={18} /> <GradientGlyph icon={Folder} size={18} />
{entry.label} {entry.label}
@@ -30,7 +30,7 @@ export default function RoutinesApp({ agent }: { agent: Agent }) {
type="button" type="button"
aria-label="Refresh routines" aria-label="Refresh routines"
onClick={refresh} onClick={refresh}
className="inline-flex size-7 items-center justify-center rounded-radius-button text-muted-foreground transition-colors duration-normal ease-app hover:bg-hover-bg hover:text-foreground" className="inline-flex size-7 items-center justify-center rounded-full text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:bg-hover-bg hover:text-foreground"
> >
<RefreshCw aria-hidden size={14} /> <RefreshCw aria-hidden size={14} />
</button> </button>
@@ -110,7 +110,7 @@ export default function SettingsApp({ agent }: { agent: Agent }) {
<button <button
type="submit" type="submit"
disabled={saving} disabled={saving}
className="rounded-radius-button bg-cream px-4 py-2 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-normal ease-app hover:bg-white disabled:opacity-50" className="rounded-full bg-cream px-4 py-2 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-(--duration-normal) ease-app hover:bg-white disabled:opacity-50"
> >
{saving ? "Saving…" : "Save profile"} {saving ? "Saving…" : "Save profile"}
</button> </button>
@@ -121,14 +121,14 @@ export default function SettingsApp({ agent }: { agent: Agent }) {
<button <button
type="button" type="button"
onClick={() => setConfirmingDelete(false)} onClick={() => setConfirmingDelete(false)}
className="rounded-radius-button border border-border px-3 py-1.5 transition-colors hover:bg-hover-bg" className="rounded-full border border-border px-3 py-1.5 transition-colors hover:bg-hover-bg"
> >
Keep Keep
</button> </button>
<button <button
type="button" type="button"
onClick={deleteClaw} onClick={deleteClaw}
className="rounded-radius-button bg-destructive px-3 py-1.5 text-foreground" className="rounded-full bg-destructive px-3 py-1.5 text-foreground"
> >
Delete claw Delete claw
</button> </button>
@@ -65,7 +65,7 @@ export default function SkillsApp({ agent }: { agent: Agent }) {
type="button" type="button"
aria-label={`Install ${skill.title}`} aria-label={`Install ${skill.title}`}
onClick={() => install(skill.id)} onClick={() => install(skill.id)}
className="shrink-0 rounded-radius-button border border-border px-2 text-sm text-muted-foreground transition-colors duration-normal ease-app hover:border-coral hover:text-foreground" className="shrink-0 rounded-full border border-border px-2 text-sm text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:border-coral hover:text-foreground"
> >
+ +
</button> </button>
@@ -101,7 +101,7 @@ export default function SkillsApp({ agent }: { agent: Agent }) {
<button <button
type="button" type="button"
onClick={() => setAdding(true)} onClick={() => setAdding(true)}
className="mx-auto w-[92%] rounded-radius-button bg-cream py-3 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-normal ease-app hover:bg-white" className="mx-auto w-[92%] rounded-full bg-cream py-3 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-(--duration-normal) ease-app hover:bg-white"
> >
Add Skill Add Skill
</button> </button>
@@ -55,7 +55,7 @@ export default function SlackApp({ agent }: { agent: Agent }) {
<div <div
role="tablist" role="tablist"
aria-label="Slack" aria-label="Slack"
className="mb-3 inline-flex gap-1 self-start rounded-radius-button bg-white/10 p-1" className="mb-3 inline-flex gap-1 self-start rounded-full bg-white/10 p-1"
> >
{TABS.map((entry) => ( {TABS.map((entry) => (
<button <button
@@ -64,7 +64,7 @@ export default function SlackApp({ agent }: { agent: Agent }) {
role="tab" role="tab"
aria-selected={tab === entry} aria-selected={tab === entry}
onClick={() => setTab(entry)} onClick={() => setTab(entry)}
className={`rounded-radius-button px-3 py-1 text-xs font-medium transition-colors duration-normal ease-app ${ className={`rounded-full px-3 py-1 text-xs font-medium transition-colors duration-(--duration-normal) ease-app ${
tab === entry tab === entry
? "bg-white text-[#4a154b]" ? "bg-white text-[#4a154b]"
: "text-white/80 hover:text-white" : "text-white/80 hover:text-white"
@@ -104,7 +104,7 @@ export default function SlackApp({ agent }: { agent: Agent }) {
<button <button
type="submit" type="submit"
disabled={saving} disabled={saving}
className="self-start rounded-radius-button bg-coral px-4 py-2 text-xs font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light disabled:opacity-50" className="self-start rounded-full bg-coral px-4 py-2 text-xs font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light disabled:opacity-50"
> >
{saving ? "Connecting…" : "Connect Slack"} {saving ? "Connecting…" : "Connect Slack"}
</button> </button>
@@ -130,7 +130,7 @@ export default function SlackApp({ agent }: { agent: Agent }) {
<button <button
type="button" type="button"
onClick={() => setTab("Connection")} onClick={() => setTab("Connection")}
className="rounded-radius-button bg-cream px-5 py-2.5 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-normal ease-app hover:bg-white" className="rounded-full bg-cream px-5 py-2.5 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-(--duration-normal) ease-app hover:bg-white"
> >
Connect Slack Connect Slack
</button> </button>
@@ -70,7 +70,7 @@ export function AppsDirectory({ apps: initial }: { apps: DirectoryApp[] }) {
role="tab" role="tab"
aria-selected={category === entry} aria-selected={category === entry}
onClick={() => setCategory(entry)} onClick={() => setCategory(entry)}
className={`rounded-radius-button px-3 py-1 text-xs font-medium transition-colors duration-normal ease-app ${ className={`rounded-full px-3 py-1 text-xs font-medium transition-colors duration-(--duration-normal) ease-app ${
category === entry category === entry
? "bg-foreground text-background" ? "bg-foreground text-background"
: "bg-surface-warm text-muted-foreground hover:text-foreground" : "bg-surface-warm text-muted-foreground hover:text-foreground"
@@ -100,7 +100,7 @@ export function AppsDirectory({ apps: initial }: { apps: DirectoryApp[] }) {
</p> </p>
</div> </div>
{app.connected ? ( {app.connected ? (
<span className="rounded-radius-button border border-border px-2 py-0.5 text-xxs text-muted-foreground"> <span className="rounded-full border border-border px-2 py-0.5 text-xxs text-muted-foreground">
✓ Connected ✓ Connected
</span> </span>
) : ( ) : (
@@ -110,7 +110,7 @@ export function AppsDirectory({ apps: initial }: { apps: DirectoryApp[] }) {
onClick={() => onClick={() =>
setConnecting(connecting === app.id ? null : app.id) setConnecting(connecting === app.id ? null : app.id)
} }
className="inline-flex size-8 shrink-0 items-center justify-center rounded-radius-button border border-border text-muted-foreground transition-colors duration-normal ease-app hover:border-coral hover:text-foreground" className="inline-flex size-8 shrink-0 items-center justify-center rounded-full border border-border text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:border-coral hover:text-foreground"
> >
<Plus aria-hidden size={15} /> <Plus aria-hidden size={15} />
</button> </button>
@@ -128,7 +128,7 @@ export function AppsDirectory({ apps: initial }: { apps: DirectoryApp[] }) {
/> />
<button <button
type="submit" type="submit"
className="rounded-radius-button bg-coral px-3 py-1.5 text-xs font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light" className="rounded-full bg-coral px-3 py-1.5 text-xs font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light"
> >
Connect Connect
</button> </button>
+2 -2
View File
@@ -53,7 +53,7 @@ function MembersTable({ members }: { members: User[] }) {
<Avatar name={member.display_name} size="sm" /> <Avatar name={member.display_name} size="sm" />
{member.display_name} {member.display_name}
{member.role === "owner" && ( {member.role === "owner" && (
<span className="rounded-radius-button bg-surface-warm-muted px-2 py-0.5 text-xxs text-muted-foreground"> <span className="rounded-full bg-surface-warm-muted px-2 py-0.5 text-xxs text-muted-foreground">
Owner Owner
</span> </span>
)} )}
@@ -98,7 +98,7 @@ function OrgChart({ nodes }: { nodes: OrgChartNode[] }) {
<Link <Link
key={claw.id} key={claw.id}
href={`/claws/${claw.id}`} href={`/claws/${claw.id}`}
className="flex items-center gap-2 rounded-radius-button bg-surface-warm px-3 py-1.5 text-xs transition-colors duration-normal ease-app hover:bg-surface-warm-muted" className="flex items-center gap-2 rounded-full bg-surface-warm px-3 py-1.5 text-xs transition-colors duration-(--duration-normal) ease-app hover:bg-surface-warm-muted"
> >
<Avatar <Avatar
name={claw.name} name={claw.name}
+1 -1
View File
@@ -50,7 +50,7 @@ export function Faq() {
<ChevronDown <ChevronDown
aria-hidden aria-hidden
size={18} size={18}
className={`shrink-0 text-marketing-slate transition-transform duration-normal ease-app ${ className={`shrink-0 text-marketing-slate transition-transform duration-(--duration-normal) ease-app ${
open === i ? "rotate-180" : "" open === i ? "rotate-180" : ""
}`} }`}
/> />
+3 -3
View File
@@ -4,7 +4,7 @@ import Link from "next/link";
* auth pills right. Our brand, our links. */ * auth pills right. Our brand, our links. */
export function MarketingNav() { export function MarketingNav() {
return ( return (
<header className="sticky top-4 z-50 mx-auto flex w-[min(960px,92%)] items-center justify-between rounded-radius-button bg-white px-5 py-2.5 shadow-[0_8px_30px_-12px_rgba(22,29,39,0.18)] ring-1 ring-marketing-border"> <header className="sticky top-4 z-50 mx-auto flex w-[min(960px,92%)] items-center justify-between rounded-full bg-white px-5 py-2.5 shadow-[0_8px_30px_-12px_rgba(22,29,39,0.18)] ring-1 ring-marketing-border">
<Link href="/" className="font-mono text-lg font-semibold tracking-tight"> <Link href="/" className="font-mono text-lg font-semibold tracking-tight">
clawmates clawmates
</Link> </Link>
@@ -22,13 +22,13 @@ export function MarketingNav() {
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Link <Link
href="/login" href="/login"
className="rounded-radius-button px-4 py-2 text-sm font-medium hover:bg-[#f1f3f7]" className="rounded-full px-4 py-2 text-sm font-medium hover:bg-[#f1f3f7]"
> >
Sign in Sign in
</Link> </Link>
<Link <Link
href="/login" href="/login"
className="rounded-radius-button bg-marketing-slate-dark px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-[#0f172a]" className="rounded-full bg-marketing-slate-dark px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-[#0f172a]"
> >
Get started Get started
</Link> </Link>
@@ -28,13 +28,13 @@ export function Hero() {
<div className="flex flex-wrap justify-center gap-3 pt-8"> <div className="flex flex-wrap justify-center gap-3 pt-8">
<Link <Link
href="/login" href="/login"
className="flex h-14 items-center rounded-radius-button bg-marketing-coral px-10 text-xl font-bold text-white transition-colors hover:bg-[#d84a4a]" className="flex h-14 items-center rounded-full bg-marketing-coral px-10 text-xl font-bold text-white transition-colors hover:bg-[#d84a4a]"
> >
Get started for free Get started for free
</Link> </Link>
<a <a
href="mailto:[email protected]" href="mailto:[email protected]"
className="flex h-14 items-center rounded-radius-button border border-marketing-border bg-white px-10 text-base font-semibold text-[#0f172a] transition-colors hover:bg-[#f1f3f7]" className="flex h-14 items-center rounded-full border border-marketing-border bg-white px-10 text-base font-semibold text-[#0f172a] transition-colors hover:bg-[#f1f3f7]"
> >
Book a demo Book a demo
</a> </a>
@@ -151,7 +151,7 @@ export function CtaBand() {
</h2> </h2>
<Link <Link
href="/login" href="/login"
className="flex h-14 items-center rounded-radius-button bg-marketing-coral px-10 text-xl font-bold text-white transition-colors hover:bg-[#d84a4a]" className="flex h-14 items-center rounded-full bg-marketing-coral px-10 text-xl font-bold text-white transition-colors hover:bg-[#d84a4a]"
> >
Get started for free Get started for free
</Link> </Link>
@@ -19,7 +19,7 @@ export function AgentRosterItem({
className="group flex w-full flex-col items-center gap-1 py-1.5" className="group flex w-full flex-col items-center gap-1 py-1.5"
> >
<span <span
className={`rounded-[19px] p-0.5 transition-colors duration-normal ease-app ${ className={`rounded-[19px] p-0.5 transition-colors duration-(--duration-normal) ease-app ${
active ? "ring-2 ring-coral" : "" active ? "ring-2 ring-coral" : ""
}`} }`}
> >
@@ -40,7 +40,7 @@ export function AgentRosterItem({
</span> </span>
</span> </span>
<span <span
className={`max-w-full truncate text-xs transition-colors duration-normal ease-app ${ className={`max-w-full truncate text-xs transition-colors duration-(--duration-normal) ease-app ${
active active
? "text-foreground" ? "text-foreground"
: "text-muted-foreground group-hover:text-foreground" : "text-muted-foreground group-hover:text-foreground"
@@ -25,7 +25,7 @@ export function GlobalNavItem({
<Link <Link
href={href} href={href}
aria-current={active ? "page" : undefined} aria-current={active ? "page" : undefined}
className={`flex h-8 items-center gap-3 rounded-radius-button px-3 text-base transition-colors duration-normal ease-app ${ className={`flex h-8 items-center gap-3 rounded-full px-3 text-sm transition-colors duration-(--duration-normal) ease-app ${
active active
? "text-foreground" ? "text-foreground"
: "text-muted-foreground hover:bg-hover-bg hover:text-foreground" : "text-muted-foreground hover:bg-hover-bg hover:text-foreground"
+10 -9
View File
@@ -3,7 +3,7 @@
import Link from "next/link"; import Link from "next/link";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { Menu, Plus, X } from "lucide-react"; import { Menu, Plus, X } from "lucide-react";
import { useRef, useState } from "react"; import { useState } from "react";
import type { Agent, User } from "@/lib/api/schemas"; import type { Agent, User } from "@/lib/api/schemas";
import { RosterList } from "./RosterList"; import { RosterList } from "./RosterList";
@@ -22,10 +22,11 @@ interface LeftRailProps {
export function LeftRail({ user, roster, creditsBalance }: LeftRailProps) { export function LeftRail({ user, roster, creditsBalance }: LeftRailProps) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const pathname = usePathname(); const pathname = usePathname();
// Close the drawer when the route changes (render-phase, no effect). // Close the drawer when the route changes (render-phase prev-state
const lastPath = useRef(pathname); // pattern — no effect, no ref).
if (lastPath.current !== pathname) { const [seenPath, setSeenPath] = useState(pathname);
lastPath.current = pathname; if (seenPath !== pathname) {
setSeenPath(pathname);
if (open) setOpen(false); if (open) setOpen(false);
} }
@@ -35,7 +36,7 @@ export function LeftRail({ user, roster, creditsBalance }: LeftRailProps) {
type="button" type="button"
aria-label="Open navigation" aria-label="Open navigation"
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
className="fixed top-4 left-3 z-30 hidden size-9 items-center justify-center rounded-radius-button bg-surface-warm text-foreground shadow-card max-md:inline-flex" className="fixed top-4 left-3 z-30 hidden size-9 items-center justify-center rounded-full bg-surface-warm text-foreground shadow-card max-md:inline-flex"
> >
<Menu aria-hidden size={18} /> <Menu aria-hidden size={18} />
</button> </button>
@@ -48,7 +49,7 @@ export function LeftRail({ user, roster, creditsBalance }: LeftRailProps) {
/> />
)} )}
<aside <aside
className={`z-50 flex h-dvh w-rail shrink-0 flex-col px-1 py-4 transition-transform duration-normal ease-app max-md:fixed max-md:bg-background max-md:shadow-edge ${ className={`z-50 flex h-dvh w-rail shrink-0 flex-col px-1 py-4 transition-transform duration-(--duration-normal) ease-app max-md:fixed max-md:bg-background max-md:shadow-edge ${
open ? "max-md:translate-x-0" : "max-md:-translate-x-full" open ? "max-md:translate-x-0" : "max-md:-translate-x-full"
}`} }`}
> >
@@ -77,11 +78,11 @@ export function LeftRail({ user, roster, creditsBalance }: LeftRailProps) {
> >
<span <span
aria-hidden aria-hidden
className="inline-flex size-12 items-center justify-center rounded-radius-squircle border border-dashed border-border text-coral transition-colors duration-normal ease-app group-hover:border-coral" className="inline-flex size-12 items-center justify-center rounded-[17px] border border-dashed border-border text-coral transition-colors duration-(--duration-normal) ease-app group-hover:border-coral"
> >
<Plus size={20} /> <Plus size={20} />
</span> </span>
<span className="text-xs text-muted-foreground transition-colors duration-normal ease-app group-hover:text-foreground"> <span className="text-xs text-muted-foreground transition-colors duration-(--duration-normal) ease-app group-hover:text-foreground">
New claw New claw
</span> </span>
</Link> </Link>
+1 -1
View File
@@ -14,7 +14,7 @@ describe("Avatar", () => {
<Avatar name="Scout" shape="squircle" size="rail" />, <Avatar name="Scout" shape="squircle" size="rail" />,
); );
const span = container.querySelector("span[aria-hidden]")!; const span = container.querySelector("span[aria-hidden]")!;
expect(span.className).toContain("rounded-radius-squircle"); expect(span.className).toContain("rounded-[17px]");
expect(span.className).not.toContain("rounded-full"); expect(span.className).not.toContain("rounded-full");
expect(span.className).toContain("size-12"); /* 48px rail size */ expect(span.className).toContain("size-12"); /* 48px rail size */
}); });
+1 -1
View File
@@ -33,7 +33,7 @@ export function Avatar({
.map((part) => part[0]!.toUpperCase()) .map((part) => part[0]!.toUpperCase())
.join(""); .join("");
const radius = const radius =
shape === "squircle" ? "rounded-radius-squircle" : "rounded-full"; shape === "squircle" ? "rounded-[17px]" : "rounded-full";
return ( return (
<span className="relative inline-flex"> <span className="relative inline-flex">
<span <span
+2 -2
View File
@@ -7,7 +7,7 @@ describe("Button", () => {
it("cream variant: pill with cream fill and dark text (the action primary)", () => { it("cream variant: pill with cream fill and dark text (the action primary)", () => {
render(<Button variant="cream">Send</Button>); render(<Button variant="cream">Send</Button>);
const button = screen.getByRole("button", { name: "Send" }); const button = screen.getByRole("button", { name: "Send" });
expect(button.className).toContain("rounded-radius-button"); expect(button.className).toContain("rounded-full");
expect(button.className).toContain("bg-cream"); expect(button.className).toContain("bg-cream");
expect(button.className).toContain("text-primary-foreground"); expect(button.className).toContain("text-primary-foreground");
}); });
@@ -35,7 +35,7 @@ describe("Button", () => {
); );
const button = screen.getByRole("button", { name: "New session" }); const button = screen.getByRole("button", { name: "New session" });
expect(button.className).toContain("size-9"); expect(button.className).toContain("size-9");
expect(button.className).toContain("rounded-radius-button"); expect(button.className).toContain("rounded-full");
}); });
it("disabled drops to half opacity and blocks clicks", async () => { it("disabled drops to half opacity and blocks clicks", async () => {
+5 -5
View File
@@ -13,14 +13,14 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
Computer opener. All pills; all on the 0.25s ease-app transition. */ Computer opener. All pills; all on the 0.25s ease-app transition. */
const VARIANTS: Record<Variant, string> = { const VARIANTS: Record<Variant, string> = {
cream: cream:
"rounded-radius-button bg-cream px-4 py-2 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-normal ease-app hover:bg-white active:translate-y-px disabled:opacity-50 disabled:shadow-none", "rounded-full bg-cream px-4 py-2 text-sm font-semibold text-primary-foreground shadow-button transition-colors duration-(--duration-normal) ease-app hover:bg-white active:translate-y-px disabled:opacity-50 disabled:shadow-none",
coral: coral:
"rounded-radius-button bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light active:bg-coral-dark disabled:opacity-50", "rounded-full bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light active:bg-coral-dark disabled:opacity-50",
ghost: ghost:
"rounded-radius-button px-3 py-1.5 text-sm text-muted-foreground transition-colors duration-normal ease-app hover:bg-hover-bg hover:text-foreground disabled:opacity-50", "rounded-full px-3 py-1.5 text-sm text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:bg-hover-bg hover:text-foreground disabled:opacity-50",
icon: "inline-flex size-9 items-center justify-center rounded-radius-button text-muted-foreground transition-colors duration-normal ease-app hover:bg-hover-bg hover:text-foreground disabled:opacity-50", icon: "inline-flex size-9 items-center justify-center rounded-full text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:bg-hover-bg hover:text-foreground disabled:opacity-50",
launcher: launcher:
"inline-flex size-[42px] items-center justify-center rounded-radius-button text-coral shadow-launcher transition-all duration-normal ease-app hover:bg-coral/10 active:scale-95 disabled:opacity-50", "inline-flex size-[42px] items-center justify-center rounded-full text-coral shadow-launcher transition-all duration-(--duration-normal) ease-app hover:bg-coral/10 active:scale-95 disabled:opacity-50",
}; };
export function Button({ variant, className, ...rest }: ButtonProps) { export function Button({ variant, className, ...rest }: ButtonProps) {
+1 -1
View File
@@ -12,7 +12,7 @@ export function Card({
<div <div
className={`rounded-3xl border border-border bg-card p-6 shadow-card${ className={`rounded-3xl border border-border bg-card p-6 shadow-card${
interactive interactive
? " transition-colors duration-normal ease-app hover:border-neutral-700" ? " transition-colors duration-(--duration-normal) ease-app hover:border-neutral-700"
: "" : ""
}${className ? ` ${className}` : ""}`} }${className ? ` ${className}` : ""}`}
{...rest} {...rest}
+1 -1
View File
@@ -11,7 +11,7 @@ export function SearchPill({
}: InputHTMLAttributes<HTMLInputElement>) { }: InputHTMLAttributes<HTMLInputElement>) {
return ( return (
<span <span
className={`flex items-center gap-2 rounded-radius-button bg-surface-warm-muted px-3 py-1.5${className ? ` ${className}` : ""}`} className={`flex items-center gap-2 rounded-full bg-surface-warm-muted px-3 py-1.5${className ? ` ${className}` : ""}`}
> >
<Search aria-hidden size={14} className="shrink-0 text-subtle-foreground" /> <Search aria-hidden size={14} className="shrink-0 text-subtle-foreground" />
<input <input
+2 -2
View File
@@ -19,7 +19,7 @@ export function SegmentedTabs({
<div <div
role="tablist" role="tablist"
aria-label={label} aria-label={label}
className="inline-flex gap-1 rounded-radius-button bg-subtle p-1" className="inline-flex gap-1 rounded-full bg-subtle p-1"
> >
{tabs.map((tab) => ( {tabs.map((tab) => (
<button <button
@@ -28,7 +28,7 @@ export function SegmentedTabs({
role="tab" role="tab"
aria-selected={tab === active} aria-selected={tab === active}
onClick={() => onChange(tab)} onClick={() => onChange(tab)}
className={`rounded-radius-button px-3 py-1 text-xs font-medium transition-colors duration-normal ease-app ${ className={`rounded-full px-3 py-1 text-xs font-medium transition-colors duration-(--duration-normal) ease-app ${
tab === active tab === active
? "bg-surface-warm-muted text-foreground" ? "bg-surface-warm-muted text-foreground"
: "text-muted-foreground hover:text-foreground" : "text-muted-foreground hover:text-foreground"
@@ -192,7 +192,7 @@ export function CreateClawForm() {
type="button" type="button"
disabled={!draft.name || !draft.jobTitle} disabled={!draft.name || !draft.jobTitle}
onClick={() => setParams({ step: "access" })} onClick={() => setParams({ step: "access" })}
className="rounded-radius-button bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light disabled:opacity-40" className="rounded-full bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light disabled:opacity-40"
> >
Continue → Continue →
</button> </button>
@@ -237,7 +237,7 @@ export function CreateClawForm() {
<button <button
type="button" type="button"
onClick={() => setParams({ step: "slack" })} onClick={() => setParams({ step: "slack" })}
className="rounded-radius-button bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light" className="rounded-full bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light"
> >
Continue → Continue →
</button> </button>
@@ -263,7 +263,7 @@ export function CreateClawForm() {
<button <button
type="button" type="button"
onClick={() => setConfirming(true)} onClick={() => setConfirming(true)}
className="rounded-radius-button bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light" className="rounded-full bg-coral px-4 py-2 text-sm font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light"
> >
Review &amp; create Review &amp; create
</button> </button>
@@ -292,7 +292,7 @@ export function CreateClawForm() {
<button <button
type="button" type="button"
onClick={create} onClick={create}
className="rounded-radius-button bg-coral px-4 py-1.5 text-xs font-medium text-white shadow-cta transition-colors duration-normal ease-app hover:bg-coral-light" className="rounded-full bg-coral px-4 py-1.5 text-xs font-medium text-white shadow-cta transition-colors duration-(--duration-normal) ease-app hover:bg-coral-light"
> >
Create claw Create claw
</button> </button>