Skip to content

Forms Module UI Specification

Overview

A clinical research EDC-style Forms module with a calm, clinical, high-trust aesthetic. This specification serves as both the Forms module design and a reference pattern for the broader Metricis portal UI refactoring.


1. Design Tokens

Color Palette

/* Primary palette */
--color-primary: #2563eb;        /* Blue 600 - primary actions */
--color-primary-hover: #1d4ed8;  /* Blue 700 - hover states */
--color-primary-light: #dbeafe; /* Blue 100 - subtle backgrounds */
--color-primary-ring: rgba(37, 99, 235, 0.3); /* Focus ring */

/* Neutral palette */
--color-bg-page: #f8fafc;        /* Slate 50 - page background */
--color-bg-surface: #ffffff;     /* White - cards, panels */
--color-bg-muted: #f1f5f9;       /* Slate 100 - subtle backgrounds */
--color-bg-hover: #f8fafc;       /* Slate 50 - hover states */

/* Border colors */
--color-border: #e2e8f0;         /* Slate 200 - default borders */
--color-border-strong: #cbd5e1;  /* Slate 300 - emphasis borders */

/* Text colors */
--color-text-primary: #0f172a;   /* Slate 900 - headings */
--color-text-secondary: #475569; /* Slate 600 - body text */
--color-text-muted: #94a3b8;     /* Slate 400 - metadata */
--color-text-inverse: #ffffff;   /* White - on dark backgrounds */

/* Status colors */
--color-success: #22c55e;        /* Green 500 */
--color-success-light: #dcfce7;  /* Green 100 */
--color-warning: #f59e0b;        /* Amber 500 */
--color-warning-light: #fef3c7;  /* Amber 100 */
--color-danger: #ef4444;         /* Red 500 */
--color-danger-light: #fee2e2;   /* Red 100 */

/* Sidebar (dark) */
--color-sidebar-bg: #1e293b;     /* Slate 800 */
--color-sidebar-text: #94a3b8;   /* Slate 400 */
--color-sidebar-text-active: #ffffff;
--color-sidebar-hover: #334155;  /* Slate 700 */
--color-sidebar-accent: #8b5cf6; /* Violet 500 */

/* Chart colors */
--color-chart-1: #6366f1;        /* Indigo 500 */
--color-chart-2: #10b981;        /* Emerald 500 */
--color-chart-3: #f59e0b;        /* Amber 500 */
--color-chart-4: #ef4444;        /* Red 500 */

Typography Scale

/* Font family */
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

/* Font sizes */
--font-size-xs: 0.75rem;    /* 12px - metadata, badges */
--font-size-sm: 0.875rem;   /* 14px - body small, labels */
--font-size-base: 1rem;     /* 16px - body default */
--font-size-lg: 1.125rem;   /* 18px - section headers */
--font-size-xl: 1.25rem;    /* 20px - card titles */
--font-size-2xl: 1.5rem;    /* 24px - page subtitles */
--font-size-3xl: 1.875rem;  /* 30px - page titles */

/* Font weights */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;

/* Line heights */
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.625;

Spacing Scale (8px grid)

--space-0: 0;
--space-1: 0.25rem;   /* 4px */
--space-2: 0.5rem;    /* 8px */
--space-3: 0.75rem;   /* 12px */
--space-4: 1rem;      /* 16px */
--space-5: 1.25rem;   /* 20px */
--space-6: 1.5rem;    /* 24px */
--space-8: 2rem;      /* 32px */
--space-10: 2.5rem;   /* 40px */
--space-12: 3rem;     /* 48px */
--space-16: 4rem;     /* 64px */

Border Radius

--radius-sm: 4px;     /* Small elements, badges */
--radius-md: 6px;     /* Buttons, inputs */
--radius-lg: 8px;     /* Cards, panels */
--radius-xl: 12px;    /* Large containers */
--radius-full: 9999px; /* Pills, avatars */

Shadows

--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);

Transitions

--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;

Z-Index Scale

--z-base: 0;
--z-dropdown: 50;
--z-sticky: 100;
--z-overlay: 200;
--z-modal: 300;
--z-toast: 400;

2. Layout Specifications

Responsive Breakpoints

Breakpoint Width Behavior
sm 640px Mobile - single column
md 768px Tablet - sidebar collapses to icon rail
lg 1024px Desktop - 2-3 column layouts
xl 1280px Large desktop - full 3-column
2xl 1536px Extra large - max content width

