Files
kite/.planning/milestones/v0.2-phases/08-stack-upgrade-backend-decomposition/08-UI-SPEC.md
T
curo1305andClaude Sonnet 4.6 123ae5b29b chore: archive v0.2 phase directories to milestones/v0.2-phases/
Moves phases 08–11 execution artifacts from .planning/phases/ to
.planning/milestones/v0.2-phases/ to keep .planning/phases/ clean
for the next milestone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:34:52 +02:00

8.7 KiB
Raw Blame History

phase, slug, status, shadcn_initialized, preset, created, reviewed_at
phase slug status shadcn_initialized preset created reviewed_at
8 stack-upgrade-backend-decomposition approved false none 2026-06-07 2026-06-07

Phase 8 — UI Design Contract

Visual and interaction contract for Phase 8: Stack Upgrade & Backend Decomposition. Generated by gsd-ui-researcher. Verified by gsd-ui-checker.

Scope Note

Phase 8 is a refactoring phase. The backend router decomposition, frontend API client decomposition, and dependency bumps are invisible to users. The ONLY user-facing UI surface in this phase is:

  1. sessions-revoked notificationSettingsAccountTab.vue and TotpEnrollment.vue already display inline session-revoked feedback using local ref state. Phase 8 (Wave 1 — Phase 7.1 absorbed) replaces that local state with a call to toastStore.show(...).
  2. useToastStore stub — a new Pinia store with a defined show() API contract that Phase 10 will implement fully. The stub must not render anything; it only defines the call contract so Phase 7.1 call sites and Phase 10 implementation are aligned.

All other design contract sections (spacing, typography, color) document the existing design system inherited by Phase 8. No new visual patterns are introduced.


Design System

Property Value
Tool none — Tailwind CSS utility classes only
Preset not applicable
Component library none (hand-rolled Vue 3 components)
Icon library Heroicons — inline SVG paths (stroke="currentColor", stroke-width="1.5" or "2")
Font system-ui / browser default (no custom font loaded)

Source: frontend/tailwind.config.js (no plugins, no theme extensions), App.vue, existing component audit.


Spacing Scale

Declared values (must be multiples of 4):

Token Value Usage
xs 4px Icon gaps (gap-1, gap-1.5), badge inner padding
sm 8px Compact element spacing (gap-2, mb-1, py-2)
md 16px Default element spacing (space-y-4, gap-4, px-3 py-3 inputs)
lg 24px Section padding (p-6), section gaps (space-y-6)
xl 32px Layout gaps (sidebar + main content separation)
2xl 48px Not actively used in Phase 8 scope
3xl 64px Not actively used in Phase 8 scope

Exceptions: none for Phase 8 scope.

Source: SettingsAccountTab.vue (p-6, space-y-6, space-y-4, gap-3), TotpEnrollment.vue (space-y-4, gap-2, px-6 py-2.5).


Typography

Role Size Weight Line Height
Body 14px (text-sm) 400 (regular) 1.5
Label / caption 12px (text-xs) 400 (regular) 1.5
Section heading 14px (text-sm) 600 (font-semibold) 1.2
Form label 14px (text-sm) 600 (font-semibold) 1.2

Note: Phase 8 introduces no new typography. The system uses exactly 2 sizes (14px, 12px) and exactly 2 weights (400, 600) for the settings/auth component surface touched in Wave 1.

Source: SettingsAccountTab.vue (text-sm font-semibold text-gray-800 for headings, text-sm text-gray-600/700 for body, text-xs text-red-600 for error captions).


Color

Role Value Usage
Dominant (60%) #ffffff / bg-white Page background, card surfaces
Secondary (30%) #f9fafb / bg-gray-50 Input backgrounds, code blocks, secondary surfaces
Accent (10%) #4f46e5 / bg-indigo-600 Primary action buttons, focus rings (focus:ring-indigo-500)
Success semantic #16a34a / text-green-600, border-green-200 Session-revoked notification, success confirmations
Destructive #dc2626 / text-red-600, border-red-300 Destructive action buttons ("Disable 2FA", "Sign out all devices"), error states

