Skip to content

Commit bb493f3

Browse files
committed
feat: Comprehensive UI/UX audit - theming, accessibility, consistency
Audit and fixes: - Sync Tailwind config with theme tokens (GREEN primary #22c55e) - Replace all hardcoded background colors with theme tokens - Add accessibility labels to interactive buttons - Standardize modal close button placement (right side) - Fix empty state capitalization (sentence case) - Fix terminology (Browse Dreams, Start Sleep Tracking) - Standardize trash icon to trash-outline - Fix FavoriteButton inactive color - Add smd (12px) spacing token - Fix back button navigation in dream detail - Remove redundant app/sleep/index.tsx screen - Replace hardcoded font family with tokens
1 parent 654a0b9 commit bb493f3

22 files changed

Lines changed: 241 additions & 701 deletions

AGENTS.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,83 @@ export function useLaunchQueue() {
125125
- `className` prop on all components
126126
- Courier Prime font family for text (`fontFamily: 'CourierPrime_400Regular'`)
127127

128+
## Design System Audit (January 2026)
129+
130+
### Theme Tokens (`theme/tokens.ts`)
131+
132+
| Category | Token | Values |
133+
| ------------- | ---------------------- | ----------------- |
134+
| Primary | `colors.primary[500]` | `#22c55e` (Green) |
135+
| Background | `darkTheme.background` | `#09090b` |
136+
| Surface | `darkTheme.surface` | `#18181b` |
137+
| Surface Alt | `darkTheme.surfaceAlt` | `#27272a` |
138+
| Spacing | `xs/sm/md/lg/xl` | 4/8/16/24/32px |
139+
| Border Radius | `sm/md/lg/xl/full` | 2/4/8/12/9999px |
140+
141+
### KNOWN ISSUES (To Fix)
142+
143+
#### HIGH PRIORITY
144+
145+
1. **Color Identity Conflict**: `tailwind.config.js` defines primary as BLUE (`#6366f1`) but `theme/tokens.ts` defines it as GREEN (`#22c55e`). Components using NativeWind appear blue, StyleSheet components appear green.
146+
147+
2. **Hardcoded Background Colors**: Many files use hardcoded hex instead of tokens:
148+
- `#0f0f1a` - Should be `darkTheme.background` or `colors.gray[950]`
149+
- `#1a1a2e` - Should be `darkTheme.surface`
150+
- `#252542` - Should be `darkTheme.surfaceAlt`
151+
152+
3. **Missing Accessibility Labels**: Icon-only buttons in `LaunchQueueCard`, `DraggableQueueList`, `SleepHistoryCard`, and home screen info button lack `accessibilityLabel`.
153+
154+
#### MEDIUM PRIORITY
155+
156+
4. **Terminology Inconsistency**:
157+
- Use "Browse Dreams" (not "Explore Dreams")
158+
- Use "Start Sleep Tracking" (not "Start Dream Mode")
159+
160+
5. **Capitalization Inconsistency**: Empty states mix Title Case and Sentence case. Standardize on Sentence case.
161+
162+
6. **Icon Style Inconsistency**: Trash icon uses both `trash` and `trash-outline`. Standardize on `trash-outline`.
163+
164+
7. **Modal Close Button**: Placement varies (left in `SleepSessionDetailModal`, right elsewhere). Standardize on right side.
165+
166+
8. **Missing 12px Spacing Token**: Add `smd: 12` to spacing scale.
167+
168+
9. **Back Button Navigation**: `app/dream/[id].tsx` uses `router.replace('/')` instead of `router.back()`.
169+
170+
#### LOW PRIORITY
171+
172+
10. **Redundant Screen**: `app/sleep/index.tsx` duplicates functionality of `app/(tabs)/dream.tsx`.
173+
174+
11. **Hardcoded Font Family**: Some files use `'CourierPrime_400Regular'` string instead of `fontFamily.regular` token.
175+
176+
### Screen Inventory
177+
178+
| Tab | File | Purpose |
179+
| --------- | -------------------------- | ------------------------- |
180+
| Home | `app/(tabs)/index.tsx` | Browse dreams by category |
181+
| Search | `app/(tabs)/search.tsx` | Full-text dream search |
182+
| Favorites | `app/(tabs)/favorites.tsx` | Saved dreams |
183+
| Queue | `app/(tabs)/queue.tsx` | Sleep session queue |
184+
| Dream | `app/(tabs)/dream.tsx` | Sleep tracking control |
185+
| Settings | `app/(tabs)/settings.tsx` | Calibration & debug |
186+
187+
| Modal/Detail | File | Purpose |
188+
| ------------ | ---------------------- | --------------------- |
189+
| Dream Detail | `app/dream/[id].tsx` | Dream info and player |
190+
| Dream Launch | `app/dream/launch.tsx` | Active dream session |
191+
| About | `app/about.tsx` | Instructions |
192+
193+
### Component Categories
194+
195+
| Category | Components |
196+
| ---------------- | --------------------------------------------------------------------------- |
197+
| Base UI | `ui/Button`, `ui/Card`, `ui/Input`, `ui/Text`, `ui/ThemedAlert` |
198+
| Dream Display | `DreamCard`, `DreamPlayer`, `DreamFeed`, `DreamCardSkeleton` |
199+
| Queue Management | `LaunchQueueCard`, `DraggableQueueList`, `QueueButton` |
200+
| Sleep Tracking | `SleepModePlayer`, `SleepStageGraph`, `SleepHistoryCard`, `SleepDebugPanel` |
201+
| Calibration | `VolumeSetup`, `MicrophoneTest`, `SensorCalibration` |
202+
| Navigation | `CategoryFilter`, `SearchBar` |
203+
| Overlays | `DarkScreenOverlay`, `SleepSessionDetailModal` |
204+
128205
## DO NOT
129206

130207
- Use `as any`, `@ts-ignore`, or `@ts-expect-error`
@@ -247,4 +324,4 @@ When rebuilding Android support:
247324

248325
---
249326

250-
_Last updated: 2026-01-11_
327+
_Last updated: 2026-01-13_

app/(tabs)/dream.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ export default function DreamScreen() {
840840
const styles = StyleSheet.create({
841841
container: {
842842
flex: 1,
843-
backgroundColor: '#0f0f1a',
843+
backgroundColor: colors.gray[950],
844844
},
845845
scrollContent: {
846846
flexGrow: 1,
@@ -858,7 +858,7 @@ const styles = StyleSheet.create({
858858
paddingHorizontal: spacing.md,
859859
},
860860
trackingActive: {
861-
backgroundColor: '#1a1a2e',
861+
backgroundColor: colors.gray[900],
862862
borderRadius: borderRadius.xl,
863863
padding: spacing.lg,
864864
gap: spacing.lg,
@@ -1005,7 +1005,7 @@ const styles = StyleSheet.create({
10051005
maxWidth: 300,
10061006
},
10071007
featureList: {
1008-
backgroundColor: '#1a1a2e',
1008+
backgroundColor: colors.gray[900],
10091009
borderRadius: borderRadius.xl,
10101010
padding: spacing.lg,
10111011
gap: spacing.md,
@@ -1062,7 +1062,7 @@ const styles = StyleSheet.create({
10621062
},
10631063
modalContainer: {
10641064
flex: 1,
1065-
backgroundColor: '#0f0f1a',
1065+
backgroundColor: colors.gray[950],
10661066
},
10671067
modalHeader: {
10681068
flexDirection: 'row',
@@ -1081,7 +1081,7 @@ const styles = StyleSheet.create({
10811081
padding: spacing.lg,
10821082
},
10831083
summaryModal: {
1084-
backgroundColor: '#1a1a2e',
1084+
backgroundColor: colors.gray[900],
10851085
borderRadius: borderRadius.xl,
10861086
padding: spacing.xl,
10871087
alignItems: 'center',

app/(tabs)/favorites.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ export default function FavoritesScreen() {
5050
<View style={styles.centerContent}>
5151
<Ionicons name="heart-outline" size={64} color={colors.gray[500]} />
5252
<Text variant="h4" color="primary" style={styles.emptyTitle}>
53-
No Favorites Yet
53+
No favorites yet
5454
</Text>
5555
<Text variant="body" color="secondary" align="center" style={styles.emptySubtitle}>
5656
Tap the heart icon on any dream to save it here
5757
</Text>
5858
<Link href="/(tabs)" asChild>
5959
<Button variant="primary" style={styles.signInButton}>
60-
Explore Dreams
60+
Browse Dreams
6161
</Button>
6262
</Link>
6363
</View>
@@ -91,7 +91,7 @@ export default function FavoritesScreen() {
9191
const styles = StyleSheet.create({
9292
container: {
9393
flex: 1,
94-
backgroundColor: '#0f0f1a',
94+
backgroundColor: colors.gray[950],
9595
},
9696
header: {
9797
paddingHorizontal: spacing.md,

app/(tabs)/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ export default function HomeScreen() {
5858
dream_stream
5959
</Text>
6060
<Link href={'/about' as any} asChild>
61-
<Pressable style={styles.aboutButton} hitSlop={8}>
61+
<Pressable
62+
style={styles.aboutButton}
63+
hitSlop={8}
64+
accessibilityLabel="About dream_stream"
65+
accessibilityRole="button"
66+
>
6267
<Ionicons name="information-circle-outline" size={24} color={colors.gray[400]} />
6368
</Pressable>
6469
</Link>

app/(tabs)/queue.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ export default function QueueScreen() {
171171
<Button
172172
variant="primary"
173173
onPress={() => router.push('/(tabs)/dream')}
174-
leftIcon={<Ionicons name="play" size={20} color="#ffffff" />}
174+
leftIcon={<Ionicons name="play" size={20} color={colors.gray[50]} />}
175175
style={styles.playQueueButton}
176176
>
177-
Start Dream Mode
177+
Start Sleep Tracking
178178
</Button>
179179
<Text variant="caption" color="muted" style={styles.dragHint}>
180180
Drag to reorder
@@ -197,7 +197,7 @@ export default function QueueScreen() {
197197
const styles = StyleSheet.create({
198198
container: {
199199
flex: 1,
200-
backgroundColor: '#0f0f1a',
200+
backgroundColor: colors.gray[950],
201201
},
202202
scrollContent: {
203203
flexGrow: 1,
@@ -220,7 +220,7 @@ const styles = StyleSheet.create({
220220
controlsRow: {
221221
flexDirection: 'row',
222222
justifyContent: 'space-around',
223-
backgroundColor: '#1a1a2e',
223+
backgroundColor: colors.gray[900],
224224
borderRadius: borderRadius.xl,
225225
padding: spacing.sm,
226226
},

app/(tabs)/settings.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { SleepDebugPanel } from '@/components/SleepDebugPanel';
1616
import { VolumeSetup } from '@/components/VolumeSetup';
1717
import { MicrophoneTest } from '@/components/MicrophoneTest';
1818
import { useHealth } from '@/hooks/useHealth';
19-
import { colors, spacing } from '@/theme/tokens';
19+
import { colors, spacing, fontFamily } from '@/theme/tokens';
2020
import {
2121
runDebugReport,
2222
formatDebugReport,
@@ -322,7 +322,7 @@ export default function SettingsScreen() {
322322
</Text>
323323
</Pressable>
324324
<Pressable style={styles.debugButton} onPress={handleClearModel}>
325-
<Ionicons name="trash" size={16} color={colors.error} />
325+
<Ionicons name="trash-outline" size={16} color={colors.error} />
326326
<Text variant="caption" color="primary">
327327
Clear
328328
</Text>
@@ -474,7 +474,7 @@ function MenuRow({ icon, label, onPress, badge }: MenuRowProps) {
474474
const styles = StyleSheet.create({
475475
container: {
476476
flex: 1,
477-
backgroundColor: '#0f0f1a',
477+
backgroundColor: colors.gray[950],
478478
},
479479
scrollContent: {
480480
flexGrow: 1,
@@ -488,9 +488,9 @@ const styles = StyleSheet.create({
488488
paddingHorizontal: spacing.md,
489489
paddingVertical: spacing.md,
490490
borderTopWidth: 1,
491-
borderTopColor: '#252542',
491+
borderTopColor: colors.gray[800],
492492
borderBottomWidth: 1,
493-
borderBottomColor: '#252542',
493+
borderBottomColor: colors.gray[800],
494494
},
495495
menuRow: {
496496
flexDirection: 'row',
@@ -502,7 +502,7 @@ const styles = StyleSheet.create({
502502
marginLeft: spacing.md,
503503
},
504504
badge: {
505-
backgroundColor: '#252542',
505+
backgroundColor: colors.gray[800],
506506
paddingHorizontal: spacing.sm,
507507
paddingVertical: 2,
508508
borderRadius: 4,
@@ -516,13 +516,13 @@ const styles = StyleSheet.create({
516516
paddingHorizontal: spacing.md,
517517
paddingTop: spacing.md,
518518
borderTopWidth: 1,
519-
borderTopColor: '#252542',
519+
borderTopColor: colors.gray[800],
520520
},
521521
debugSection: {
522522
paddingHorizontal: spacing.md,
523523
paddingTop: spacing.md,
524524
borderTopWidth: 1,
525-
borderTopColor: '#252542',
525+
borderTopColor: colors.gray[800],
526526
},
527527
expandedSection: {
528528
paddingVertical: spacing.md,
@@ -542,7 +542,7 @@ const styles = StyleSheet.create({
542542
actionButton: {
543543
flexDirection: 'row',
544544
alignItems: 'center',
545-
backgroundColor: '#252542',
545+
backgroundColor: colors.gray[800],
546546
paddingVertical: spacing.sm,
547547
paddingHorizontal: spacing.md,
548548
borderRadius: 8,
@@ -608,7 +608,7 @@ const styles = StyleSheet.create({
608608
},
609609
modalContainer: {
610610
flex: 1,
611-
backgroundColor: '#0f0f1a',
611+
backgroundColor: colors.gray[950],
612612
},
613613
modalHeader: {
614614
flexDirection: 'row',
@@ -629,19 +629,19 @@ const styles = StyleSheet.create({
629629
flexDirection: 'row',
630630
alignItems: 'center',
631631
gap: spacing.xs,
632-
backgroundColor: '#252542',
632+
backgroundColor: colors.gray[800],
633633
paddingHorizontal: spacing.sm,
634634
paddingVertical: spacing.xs,
635635
borderRadius: 6,
636636
},
637637
debugOutput: {
638638
maxHeight: 400,
639-
backgroundColor: '#1a1a2e',
639+
backgroundColor: colors.gray[900],
640640
borderRadius: 8,
641641
padding: spacing.sm,
642642
},
643643
debugOutputText: {
644-
fontFamily: 'CourierPrime_400Regular',
644+
fontFamily: fontFamily.regular,
645645
fontSize: 11,
646646
lineHeight: 16,
647647
},

app/dream/[id].tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,14 @@ export default function DreamDetailScreen() {
112112
<Stack.Screen options={{ headerShown: false }} />
113113

114114
<SafeAreaView edges={['top']} style={styles.header} pointerEvents="box-none">
115-
<Pressable onPress={() => router.replace('/')} style={styles.headerButton} hitSlop={8}>
116-
<Ionicons name="arrow-back" size={24} color="#ffffff" />
115+
<Pressable
116+
onPress={() => router.back()}
117+
style={styles.headerButton}
118+
hitSlop={8}
119+
accessibilityLabel="Go back"
120+
accessibilityRole="button"
121+
>
122+
<Ionicons name="arrow-back" size={24} color={colors.gray[50]} />
117123
</Pressable>
118124
<View style={styles.headerSpacer} pointerEvents="none" />
119125
<View style={styles.headerActions}>
@@ -322,7 +328,7 @@ const styles = StyleSheet.create({
322328
},
323329
modalContainer: {
324330
flex: 1,
325-
backgroundColor: '#0f0f1a',
331+
backgroundColor: colors.gray[950],
326332
},
327333
modalHeader: {
328334
flexDirection: 'row',

app/dream/launch.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export default function DreamLaunchScreen() {
6161
<StatusBar style="light" />
6262
<View style={styles.centeredContent}>
6363
<Text variant="h4" color="primary" align="center">
64-
No Dream Ready
64+
No dream ready
6565
</Text>
6666
<Text variant="body" color="secondary" align="center" style={styles.noItemMessage}>
6767
Queue a dream and mark it as ready to launch it here
@@ -112,7 +112,7 @@ export default function DreamLaunchScreen() {
112112
const styles = StyleSheet.create({
113113
container: {
114114
flex: 1,
115-
backgroundColor: '#0a0a14',
115+
backgroundColor: colors.gray[950],
116116
},
117117
centeredContent: {
118118
flex: 1,

0 commit comments

Comments
 (0)