From ea682fdecd5ff3f777def1465483b9aeb1bab21b Mon Sep 17 00:00:00 2001 From: curo1305 Date: Thu, 18 Jun 2026 22:16:22 +0200 Subject: [PATCH] docs(phase-12): add UI design contract for cloud-resource-foundation Co-Authored-By: Claude Sonnet 4.6 --- .../12-UI-SPEC.md | 264 ++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 .planning/phases/12-cloud-resource-foundation/12-UI-SPEC.md diff --git a/.planning/phases/12-cloud-resource-foundation/12-UI-SPEC.md b/.planning/phases/12-cloud-resource-foundation/12-UI-SPEC.md new file mode 100644 index 0000000..76f243a --- /dev/null +++ b/.planning/phases/12-cloud-resource-foundation/12-UI-SPEC.md @@ -0,0 +1,264 @@ +--- +phase: 12 +slug: cloud-resource-foundation +status: draft +shadcn_initialized: false +preset: none +created: 2026-06-18 +--- + +# Phase 12 — UI Design Contract + +> Visual and interaction contract for Phase 12: cloud-resource-foundation. +> Generated by gsd-ui-researcher, verified by gsd-ui-checker. + +--- + +## Design System + +| Property | Value | +|----------|-------| +| Tool | none — manual Tailwind CSS | +| Preset | not applicable | +| Component library | none (Vue 3 custom components) | +| Icon library | AppIcon.vue (Heroicons-based, internal wrapper) | +| Font | system-ui / Inter (Tailwind default sans stack) | + +No `components.json` was found. The project uses manual Tailwind CSS v3 with `@tailwindcss/forms`. No shadcn initialization is needed or applicable. All new UI must match the existing `StorageBrowser.vue` component patterns. + +--- + +## Spacing Scale + +Declared values (must be multiples of 4): + +| Token | Value | Usage | +|-------|-------|-------| +| xs | 4px | Icon gaps, inline badge padding (`gap-1`, `px-1`) | +| sm | 8px | Compact element spacing, toolbar icon buttons (`p-1.5`, `gap-2`) | +| md | 16px | Default element spacing, row padding (`px-4`) | +| lg | 24px | Section padding, horizontal gutters (`px-6`) | +| xl | 32px | Layout gaps | +| 2xl | 48px | Major section breaks | +| 3xl | 64px | Page-level spacing | + +Exceptions: +- Touch target minimum: 36×36px (`min-w-[36px] min-h-[36px]`) for row action buttons on mobile — matches existing `StorageBrowser.vue` pattern. +- Sync indicator: inline next to breadcrumb or toolbar, 20×20px icon (`w-5 h-5`), no extra surrounding padding. + +--- + +## Typography + +| Role | Size | Weight | Line Height | +|------|------|--------|-------------| +| Body | 14px (`text-sm`) | 400 regular | 1.5 | +| Label / metadata | 12px (`text-xs`) | 600 semibold (`font-semibold`) | 1.4 | +| Row primary name | 14px (`text-sm`) | 500 medium (`font-medium`) | 1.5 | +| Column header | 12px (`text-xs`) | 600 semibold, `uppercase tracking-wider` | 1.4 | + +Source: extracted from `StorageBrowser.vue` — do not deviate without updating this contract. + +--- + +## Color + +| Role | Tailwind Token | Usage | +|------|----------------|-------| +| Dominant (60%) | `white` / `bg-white` | Page background, sticky toolbar, row base | +| Secondary (30%) | `gray-50` / `gray-100` | List header row, alternating hover state, sidebar | +| Accent (10%) | `indigo-500` / `indigo-600` | See reserved list below | +| Warning | `amber-400` / `amber-500` | Folder icons, new-folder input border | +| Destructive | `red-500` / `red-50` | Delete action hover, error text | + +**Accent (`indigo`) reserved exclusively for:** +- Primary action buttons (e.g., "Connect account", "Browse") +- Focus rings (`focus-visible:ring-indigo-500`) on all interactive elements +- Active/selected navigation items +- Inline text links and "Clear search" calls-to-action +- Connection root icon in breadcrumb bar + +**Do NOT use indigo for:** +- Disabled/unsupported action controls (use `gray-400` text on `gray-100` background) +- Temporary-failure warning state (use `amber-600` text on `amber-50` background) +- Metadata labels or column headers + +### New semantic colors for Phase 12 + +| Semantic role | Tailwind token | Applied to | +|---------------|----------------|------------| +| Unsupported (permanent) | `text-gray-400 bg-gray-100` | Disabled action buttons for structurally unsupported operations | +| Temporarily blocked | `text-amber-600 bg-amber-50 border-amber-200` | Disabled action buttons for recoverable failures (scope, auth, offline) | +| Refreshing | `text-indigo-400` (animated) | Breadcrumb sync spinner | +| Up to date | `text-green-500` | Breadcrumb sync indicator after successful refresh | +| Connection warning | `text-amber-500` | Breadcrumb sync indicator on refresh failure | + +Source: D-09 from CONTEXT.md — grey = structurally unsupported; amber/warning = temporarily blocked. + +--- + +## Component Inventory + +These components are extended or introduced in Phase 12. All must follow existing architecture rules: views are thin data providers; smart components receive props and emit actions. + +### Extended: `StorageBrowser.vue` + +**New props (data-driven):** + +| Prop | Type | Description | +|------|------|-------------| +| `capabilities` | `Record` | Map of action name to `{ state: 'supported' \| 'unsupported' \| 'temporarily_unavailable', message: string, reasonCode: string }` | +| `folderFreshness` | `'fresh' \| 'refreshing' \| 'warning'` | Current sync state of the displayed folder | +| `lastRefreshedAt` | `string \| null` | ISO timestamp for tooltip on sync indicator | +| `connectionRoot` | `{ id: string, displayName: string, providerType: string }` | Identity of the current connection root | +| `byteAvailability` | `Record` | Per-item byte state keyed by DocuVault item UUID | + +**Existing `mode` prop behavior change:** replace `mode === 'local'` action-hiding with capability rendering. Local mode supplies a full-supported capability set; cloud mode supplies provider-normalized capabilities. One rendering path serves both. + +**New emitted events:** + +| Event | Payload | Description | +|-------|---------|-------------| +| `capability-explain` | `{ actionKey: string, message: string }` | User tapped/focused a disabled control on touch | + +### Extended: `BreadcrumbBar.vue` + +Adds a sync state indicator immediately after the last breadcrumb segment: +- Refreshing: `AppSpinner` sized 16px (`w-4 h-4`) in `text-indigo-400` +- Up to date: checkmark icon 16px in `text-green-500`, fades out after 3 s +- Connection warning: warning triangle icon 16px in `text-amber-500`, persists + +Tooltip on the indicator (desktop hover, touch tap): `"Last updated [relative time]"` or `"Refresh failed — retrying"`. + +The breadcrumb root segment shows the connection display name and a small provider/cloud icon (16px) before it. No separate `Cloud` prefix segment. + +### New: Disabled action button pattern + +Unsupported and temporarily-blocked actions render as `