Polish every product workflow across desktop and mobile
CI / verify (push) Successful in 3m32s

Reframe each screen around the decisions compute brokers make: sellable capacity, full-cost margin, pipeline movement, contract deadlines, evidence review, staged imports, and controlled agent access. Group the shell by operating domain, strengthen mobile navigation and sheets, add responsive record treatments, and make loading, error, empty, readiness, and retry states explicit.

The visual audit exposed sortable table targets and an unnamed file input only after exercising the rendered app, so this commit also pins those accessibility decisions at their actual interaction boundaries. Manrope is self-hosted as a single Latin variable subset to keep the stronger hierarchy without shipping unused font payloads.
This commit is contained in:
2026-08-13 05:34:23 -07:00
parent 1318c0b841
commit e12d27edd1
28 changed files with 672 additions and 522 deletions
+25 -11
View File
@@ -30,16 +30,26 @@ export function Settings() {
const { data: me } = useQuery({ queryKey: ['me'], queryFn: () => get<Me>('/api/me') });
return (
<div className="space-y-6">
<header>
<h1 className="text-xl font-semibold tracking-tight sm:text-2xl">Settings</h1>
<div className="space-y-6 pb-4">
<header className="flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
<div>
<h1 className="text-xl font-semibold tracking-tight sm:text-2xl">Settings</h1>
<p className="mt-1 max-w-2xl text-sm text-muted">
Personal preferences, workspace access, and server-managed integration readiness.
</p>
</div>
{me?.isPlatformAdmin ? <Badge tone="warning">Platform admin view</Badge> : null}
</header>
<Appearance />
<Profile me={me} />
<div className="grid gap-6 xl:grid-cols-2">
<Appearance />
<Profile me={me} />
</div>
{me?.isPlatformAdmin ? <AdminSettings /> : null}
<ConnectAgent />
<SessionCard />
<div className="grid gap-6 xl:grid-cols-2">
<ConnectAgent />
<SessionCard />
</div>
</div>
);
}
@@ -64,6 +74,7 @@ function Appearance() {
return (
<button
key={value}
type="button"
onClick={() => setMode(value as ThemeMode)}
aria-pressed={mode === value}
className={[
@@ -88,6 +99,7 @@ function Appearance() {
return (
<button
key={option.key}
type="button"
onClick={() => setAccent(option.key)}
aria-pressed={selected}
aria-label={option.label}
@@ -193,13 +205,15 @@ function Profile({ me }: { me: Me | undefined }) {
save.mutate();
}}
>
<label className="block">
<label className="block" htmlFor="profile-display-name">
<span className="mb-1 block text-xs font-medium text-muted">Display name</span>
<Input value={name} onChange={(e) => setName(e.target.value)} placeholder={me.name} />
<Input id="profile-display-name" name="displayName" value={name} onChange={(e) => setName(e.target.value)} placeholder={me.name} />
</label>
<label className="block">
<label className="block" htmlFor="profile-title">
<span className="mb-1 block text-xs font-medium text-muted">Title</span>
<Input
id="profile-title"
name="title"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Head of Compute"
@@ -288,7 +302,7 @@ function SessionCard() {
</p>
</CardHeader>
<CardContent>
<Button variant="outline" onClick={signOut} disabled={busy}>
<Button type="button" variant="outline" onClick={signOut} disabled={busy}>
<LogOut className="h-4 w-4" aria-hidden />
{busy ? 'Signing out…' : 'Sign out'}
</Button>