Privacy-Period-Tracker/docs/design/dist/README.md

8.0 KiB
Raw Permalink Blame History

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 §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:

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/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:

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/ uses for the marks privacyllc.dev renders. The delivery .zip archives are deliberately not tracked; see .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.