penpot design work summaries

This commit is contained in:
2026-08-20 00:36:55 -06:00
parent f731947b51
commit d2d67b43c1
3 changed files with 74 additions and 0 deletions
@@ -0,0 +1,34 @@
# Work Summary — 2026-08-10 15:43
## Task
"Play around in Penpot and see if you can generalize any of the common elements." Not a git-tracked code change — this is design-system work in the connected Penpot file. Recorded here for continuity since it's real project work.
## Context
The connected Penpot file turned out to be the *unmodified* default Tailwind CSS starter template (raw, unrenamed color swatches, a breakpoint reference, a shadow reference) - no existing mockups of this app's actual UI. Clarified with the user that "generalize the common elements" meant reverse-engineering the app's *real*, already-implemented UI (`templates/components/*.html.tmpl`, `styles/typography.css`) into actual Penpot library assets, not curating the generic starter kit.
`styles/typography.css` turned out to hold a full custom shadcn/ui-style design system already: three OKLCH color scales (`base`, `primary`, `secondary`, 50-1000 each), ~38 semantic tokens (`background`, `card`, `accent`, `border`, `chart-1..5`, `sidebar-*`, `table-*`, etc.) with distinct light/dark values via `@media (prefers-color-scheme: dark)`, and two custom fonts (Geist 600 for headings, Alexandria 300 for body).
No browser extension was available to read live computed styles, so exact OKLCH→hex conversion had to be done by hand-implementing the standard algorithm (Björn Ottosson's OKLab, CSS Color 4 matrices) inside Penpot's JS sandbox, rather than relying on assumption or memory.
## What was built in Penpot
- **OKLCH→hex conversion**: implemented and validated against known-correct reference points (pure black/white exactly, and `oklch(0.577 0.245 27.325)``#E7000B`, which independently matches shadcn/ui's well-known default destructive red) before trusting it for the full palette.
- **Design Tokens** (Penpot's native token system, chosen over flat colors specifically so light/dark could be modeled properly):
- `Primitives` set (40 tokens, always active): `base.50`-`base.1000`, `primary.50`-`primary.1000`, `secondary.50`-`secondary.1000`, `destructive.light`/`.dark`, `white`, `black`.
- `Semantic/Light` and `Semantic/Dark` sets (38 tokens each): every semantic token name the app's CSS defines, referencing the right primitive per theme.
- A `Mode` theme group (Light/Dark), Light active by default - mirrors the app's `:root` vs. `@media (prefers-color-scheme: dark)` structure. Verified references resolve correctly end-to-end.
- **Typography**: `Display/H1`-`H4`,`H6` (Geist 600, sized from Tailwind's `text-6xl`/`3xl`/`xl`/`lg`/`sm`) and `Text/Body` (Alexandria 300, 16px). `H5` deliberately skipped - the source CSS references `--text-md`, which isn't defined anywhere (a real gap in the app's CSS, not something to guess a value for).
- **Button component** (from `templates/components/button.html.tmpl`): a proper Penpot Variant group (`State` property: `Default`/`Hover`/`Active-Disabled`) built entirely from the token system rather than hardcoded colors - background/border/text colors all come from `color.card`/`color.border`/`color.foreground`/`color.accent`/`color.accent-secondary` tokens. Visually verified via export at each stage.
## A real Penpot platform quirk hit and worked around
`penpot.createVariantFromComponents` (and the `penpotUtils.createVariantContainer` wrapper built on it) failed with a server-side validation error (`Value not valid: [object ShapeProxy]... Code: :shapes`) when passed boards where two of the three had been created via `.clone()` of a board that was *already* a component's main instance. Isolated the cause with targeted diagnostics (confirmed flex layout alone was fine; confirmed applied color tokens alone were fine; the only remaining variable - clone-of-an-existing-main-instance - was the actual cause). Fix: rebuild each variant state as an independent board from scratch rather than cloning an already-componentized one, then create each as its own component before combining. Worth remembering if building more variant groups in this file.
## Verification
- OKLCH conversion validated against known reference values before trusting it for ~40 colors.
- Token resolution spot-checked (`color.background``#FAFAFE`, `color.primary``#B8E954`, `color.destructive``#E7000B`), all correct.
- Button auto-sizing confirmed (73×36, correctly hugging text + 8px padding on `p-[0.5em]` at 16px base).
- All three button states exported and visually inspected individually and as a working variant group; no `variantError` on any of the three.
- A Penpot plugin disconnect happened mid-session (browser-side, not caused by this work) - the already-computed, validated hex map was saved to the scratchpad before it could be lost, and reloaded directly (no recomputation needed) once reconnected.
## Follow-ups / not done here
- `Accordion` (`templates/components/accordion.html.tmpl`) and `TutorialTooltip` (`templates/components/tutorial-tooltip.html.tmpl`) components not yet built - user chose to first wire the Button into a proper Variant group (done above) rather than continue to these; picking this back up is the natural next step.
- `H5` typography intentionally left unresolved (`--text-md` undefined in source CSS) - worth a decision on the actual code side (define `--text-md`, or change `h5` to reference an existing size) independent of the Penpot work.