Files
maternal-app/docs/maternal-app-ui-improvements.md
Andrei 75e5c2866d
Some checks failed
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
feat: Redesign UI with consistent card styling and mobile header
- Updated track page cards to match home page styling with vibrant colors
- Applied consistent 140px height cards across track and insights pages
- Added mobile header bar with connection status and user menu
- Moved user menu from floating top-left to fixed header top-right
- Updated insights dashboard with home page color palette (#E91E63, #1976D2, etc.)
- Centered cards with minWidth constraints (200px for stats, 400px for charts)
- Fixed hydration mismatch by replacing JS media queries with CSS breakpoints
- Improved accessibility with viewport settings (removed zoom restrictions)
- Added UI improvements documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 20:34:06 +00:00

24 KiB

Maternal App - UI Consistency & Alignment Guide

Overview

This document provides comprehensive instructions for fixing UI/UX inconsistencies across the Maternal app. The main dashboard screen serves as the design reference for all other screens.

Reference Design Pattern (Main Dashboard)

The main dashboard successfully implements:

  • 6 symmetric action cards with consistent spacing
  • Soft rounded corners (borderRadius: 16-20px)
  • Consistent color palette with meaningful color associations
  • Clear visual hierarchy with proper typography scaling
  • Adequate whitespace between sections
  • Mobile-first responsive design

Global Design Tokens to Apply

Spacing System

const spacing = {
  xs: 8,    // 0.5rem
  sm: 12,   // 0.75rem
  md: 16,   // 1rem (base unit)
  lg: 24,   // 1.5rem
  xl: 32,   // 2rem
  xxl: 48,  // 3rem
  xxxl: 64  // 4rem
}

Color Palette

const colors = {
  primary: {
    main: '#EC407A',      // Pink (Feeding)
    light: '#FFB3C1',
    dark: '#C2185B'
  },
  secondary: {
    sleep: '#2196F3',     // Blue
    diaper: '#FF9800',    // Orange
    medicine: '#F44336',  // Red
    activities: '#66BB6A', // Green
    assistant: '#FF7043'  // Deep Orange
  },
  background: {
    default: '#FFF5F7',   // Light pink background
    paper: '#FFFFFF',
    card: '#FFF0F3'       // Slightly pink card background
  },
  text: {
    primary: '#2D3436',
    secondary: '#636E72',
    disabled: '#B2BEC3'
  }
}

Typography Scale

const typography = {
  h1: { fontSize: '2rem', fontWeight: 600, lineHeight: 1.2 },
  h2: { fontSize: '1.5rem', fontWeight: 600, lineHeight: 1.3 },
  h3: { fontSize: '1.25rem', fontWeight: 500, lineHeight: 1.4 },
  body1: { fontSize: '1rem', fontWeight: 400, lineHeight: 1.5 },
  body2: { fontSize: '0.875rem', fontWeight: 400, lineHeight: 1.5 },
  caption: { fontSize: '0.75rem', fontWeight: 400, lineHeight: 1.4 }
}

Screen-Specific Fixes

1. Track Activity Screen (/track)

Current Issues:

  • Icons and labels not properly centered
  • Inconsistent spacing between activity options
  • No visual feedback on hover/press

Required Fixes:

// Container structure
<Container maxWidth="sm" sx={{ px: 2, py: 3 }}>
  <Typography variant="h2" sx={{ mb: 1, fontWeight: 600 }}>
    Track Activity
  </Typography>
  <Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}>
    Select an activity to track
  </Typography>
  
  <Grid container spacing={2}>
    {activities.map(activity => (
      <Grid item xs={4} sm={4} key={activity.id}>
        <Paper
          elevation={0}
          sx={{
            p: 3,
            borderRadius: 3,
            backgroundColor: activity.bgColor,
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
            aspectRatio: '1/1',
            cursor: 'pointer',
            transition: 'all 0.2s ease',
            '&:hover': {
              transform: 'scale(1.05)',
              boxShadow: 2
            }
          }}
        >
          <Box sx={{ fontSize: 48, mb: 1 }}>{activity.icon}</Box>
          <Typography variant="body2" fontWeight={500}>
            {activity.label}
          </Typography>
        </Paper>
      </Grid>
    ))}
  </Grid>
