Date: 2025-10-29 Status: Implemented Complexity: 8 story points
Comprehensive responsive enhancement implementing mobile-first design patterns across entire portfolio site with atomic migration strategy. Includes typography component system, button responsive scaling, and design system color enforcement.
- Responsive Typography: Create reusable Typography components with mobile-first responsive scaling
- Button Sizing: Auto-scale button sizes across breakpoints without consumer configuration
- Design System Compliance: Replace arbitrary Tailwind colors with semantic design system tokens
- Visual Hierarchy: Establish clear Display → Heading → Body hierarchy
- Accessibility: Ensure WCAG AA compliance for all color contrast ratios
Mobile-first with md: only
- Base styles = mobile (<768px)
md:prefix = desktop (≥768px)- Rationale: Simplest approach, matches existing codebase patterns
Created: src/components/typography/
For hero/landing headlines only - prominently larger than standard headings.
// Display.astro
level: {
1: 'text-2xl md:text-3xl', // 40px → 48px (hero)
2: 'text-xl md:text-2xl', // 32px → 40px (sub-hero)
}Usage:
<Display level={1} as="h1">Saad Shahd</Display>For page structure - section titles, page headings.
// Heading.astro
level: {
1: 'text-lg md:text-2xl', // 24px → 40px (page titles)
2: 'text-lg md:text-xl', // 24px → 32px (section headings)
3: 'text-base md:text-lg', // 18px → 24px (sub-sections)
}Usage:
<Heading level={1} as="h1">Portfolio</Heading>
<Heading level={2} as="h2">Case Studies</Heading>For content text - paragraphs, descriptions, lists.
// Body.astro
size: {
sm: 'text-sm leading-normal', // 14px (captions, metadata)
base: 'text-base leading-normal', // 18px (standard body)
lg: 'text-lg md:text-xl leading-normal', // 24px → 32px (lead paragraphs)
}Usage:
<Body size="lg" as="p">Lead paragraph text...</Body>
<Body size="base">Standard body content...</Body>
<Body size="sm" as="span">Caption or metadata</Body>Line-height: Standardized to leading-normal (1.5) across all sizes for readability.
| Element | Mobile | Desktop | Notes |
|---|---|---|---|
| Display 1 | 40px (text-2xl) | 48px (text-3xl) | Hero headlines |
| Display 2 | 32px (text-xl) | 40px (text-2xl) | Sub-hero |
| Heading 1 | 24px (text-lg) | 40px (text-2xl) | Page titles |
| Heading 2 | 24px (text-lg) | 32px (text-xl) | Sections |
| Heading 3 | 18px (text-base) | 24px (text-lg) | Sub-sections |
| Body lg | 24px (text-lg) | 32px (text-xl) | Lead text |
| Body base | 18px (text-base) | 18px (text-base) | Standard |
| Body sm | 14px (text-sm) | 14px (text-sm) | Captions |
Hierarchy validation:
- Display 1 (48px) > Heading 1 (40px) ✅ Clear separation
- Heading 1 (40px) > Heading 2 (32px) ✅ 8px difference
- Body lg (32px) < Heading 2 (32px) ✅ Same size but different weight
Auto-scaling strategy: Buttons automatically scale down on mobile without consumer configuration.
// Button.astro
size: {
sm: 'px-3 py-1.5 text-xs md:px-4 md:py-2 md:text-sm rounded-md',
md: 'px-4 py-2 text-sm md:px-5 md:py-2.5 md:text-base rounded-md',
lg: 'px-5 py-2.5 text-sm md:px-7 md:py-3 md:text-base rounded-lg',
}Behavior:
size="sm"→ xs/sm mobile, sm desktopsize="md"→ sm mobile, base desktop (most common)size="lg"→ sm mobile, base desktop (hero CTAs)
No API changes required - consumers keep using <Button size="lg"> prop.
Philosophy: Neutral monochrome with hierarchy through opacity, aligns with Egyptian minimalism.
// Badge.astro
variant: {
skill: 'bg-accent/10 text-accent border border-accent/20',
category: 'bg-accent/15 text-accent border border-accent/30',
status: 'bg-accent/20 text-accent border border-accent/40',
}Hierarchy: 10% (subtle) → 15% (medium) → 20% (strong) background opacity.
Accessibility: text-accent (dark brown) ensures WCAG AA compliance over all background opacities.
Philosophy: Borders should define structure without dominating visually.
// Card.astro
variant: {
'case-study': 'bg-surface border border-accent/20 hover:shadow-xl hover:-translate-y-1 p-0',
'blog': 'bg-surface border border-accent/15 hover:border-secondary/30 p-6',
'minimal': 'bg-surface border border-accent/10 shadow-sm hover:shadow-md p-6',
}Before: Solid border-accent (thick black appearance)
After: Opacity-based borders (minimal contrast, 10-20%)
Before: text-slate-700 (arbitrary Tailwind)
After: text-accent-light (design system token)
src/components/typography/Display.astro- Hero/landing headlinessrc/components/typography/Heading.astro- Page structure headingssrc/components/typography/Body.astro- Content text
Components (4 files):
src/components/Button.astro- Responsive size variantssrc/components/Badge.astro- Monochrome design system colorssrc/components/Card.astro- Minimal border opacitysrc/components/Link.astro- Design system text color
Pages (6 files):
src/pages/index.astro- Hero sectionsrc/pages/portfolio.astro- Case study listsrc/pages/portfolio/statsbomb.astro- Case study detailsrc/pages/about.astro- Bio pagesrc/pages/resume.astro- Professional experiencesrc/pages/contact.astro- Contact information
Page Changes:
- Replaced raw
<h1>/<h2>/<h3>/<p>with Typography components - Updated container padding:
px-6→px-4 md:px-6 - Preserved all animation classes, data attributes, JavaScript hooks
Example transformation:
<!-- Before -->
<h1 class="text-2xl font-bold text-accent mb-12">
Portfolio
</h1>
<p class="text-xl text-neutral mb-16">
Selected case studies...
</p>
<!-- After -->
<Heading level={1} as="h1" class="mb-12">
Portfolio
</Heading>
<Body size="lg" as="p" class="text-neutral mb-16">
Selected case studies...
</Body>Benefits:
- Typography sizing centralized in components
- Responsive behavior automatic
- Design system tokens enforced via CVA
- All Typography components created
- Button responsive sizing implemented
- Design system colors enforced
- All pages migrated atomically
- Container padding responsive
- Badge WCAG AA contrast validated
- Card border contrast minimized
- Display > Heading hierarchy established
- Dev server manual testing (mobile 375px, tablet 768px, desktop 1440px)
- Animation verification (hero stagger, pattern reveals)
- Accessibility audit (keyboard nav, screen reader, contrast)
- ✅ Zero arbitrary Tailwind colors (
text-slate-*,bg-amber-*,text-gray-*) - ✅ All headings use Typography components (Display/Heading)
- ✅ Buttons scale responsively without consumer config
- ✅ Container padding responsive (
px-4 md:px-6) - ✅ Design system compliance enforced via CVA
- ✅ WCAG AA contrast ratios met (Badge text-accent over bg-accent/10-20%)
- ✅ Clear visual hierarchy (Display > Heading > Body)
Reversible: YES (85% confident)
Rollback command:
git revert <commit-hash>Why reversible:
- Pure frontend CSS/markup changes
- No database migrations
- No API contract changes
- Git revert removes all changes atomically
Risk factors:
- Typography components are NEW - consumers might not exist yet (low risk)
- Button size changes affect hero CTAs (visual regression possible)
- CVA for type-safe variants - Prevented typos, ensured consistency
- Atomic migration - One commit eliminated cognitive split across pages
- Monochrome badge system - Aligned with Egyptian minimalism, solved WCAG AA
- Mobile-first breakpoints - Simplified responsive logic (only
md:needed)
- Initial sizing too aggressive - First pass scaled down too much, required Goldilocks adjustment
- Badge color exploration - Needed multiple iterations to find neutral monochrome solution
- Display hierarchy unclear - Required explicit mobile size increase (text-xl → text-2xl)
asprop pattern - Astro-idiomatic composition without React overhead- Opacity-based hierarchy - Subtle visual weight without color explosion
- Typography component system - Scalable to future additions (Callout, Quote, etc.)
- Add text-4xl to design system - Enable even larger Display 1 (56px) for hero
- Create Callout component - Styled Body variant for emphasis blocks
- Add dark mode support - Extend CVA variants with dark: modifiers
- Responsive spacing utilities - Abstract
px-4 md:px-6into spacing tokens
- Design System:
src/styles/global.css(@theme block) - CLAUDE.md Principles: Atomic migration, Library-first, Illegal states unrepresentable
- WCAG AA Contrast: 4.5:1 minimum for normal text, 3:1 for large text (18px+)
- Content-First Typography Scale: 12px, 14px, 18px, 24px, 32px, 40px, 48px