phase, slug, status, shadcn_initialized, preset, created
| phase |
slug |
status |
shadcn_initialized |
preset |
created |
| 31 |
mobile-polish |
draft |
false |
none |
2026-04-12 |
Phase 31 — UI Design Contract
Visual and interaction contract for mobile icon-based action buttons. Generated by gsd-ui-researcher, verified by gsd-ui-checker.
Design System
| Property |
Value |
| Tool |
none |
| Preset |
not applicable |
| Component library |
none (plain Tailwind) |
| Icon library |
lucide-react via LucideIcon component |
| Font |
System default (Tailwind default stack) |
Spacing Scale
Declared values (must be multiples of 4):
| Token |
Value |
Usage |
| xs |
4px |
Icon gaps, inline padding |
| sm |
8px |
Compact element spacing, icon button padding |
| md |
16px |
Default element spacing |
| lg |
24px |
Section padding |
| xl |
32px |
Layout gaps |
| 2xl |
48px |
Major section breaks |
| 3xl |
64px |
Page-level spacing |
Exceptions: Touch targets minimum 44x44px (11 Tailwind units) for icon-only buttons on mobile
Typography
| Role |
Size |
Weight |
Line Height |
| Body |
14px (text-sm) |
400 |
1.5 |
| Label |
12px (text-xs) |
500 |
1.5 |
| Heading |
24px (text-2xl) |
700 (bold) |
1.2 |
| Display |
20px (text-xl) |
600 (semibold) |
1.2 |
Note: Icon-only buttons have no text labels on mobile. Tooltips (if added) use text-xs (12px).
Color
| Role |
Value |
Usage |
| Dominant (60%) |
white (#ffffff) |
Background, surfaces |
| Secondary (30%) |
gray-50 (#f9fafb) / gray-100 (#f3f4f6) |
Cards, hover states, icon button hover bg |
| Accent (10%) |
gray-700 (#374151) |
Primary action icon buttons (Edit) |
| Destructive |
red-500 (#ef4444) |
Delete/Remove icon buttons only |
Accent reserved for: Edit button (primary action), icon button active/pressed states
Icon Button Color Mapping
| Action |
Icon Color |
Hover BG |
Notes |
| Edit |
gray-700 (white bg variant) |
gray-100 |
Primary action, most prominent |
| Duplicate |
gray-500 |
gray-50 |
Secondary action |
| Delete/Remove |
red-400 |
red-50 |
Destructive — matches existing pattern |
| Pick as Winner |
amber-700 |
amber-100 |
Matches existing candidate resolve pattern |
| Add to Collection |
white (on gray-700 bg) |
gray-800 |
Primary CTA on catalog detail |
| Add to Thread |
gray-700 |
gray-50 |
Secondary CTA on catalog detail |
Copywriting Contract
| Element |
Copy |
| Primary CTA |
n/a (icon-only on mobile, text preserved on desktop) |
| Empty state heading |
n/a (no new empty states in this phase) |
| Empty state body |
n/a |
| Error state |
n/a (no new error states in this phase) |
| Destructive confirmation |
Existing ConfirmDialog patterns unchanged |
Icon-to-Action Mapping (Mobile)
| Action |
Lucide Icon Name |
Size |
aria-label |
| Edit |
pencil |
16px |
"Edit" |
| Delete |
trash-2 |
16px |
"Delete" |
| Remove from Collection |
trash-2 |
16px |
"Remove from Collection" |
| Duplicate |
copy |
16px |
"Duplicate" |
| Pick as Winner |
trophy |
14px |
"Pick as winner" |
| Add to Collection |
plus |
16px |
"Add to Collection" |
| Add to Thread |
message-square-plus |
16px |
"Add to Thread" |
| Add Items (setup) |
plus |
16px |
"Add Items" |
| Toggle Public |
globe |
16px |
"Toggle public" |
| Delete Setup |
trash-2 |
16px |
"Delete Setup" |
Accessibility
- Every icon-only button MUST have
aria-label matching the action text shown on desktop
- Icon buttons use
title attribute matching aria-label for hover tooltip on touch-and-hold
- Minimum touch target: 44x44px (achieved via
min-w-[44px] min-h-[44px] or equivalent padding)
Responsive Breakpoint Contract
| Breakpoint |
Behavior |
Below md: (< 768px) |
Icon-only buttons, no text labels |
md: and above (>= 768px) |
Full text buttons (current behavior, unchanged) |
Implementation pattern:
Registry Safety
| Registry |
Blocks Used |
Safety Gate |
| n/a |
none |
not required |
No shadcn or third-party registries. All components are hand-rolled with Tailwind CSS.
Checker Sign-Off
Approval: pending