Skip to content

Commit 294c2d7

Browse files
authored
feat(typography): unify body to 16px baseline + reposition bird tufts/sleeves (#58)
**Typography baseline.** Anchors every routed sheet on a six-step scale aimed at Sec students reading long-form reflection on phones: text-xs 12px eyebrows, badges, numerical labels text-sm 14px chrome, metadata, secondary captions text-base 16px ALL prose body (paragraphs, descriptions) text-lg 18px sub-headings, card titles text-xl 20px section headings (h3) text-2xl 24px page headings (h2) 16px clears WCAG, prevents iOS input auto-zoom, and matches the BBC/Guardian/Apple News range for sustained mobile reading. For developing readers (~13-16), it cuts cognitive load enough to justify the slight density loss versus 14px. Line-heights settle on relaxed (1.625) for body, snug (1.375) for sub-headings, tight (1.25) for page titles. Touched surfaces: - sheet.tsx primitive: SheetEyebrow 11px→text-xs, SheetDescription text-sm→text-base - ProfileSheet: paragraph thesis/evidence, BigFive trait body, score readouts, quote, eyebrow + replaced text-black/[0.NN] alpha magic numbers with --color-sheet-ink-soft token - LettersSheet, SettingsSheet, HistorySheet: body prose text-sm→text-base, kept text-sm for list-row chrome - TrajectorySheet, DayDetailCard, GrowthIslandPreview, CalendarPane: eyebrow text-[10/11px]→text-xs and one text-[13.5px]→text-base - Removed every arbitrary text-[Npx] from src/components/student-space/sheets/ **Bird visibility.** PR #57 added hair tufts + cap-sleeves but positioned the cones inside the head sphere and the cylinders mostly inside the torso — visually invisible. Repositioned: - Hair tufts: y=0.90-1.10 in head-local (was 0.32-0.45) so the cone base clears the head sphere; center cone taller and tilted forward, side cones shorter and fanned out - Cap-sleeves: x=±0.55 (was ±0.46), larger taper (0.34-0.40 radius, 0.50 length) so the outer face shows past the body No animation changes; all four routed sheets continue rendering the same content layout, just sized for a phone in a teenager's hand.
1 parent 2eb7de8 commit 294c2d7

10 files changed

Lines changed: 80 additions & 68 deletions

File tree

src/components/student-space/sheets/CalendarPane.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ export function CalendarPane({
221221
</BaseButton>
222222
</div>
223223
</header>
224-
<div className="mb-1.5 grid grid-cols-7 text-center text-[11px] font-semibold text-(--color-sheet-ink-soft)">
224+
<div className="mb-1.5 grid grid-cols-7 text-center text-xs font-semibold text-(--color-sheet-ink-soft)">
225225
{DAY_LABELS.map((d, i) => (
226226
// biome-ignore lint/suspicious/noArrayIndexKey: weekday labels are positional
227227
<div key={i}>{d}</div>
@@ -294,7 +294,7 @@ export function CalendarPane({
294294
/>
295295
) : null}
296296
{cellEvents > 0 ? (
297-
<span aria-hidden className="text-[10px] leading-none">
297+
<span aria-hidden className="text-xs leading-none">
298298
·
299299
</span>
300300
) : null}
@@ -313,7 +313,7 @@ function CalendarLegend() {
313313
return (
314314
<ul
315315
aria-label="Calendar marker legend"
316-
className="mt-3 flex flex-wrap items-center gap-x-3 gap-y-1.5 border-t border-(--color-sheet-divider)/70 pt-3 text-[11px] text-(--color-sheet-ink-soft)"
316+
className="mt-3 flex flex-wrap items-center gap-x-3 gap-y-1.5 border-t border-(--color-sheet-divider)/70 pt-3 text-xs text-(--color-sheet-ink-soft)"
317317
>
318318
<li className="inline-flex items-center gap-1.5">
319319
<span aria-hidden className="size-1.5 rounded-full bg-(--color-sheet-ink)" />
@@ -328,7 +328,7 @@ function CalendarLegend() {
328328
Photo
329329
</li>
330330
<li className="inline-flex items-center gap-1.5">
331-
<span aria-hidden className="text-[10px] leading-none text-(--color-sheet-ink)">
331+
<span aria-hidden className="text-xs leading-none text-(--color-sheet-ink)">
332332
·
333333
</span>
334334
Event

src/components/student-space/sheets/DayDetailCard.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ export function DayDetailCard({
229229
className="rounded-2xl border border-(--color-sheet-divider) bg-(--color-sheet-pane-left) p-5"
230230
>
231231
<header className="mb-4">
232-
<p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
232+
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
233233
Day
234234
</p>
235235
<h3 className="mt-0.5 text-base font-semibold text-(--color-sheet-ink)">
@@ -242,7 +242,7 @@ export function DayDetailCard({
242242
<div className="space-y-5">
243243
{moods.length > 0 ? (
244244
<div>
245-
<p className="mb-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
245+
<p className="mb-2 text-xs font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
246246
Moods
247247
</p>
248248
<ul className="space-y-1.5">
@@ -275,7 +275,7 @@ export function DayDetailCard({
275275
) : null}
276276
{captures.length > 0 ? (
277277
<div>
278-
<p className="mb-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
278+
<p className="mb-2 text-xs font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
279279
Captures
280280
</p>
281281
<ul className="space-y-2">
@@ -309,7 +309,7 @@ export function DayDetailCard({
309309
) : null}
310310
{events.length > 0 ? (
311311
<div>
312-
<p className="mb-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
312+
<p className="mb-2 text-xs font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
313313
Events
314314
</p>
315315
<ul className="space-y-1.5 text-sm">

src/components/student-space/sheets/GrowthIslandPreview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export function GrowthIslandPreview({ year, engine }: { year: number; engine: un
145145
className="relative aspect-[4/3] w-full overflow-hidden rounded-2xl border border-(--color-sheet-divider) bg-(--color-sheet-pane-left)"
146146
>
147147
<canvas ref={canvasRef} className="absolute inset-0 size-full" />
148-
<p className="pointer-events-none absolute bottom-2 right-3 text-[11px] font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
148+
<p className="pointer-events-none absolute bottom-2 right-3 text-xs font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
149149
Drag · scroll
150150
</p>
151151
</div>

src/components/student-space/sheets/HistorySheet.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,9 @@ function PaneHeader({
313313
{titleNode ?? title}
314314
</h2>
315315
{subtitle ? (
316-
<p className="mt-1 text-sm text-(--color-sheet-ink-soft)">{subtitle}</p>
316+
<p className="mt-1 text-base leading-relaxed text-(--color-sheet-ink-soft)">
317+
{subtitle}
318+
</p>
317319
) : null}
318320
</div>
319321
{actions ? <div className="shrink-0">{actions}</div> : null}
@@ -500,7 +502,7 @@ function GrowthYearSummary({ year, term }: { year: number; term?: number }) {
500502
return (
501503
<div className="space-y-4">
502504
{summary.narrative ? (
503-
<p className="text-sm leading-relaxed text-(--color-sheet-ink)">{summary.narrative}</p>
505+
<p className="text-base leading-relaxed text-(--color-sheet-ink)">{summary.narrative}</p>
504506
) : null}
505507
<dl className="grid grid-cols-2 gap-3 sm:grid-cols-4">
506508
<StatTile value={summary.reflections} label="Voice reflections" />

src/components/student-space/sheets/LettersSheet.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export function LettersSheet() {
123123
</SheetIdentityHeader>
124124
<div className="px-4 pb-6">
125125
{sorted.length === 0 ? (
126-
<p className="text-sm text-(--color-sheet-ink-soft)">
126+
<p className="text-base leading-relaxed text-(--color-sheet-ink-soft)">
127127
No letters yet. Your teacher will write when they notice something.
128128
</p>
129129
) : (
@@ -153,7 +153,9 @@ export function LettersSheet() {
153153
<LetterBodyContent letter={selected} />
154154
{selected.prompt ? (
155155
<div className="mt-8 rounded-xl border border-(--color-sheet-divider) bg-(--color-sheet-pane-left) p-5">
156-
<p className="text-sm text-(--color-sheet-ink)">{selected.prompt}</p>
156+
<p className="text-base leading-relaxed text-(--color-sheet-ink)">
157+
{selected.prompt}
158+
</p>
157159
<button
158160
type="button"
159161
onClick={() => handleCapture(selected.prompt ?? '')}
@@ -168,7 +170,9 @@ export function LettersSheet() {
168170
</>
169171
) : (
170172
<SheetBody>
171-
<p className="text-sm text-(--color-sheet-ink-soft)">Tap a letter to read it.</p>
173+
<p className="text-base leading-relaxed text-(--color-sheet-ink-soft)">
174+
Tap a letter to read it.
175+
</p>
172176
</SheetBody>
173177
)}
174178
</SheetContent>

src/components/student-space/sheets/ProfileSheet.tsx

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import type { CSSProperties } from 'react'
2020
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
2121
import { ChoicesPageView } from '~/components/ChoicesPageView'
2222
import { RelationshipsPageView } from '~/components/RelationshipsPageView'
23-
import { Button } from '~/components/ui/button'
2423
import {
2524
PageSurface,
2625
SheetBody,
@@ -420,7 +419,7 @@ function AccountMenuButton({ authMenu }: { authMenu: AuthMenu | undefined }) {
420419
className="absolute right-0 top-[calc(100%+8px)] z-20 w-60 rounded-xl border border-(--color-sheet-divider) bg-white p-2 shadow-[0_18px_48px_rgba(43,38,32,0.14)]"
421420
>
422421
<div className="px-3 py-2">
423-
<p className="text-[11px] font-semibold uppercase tracking-[0.12em] text-(--color-sheet-ink-soft)">
422+
<p className="text-xs font-semibold uppercase tracking-[0.12em] text-(--color-sheet-ink-soft)">
424423
{authMenu?.label || 'Signed in'}
425424
</p>
426425
{authMenu?.detail ? (
@@ -595,10 +594,10 @@ function VipsProfileTab({
595594

596595
{facet?.openQuestion ? (
597596
<aside className="rounded-xl border border-(--profile-accent)/30 bg-(--profile-soft) p-4 text-(--profile-ink)">
598-
<p className="text-[11px] font-semibold uppercase tracking-[0.16em] opacity-70">
597+
<p className="text-xs font-semibold uppercase tracking-[0.16em] opacity-70">
599598
Open question
600599
</p>
601-
<p className="mt-1 text-sm leading-6">{facet.openQuestion}</p>
600+
<p className="mt-1 text-base leading-relaxed">{facet.openQuestion}</p>
602601
</aside>
603602
) : null}
604603

@@ -609,7 +608,7 @@ function VipsProfileTab({
609608
{isPersonality ? null : (
610609
<section>
611610
<div className="mb-3 flex items-center justify-between gap-3">
612-
<h3 className="text-[11px] font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
611+
<h3 className="text-xs font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
613612
Collection
614613
</h3>
615614
{selectedClaimId ? (
@@ -679,7 +678,7 @@ function VipsProfileTab({
679678

680679
<section>
681680
<div className="mb-3 flex flex-wrap items-center justify-between gap-3">
682-
<h3 className="text-[11px] font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
681+
<h3 className="text-xs font-semibold uppercase tracking-[0.18em] text-(--color-sheet-ink-soft)">
683682
Timeline
684683
{selectedClaimId ? (
685684
<span className="ml-2 normal-case tracking-normal text-(--profile-ink)">
@@ -743,7 +742,11 @@ function ParagraphBlock({
743742
const [expanded, setExpanded] = useState(false)
744743
const text = paragraph?.trim()
745744
if (!text) {
746-
return <p className="max-w-2xl text-sm leading-6 text-(--color-sheet-ink-soft)">{fallback}</p>
745+
return (
746+
<p className="max-w-2xl text-base leading-relaxed text-(--color-sheet-ink-soft)">
747+
{fallback}
748+
</p>
749+
)
747750
}
748751
const { thesis, evidence } = splitThesisAndEvidence(text)
749752
// Reset back to clamped whenever the underlying paragraph changes (e.g.
@@ -755,13 +758,13 @@ function ParagraphBlock({
755758
const showToggle = hasEvidence && evidence.length > 160
756759
return (
757760
<div className="flex flex-col gap-3">
758-
<p className="max-w-2xl text-[15px] font-medium leading-relaxed text-(--color-sheet-ink)">
761+
<p className="max-w-2xl text-base font-semibold leading-relaxed text-(--color-sheet-ink)">
759762
{thesis}
760763
</p>
761764
{hasEvidence ? (
762765
<p
763766
className={cn(
764-
'max-w-2xl text-[13px] leading-6 text-(--color-sheet-ink-soft)',
767+
'max-w-2xl text-base leading-relaxed text-(--color-sheet-ink-soft)',
765768
showToggle && !expanded && 'line-clamp-2',
766769
)}
767770
>
@@ -808,7 +811,7 @@ function TldrHero({
808811

809812
return (
810813
<section className="rounded-2xl border border-(--profile-accent)/20 bg-[linear-gradient(135deg,var(--profile-soft),rgba(255,255,255,0.78))] p-5">
811-
<p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-(--profile-ink)">
814+
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-(--profile-ink)">
812815
{voiced.length >= 3
813816
? `Top voices in your ${PROFILE_HEADERS[tab].tag}`
814817
: `In your ${PROFILE_HEADERS[tab].tag}`}
@@ -870,7 +873,7 @@ function PersonalityTldr({ tldr }: { tldr: BigFiveTldr }) {
870873
data-testid="personality-tldr"
871874
className="rounded-2xl border border-(--profile-accent)/20 bg-[linear-gradient(135deg,var(--profile-soft),rgba(255,255,255,0.78))] p-5"
872875
>
873-
<p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-(--profile-ink)">
876+
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-(--profile-ink)">
874877
{tldr.eyebrow ?? 'YOUR PERSONALITY AT A GLANCE'}
875878
</p>
876879
{tldr.headline ? (
@@ -957,15 +960,15 @@ function BigFiveCards({ traits }: { traits: BigFiveTrait[] }) {
957960
<Icon className="size-5" />
958961
</span>
959962
<span className="flex min-w-0 shrink basis-[220px] flex-col gap-0.5 max-[720px]:col-start-2 max-[720px]:row-start-1 max-[720px]:basis-auto">
960-
<span className="text-balance text-[15px] font-semibold leading-snug tracking-tight text-(--color-sheet-ink)">
963+
<span className="text-balance text-lg font-semibold leading-snug tracking-tight text-(--color-sheet-ink)">
961964
{trait.tag ?? trait.name}
962965
</span>
963-
<span className="mt-0.5 text-[10.5px] font-semibold uppercase tracking-[0.08em] text-black/55">
966+
<span className="mt-0.5 text-xs font-semibold uppercase tracking-[0.08em] text-(--color-sheet-ink-soft)">
964967
{trait.name}
965968
</span>
966969
</span>
967970
<span className="flex min-w-0 grow basis-[280px] items-center gap-3 max-[720px]:col-span-3 max-[720px]:row-start-2 max-[720px]:basis-auto max-[720px]:border-t max-[720px]:border-dashed max-[720px]:border-black/[0.08] max-[720px]:pt-1.5">
968-
<span className="max-w-[14ch] shrink-0 text-balance text-right text-[10.5px] font-semibold uppercase leading-tight tracking-[0.06em] text-black/[0.52] max-[720px]:max-w-none max-[720px]:text-left">
971+
<span className="max-w-[14ch] shrink-0 text-balance text-right text-xs font-semibold uppercase leading-tight tracking-[0.06em] text-(--color-sheet-ink-soft) max-[720px]:max-w-none max-[720px]:text-left">
969972
{trait.poleLeft}
970973
</span>
971974
<span className="relative h-[3px] min-w-20 grow rounded-full bg-black/10">
@@ -975,7 +978,7 @@ function BigFiveCards({ traits }: { traits: BigFiveTrait[] }) {
975978
className="absolute top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-(--trait-accent) shadow-[0_0_0_3px_color-mix(in_srgb,var(--trait-accent)_22%,transparent),0_1px_0_rgba(0,0,0,0.06)] transition-[left] duration-200 ease-out"
976979
/>
977980
</span>
978-
<span className="max-w-[14ch] shrink-0 text-balance text-left text-[10.5px] font-semibold uppercase leading-tight tracking-[0.06em] text-black/[0.52] max-[720px]:max-w-none">
981+
<span className="max-w-[14ch] shrink-0 text-balance text-left text-xs font-semibold uppercase leading-tight tracking-[0.06em] text-(--color-sheet-ink-soft) max-[720px]:max-w-none">
979982
{trait.poleRight}
980983
</span>
981984
</span>
@@ -993,7 +996,7 @@ function BigFiveCards({ traits }: { traits: BigFiveTrait[] }) {
993996
className="border-t border-black/[0.06] px-[18px] pb-4 pt-3 max-[720px]:px-4"
994997
>
995998
{trait.schoolReadout ? (
996-
<p className="text-pretty text-[13px] leading-[1.55] text-black/[0.74]">
999+
<p className="text-pretty text-base leading-relaxed text-(--color-sheet-ink-soft)">
9971000
{trait.schoolReadout}
9981001
</p>
9991002
) : null}
@@ -1005,15 +1008,15 @@ function BigFiveCards({ traits }: { traits: BigFiveTrait[] }) {
10051008
className="border-t border-black/[0.06] pt-2 first:border-t-0 first:pt-0"
10061009
>
10071010
<div className="mb-1 flex items-baseline justify-between gap-2">
1008-
<span className="text-[12.5px] font-semibold tracking-tight text-(--trait-accent)">
1011+
<span className="text-sm font-semibold tracking-tight text-(--trait-accent)">
10091012
{aspect.name}
10101013
</span>
1011-
<span className="text-[12px] font-semibold tabular-nums text-black/60">
1014+
<span className="text-xs font-semibold tabular-nums text-(--color-sheet-ink-soft)">
10121015
{aspect.score}/20
10131016
</span>
10141017
</div>
10151018
{aspect.blurb ? (
1016-
<p className="text-pretty text-[12px] leading-[1.5] text-black/60">
1019+
<p className="text-pretty text-sm leading-relaxed text-(--color-sheet-ink-soft)">
10171020
{aspect.blurb}
10181021
</p>
10191022
) : null}
@@ -1096,7 +1099,7 @@ function TimelineQuote({
10961099
data-forgetting={forgetting || undefined}
10971100
className="rounded-xl border border-(--color-sheet-divider) bg-(--color-sheet-pane-left) p-4 transition-opacity data-[forgetting=true]:opacity-0"
10981101
>
1099-
<p className="text-[15px] italic leading-7 text-(--color-sheet-ink)">"{quote.text}"</p>
1102+
<p className="text-base italic leading-relaxed text-(--color-sheet-ink)">"{quote.text}"</p>
11001103
<div className="mt-3 flex flex-wrap items-center gap-2">
11011104
<span className="rounded-full bg-(--profile-soft) px-2.5 py-1 text-xs font-semibold text-(--profile-ink)">
11021105
{claimLabel(quote.canonicalClaimId)}
@@ -1219,7 +1222,7 @@ function ShareDialog({
12191222
<h2 id="share-dialog-title" className="text-xl font-semibold text-(--color-sheet-ink)">
12201223
Share your profile
12211224
</h2>
1222-
<p className="mt-1 text-sm leading-6 text-(--color-sheet-ink-soft)">
1225+
<p className="mt-1 text-base leading-relaxed text-(--color-sheet-ink-soft)">
12231226
Generate a link for parents, teachers, or friends. Quotes are hidden by default.
12241227
</p>
12251228
</div>

src/components/student-space/sheets/SettingsSheet.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export function SettingsSheet() {
6868
<SheetDescription>Tools for adjusting how the world behaves.</SheetDescription>
6969
</SheetIdentityHeader>
7070
<div className="px-7 pb-6">
71-
<p className="text-[13.5px] leading-[1.55] text-(--color-sheet-ink-soft)">
71+
<p className="text-base leading-relaxed text-(--color-sheet-ink-soft)">
7272
Adjust how the world behaves and replay the first-run ceremony. Changes apply
7373
immediately and persist across sessions.
7474
</p>

0 commit comments

Comments
 (0)