</Container>

2. AI Assistant Screen (/ai-assistant)

Current Issues:

  • Chat history sidebar has poor alignment
  • Suggested questions buttons inconsistent
  • Input field not properly styled
  • No proper container padding

Required Fixes:

// Main layout structure
<Box sx={{ display: 'flex', height: '100vh', bgcolor: 'background.default' }}>
  {/* Sidebar */}
  <Drawer
    variant="permanent"
    sx={{
      width: { xs: 0, sm: 280 },
      display: { xs: 'none', sm: 'block' },
      '& .MuiDrawer-paper': {
        width: 280,
        bgcolor: 'background.paper',
        borderRight: 'none',
        boxShadow: 1
      }
    }}
  >
    <Box sx={{ p: 2 }}>
      <Typography variant="h3" sx={{ mb: 3 }}>Chat History</Typography>
      <Button
        fullWidth
        variant="contained"
        startIcon={<AddIcon />}
        sx={{
          mb: 3,
          borderRadius: 2,
          textTransform: 'none',
          bgcolor: 'primary.light',
          color: 'primary.main',
          '&:hover': { bgcolor: 'primary.main', color: 'white' }
        }}
      >
        New Chat
      </Button>
      
      {/* Chat list items */}
      <List sx={{ p: 0 }}>
        {chats.map(chat => (
          <ListItem
            button
            key={chat.id}
            sx={{
              borderRadius: 2,
              mb: 1,
              '&:hover': { bgcolor: 'background.default' }
            }}
          >
            <ListItemText
              primary={chat.title}
              secondary={chat.date}
              primaryTypographyProps={{ fontSize: '0.875rem' }}
              secondaryTypographyProps={{ fontSize: '0.75rem' }}
            />
          </ListItem>
        ))}
      </List>
    </Box>
  </Drawer>
  
  {/* Main content */}
  <Box sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column' }}>
    {/* Header */}
    <Box sx={{ p: 3, bgcolor: 'background.paper', borderBottom: 1, borderColor: 'divider' }}>
      <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
        <Avatar sx={{ bgcolor: 'primary.main', width: 48, height: 48 }}>
          <SmartToyIcon />
        </Avatar>
        <Box>
          <Typography variant="h3">AI Parenting Assistant</Typography>
          <Typography variant="caption" color="text.secondary">
            Ask me anything about parenting and childcare
          </Typography>
        </Box>
      </Box>
    </Box>
    
    {/* Chat area */}
    <Box sx={{ flexGrow: 1, p: 3, overflowY: 'auto' }}>
      {/* Welcome message */}
      <Box sx={{ textAlign: 'center', py: 4 }}>
        <Typography variant="h2" sx={{ mb: 2 }}>
          Hi Andrei! How can I help you today?
        </Typography>
        
        {/* Suggested questions */}
        <Grid container spacing={2} justifyContent="center" sx={{ mt: 3, maxWidth: 600, mx: 'auto' }}>
          {suggestions.map(suggestion => (
            <Grid item xs={12} sm={6} key={suggestion.id}>
              <Chip
                label={suggestion.text}
                onClick={() => {}}
                sx={{
                  width: '100%',
                  py: 2,
                  borderRadius: 2,
                  fontSize: '0.875rem',
                  bgcolor: 'background.paper',
                  border: 1,
                  borderColor: 'divider',
                  '&:hover': {
                    bgcolor: 'primary.light',
                    borderColor: 'primary.main'
                  }
                }}
              />
            </Grid>
          ))}
        </Grid>
      </Box>
    </Box>
    
    {/* Input area */}
    <Box sx={{ p: 3, bgcolor: 'background.paper', borderTop: 1, borderColor: 'divider' }}>
      <Box sx={{ maxWidth: 800, mx: 'auto' }}>
        <TextField
          fullWidth
          placeholder="Ask me anything..."
          variant="outlined"
          sx={{
            '& .MuiOutlinedInput-root': {
              borderRadius: 3,
              bgcolor: 'background.default',
              '&:hover fieldset': { borderColor: 'primary.main' },
              '&.Mui-focused fieldset': { borderColor: 'primary.main' }
            }
          }}
          InputProps={{
            endAdornment: (
              <IconButton color="primary">
                <SendIcon />
              </IconButton>
            )
          }}
        />
        <Typography variant="caption" color="text.secondary" sx={{ mt: 1, display: 'block', textAlign: 'center' }}>
          This AI assistant provides general information. Always consult healthcare professionals for medical advice.
        </Typography>
      </Box>
    </Box>
  </Box>
