docs(31): UI design contract
This commit is contained in:
parent
431c504dd4
commit
af1dc9cb15
1 changed files with 258 additions and 0 deletions
258
.planning/phases/31-puter.js-zero-config-cloud/31-UI-SPEC.md
Normal file
258
.planning/phases/31-puter.js-zero-config-cloud/31-UI-SPEC.md
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
---
|
||||
phase: 31
|
||||
slug: puter.js-zero-config-cloud
|
||||
status: draft
|
||||
shadcn_initialized: true
|
||||
preset: new-york / neutral / cssVariables
|
||||
created: 2026-04-02
|
||||
---
|
||||
|
||||
# Phase 31 — UI Design Contract
|
||||
|
||||
> Visual and interaction contract for Phase 31: Puter.js Zero-Config Cloud.
|
||||
> Generated by gsd-ui-researcher. Verified by gsd-ui-checker.
|
||||
|
||||
---
|
||||
|
||||
## Design System
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Tool | shadcn |
|
||||
| Preset | new-york, baseColor: neutral, cssVariables: true, style: new-york |
|
||||
| Component library | Radix UI (via shadcn) |
|
||||
| Icon library | lucide-react |
|
||||
| Font | System UI (inherited from body; no custom font declared in index.css) |
|
||||
|
||||
Source: `/opt/nexus/ui/components.json` + `/opt/nexus/ui/src/index.css`
|
||||
|
||||
---
|
||||
|
||||
## Spacing Scale
|
||||
|
||||
Declared values (must be multiples of 4):
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| xs | 4px | Icon gaps (`gap-1`), inline badge padding |
|
||||
| sm | 8px | Compact element spacing (`gap-2`), within-form row gaps |
|
||||
| md | 16px | Default element spacing (`gap-4`), form field gaps |
|
||||
| lg | 24px | Section padding (`p-6`), card interior padding |
|
||||
| xl | 32px | Layout gaps (`p-8`) — matches existing wizard card `p-8` |
|
||||
| 2xl | 48px | Major section breaks — not used in wizard context |
|
||||
| 3xl | 64px | Page-level spacing — not used in wizard context |
|
||||
|
||||
Exceptions:
|
||||
- Touch targets: `min-height: 44px` enforced globally via `@media (pointer: coarse)` in `index.css` — no per-component override required.
|
||||
- Provider option cards: `p-4` (16px) interior padding, matching `ModeSelector` card pattern.
|
||||
- Warning callout (Google OAuth risk): `px-3 py-2` (12px/8px) — compact inline alert pattern matching existing error state style.
|
||||
|
||||
Source: existing `NexusOnboardingWizard.tsx` uses `p-8`, `gap-6`, `gap-4`, `gap-2`. ModeSelector uses `p-4`, `gap-3`, `gap-1`.
|
||||
|
||||
---
|
||||
|
||||
## Typography
|
||||
|
||||
| Role | Size | Weight | Line Height |
|
||||
|------|------|--------|-------------|
|
||||
| Body | 14px (0.875rem) | 400 | 1.5 |
|
||||
| Heading | 24px (1.5rem / text-2xl) | 600 | 1.2 |
|
||||
| Caption / muted | 12px (0.75rem / text-xs) | 400 | 1.4 |
|
||||
|
||||
Notes:
|
||||
- Heading size matches existing wizard `h1` (`text-2xl font-semibold`) — locked by Phase 30 component pattern.
|
||||
- Label size matches existing form label pattern (`text-sm font-medium`).
|
||||
- Body size matches existing paragraph + description pattern (`text-sm`).
|
||||
- Caption is used for step indicator (`text-xs text-muted-foreground`), provider descriptions, and warning footnotes.
|
||||
- No display-size text (>24px) is needed in this phase — the wizard card is constrained to `max-w-md`.
|
||||
|
||||
Source: `NexusOnboardingWizard.tsx` lines 214, 245, 281–283, 294.
|
||||
|
||||
---
|
||||
|
||||
## Color
|
||||
|
||||
All values are shadcn CSS custom properties resolved from `/opt/nexus/ui/src/index.css`.
|
||||
Both light (Catppuccin Latte) and dark (Catppuccin Mocha) themes are supported.
|
||||
|
||||
| Role | Light value | Dark value | Usage |
|
||||
|------|-------------|------------|-------|
|
||||
| Dominant (60%) | `--background` (#eff1f5) | `--background` (#1e1e2e) | Wizard backdrop, page background |
|
||||
| Secondary (30%) | `--card` (#e6e9ef) | `--card` (#181825) | Wizard card surface, provider option cards |
|
||||
| Accent (10%) | `--primary` (#1e66f5) | `--primary` (#89b4fa) | Selected provider card border + tint, primary CTA button |
|
||||
| Destructive | `--destructive` (#d20f39) | `--destructive` (#f38ba8) | Google OAuth policy-risk warning text; error state text |
|
||||
|
||||
Accent reserved for:
|
||||
1. The currently selected provider option card border (`border-primary`) and tint (`bg-primary/5`)
|
||||
2. The primary CTA button ("Continue with Puter", "Continue", "Get Started")
|
||||
3. The focus ring on interactive inputs and buttons (`--ring`)
|
||||
|
||||
Do NOT use accent on: provider logos, status badges, neutral labels, section headings.
|
||||
|
||||
Source: `index.css` CSS custom properties; `ModeSelector.tsx` selected-state pattern (`border-primary bg-primary/5`).
|
||||
|
||||
---
|
||||
|
||||
## Component Inventory
|
||||
|
||||
New components introduced in this phase:
|
||||
|
||||
| Component | File | Reuses |
|
||||
|-----------|------|--------|
|
||||
| `ProviderSelectionStep` | `ui/src/components/onboarding/ProviderSelectionStep.tsx` | `Button`, `cn`, NexusOnboardingWizard card patterns |
|
||||
| `PuterAuthButton` | `ui/src/components/onboarding/PuterAuthButton.tsx` | `Button` (variant default), lucide `LogIn` icon |
|
||||
| `GoogleOAuthButton` | `ui/src/components/onboarding/GoogleOAuthButton.tsx` | `Button` (variant outline), lucide `AlertTriangle` icon for warning |
|
||||
| `ApiKeyEntryForm` | `ui/src/components/onboarding/ApiKeyEntryForm.tsx` | `Input`, `Label`, `Button` |
|
||||
| `ProviderRiskWarning` | inline in `GoogleOAuthButton` | styled `div` with `text-destructive` + `bg-destructive/10` — matches existing error block |
|
||||
|
||||
Existing components consumed without modification:
|
||||
|
||||
| Component | Source |
|
||||
|-----------|--------|
|
||||
| `Button` | `@/components/ui/button` |
|
||||
| `Input` | `@/components/ui/input` |
|
||||
| `Label` | `@/components/ui/label` |
|
||||
| `Skeleton` | `@/components/ui/skeleton` |
|
||||
| `NexusOnboardingWizard` | `@/components/NexusOnboardingWizard` — extended with new Step 4 |
|
||||
|
||||
---
|
||||
|
||||
## Interaction Contract
|
||||
|
||||
### Wizard Step Extension
|
||||
|
||||
The existing 3-step wizard becomes a 4-step wizard for users without a detected local adapter:
|
||||
|
||||
```
|
||||
Step 1: Hardware Detection → Step 2: Mode Selection → Step 3: Provider Selection (NEW) → Step 4: Root Directory
|
||||
```
|
||||
|
||||
For users with a detected local adapter (hermes_local or claude_local), Step 3 is shown but pre-populated with the detected provider highlighted and a "Continue" shortcut.
|
||||
|
||||
Step indicator text: "Step {N} of 4" (updated from current "Step {N} of 3").
|
||||
|
||||
### Provider Selection Step Layout
|
||||
|
||||
Three option cards in a vertical stack (matching `ModeSelector` grid pattern):
|
||||
|
||||
1. **Puter (free, zero-config)** — primary recommendation when no local AI and no API key
|
||||
- Card border: `border-primary bg-primary/5` when selected
|
||||
- Action: "Continue with Puter" button appears below cards when Puter is selected
|
||||
- Auth state: button shows spinner during `puter.auth.signIn()` popup
|
||||
- Post-auth state: button label changes to "Puter connected — Continue", icon: `CheckCircle` (lucide), border stays `border-primary`
|
||||
|
||||
2. **Google (Gemini free tier)** — shown with risk callout
|
||||
- Risk callout: amber/destructive inline alert (see Copywriting section) rendered inside the card when this option is selected — always visible before the "Sign in with Google" button is enabled
|
||||
- Action: "Sign in with Google" (disabled until risk callout has been displayed for 3 seconds — anti-accidental-click gate)
|
||||
- Post-auth state: "Google connected — Continue"
|
||||
|
||||
3. **API Key (subscription providers)** — manual entry
|
||||
- When selected: inline form expands below card (no new page) with provider select dropdown + API key input
|
||||
- Supported providers listed in dropdown: OpenAI, Anthropic, Groq (extensible)
|
||||
|
||||
4. **Skip for now** — ghost button below the three cards, always visible
|
||||
- Does not require a selection; proceeds to Step 4 with the probed default adapter
|
||||
|
||||
### Loading States
|
||||
|
||||
| State | Treatment |
|
||||
|-------|-----------|
|
||||
| Puter auth popup in progress | Button disabled, spinner icon (h-4 w-4 animate-spin), label "Connecting to Puter…" |
|
||||
| Google OAuth in progress | Button disabled, spinner, label "Signing in…" |
|
||||
| API key saving | Submit button disabled, spinner, label "Saving…" |
|
||||
| Adapter probe in progress | Provider cards render with `Skeleton` placeholders where pre-detected tool badges would appear; probe is fire-and-forget (cards still interactive) |
|
||||
|
||||
### Error States
|
||||
|
||||
All errors render inline below the triggering element using the existing error block pattern:
|
||||
```
|
||||
<p className="text-sm text-destructive bg-destructive/10 rounded-md px-3 py-2">
|
||||
{errorMessage}
|
||||
</p>
|
||||
```
|
||||
|
||||
### Keyboard and Accessibility
|
||||
|
||||
- All provider option cards are `<button type="button">` elements (matching ModeSelector pattern) — keyboard navigable, focus ring via `--ring`.
|
||||
- Risk warning callout uses `role="alert"` so screen readers announce it immediately when the Google option is selected.
|
||||
- Auth buttons have `aria-busy="true"` during loading states.
|
||||
- Skip button has accessible label: "Skip provider setup for now".
|
||||
|
||||
---
|
||||
|
||||
## Copywriting Contract
|
||||
|
||||
| Element | Copy |
|
||||
|---------|------|
|
||||
| Step heading (provider step) | "Choose a provider" |
|
||||
| Step subheading | "No API keys needed for the zero-config path." |
|
||||
| Primary CTA — Puter | "Continue with Puter" |
|
||||
| Primary CTA — Google | "Sign in with Google" |
|
||||
| Primary CTA — API key | "Save API key" |
|
||||
| Primary CTA — generic Continue | "Continue" |
|
||||
| Skip action | "Skip for now" |
|
||||
| Puter card label | "Puter — free, zero-config" |
|
||||
| Puter card description | "Free AI powered by your Puter.com account. No API key needed." |
|
||||
| Puter cost attribution note | "Usage is billed to your Puter account, not to Nexus." |
|
||||
| Google card label | "Google — Gemini free tier" |
|
||||
| Google card description | "Sign in with Google to access Gemini via your Google account." |
|
||||
| Google risk warning heading | "Policy risk — read before continuing" |
|
||||
| Google risk warning body | "Google has suspended accounts that used third-party apps with Gemini credentials. This may affect your Gmail and Workspace access. Use a Google AI Studio API key instead if you want to avoid this risk." |
|
||||
| Google safe alternative hint | "Safer option: enter a Gemini API key from Google AI Studio below." |
|
||||
| API key card label | "API key — subscription provider" |
|
||||
| API key card description | "Use your own OpenAI, Anthropic, or Groq API key." |
|
||||
| Puter connected success | "Puter connected — Continue" |
|
||||
| Google connected success | "Google connected — Continue" |
|
||||
| Empty state (no provider selected, user tries to continue without skipping) | Not applicable — "Skip for now" is always available; no blocking empty state. |
|
||||
| Error: Puter popup blocked | "Puter sign-in was blocked. Click 'Continue with Puter' directly — do not use keyboard shortcuts." |
|
||||
| Error: Puter auth failed | "Puter sign-in failed. Check your Puter.com account and try again." |
|
||||
| Error: Google auth failed | "Google sign-in failed. Try again or use an API key instead." |
|
||||
| Error: API key save failed | "Could not save API key. Check the key is valid and try again." |
|
||||
| Error: generic setup failure | "Setup failed. Please try again." |
|
||||
| Puter auth button loading | "Connecting to Puter…" |
|
||||
| Google auth button loading | "Signing in…" |
|
||||
| API key submit loading | "Saving…" |
|
||||
| Auto-detected tool badge | "{ToolName} detected" (e.g. "Hermes detected", "Claude Code detected") |
|
||||
| Step indicator | "Step {N} of 4" |
|
||||
|
||||
Destructive actions: None in this phase. The Google OAuth risk warning is a caution, not a destructive action confirmation (no data is deleted).
|
||||
|
||||
---
|
||||
|
||||
## Registry Safety
|
||||
|
||||
| Registry | Blocks Used | Safety Gate |
|
||||
|----------|-------------|-------------|
|
||||
| shadcn official (ui.shadcn.com) | button, input, label, skeleton, dialog | not required |
|
||||
| Third-party | none | not applicable |
|
||||
|
||||
No third-party shadcn registry blocks are used in this phase. `@heyputer/puter.js` is an npm package loaded via CDN script tag at runtime (not a shadcn registry block) — registry vetting gate does not apply.
|
||||
|
||||
---
|
||||
|
||||
## Notes for Executor
|
||||
|
||||
1. **Wizard step count:** Update the "Step N of 3" indicator to "Step N of 4" in `NexusOnboardingWizard.tsx`. The existing step counter is a plain string — a one-line change.
|
||||
|
||||
2. **Puter CDN load:** Load `https://js.puter.com/v2/` dynamically via `loadScript()` helper only when the user clicks "Continue with Puter" — not on wizard open. This avoids loading a large third-party script unnecessarily.
|
||||
|
||||
3. **Google risk warning timing gate:** The "Sign in with Google" button must remain disabled for 3 seconds after the Google card is selected to prevent accidental clicks. Use a `useEffect` with a `setTimeout` keyed to the selected card state.
|
||||
|
||||
4. **Provider card pre-detection:** Run `agentsApi.probeAdapter()` for `claude_local`, `hermes_local`, and `openclaw_gateway` when the wizard opens (parallel, fire-and-forget). Detected tools surface as a `text-xs text-primary` badge inside the card ("Hermes detected"). Non-detected tools show nothing extra.
|
||||
|
||||
5. **Skip-all valid state:** When the user skips Step 3 entirely, the wizard must still complete Step 4 (root directory) and create at least one working agent. The existing `defaultAdapter` probe result handles this — if hermes_local was detected, it's used; otherwise claude_local.
|
||||
|
||||
6. **No new shadcn components needed:** All required UI elements are covered by the existing component inventory (button, input, label, skeleton). Do not install additional shadcn components for this phase.
|
||||
|
||||
---
|
||||
|
||||
## Checker Sign-Off
|
||||
|
||||
- [ ] Dimension 1 Copywriting: PASS
|
||||
- [ ] Dimension 2 Visuals: PASS
|
||||
- [ ] Dimension 3 Color: PASS
|
||||
- [ ] Dimension 4 Typography: PASS
|
||||
- [ ] Dimension 5 Spacing: PASS
|
||||
- [ ] Dimension 6 Registry Safety: PASS
|
||||
|
||||
**Approval:** pending
|
||||
Loading…
Add table
Reference in a new issue