Skip to content

Commit 0a009bd

Browse files
Dark mode color variables (#92)
* refactor: use semantic dark mode tokens Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com> * chore: apply formatting updates Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 982efdb commit 0a009bd

14 files changed

Lines changed: 258 additions & 98 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
- name: 🥟 Setup bun
3131
uses: oven-sh/setup-bun@v1
3232
with:
33-
bun-version: "1.3.8"
33+
bun-version: '1.3.8'
3434

3535
- name: 📥 Download deps
3636
run: bun install --frozen-lockfile
@@ -56,7 +56,7 @@ jobs:
5656
- name: 🥟 Setup bun
5757
uses: oven-sh/setup-bun@v1
5858
with:
59-
bun-version: "1.3.8"
59+
bun-version: '1.3.8'
6060

6161
- name: 📥 Download deps
6262
run: bun install --frozen-lockfile
@@ -82,7 +82,7 @@ jobs:
8282
- name: 🥟 Setup bun
8383
uses: oven-sh/setup-bun@v1
8484
with:
85-
bun-version: "1.3.8"
85+
bun-version: '1.3.8'
8686

8787
- name: 📥 Download deps
8888
run: bun install --frozen-lockfile
@@ -108,7 +108,7 @@ jobs:
108108
- name: 🥟 Setup bun
109109
uses: oven-sh/setup-bun@v1
110110
with:
111-
bun-version: "1.3.8"
111+
bun-version: '1.3.8'
112112

113113
- name: 📥 Download deps
114114
run: bun install --frozen-lockfile
@@ -146,7 +146,7 @@ jobs:
146146
- name: 🥟 Setup bun
147147
uses: oven-sh/setup-bun@v1
148148
with:
149-
bun-version: "1.3.8"
149+
bun-version: '1.3.8'
150150

151151
- name: 📥 Download deps
152152
run: bun install --frozen-lockfile

app/components/search-bar.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ export function SearchBar({
4444
>
4545
<div className="flex w-full items-center gap-2 sm:flex-1">
4646
<div className="min-w-0 flex-1">
47-
<Label htmlFor={id} className="sr-only">
48-
Search
49-
</Label>
50-
<Input
51-
type="search"
52-
name="search"
53-
id={id}
54-
defaultValue={searchParams.get('search') ?? ''}
55-
placeholder="Search"
56-
className="w-full"
57-
autoFocus={autoFocus}
47+
<Label htmlFor={id} className="sr-only">
48+
Search
49+
</Label>
50+
<Input
51+
type="search"
52+
name="search"
53+
id={id}
54+
defaultValue={searchParams.get('search') ?? ''}
55+
placeholder="Search"
56+
className="w-full"
57+
autoFocus={autoFocus}
5858
/>
5959
</div>
6060
<StatusButton

app/components/ui/button.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,17 @@ const buttonVariants = cva(
1212
variant: {
1313
default:
1414
'bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm',
15-
brand:
16-
'bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-green-700))] shadow-sm',
15+
brand: 'bg-brand text-brand-foreground hover:bg-brand/90 shadow-sm',
1716
'brand-soft':
18-
'bg-[hsl(var(--palette-green-300))] text-[hsl(var(--palette-dark-navy))] hover:bg-[hsl(var(--palette-green-500))] hover:text-[hsl(var(--palette-cream))] shadow-sm',
19-
warm:
20-
'bg-[hsl(var(--palette-chestnut))] text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-hot-fire-red))] shadow-sm',
17+
'bg-brand-soft text-brand-soft-foreground hover:bg-brand hover:text-brand-foreground shadow-sm',
18+
warm: 'bg-warm text-warm-foreground hover:bg-warm/90 shadow-sm',
2119
destructive:
2220
'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm',
2321
outline: 'border-border bg-card text-foreground hover:bg-muted border',
2422
secondary:
2523
'border-border text-foreground hover:bg-muted border bg-transparent',
2624
ghost: 'text-foreground hover:bg-muted',
27-
'ghost-inverse':
28-
'text-[hsl(var(--palette-cream))] hover:bg-[hsl(var(--palette-cream))/0.15]',
25+
'ghost-inverse': 'text-inverse hover:bg-inverse/15',
2926
link: 'text-primary underline-offset-4 hover:underline',
3027
},
3128
size: {

app/routes/_app+/_auth+/verify.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export default function VerifyRoute() {
132132
errors={fields[codeQueryParam].errors}
133133
groupClassName="gap-2 sm:gap-3"
134134
showSeparator={false}
135-
slotClassName="h-11 w-11 rounded-full bg-white text-base font-semibold shadow-none dark:bg-[hsl(var(--palette-navy))] sm:h-14 sm:w-14 sm:text-lg"
135+
slotClassName="bg-card text-foreground h-11 w-11 rounded-full text-base font-semibold shadow-none sm:h-14 sm:w-14 sm:text-lg"
136136
/>
137137
<div className="text-body-sm text-muted-foreground flex flex-wrap items-center gap-1">
138138
<span>No text after 5 minutes?</span>

app/routes/_app+/_layout.tsx

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useRef, useState, type CSSProperties } from 'react'
1+
import { useRef, useState } from 'react'
22
import {
33
Form,
44
Link,
@@ -67,18 +67,8 @@ export default function Layout() {
6767
const data = useLoaderData<typeof loader>()
6868
const user = useOptionalUser()
6969
const requestInfo = useRequestInfo()
70-
const isRecipientsRoute = requestInfo.path.startsWith('/recipients')
71-
const recipientsTheme = isRecipientsRoute
72-
? ({
73-
'--background': '0 0% 100%',
74-
'--card': '0 0% 100%',
75-
} as CSSProperties)
76-
: undefined
7770
return (
78-
<div
79-
className="bg-background flex h-screen flex-col justify-between"
80-
style={recipientsTheme}
81-
>
71+
<div className="bg-background flex h-screen flex-col justify-between">
8272
<header className="border-border border-b">
8373
<div className="container py-5 md:py-6">
8474
<nav className="flex flex-wrap items-center justify-between gap-4 sm:flex-nowrap md:gap-8">
@@ -123,35 +113,41 @@ export default function Layout() {
123113
<nav>
124114
<ul className="flex list-none flex-col gap-2 sm:flex-row sm:flex-wrap sm:gap-4">
125115
<li>
126-
<Link to="/about" className="text-gray-600 hover:text-gray-900">
116+
<Link
117+
to="/about"
118+
className="text-muted-foreground hover:text-foreground"
119+
>
127120
About
128121
</Link>
129122
</li>
130123
<li>
131124
<Link
132125
to="/privacy"
133-
className="text-gray-600 hover:text-gray-900"
126+
className="text-muted-foreground hover:text-foreground"
134127
>
135128
Privacy
136129
</Link>
137130
</li>
138131
<li>
139-
<Link to="/tos" className="text-gray-600 hover:text-gray-900">
132+
<Link
133+
to="/tos"
134+
className="text-muted-foreground hover:text-foreground"
135+
>
140136
Terms of Service
141137
</Link>
142138
</li>
143139
<li>
144140
<Link
145141
to="/support"
146-
className="text-gray-600 hover:text-gray-900"
142+
className="text-muted-foreground hover:text-foreground"
147143
>
148144
Support
149145
</Link>
150146
</li>
151147
<li>
152148
<Link
153149
to="/contact"
154-
className="text-gray-600 hover:text-gray-900"
150+
className="text-muted-foreground hover:text-foreground"
155151
>
156152
Contact
157153
</Link>
@@ -266,7 +262,7 @@ function MobileMenu() {
266262
<div className="fixed inset-0 z-50 flex justify-center">
267263
<button
268264
type="button"
269-
className="absolute inset-0 h-full w-full bg-black/20"
265+
className="bg-overlay/30 absolute inset-0 h-full w-full"
270266
onClick={() => setOpen(false)}
271267
aria-label="Close menu"
272268
/>
@@ -286,12 +282,7 @@ function MobileMenu() {
286282
<Icon name="close" size="lg" aria-hidden="true" />
287283
</Button>
288284
</div>
289-
<Button
290-
asChild
291-
size="lg"
292-
variant="warm"
293-
className="mt-6 w-full"
294-
>
285+
<Button asChild size="lg" variant="warm" className="mt-6 w-full">
295286
<Link to="/login" onClick={() => setOpen(false)}>
296287
<Icon name="star" size="sm" aria-hidden="true">
297288
Start 14-day FREE Trial
@@ -307,7 +298,7 @@ function MobileMenu() {
307298
<Icon
308299
name="log in"
309300
size="sm"
310-
className="text-[hsl(var(--palette-cloud))]"
301+
className="text-muted-foreground"
311302
aria-hidden="true"
312303
/>
313304
Log In
@@ -323,7 +314,7 @@ function MobileMenu() {
323314
<Icon
324315
name={themeIcon}
325316
size="sm"
326-
className="text-[hsl(var(--palette-cloud))]"
317+
className="text-muted-foreground"
327318
aria-hidden="true"
328319
/>
329320
{themeLabel}

app/routes/_app+/_marketing+/index.tsx

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ export default function Index() {
1212
<section className="container grid gap-10 lg:grid-cols-[0.95fr_1.05fr] lg:items-center">
1313
<div className="order-1 flex justify-center lg:order-2">
1414
<div className="relative w-full max-w-xs sm:max-w-sm">
15-
<div className="absolute top-1/2 left-1/2 h-[260px] w-[260px] -translate-x-1/2 -translate-y-1/2 rounded-full bg-[hsl(var(--palette-baby-blue))] sm:h-[320px] sm:w-[320px]" />
15+
<div className="bg-hero-orb absolute top-1/2 left-1/2 h-[260px] w-[260px] -translate-x-1/2 -translate-y-1/2 rounded-full sm:h-[320px] sm:w-[320px]" />
1616
<Icon
1717
name="star"
1818
size="lg"
1919
aria-hidden="true"
20-
className="absolute top-2 left-2 text-[hsl(var(--palette-orange))]"
20+
className="text-hero-sparkle absolute top-2 left-2"
2121
/>
2222
<Icon
2323
name="star"
2424
size="md"
2525
aria-hidden="true"
26-
className="absolute top-16 left-12 text-[hsl(var(--palette-orange))]"
26+
className="text-hero-sparkle absolute top-16 left-12"
2727
/>
28-
<div className="absolute top-24 left-4 h-6 w-10 rounded-full bg-[hsl(var(--palette-orange))]" />
29-
<div className="absolute bottom-6 left-6 h-12 w-12 rounded-[22px] bg-[hsl(var(--palette-orange))]" />
30-
<div className="absolute top-1/2 -right-2 flex h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full bg-[hsl(var(--palette-green-500))] text-[hsl(var(--palette-cream))] shadow-lg">
28+
<div className="bg-hero-sparkle absolute top-24 left-4 h-6 w-10 rounded-full" />
29+
<div className="bg-hero-sparkle absolute bottom-6 left-6 h-12 w-12 rounded-[22px]" />
30+
<div className="bg-brand text-brand-foreground absolute top-1/2 -right-2 flex h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full shadow-lg">
3131
<Icon name="message" size="sm" aria-hidden="true" />
3232
</div>
3333
<img
@@ -81,17 +81,17 @@ export default function Index() {
8181
</section>
8282

8383
<section className="container mt-16">
84-
<div className="relative overflow-hidden rounded-[48px] bg-[hsl(var(--palette-green-700))] px-6 py-12 text-[hsl(var(--palette-cream))] shadow-sm dark:bg-[hsl(var(--palette-green-900))]">
85-
<div className="absolute -top-6 -left-6 hidden h-20 w-20 rounded-full bg-[hsl(var(--palette-sunny))] opacity-80 md:block" />
86-
<div className="absolute right-10 -bottom-6 hidden h-24 w-24 rounded-[32px] bg-[hsl(var(--palette-orange))] opacity-70 md:block" />
84+
<div className="bg-marketing-feature text-marketing-feature-foreground relative overflow-hidden rounded-[48px] px-6 py-12 shadow-sm">
85+
<div className="bg-marketing-feature-accent absolute -top-6 -left-6 hidden h-20 w-20 rounded-full opacity-80 md:block" />
86+
<div className="bg-marketing-feature-accent-secondary absolute right-10 -bottom-6 hidden h-24 w-24 rounded-[32px] opacity-70 md:block" />
8787
<div className="mx-auto max-w-3xl text-center">
88-
<p className="text-xs font-semibold tracking-[0.3em] text-[hsl(var(--palette-green-100))] uppercase">
88+
<p className="text-marketing-feature-muted text-xs font-semibold tracking-[0.3em] uppercase">
8989
Messages written by you
9090
</p>
9191
<h2 className="mt-3 text-3xl font-bold md:text-4xl">
9292
Messages written by you... Not by AI.
9393
</h2>
94-
<p className="mx-auto mt-4 max-w-2xl text-base text-[hsl(var(--palette-green-100))]">
94+
<p className="text-marketing-feature-muted mx-auto mt-4 max-w-2xl text-base">
9595
Our platform schedules and delivers personal, heartfelt messages
9696
on your schedule, so you can stay connected without losing your
9797
voice.
@@ -150,7 +150,7 @@ export default function Index() {
150150
key={step.title}
151151
className="border-border bg-card rounded-[28px] border p-6 shadow-sm"
152152
>
153-
<p className="text-3xl font-bold text-[hsl(var(--palette-chestnut))]">
153+
<p className="text-marketing-step-index text-3xl font-bold">
154154
{String(index + 1).padStart(2, '0')}
155155
</p>
156156
<h3 className="text-foreground mt-2 text-xl font-bold">
@@ -186,9 +186,7 @@ export default function Index() {
186186
1 message per day
187187
</p>
188188
</div>
189-
<p className="text-2xl font-bold text-[hsl(var(--palette-cloud))]">
190-
$4.99
191-
</p>
189+
<p className="text-price-basic text-2xl font-bold">$4.99</p>
192190
</div>
193191
<div className="mt-6">
194192
<Button asChild variant="secondary">
@@ -204,9 +202,7 @@ export default function Index() {
204202
10 messages per day
205203
</p>
206204
</div>
207-
<p className="text-2xl font-bold text-[hsl(var(--palette-chestnut))]">
208-
$14.99
209-
</p>
205+
<p className="text-price-premium text-2xl font-bold">$14.99</p>
210206
</div>
211207
<div className="mt-6">
212208
<Button asChild>
@@ -219,24 +215,21 @@ export default function Index() {
219215
</section>
220216

221217
<section className="container py-16">
222-
<div className="rounded-[32px] bg-[hsl(var(--palette-dust-pink))] px-8 py-12 text-[hsl(var(--palette-chocolate))]">
218+
<div className="bg-marketing-cta text-marketing-cta-foreground rounded-[32px] px-8 py-12">
223219
<div className="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
224220
<div className="space-y-3">
225-
<p className="text-xs font-semibold tracking-[0.3em] text-[hsl(var(--palette-chestnut))] uppercase">
221+
<p className="text-marketing-cta-accent text-xs font-semibold tracking-[0.3em] uppercase">
226222
Ready to start
227223
</p>
228224
<h2 className="text-3xl font-bold md:text-4xl">
229225
Create your account today and get 2 weeks for free.
230226
</h2>
231-
<p className="text-body-sm text-[hsl(var(--palette-chestnut))]">
227+
<p className="text-marketing-cta-accent text-body-sm">
232228
No credit card required to get started.
233229
</p>
234230
</div>
235231
<div className="flex flex-col gap-3 sm:flex-row">
236-
<Button
237-
asChild
238-
variant="warm"
239-
>
232+
<Button asChild variant="warm">
240233
<Link to="/login">Get started</Link>
241234
</Button>
242235
</div>

app/routes/_app+/recipients+/$recipientId.index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ export default function RecipientRoute() {
605605
{hasAnyMessages ? (
606606
<div
607607
ref={setScrollContainer}
608-
className="max-h-[65vh] overflow-y-auto bg-[linear-gradient(90deg,_hsl(var(--palette-cream)),_hsl(var(--palette-beige))_45%,_hsl(0_0%_100%)_100%)] px-4 py-5 sm:px-5 sm:py-6"
608+
className="thread-gradient max-h-[65vh] overflow-y-auto px-4 py-5 sm:px-5 sm:py-6"
609609
>
610610
{hasPastMessages || pastNextCursor ? (
611611
<div className="text-muted-foreground flex flex-col items-center gap-2 text-xs font-semibold tracking-[0.2em] uppercase">
@@ -615,7 +615,7 @@ export default function RecipientRoute() {
615615
<ul className="flex flex-col gap-4 sm:gap-5">
616616
{pastMessagesForDisplay.map((m) => (
617617
<li key={m.id} className="flex flex-col items-end gap-1">
618-
<div className="max-w-[75%] rounded-[24px] bg-[hsl(var(--palette-green-500))] px-4 py-3 text-sm leading-relaxed text-[hsl(var(--palette-cream))] shadow-sm sm:max-w-[65%] sm:px-5 sm:py-4">
618+
<div className="bg-message-bubble text-message-bubble-foreground max-w-[75%] rounded-[24px] px-4 py-3 text-sm leading-relaxed shadow-sm sm:max-w-[65%] sm:px-5 sm:py-4">
619619
<p className="whitespace-pre-wrap">{m.content}</p>
620620
</div>
621621
<time
@@ -632,7 +632,7 @@ export default function RecipientRoute() {
632632
</ul>
633633
</div>
634634
) : (
635-
<div className="bg-[linear-gradient(90deg,_hsl(var(--palette-cream)),_hsl(var(--palette-beige))_45%,_hsl(0_0%_100%)_100%)] px-4 py-10 text-center text-sm sm:px-5 sm:py-12">
635+
<div className="thread-gradient px-4 py-10 text-center text-sm sm:px-5 sm:py-12">
636636
<p className="text-muted-foreground">{emptyThreadMessage}</p>
637637
<Link
638638
to="new"
@@ -647,7 +647,7 @@ export default function RecipientRoute() {
647647
<newMessageFetcher.Form
648648
method="POST"
649649
action="new"
650-
className="border-border/40 rounded-full border bg-white p-2 shadow-sm transition focus-within:rounded-[28px] focus-within:border-border/60 focus-within:shadow-md"
650+
className="border-border/40 bg-card focus-within:border-border/60 rounded-full border p-2 shadow-sm transition focus-within:rounded-[28px] focus-within:shadow-md"
651651
>
652652
<label htmlFor="new-message" className="sr-only">
653653
Add a new message
@@ -706,7 +706,7 @@ function MessageForms({ message }: { message: FutureMessage }) {
706706
},
707707
shouldRevalidate: 'onBlur',
708708
})
709-
const cardTone = 'bg-[hsl(var(--palette-blues))]'
709+
const cardTone = 'bg-message-card'
710710
const scheduleLabel = message.sendAtDisplay
711711
? `Scheduled for ${message.sendAtDisplay}`
712712
: 'Scheduled message'
@@ -762,9 +762,9 @@ function MessageForms({ message }: { message: FutureMessage }) {
762762
return (
763763
<li className="flex flex-col items-end gap-2">
764764
<div
765-
className={`max-w-[75%] rounded-[24px] px-4 py-3 text-[hsl(var(--palette-cream))] shadow-sm sm:max-w-[65%] sm:px-5 sm:py-4 ${cardTone}`}
765+
className={`text-message-card-foreground max-w-[75%] rounded-[24px] px-4 py-3 shadow-sm sm:max-w-[65%] sm:px-5 sm:py-4 ${cardTone}`}
766766
>
767-
<div className="flex items-start justify-between gap-4 text-[0.7rem] font-semibold tracking-[0.2em] text-[hsl(var(--palette-cream))] uppercase">
767+
<div className="text-message-card-foreground flex items-start justify-between gap-4 text-[0.7rem] font-semibold tracking-[0.2em] uppercase">
768768
<div className="flex items-center gap-2">
769769
<Icon name="clock" size="sm" />
770770
<span>{scheduleLabel}</span>
@@ -846,7 +846,7 @@ function MessageForms({ message }: { message: FutureMessage }) {
846846
setCurrentContent(event.currentTarget.value)
847847
}}
848848
ref={textareaRef}
849-
className="mt-2 w-full resize-none bg-transparent text-sm leading-relaxed text-[hsl(var(--palette-cream))] placeholder:text-[hsl(var(--palette-cream))]/80 focus-visible:outline-none"
849+
className="text-message-card-foreground placeholder:text-message-card-foreground/80 mt-2 w-full resize-none bg-transparent text-sm leading-relaxed focus-visible:outline-none"
850850
rows={2}
851851
/>
852852
</updateContentFetcher.Form>

0 commit comments

Comments
 (0)