</Box>

3. Insights & Analytics Screen (/insights)

Current Issues:

  • Time period tabs not properly styled
  • Stats cards have inconsistent heights
  • Charts not properly aligned
  • Legend placement issues

Required Fixes:

// Container and layout
<Container maxWidth="lg" sx={{ px: { xs: 2, sm: 3 }, py: 3 }}>
  <Typography variant="h2" sx={{ mb: 1 }}>Insights & Analytics</Typography>
  <Typography variant="body2" color="text.secondary" sx={{ mb: 4 }}>
    Track patterns and get insights about your child's activities
  </Typography>
  
  {/* Time period selector */}
  <Tabs
    value={selectedPeriod}
    onChange={handlePeriodChange}
    sx={{
      mb: 4,
      '& .MuiTabs-indicator': { backgroundColor: 'primary.main' },
      '& .MuiTab-root': {
        textTransform: 'none',
        fontWeight: 500,
        minWidth: { xs: 80, sm: 120 }
      }
    }}
  >
    <Tab label="7 DAYS" />
    <Tab label="30 DAYS" />
    <Tab label="3 MONTHS" />
  </Tabs>
  
  {/* Stats cards */}
  <Grid container spacing={2} sx={{ mb: 4 }}>
    {stats.map(stat => (
      <Grid item xs={6} sm={3} key={stat.id}>
        <Paper
          elevation={0}
          sx={{
            p: 2.5,
            borderRadius: 3,
            bgcolor: stat.bgColor,
            height: '100%',
            display: 'flex',
            flexDirection: 'column',
            justifyContent: 'space-between'
          }}
        >
          <Box sx={{ fontSize: 32, mb: 1 }}>{stat.icon}</Box>
          <Typography variant="h3" fontWeight={600}>{stat.value}</Typography>
          <Typography variant="caption" color="text.secondary">
            {stat.label}
          </Typography>
        </Paper>
      </Grid>
    ))}
  </Grid>
  
  {/* Charts grid */}
  <Grid container spacing={3}>
    {charts.map(chart => (
      <Grid item xs={12} md={6} key={chart.id}>
        <Paper
          elevation={0}
          sx={{
            p: 3,
            borderRadius: 3,
            bgcolor: 'background.paper',
            height: 400,
            display: 'flex',
            flexDirection: 'column'
          }}
        >
          <Typography variant="h3" sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 1 }}>
            {chart.icon} {chart.title}
          </Typography>
          <Box sx={{ flexGrow: 1, position: 'relative' }}>
            {/* Chart component here */}
          </Box>
        </Paper>
      </Grid>
    ))}
  </Grid>
</Container>

4. Children Management Screen (/children)

Current Issues:

  • Child card not properly structured
  • Age text alignment issues
  • Action buttons placement

Required Fixes:

<Container maxWidth="md" sx={{ px: { xs: 2, sm: 3 }, py: 3 }}>
  <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 4 }}>
    <Box>
      <Typography variant="h2">Children</Typography>
      <Typography variant="body2" color="text.secondary">
        Manage your family's children profiles
      </Typography>
    </Box>
    <Button
      variant="contained"
      startIcon={<AddIcon />}
      sx={{
        borderRadius: 2,
        textTransform: 'none',
        px: 3
      }}
    >
      Add Child
    </Button>
  </Box>
  
  <Grid container spacing={3}>
    {children.map(child => (
      <Grid item xs={12} sm={6} key={child.id}>
        <Paper
          elevation={0}
          sx={{
            p: 3,
            borderRadius: 3,
            bgcolor: 'background.paper',
            border: 1,
            borderColor: 'divider'
          }}
        >
          <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>
            <Avatar
              sx={{
                width: 64,
                height: 64,
                bgcolor: 'primary.light',
                fontSize: 24
              }}
            >
              {child.name[0]}
            </Avatar>
            <Box sx={{ flexGrow: 1 }}>
              <Typography variant="h3">{child.name}</Typography>
              <Typography variant="body2" color="text.secondary">
                {child.gender}
              </Typography>
              <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mt: 1 }}>
                <CalendarIcon fontSize="small" color="action" />
                <Typography variant="caption">{child.birthDate}</Typography>
              </Box>
              <Typography variant="caption" color="primary.main">
                Age: {child.age}
              </Typography>
            </Box>
            <IconButton>
              <MoreVertIcon />
            </IconButton>
          </Box>
          
          <Box sx={{ display: 'flex', gap: 1, mt: 2 }}>
            <IconButton size="small" color="primary">
              <EditIcon />
            </IconButton>
            <IconButton size="small" color="error">
              <DeleteIcon />
            </IconButton>
          </Box>
        </Paper>
      </Grid>
    ))}
  </Grid>