3-Column Layout

┌─────────────────────────────────────────────────────────────────┐
│ Sidebar (260px) │ List Pane (320px)   │ Detail Pane (flex-1)   │
│                 │                      │                        │
│ ┌─────────────┐ │ ┌──────────────────┐ │ ┌────────────────────┐ │
│ │ Logo        │ │ │ Breadcrumb       │ │ │ Header + Actions   │ │
│ ├─────────────┤ │ ├──────────────────┤ │ ├────────────────────┤ │
│ │ Nav Section │ │ │ Search + Filter  │ │ │                    │ │
│ │ - Item      │ │ ├──────────────────┤ │ │ Content Area       │ │
│ │ - Item      │ │ │                  │ │ │ (max-w-3xl)        │ │
│ │ - Item      │ │ │ List Items       │ │ │                    │ │
│ ├─────────────┤ │ │ - Selected ▌     │ │ │ Form sections,     │ │
│ │ Study       │ │ │ - Item           │ │ │ fields, etc.       │ │
│ │ Selector    │ │ │ - Item           │ │ │                    │ │
│ ├─────────────┤ │ │                  │ │ │                    │ │
│ │ Section 2   │ │ │                  │ │ │                    │ │
│ │ - Item      │ │ │                  │ │ │                    │ │
│ ├─────────────┤ │ │                  │ │ │                    │ │
│ │ User Menu   │ │ │                  │ │ │                    │ │
│ └─────────────┘ │ └──────────────────┘ │ └────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

Column Specifications

Column Width Behavior
Sidebar 260px fixed Collapses to 64px icon rail < lg
List Pane 320px fixed Collapsible on lg+, full screen < md
Detail Pane flex-1 Min 480px, content max-w-3xl centered

3. Component Specifications

StatusPill

States: draft | published | locked | archived
Size: sm (h-5) | md (h-6)
Style: Rounded-full, subtle background, medium text
Status Background Text Border
draft bg-slate-100 text-slate-600 -
published bg-green-50 text-green-700 -
locked bg-amber-50 text-amber-700 -
archived bg-slate-50 text-slate-500 border-slate-200

ListItem

Height: 56px minimum
Padding: px-4 py-3
Selected: left-2 border-l-2 border-primary bg-primary-light/30
Hover: bg-slate-50

Structure:

┌─────────────────────────────────────────┐
│ ▌ [Icon] Title                    [···] │
│         Subtitle / metadata             │
└─────────────────────────────────────────┘

FormSection

Background: white
Border: 1px solid border
Border-radius: radius-lg
Padding: p-6
Gap between sections: gap-6

ConditionalBlock

Border: 1px dashed border-strong
Background: bg-slate-50/50
Padding: p-4
Condition chip: bg-primary-light text-primary text-xs rounded-md px-2 py-1

Input States

State Border Ring Background
Default border - white
Hover border-strong - white
Focus border-primary ring-2 ring-primary/30 white
Error border-danger ring-2 ring-danger/30 white
Disabled border - bg-muted

4. Route Structure

/forms                              # Forms module root
/forms/:studyId                     # Study forms list
/forms/:studyId/events              # Events list (visits/timepoints)
/forms/:studyId/events/:eventId     # Event detail with forms list
/forms/:studyId/events/:eventId/forms/:formId   # Form detail/editor
/forms/:studyId/library             # Form templates library
/forms/:studyId/settings            # Forms module settings

URL Examples

/forms/study-123/events/baseline/forms/demographics
/forms/study-123/events/week-4/forms/adverse-events
/forms/study-123/library

5. State Model

Forms Module State

interface FormsModuleState {
  // Navigation
  selectedStudyId: string | null;
  selectedEventId: string | null;
  selectedFormId: string | null;

  // UI State
  sidebarCollapsed: boolean;
  listPaneCollapsed: boolean;

  // Data
  events: Event[];
  forms: Form[];
  selectedForm: FormDetail | null;

  // Filters
  searchQuery: string;
  statusFilter: FormStatus[];

  // Editor State
  isDirty: boolean;
  validationErrors: ValidationError[];
}

interface Event {
  id: string;
  code: string;
  name: string;
  targetDay: number;
  formCount: number;
}

interface Form {
  id: string;
  code: string;
  name: string;
  subtitle: string;
  status: 'draft' | 'published' | 'locked' | 'archived';
  questionCount: number;
  lastModified: string;
  languages: string[];
}