Accent (indigo-600) reserved for:

  • Primary submit buttons (bg-indigo-600 hover:bg-indigo-700)
  • Input focus rings (focus:ring-indigo-500 focus:border-indigo-500)
  • Role badge for admin users (bg-indigo-100 text-indigo-700)

Source: SettingsAccountTab.vue, TotpEnrollment.vue — exhaustive class audit.


useToastStore API Contract

This is the primary design deliverable for Phase 8 (Wave 1). The stub Pinia store must define and export exactly this show() signature. Phase 10 will implement the rendering.

Store location

frontend/src/stores/toast.js

show() method signature

toastStore.show(message, type = 'success', duration = 4000)
Parameter Type Values Default Notes
message string Any non-empty string required Plain text only — no HTML
type string 'success' | 'error' | 'info' 'success' Controls icon and border color in Phase 10
duration number Milliseconds until auto-dismiss 4000 0 = persist until manually dismissed (Phase 10 contract)

Stub implementation contract

The stub MUST:

  • Export useToastStore as a named export from stores/toast.js
  • Expose show(message, type, duration) as a callable method
  • NOT throw, NOT warn, NOT render anything — silently no-op in Phase 8

The stub MUST NOT:

  • Accept an object argument shape (e.g. show({ message, type })) — positional parameters only, for simplicity
  • Render a DOM element or inject CSS
  • Import or depend on any component

Phase 10 rendering contract (locked now to align implementor)

When Phase 10 implements the full store, it MUST honor the same show() signature without modification to any Phase 8 call site. The rendering target is a fixed-positioned stack at top-4 right-4 z-50 (matching the existing inline toast placement in SettingsAccountTab.vue). Auto-dismiss fires after duration ms. Manual dismiss on click. Toasts stack vertically with gap-2 between items. No interaction blocking.


Sessions-Revoked Notification — Interaction Contract

Current state (before Phase 8 Wave 1)

Both SettingsAccountTab.vue and TotpEnrollment.vue implement sessions-revoked feedback with identical local state: const sessionRevokedToast = ref(false) + setTimeout(..., 5000).

Target state (after Phase 8 Wave 1)

The local sessionRevokedToast ref and setTimeout are removed from both components. The API response handler calls toastStore.show(...) instead.

Trigger conditions

Component Trigger Call
SettingsAccountTab.vuechangePassword() data.sessions_revoked > 0 toastStore.show('Other sessions have been terminated.', 'success')
SettingsAccountTab.vuedisableTotp() data.sessions_revoked > 0 toastStore.show('Other sessions have been terminated.', 'success')
TotpEnrollment.vueconfirmEnrollment() data.sessions_revoked > 0 toastStore.show('Other sessions have been terminated.', 'success')

Message copy (locked)

'Other sessions have been terminated.'

This exact string is used in all three call sites. It matches the copy already displayed by the existing inline implementation (confirmed in both component files).

Notification visual spec (Phase 10 will render; locked here for alignment)

Property Value
Position Fixed, top-4 right-4, z-50
Background bg-white
Border border border-green-200
Border radius rounded-xl
Shadow shadow-lg
Padding px-5 py-4
Max width max-w-sm
Icon Heroicons check-circle (outline, w-5 h-5 text-green-500)
Text text-sm font-semibold text-gray-900
Dismiss button text-gray-400 hover:text-gray-600, Heroicons x-mark w-4 h-4
Auto-dismiss After 4000ms (using duration param default)

Source: existing inline implementation in SettingsAccountTab.vue lines 525, adapted to use the duration param default of 4000ms instead of the current hardcoded 5000ms.


Copywriting Contract

Element Copy
Sessions-revoked notification Other sessions have been terminated.
Toast dismiss aria-label Dismiss notification

No other new user-facing copy is introduced in Phase 8. All other interactions (backend decomposition, client.js refactor, dependency bumps) are invisible to the user.


Registry Safety

Registry Blocks Used Safety Gate
shadcn official none — not initialized not applicable
Third-party none not applicable

No third-party component registries are used. No new UI components are added beyond the useToastStore stub (a store, not a component).


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: approved 2026-06-07