- 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>
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
- Touch targets: Minimum 48x48px for all interactive elements
- Padding: Use
px: { xs: 2, sm: 3 }for container padding - Font sizes: Scale down by 10-15% on mobile
- Grid columns: Use
xs={12}for single column on mobile,sm={6}for two columns on tablets - Navigation: Hide sidebar on mobile, use bottom navigation or hamburger menu
- 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
- Test on iPhone SE (375px width) for minimum mobile size
- Test on iPad (768px width) for tablet view
- Test on desktop (1920px width) for full experience
- Verify touch interactions on actual mobile devices
- Check color contrast ratios for accessibility (WCAG AA compliance)
- 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:
- axe DevTools: Browser extension for accessibility testing
- Chrome DevTools Lighthouse: Run accessibility audit
- WAVE: WebAIM's accessibility evaluation tool
- 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