</Container>

5. Family Management Screen (/family)

Current Issues:

  • Share code styling inconsistent
  • Member list alignment
  • Proper spacing between sections

Required Fixes:

<Container maxWidth="md" sx={{ px: { xs: 2, sm: 3 }, py: 3 }}>
  <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 4 }}>
    <Box>
      <Typography variant="h2">Family</Typography>
      <Typography variant="body2" color="text.secondary">
        Manage your family members and share access
      </Typography>
    </Box>
    <Box sx={{ display: 'flex', gap: 2 }}>
      <Button
        variant="outlined"
        startIcon={<GroupAddIcon />}
        sx={{ borderRadius: 2, textTransform: 'none' }}
      >
        Join Family
      </Button>
      <Button
        variant="contained"
        startIcon={<PersonAddIcon />}
        sx={{ borderRadius: 2, textTransform: 'none' }}
      >
        Invite Member
      </Button>
    </Box>
  </Box>
  
  <Grid container spacing={4}>
    <Grid item xs={12} md={6}>
      <Paper elevation={0} sx={{ p: 3, borderRadius: 3, bgcolor: 'background.paper' }}>
        <Typography variant="h3" sx={{ mb: 2 }}>Family Share Code</Typography>
        <Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
          Share this code with family members to give them access to your family's data
        </Typography>
        <Box sx={{ display: 'flex', gap: 2, alignItems: 'center' }}>
          <Chip
            label="XXIG62"
            sx={{
              px: 3,
              py: 1,
              fontSize: '1.25rem',
              fontWeight: 600,
              bgcolor: 'primary.light',
              color: 'primary.main'
            }}
          />
          <Button
            variant="outlined"
            startIcon={<ContentCopyIcon />}
            sx={{ borderRadius: 2, textTransform: 'none' }}
          >
            Copy Code
          </Button>
        </Box>
      </Paper>
    </Grid>
    
    <Grid item xs={12} md={6}>
      <Paper elevation={0} sx={{ p: 3, borderRadius: 3, bgcolor: 'background.paper' }}>
        <Typography variant="h3" sx={{ mb: 3 }}>
          Family Members ({members.length})
        </Typography>
        <List sx={{ p: 0 }}>
          {members.map(member => (
            <ListItem
              key={member.id}
              sx={{
                px: 2,
                py: 1.5,
                borderRadius: 2,
                mb: 1,
                bgcolor: 'background.default'
              }}
            >
              <ListItemAvatar>
                <Avatar sx={{ bgcolor: 'primary.main' }}>
                  {member.name[0]}
                </Avatar>
              </ListItemAvatar>
              <ListItemText
                primary={member.name}
                secondary={member.email}
                primaryTypographyProps={{ fontWeight: 500 }}
              />
              <Chip
                label={member.role}
                size="small"
                color={member.role === 'Parent' ? 'primary' : 'default'}
                sx={{ borderRadius: 1 }}
              />
            </ListItem>
          ))}
        </List>
      </Paper>
    </Grid>
  </Grid>
</Container>

Mobile-First Responsive Guidelines

Breakpoint System

const breakpoints = {
  xs: 0,    // Mobile phones
  sm: 600,  // Small tablets
  md: 900,  // Tablets
  lg: 1200, // Desktop
  xl: 1536  // Large screens
}

