Skip to content

Latest commit

 

History

History
290 lines (225 loc) · 9.6 KB

File metadata and controls

290 lines (225 loc) · 9.6 KB

Responsive Design + Design System Cleanup

Date: 2025-10-29 Status: Implemented Complexity: 8 story points

Overview

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.

Objectives

  1. Responsive Typography: Create reusable Typography components with mobile-first responsive scaling
  2. Button Sizing: Auto-scale button sizes across breakpoints without consumer configuration
  3. Design System Compliance: Replace arbitrary Tailwind colors with semantic design system tokens
  4. Visual Hierarchy: Establish clear Display → Heading → Body hierarchy
  5. Accessibility: Ensure WCAG AA compliance for all color contrast ratios

Architecture Decisions

Breakpoint Strategy

Mobile-first with md: only

  • Base styles = mobile (<768px)
  • md: prefix = desktop (≥768px)
  • Rationale: Simplest approach, matches existing codebase patterns

Typography Component System

Created: src/components/typography/

Display Component

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>

Heading Component

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>

Body Component

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.

Typography Scaling Rules

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

Button Responsive Sizing

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 desktop
  • size="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.

Design System Color Enforcement

Badge Component - Monochrome System

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.

Card Component - Minimal Borders

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%)

Link Component

Before: text-slate-700 (arbitrary Tailwind) After: text-accent-light (design system token)

Implementation

Files Created

  1. src/components/typography/Display.astro - Hero/landing headlines
  2. src/components/typography/Heading.astro - Page structure headings
  3. src/components/typography/Body.astro - Content text

Files Modified

Components (4 files):

  1. src/components/Button.astro - Responsive size variants
  2. src/components/Badge.astro - Monochrome design system colors
  3. src/components/Card.astro - Minimal border opacity
  4. src/components/Link.astro - Design system text color

Pages (6 files):

  1. src/pages/index.astro - Hero section
  2. src/pages/portfolio.astro - Case study list
  3. src/pages/portfolio/statsbomb.astro - Case study detail
  4. src/pages/about.astro - Bio page
  5. src/pages/resume.astro - Professional experience
  6. src/pages/contact.astro - Contact information

Page Changes:

  • Replaced raw <h1>/<h2>/<h3>/<p> with Typography components
  • Updated container padding: px-6px-4 md:px-6
  • Preserved all animation classes, data attributes, JavaScript hooks

Migration Pattern

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

Pre-Launch Checklist

  • 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)

Success Criteria

  • ✅ 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)

Rollback Plan

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)

Lessons Learned

What Worked Well

  1. CVA for type-safe variants - Prevented typos, ensured consistency
  2. Atomic migration - One commit eliminated cognitive split across pages
  3. Monochrome badge system - Aligned with Egyptian minimalism, solved WCAG AA
  4. Mobile-first breakpoints - Simplified responsive logic (only md: needed)

What to Improve

  1. Initial sizing too aggressive - First pass scaled down too much, required Goldilocks adjustment
  2. Badge color exploration - Needed multiple iterations to find neutral monochrome solution
  3. Display hierarchy unclear - Required explicit mobile size increase (text-xl → text-2xl)

Patterns to Reuse

  1. as prop pattern - Astro-idiomatic composition without React overhead
  2. Opacity-based hierarchy - Subtle visual weight without color explosion
  3. Typography component system - Scalable to future additions (Callout, Quote, etc.)

Future Enhancements

  1. Add text-4xl to design system - Enable even larger Display 1 (56px) for hero
  2. Create Callout component - Styled Body variant for emphasis blocks
  3. Add dark mode support - Extend CVA variants with dark: modifiers
  4. Responsive spacing utilities - Abstract px-4 md:px-6 into spacing tokens

References

  • 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