Files

7.9 KiB

phase, slug, status, shadcn_initialized, preset, created
phase slug status shadcn_initialized preset created
32 setup-sharing-system approved false none 2026-04-13

Phase 32 — UI Design Contract

Visual and interaction contract for the Setup Sharing System. Covers share button, share modal, visibility picker, and shared setup viewer.


Design System

Property Value
Tool none
Preset not applicable
Component library none (custom Tailwind components)
Icon library Lucide via LucideIcon component from lib/iconData
Font System font stack (inherited from existing app)

Spacing Scale

Declared values (must be multiples of 4):

Token Value Usage
xs 4px Icon gaps, inline padding
sm 8px Compact element spacing, gap-2
md 16px Default element spacing, gap-4, p-4
lg 24px Section padding, p-6
xl 32px Layout gaps
2xl 48px Major section breaks
3xl 64px Page-level spacing

Exceptions: none


Typography

Role Size Weight Line Height
Body 14px (text-sm) 400 1.5
Label 14px (text-sm) 500 (font-medium) 1.5
Heading 16px (text-base) 600 (font-semibold) 1.5
Display 20px (text-xl) 600 (font-semibold) 1.5

Color

Role Value Usage
Dominant (60%) gray-50 (#f9fafb) Page background, surfaces
Secondary (30%) white (#ffffff) Cards, modals, panels
Accent (10%) gray-700 (#374151) Primary action buttons (Add Items, share CTA)
Destructive red-600 (#dc2626) Revoke link, delete actions

Accent reserved for: primary action buttons only (Add Items, Create Link)

Visibility State Colors

State Icon Text Color Background
Private lock gray-500 gray-50
Link link blue-600 blue-50
Public globe green-700 green-50

Component Specifications

Share Button (replaces globe toggle)

Desktop variant:

  • Position: same location as current globe toggle button in setup detail header bar
  • Layout: inline-flex items-center gap-1.5 px-3 py-2
  • Text: "Share" (always visible regardless of visibility state)
  • Icon: varies by visibility state (see color table above), size 16px
  • Background/text color: matches visibility state from color table
  • Rounded: rounded-lg
  • Hover: lighten background one shade

Mobile variant:

  • Layout: inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2
  • Icon only (no text), same icon/color logic as desktop
  • aria-label: "Share settings"
  • Rounded: rounded-lg

Share Modal

Overlay: fixed inset-0 z-50 bg-black/50 flex items-center justify-center

Modal container:

  • Desktop: bg-white rounded-xl shadow-lg p-6 max-w-md mx-4 w-full
  • Max height: max-h-[80vh] overflow-y-auto
  • Matches existing modal pattern (see ConfirmDialog.tsx, CreateThreadModal.tsx)

Header:

  • Title: "Share Setup" (text-lg font-semibold text-gray-900)
  • Close button: top-right, LucideIcon name="x" size={20}, text-gray-400 hover:text-gray-600
  • Divider: border-b border-gray-100 pb-4 mb-4

Visibility Picker Section:

  • Label: "Visibility" (text-sm font-medium text-gray-700 mb-2)
  • Three radio-style buttons in a vertical stack, gap-2
  • Each option: flex items-center gap-3 p-3 rounded-lg border cursor-pointer transition-colors
    • Unselected: border-gray-200 hover:border-gray-300
    • Selected: border-{state-color}-200 bg-{state-color}-50
  • Option layout:
    • Icon (size 20, state color)
    • Label (text-sm font-medium text-gray-900): "Private" / "Link sharing" / "Public"
    • Description (text-xs text-gray-500): "Only you can access" / "Anyone with the link" / "Visible on your profile"

Create Link Section (visible when visibility is link or public):

  • Divider: border-t border-gray-100 pt-4 mt-4
  • Section label: "Share Links" (text-sm font-medium text-gray-700 mb-3)
  • Create row: flex items-center gap-2
    • Expiration dropdown: select element styled with px-3 py-2 text-sm border border-gray-200 rounded-lg bg-white
      • Options: "7 days", "14 days" (default), "30 days", "No expiration"
    • Create button: px-4 py-2 bg-gray-700 hover:bg-gray-800 text-white text-sm font-medium rounded-lg
      • Text: "Create Link"

Active Links List:

  • Each link: flex items-center gap-2 p-3 bg-gray-50 rounded-lg mb-2
    • URL display: text-sm text-gray-600 truncate flex-1 showing /s/{token-prefix}...
    • Expiration badge: text-xs text-gray-400 showing "Expires {date}" or "No expiration"
    • Copy button: p-1.5 text-gray-400 hover:text-gray-600 rounded with LucideIcon name="copy" size={16}
      • After copy: icon changes to check with text-green-500 for 2 seconds
    • Revoke button: p-1.5 text-gray-400 hover:text-red-500 rounded with LucideIcon name="x" size={16}

Empty state (no links yet):

  • Text: "No share links yet" (text-sm text-gray-400 text-center py-4)

Deactivation warning (when switching to private with active links):

  • Inline warning below visibility picker: flex items-start gap-2 p-3 bg-amber-50 border border-amber-200 rounded-lg mt-2
    • Icon: LucideIcon name="alert-triangle" size={16} in text-amber-500
    • Text: "Switching to private will deactivate all share links. They can be reactivated by switching back." (text-sm text-amber-700)

Shared Setup Viewer

Route: /setups/:setupId?share={token}

Shared banner:

  • Position: top of setup detail page, before header
  • Layout: flex items-center gap-2 px-4 py-2 bg-blue-50 border-b border-blue-100
  • Icon: LucideIcon name="link" size={16} in text-blue-500
  • Text: "Shared setup" (text-sm text-blue-700)
  • Appears only when viewing via share token

Content: Identical to public setup view (read-only item list with weight summary, no action buttons)


Copywriting Contract

Element Copy
Modal title Share Setup
Visibility: Private label Private
Visibility: Private description Only you can access
Visibility: Link label Link sharing
Visibility: Link description Anyone with the link
Visibility: Public label Public
Visibility: Public description Visible on your profile
Create link CTA Create Link
Empty links state No share links yet
Deactivation warning Switching to private will deactivate all share links. They can be reactivated by switching back.
Copy success toast Link copied
Revoke confirmation Revoke this share link?
Shared banner text Shared setup
Expired link error This share link has expired
Invalid link error This share link is no longer valid

Registry Safety

Registry Blocks Used Safety Gate
No external registries N/A N/A

All components are custom Tailwind — no shadcn or third-party UI registry blocks.


Responsive Behavior

Breakpoint Share Button Share Modal
Mobile (<768px) Icon only, 44x44px touch target Full width with mx-4 margin
Desktop (>=768px) Icon + "Share" text max-w-md centered

Interaction States

Interaction Behavior
Open modal Click share button, modal appears with current visibility pre-selected
Change visibility Immediate API call on selection, optimistic update
Create link API call, new link appears in list, auto-copy to clipboard
Copy link Copy full URL to clipboard, show check icon for 2s
Revoke link Confirmation prompt (reuse ConfirmDialog pattern), then remove from list
Close modal Click X, click overlay, or press Escape

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-04-13