Mobile-Specific Rules

  1. Touch targets: Minimum 48x48px for all interactive elements
  2. Padding: Use px: { xs: 2, sm: 3 } for container padding
  3. Font sizes: Scale down by 10-15% on mobile
  4. Grid columns: Use xs={12} for single column on mobile, sm={6} for two columns on tablets
  5. Navigation: Hide sidebar on mobile, use bottom navigation or hamburger menu
  6. Modals: Full screen on mobile, centered dialog on desktop

Component Responsiveness

// Responsive spacing
sx={{
  p: { xs: 2, sm: 3, md: 4 },
  m: { xs: 1, sm: 2, md: 3 }
}}

// Responsive typography
sx={{
  fontSize: { xs: '1rem', sm: '1.125rem', md: '1.25rem' }
}}

// Responsive grid
<Grid container spacing={{ xs: 2, sm: 3 }}>
  <Grid item xs={12} sm={6} md={4}>

Common MUI Theme Overrides

const theme = createTheme({
  palette: {
    primary: { main: '#EC407A' },
    background: {
      default: '#FFF5F7',
      paper: '#FFFFFF'
    }
  },
  shape: {
    borderRadius: 12
  },
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          borderRadius: 12,
          textTransform: 'none',
          fontWeight: 500,
          padding: '10px 24px'
        }
      }
    },
    MuiPaper: {
      styleOverrides: {
        root: {
          borderRadius: 16,
          boxShadow: 'none',
          border: '1px solid rgba(0,0,0,0.08)'
        }
      }
    },
    MuiTextField: {
      styleOverrides: {
        root: {
          '& .MuiOutlinedInput-root': {
            borderRadius: 12
          }
        }
      }
    }
  }
});

Implementation Checklist

  • Apply consistent spacing using the defined spacing system
  • Update all color values to use the defined palette
  • Ensure all interactive elements have proper hover/active states
  • Add proper transitions (0.2s ease) for all interactive elements
  • Verify mobile responsiveness for all screens
  • Test touch target sizes on mobile (minimum 48x48px)
  • Ensure consistent border radius (12-16px for cards, 8-12px for buttons)
  • Add proper loading states for async operations
  • Implement consistent error messaging styles
  • Verify text hierarchy and readability on all screen sizes

Testing Requirements

  1. Test on iPhone SE (375px width) for minimum mobile size
  2. Test on iPad (768px width) for tablet view
  3. Test on desktop (1920px width) for full experience
  4. Verify touch interactions on actual mobile devices
  5. Check color contrast ratios for accessibility (WCAG AA compliance)
  6. Test with both light and dark system preferences

Critical Accessibility Fixes (Console Errors)

1. Color Contrast Issues (WCAG AA Compliance)

Problem: Elements don't meet minimum color contrast ratio thresholds (4.5:1 for normal text, 3:1 for large text)

Fix for the color palette:

const colors = {
  primary: {
    main: '#D81B60',      // Darker pink for better contrast (was #EC407A)
    light: '#FFB3C1',
    dark: '#AD1457'       // Even darker for text on light backgrounds
  },
  secondary: {
    sleep: '#1976D2',     // Darker blue (was #2196F3)
    diaper: '#F57C00',    // Darker orange (was #FF9800)
    medicine: '#D32F2F',  // Darker red (was #F44336)
    activities: '#388E3C', // Darker green (was #66BB6A)
    assistant: '#E64A19'  // Darker deep orange (was #FF7043)
  },
  background: {
    default: '#FFF5F7',
    paper: '#FFFFFF',
    card: '#FFF0F3'
  },
  text: {
    primary: 'rgba(0, 0, 0, 0.87)',    // Higher opacity for better contrast
    secondary: 'rgba(0, 0, 0, 0.6)',   // Darker secondary text
    disabled: 'rgba(0, 0, 0, 0.38)'
  }
}

Fix for MUI TextField labels:

