Responsive Design
The responsive system has three layers: reference devices for testing, Tailwind breakpoints for CSS, and a JS tier system for component logic.
Reference Devices
These are the specific viewports used for screenshots, manual QA, and design review. Every layout must look correct at these sizes.
| Tier | Width | Height | DPR |
|---|---|---|---|
| Phone | 393px | 852px | 3 |
| Tablet | 820px | 1180px | 2 |
| Laptop | 1280px | 720px | 1.5 |
| Desktop 16:9 | 1920px | 1080px | 1 |
| Desktop 16:10 | 1920px | 1200px | 1 |
Tailwind Breakpoints
These are defined in index.css and used in Tailwind classes (sm:, lg:, 2xl:, etc.).
Device-Tier Breakpoints
Control layout, navigation, and grid structure:
| Breakpoint | CSS min-width | Transition |
|---|---|---|
sm | 640px | Phone → tablet |
lg | 1080px | Tablet → laptop |
2xl | 1536px | Laptop → desktop |
Fine-Grained Breakpoints
Adjustments within a tier:
| Breakpoint | CSS min-width | Usage |
|---|---|---|
md | 768px | Mid-tablet adjustments |
xl | 1280px | Mid-laptop adjustments |
Custom Component Breakpoints
Pixel-specific breakpoints for table and component overflow. Do not modify these without updating the corresponding components:
| Breakpoint | Component |
|---|---|
1235px | FMEvaluationTable layout |
1315px | FMEvaluationTable label display |
1375px | PFM01GeometrySection layout |
1415px | Failure Mode Selection page layout |
1655px | FMEvaluationTable APF/EALL/EAD labels |
1730px | EmbankmentMaterialTable horizontal scrolling |
JS Tier System
Layout.jsx computes a tier value ('phone' | 'tablet' | 'laptop' | 'desktop') from the viewport width and passes it to layout components like TabNavigation. Use the tier system for navigation and layout decisions in JavaScript instead of raw window.innerWidth checks.
| Tier | Viewport | Maps To |
|---|---|---|
phone | < 640px | sm breakpoint |
tablet | 640–1079px | lg breakpoint |
laptop | 1080–1535px | 2xl breakpoint |
desktop | ≥ 1536px | Above 2xl |
Navigation by Tier
| Tier | Navigation Style |
|---|---|
| Phone | Hamburger menu with slide-out drawer (no sidebar) |
| Tablet | Collapsed icon sidebar (56px, always collapsed, no toggle) |
| Laptop/Desktop | Full expandable sidebar (240px, with collapse toggle) |
Common Responsive Patterns
{/* Two-column section layout (dam-information pattern) */}
<PageContainer>
<div className="w-full divide-y divide-slate-200 *:pt-6 *:first:pt-0 *:pb-6 *:last:pb-0">
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
<DamOverviewSection />
<EmbankmentComponentsSection />
</div>
<EmbankmentMaterialsSection />
</div>
</PageContainer>
{/* Form inputs beside diagram (pfm01 pattern) */}
<Section title="Embankment overtopping parameters">
<div className="grid grid-cols-1 items-center gap-4 lg:grid-cols-[45%_1fr]">
<div className="grid grid-cols-2 gap-x-4 gap-y-4">
<InputField label="Embankment Height (ft)" inputVariant="compact" ... />
<InputField label="Downstream Slope (H:V)" inputVariant="compact" ... />
</div>
<OvertoppingProfileDiagram ... />
</div>
</Section>
{/* Table + chart side-by-side (40/60 split) */}
<div className="grid grid-cols-1 gap-6 xl:grid-cols-[40%_60%]">
<div className="min-w-0"><SRPTable /></div>
<div className="h-96 min-w-0"><SRPChart /></div>
</div>
{/* Responsive form grid */}
<FormFieldGroup columns={3}>
<InputField label="Field 1" ... />
<InputField label="Field 2" ... />
<InputField label="Field 3" ... />
</FormFieldGroup>
{/* Two-column with divider (failure-mode-screening pattern) */}
<div className="grid grid-cols-1 gap-8 xl:grid-cols-2 xl:gap-6">
<div className="space-y-6">{/* Column 1 */}</div>
<div className="space-y-6 xl:border-l xl:border-slate-300 xl:pl-6">{/* Column 2 */}</div>
</div>
Key patterns:
- Use
divide-y divide-slate-200with*:pt-6 *:pb-6for vertically stacked sections with dividers - Always add
min-w-0to grid children to prevent content overflow - Use
grid-cols-[45%_1fr]orgrid-cols-[minmax(0,2fr)_minmax(0,3fr)]for flexible asymmetric splits - Use
space-y-2for tight checkbox lists,space-y-6for section spacing
Fluid Typography
Font sizes use clamp() for responsive scaling between 375px and 1920px viewport widths. These are defined in index.css and override Tailwind's defaults — just use standard Tailwind text size classes (text-sm, text-lg, etc.) and the responsive scaling is automatic.