interface FormDetail extends Form {
  sections: FormSection[];
  metadata: FormMetadata;
}

interface FormSection {
  id: string;
  title: string;
  description?: string;
  fields: FormField[];
  condition?: ConditionalLogic;
}

interface FormField {
  id: string;
  type: 'text' | 'number' | 'date' | 'select' | 'radio' | 'checkbox' | 'textarea';
  label: string;
  helpText?: string;
  required: boolean;
  validation?: FieldValidation;
  condition?: ConditionalLogic;
  options?: FieldOption[]; // For select/radio/checkbox
}

6. Accessibility Requirements

Keyboard Navigation

Key Action
Tab Move between focusable elements
Shift+Tab Move backwards
Enter/Space Activate buttons, select items
Arrow Up/Down Navigate list items, menu items
Escape Close modals, dropdowns, cancel
Cmd/Ctrl+S Save form (when editing)

ARIA Requirements

  • Sidebar: nav with aria-label="Main navigation"
  • List pane: role="listbox" with aria-activedescendant
  • Selected items: aria-selected="true"
  • Status pills: Include aria-label for screen readers
  • Form fields: Proper label association, aria-describedby for help text
  • Error states: aria-invalid="true", aria-errormessage

Focus Management

  • Visible focus ring on all interactive elements
  • Focus trap in modals and dropdowns
  • Return focus to trigger element on close
  • Skip link for main content

7. Responsive Behavior

Mobile (< 768px)

  • Sidebar: Hidden, accessible via hamburger menu (drawer)
  • List pane: Full screen view
  • Detail pane: Full screen view (navigated to via route)
  • Navigation: Stack views, use back button

Tablet (768px - 1024px)

  • Sidebar: Collapsed to 64px icon rail
  • List pane: 280px width, collapsible
  • Detail pane: Remaining width
  • Touch: Larger hit targets (min 44px)

Desktop (> 1024px)

  • Full 3-column layout
  • Sidebar: 260px
  • List pane: 320px (collapsible)
  • Detail pane: flex-1

8. Animation & Transitions

Micro-interactions

Element Property Duration Easing
Buttons background, transform 150ms ease
List selection background, border 150ms ease
Dropdown open opacity, transform 200ms ease-out
Sidebar collapse width 200ms ease
Toast enter transform, opacity 300ms ease-out
Toast exit opacity 200ms ease-in

Loading States

  • Skeleton loaders for content areas
  • Subtle pulse animation
  • Maintain layout stability (no layout shift)

9. Component Inventory

Required Components (shadcn/ui + custom)

  • [ ] SidebarNav
  • [ ] SidebarSection
  • [ ] SidebarLink
  • [ ] SidebarUserMenu
  • [ ] Breadcrumbs
  • [ ] IconRail (collapsed sidebar)

List Pane

  • [ ] SearchInput
  • [ ] FilterButton + Popover
  • [ ] ListItem
  • [ ] ListItemSkeleton
  • [ ] EmptyState

Detail Pane

  • [ ] DetailHeader
  • [ ] StatusPill
  • [ ] LanguageSelector
  • [ ] OptionsMenu

Form Builder

  • [ ] FormSection
  • [ ] ConditionalBlock
  • [ ] FieldRow
  • [ ] TextInput
  • [ ] NumberInput
  • [ ] DateInput
  • [ ] Select
  • [ ] RadioGroup
  • [ ] CheckboxGroup
  • [ ] Textarea
  • [ ] InlineHelp

Feedback

  • [ ] Toast
  • [ ] LoadingSkeleton
  • [ ] ErrorState
  • [ ] ConfirmDialog

10. Implementation Priority

Phase 1: Foundation

  1. Design tokens in Tailwind config
  2. Base layout components (AppShell, Sidebar)
  3. Core UI primitives (Button, Input, Select)

Phase 2: Navigation

  1. SidebarNav with collapsed state
  2. Breadcrumbs
  3. List pane with search/filter

Phase 3: Forms Module

  1. Events list view
  2. Forms list within event
  3. Form detail view
  4. Form sections and fields

Phase 4: Interactivity

  1. Form editing capabilities
  2. Conditional logic UI
  3. Validation and error states
  4. Save/publish workflow

Phase 5: Polish

  1. Loading states and skeletons
  2. Animations and transitions
  3. Keyboard navigation refinement
  4. Accessibility audit