// Global theme override for input labels
const theme = createTheme({
  components: {
    MuiInputLabel: {
      styleOverrides: {
        root: {
          color: 'rgba(0, 0, 0, 0.87)', // Darker label color
          '&.Mui-focused': {
            color: '#AD1457' // Dark pink when focused
          },
          '&.MuiFormLabel-filled': {
            color: 'rgba(0, 0, 0, 0.87)' // Ensure filled state has good contrast
          }
        }
      }
    },
    MuiOutlinedInput: {
      styleOverrides: {
        root: {
          '& .MuiOutlinedInput-notchedOutline': {
            borderColor: 'rgba(0, 0, 0, 0.38)' // Darker border
          },
          '&:hover .MuiOutlinedInput-notchedOutline': {
            borderColor: 'rgba(0, 0, 0, 0.87)'
          },
          '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
            borderColor: '#AD1457'
          }
        }
      }
    },
    MuiButton: {
      styleOverrides: {
        containedPrimary: {
          backgroundColor: '#D81B60',
          '&:hover': {
            backgroundColor: '#AD1457'
          }
        }
      }
    }
  }
});

2. Viewport Meta Tag Issue

Problem: Zooming and scaling must not be disabled (critical accessibility issue)

Fix for viewport meta tag:

<!-- In your index.html or _document.js -->
<!-- WRONG - Do not use this: -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

<!-- CORRECT - Use this instead: -->
<meta name="viewport" content="width=device-width, initial-scale=1">

For Next.js apps:

// In pages/_document.js or app/layout.js
<Head>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>

3. Additional Accessibility Enhancements

Form Input Enhancements:

<TextField
  id="email-input"
  label="Email"
  type="email"
  autoComplete="email"
  inputProps={{
    'aria-label': 'Email address',
    'aria-required': true
  }}
  FormLabelProps={{
    sx: {
      color: 'rgba(0, 0, 0, 0.87)',
      '&.Mui-focused': {
        color: '#AD1457'
      }
    }
  }}
  sx={{
    '& .MuiOutlinedInput-root': {
      '& fieldset': {
        borderColor: 'rgba(0, 0, 0, 0.38)'
      },
      '&:hover fieldset': {
        borderColor: 'rgba(0, 0, 0, 0.87)'
      },
      '&.Mui-focused fieldset': {
        borderColor: '#AD1457'
      }
    }
  }}
/>

Button Accessibility:

<Button
  variant="contained"
  sx={{
    backgroundColor: '#D81B60',
    color: '#FFFFFF',
    '&:hover': {
      backgroundColor: '#AD1457'
    },
    '&:focus-visible': {
      outline: '2px solid #AD1457',
      outlineOffset: '2px'
    },
    // Ensure minimum touch target size
    minHeight: 48,
    minWidth: 48
  }}
  aria-label="Sign in to your account"
>
  Sign In
</Button>

Focus Indicators:

// Global focus styles
const theme = createTheme({
  components: {
    MuiButtonBase: {
      styleOverrides: {
        root: {
          '&:focus-visible': {
            outline: '2px solid #AD1457',
            outlineOffset: '2px'
          }
        }
      }
    }
  }
});

4. Testing for Accessibility

Use these tools to verify fixes:

  1. axe DevTools: Browser extension for accessibility testing
  2. Chrome DevTools Lighthouse: Run accessibility audit
  3. WAVE: WebAIM's accessibility evaluation tool
  4. Contrast Checker: Use WebAIM's contrast checker to verify color combinations

Minimum contrast ratios to maintain:

  • Normal text: 4.5:1
  • Large text (18pt or 14pt bold): 3:1
  • UI components and graphics: 3:1

Quick contrast check for main colors:

// Verified color combinations with good contrast
const safeColorCombos = {
  // Text on backgrounds
  darkTextOnLight: '#000000 on #FFF5F7', // 20.3:1 ✓
  primaryTextOnWhite: '#D81B60 on #FFFFFF', // 4.7:1 ✓
  whiteOnPrimary: '#FFFFFF on #D81B60', // 4.7:1 ✓
  
  // Labels and secondary text
  labelOnWhite: 'rgba(0,0,0,0.87) on #FFFFFF', // 16:1 ✓
  secondaryTextOnWhite: 'rgba(0,0,0,0.6) on #FFFFFF', // 7.4:1 ✓
}

Additional Notes

  • Maintain the soft, nurturing aesthetic with accessible color choices
  • Keep interactions smooth and delightful with subtle animations
  • Prioritize clarity and ease of use for sleep-deprived parents
  • Ensure all text is easily readable at a glance
  • Use icons consistently from the same icon library (Material Icons)
  • Maintain visual hierarchy with proper use of whitespace
  • Always test with screen readers and keyboard navigation