150 lines
8.0 KiB
Markdown
150 lines
8.0 KiB
Markdown
# Onboarding illustrations — the decided direction
|
||
|
||
```
|
||
Status: Current
|
||
Owner: _null
|
||
Last reviewed: 2026-08-20
|
||
Governs: docs/design/dist/** — the onboarding illustration set and what it is for
|
||
Review trigger: Any illustration added or replaced here; the onboarding artwork
|
||
in issue #29 landing in the app
|
||
```
|
||
|
||
> **References, not shipping assets.** Nothing in this folder goes in the APK.
|
||
> These are the decided direction for onboarding, drawn from
|
||
> [`../BRAND_GUIDE.md`](../BRAND_GUIDE.md) §22's master prompt. The vectors that
|
||
> eventually ship are drawn *from* these.
|
||
|
||
Seven illustrations in a matched light/dark pair, named for the composables they
|
||
replace in
|
||
[`../../../core/designsystem/src/main/kotlin/dev/privacyllc/period/designsystem/art/Illustrations.kt`](../../../core/designsystem/src/main/kotlin/dev/privacyllc/period/designsystem/art/Illustrations.kt):
|
||
|
||
| File stem | Onboarding step | Composable |
|
||
| --- | --- | --- |
|
||
| `01_WelcomeIllustration` | 1 Welcome | `WelcomeIllustration` |
|
||
| `02_LastPeriodIllustration` | 2 Last period start | *new* |
|
||
| `03_PeriodEndIllustration` | 3 Period end | *new* |
|
||
| `04_LearningIllustration` | 4 Previous history | `LearningIllustration` |
|
||
| `05_PrivacyIllustration` | 5 Privacy promise | `PrivacyIllustration` |
|
||
| `06_NotificationPrivacyIllustration` | 6 Reminder privacy | *new* |
|
||
| `07_ForecastIllustration` | 7 First forecast | *new* |
|
||
| `EmptyStateIllustration` | — not onboarding | `EmptyStateIllustration` |
|
||
|
||
Each stem exists as `Light/<stem>_light.webp` and `Dark/<stem>_dark.webp`, at
|
||
the **same aspect ratio**, so a theme switch swaps the image without moving the
|
||
layout. Fifteen are 2048 × 1365; `07_Forecast` dark is 1536 × 1024, which is the
|
||
same 3:2 to within 0.02% — 274.00 dp tall against 273.93 at a 411 dp hero.
|
||
|
||
**They are 3:2 landscape, composed for a full-bleed hero.** That is the second
|
||
attempt. The first delivery met the canvas size by upscaling the old portrait
|
||
art ~2.8× and padding the sides with a blurred copy of itself: measured edge
|
||
detail fell 2.1×–8.8× in the outer quarters on 15 of 16 files, and at real hero
|
||
size a hard seam showed around the sharp centre. The canvas was right and the
|
||
composition was still portrait.
|
||
|
||
The set here is natively wide — real painted content to all four edges, verified
|
||
by measuring detail across each image and looking for a step change that would
|
||
betray a pasted rectangle. None has one.
|
||
|
||
`EmptyStateIllustration` is the odd one and deliberately unnumbered: it is
|
||
Today's "nothing logged yet" state, not an onboarding step, and it is also drawn
|
||
in the onboarding previews. Its ring is empty because nothing has been logged —
|
||
the same ring the other illustrations fill with cycle-day markers, which is what
|
||
makes the empty state read as *waiting* rather than *broken*.
|
||
|
||
## What these got right, and why it is worth not undoing
|
||
|
||
Each of these was a correction during review, and every one of them would be easy
|
||
to reintroduce by regenerating carelessly:
|
||
|
||
- **No text of any kind is painted into the pixels.** The app renders all seven
|
||
titles and subtitles itself through `Heading(...)` in `OnboardingScreen.kt`.
|
||
Art carrying its own title prints every heading twice, cannot be translated,
|
||
cannot scale with the user's font size, and is invisible to TalkBack.
|
||
- **No step-number badge.** `LearningIllustration` is not only onboarding step 4
|
||
— it is also the Insights empty state, where a "4" means nothing. Baked numbers
|
||
also freeze the running order, and this flow has already changed shape once. A
|
||
step indicator, if wanted, belongs in live UI where TalkBack can read it.
|
||
- **`07_Forecast` shows a calendar and a cycle arc, and names no fields.** An
|
||
earlier draft drew a forecast panel listing *Fertile window* and *Ovulation*,
|
||
which the real first-forecast screen deliberately does not show — on a fresh
|
||
install it reports confidence Low and Today reads "Not enough history to
|
||
estimate". A later draft named the correct fields but painted *Confidence —
|
||
Low* permanently, which is wrong for anyone with a settled cycle. Naming
|
||
nothing is the only version that cannot contradict the live forecast.
|
||
- **`01_Welcome` is overlapping cycle rings in both themes.** Dark `01` once
|
||
drifted into the forecast vocabulary — calendar, dashed predicted days and an
|
||
arrow — while light `01` stayed correct. Judge any future replacement against
|
||
light `01`, not dark `07`.
|
||
- **The dark set is a real dark composition**, not the light one dimmed — the
|
||
midnight-plum ground `BRAND_GUIDE.md` §22 specifies.
|
||
|
||
## These now ship
|
||
|
||
**#29 is closed.** All eight are in the app, in both themes, as WebP drawables in
|
||
[`../../../core/designsystem/src/main/res/`](../../../core/designsystem/src/main/res/)
|
||
— `drawable/` for light and `drawable-night/` for dark, so Android resolves the
|
||
theme rather than any code of ours. The files here stay as the full-resolution
|
||
sources; the shipped copies are downscaled to the height they are actually drawn
|
||
at.
|
||
|
||
They are **not** redrawn as vectors, which is what #29 originally called for.
|
||
That was the right plan for artwork that did not exist and the wrong one for
|
||
gradient landscapes: there is no honest `VectorDrawable` of one, §42 objects only
|
||
to *unnecessary* raster, and the whole set costs 130 KB of the release APK.
|
||
`CycleMarkers.kt` keeps its vectors, because a marker's shape carries meaning and
|
||
the progress arc is drawn from the user's own cycle.
|
||
|
||
**The painted-in corners needed clipping.** Each drawing is composed as a card
|
||
with its own rounded corner, so the pixels outside that curve are the card's own
|
||
backdrop — near-black in the dark set, near-white in the light one. Drawn
|
||
unclipped they showed as four notches against the app background: obvious on a
|
||
device, invisible in code review. `Illustration` in `Illustrations.kt` clips just
|
||
inside the painted curve, and what is left reads as a deliberate rounded card.
|
||
|
||
## `splash.webp` — the redrawn lockup
|
||
|
||
Not an onboarding illustration, and it sits here because it arrived with them.
|
||
It is the full brand lockup — emblem, wordmark, divider, tagline — and it is the
|
||
artwork that closed **#28**: the first lockup set the name as
|
||
*Privacy:Period Tracker* with no space after the colon, disagreeing with
|
||
`app_full_name` and with every document.
|
||
|
||
`../../data/img/logo.webp` and `banner.webp` are generated from it:
|
||
|
||
```bash
|
||
magick splash.webp -trim +repage -resize 900x900 lockup.png
|
||
magick -size 1024x1024 xc:'#F0E6F0' -fill '#FAF0F5' \
|
||
-draw 'roundrectangle 8,8,1015,1015,88,88' \
|
||
lockup.png -gravity center -composite -quality 86 logo.webp
|
||
```
|
||
|
||
The banner is the same recipe on a 2176×725 canvas with a 660px square card
|
||
centred. **It is composed, never cropped** — the lockup is square and a 3:1 crop
|
||
takes the wordmark's ends off, which is the trap the first pass at these assets
|
||
hit.
|
||
|
||
No flood-fill this time: `splash.webp` has real transparency, where the earlier
|
||
sources rendered their rounded corners against black.
|
||
|
||
## Format
|
||
|
||
WebP at the delivered resolution — 4.2 MB for all sixteen, and the same format
|
||
[`../../data/img/`](../../data/img/) uses for the marks privacyllc.dev renders.
|
||
The delivery `.zip` archives are deliberately not tracked; see
|
||
[`.gitignore`](.gitignore).
|
||
|
||
**These are sources, not shipping assets, and the size is why that matters.** A
|
||
2048 px file dropped into a density-less `drawable/` is decoded at the device's
|
||
bucket and costs ~11 MB of heap on every device. The shipped copies are
|
||
downscaled into `drawable-*dpi` buckets — see the KDoc in `Illustrations.kt`.
|
||
|
||
## Two things left unmatched, deliberately
|
||
|
||
- **`07_Forecast` light and dark are different compositions.** Light draws a
|
||
partial ring of hollow beads; dark draws a full arc of dashed circles ending
|
||
in an arrow. Dark states "predicted" more clearly, so it is the one to copy if
|
||
they are ever reconciled — not the other way round.
|
||
- **Eight of the sixteen have a busy bottom quarter**, mostly the dark set,
|
||
where foliage and water reach into the band the fade covers. The fade still
|
||
works; it simply covers more drawing than intended.
|