mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 19:07:17 +01:00
Drop motion-tokens twin; shipped (DOCS-motion)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d666e47e16
commit
82119bdd47
@ -1,140 +0,0 @@
|
||||
Add motion, haptic and sound tokens to the unified design system
|
||||
|
||||
## findings (3, ranked by value over effort)
|
||||
|
||||
1. **No motion token exists in any stack** — greenfield. Every app that wants an
|
||||
animation currently invents its own number, and one already has.
|
||||
2. **No haptic vocabulary exists** — the highest-value gap, because
|
||||
`HapticFeedback` needs no dependency, so three of four apps can adopt it
|
||||
the day this lands.
|
||||
3. **`tokens.md` is 260 lines against a 250 cap** — it cannot absorb a new
|
||||
section, so motion needs a sibling file.
|
||||
|
||||
## what
|
||||
|
||||
The shared design system has colour, spacing, radius, type and shadow tokens —
|
||||
and **no motion tokens at all**. Verified 2026-08-16: no `Duration`, `Curve`,
|
||||
`--duration-*`, `--ease-*`, or haptic constant exists in any stack copy. There is
|
||||
not even a prose position that motion is out of scope.
|
||||
|
||||
Consequence across kuhy's Flutter fleet: **exactly one animation exists in four
|
||||
apps** — a lone `AnimatedContainer(duration: Duration(milliseconds: 200))` with an
|
||||
inline magic number. Every other transition is a Flutter/browser default.
|
||||
|
||||
Create the motion token layer so the per-app prompts (03–09) have something
|
||||
canonical to consume instead of each inventing durations.
|
||||
|
||||
## where
|
||||
|
||||
Repo: `~/src/utils` (git repo, has CI + the file-length gate wired).
|
||||
|
||||
**Create** `~/src/utils/unified-design-system/motion.md` — the prose freeze.
|
||||
|
||||
**Do NOT append to `~/src/utils/unified-design-system/tokens.md`.** It is 260 lines
|
||||
and the cap is 250, so it already fails the gate; adding to it makes that worse.
|
||||
`screen-size.md` was split out of it for exactly this reason — follow that
|
||||
precedent and add a pointer line in `tokens.md` only if you can do so without
|
||||
growing it (i.e. by shortening another line).
|
||||
|
||||
Then mirror the tokens into the three code stacks:
|
||||
|
||||
| Stack | File | Form |
|
||||
|---|---|---|
|
||||
| Flutter/Dart | `~/src/utils/design_system/lib/src/tokens.dart` | `class AppDuration` / `class AppCurve` |
|
||||
| web/React | `~/src/utils/web_ui/src/tokens.css` | `--duration-*`, `--ease-*` custom props |
|
||||
| Python/Tkinter | `~/src/utils/gatelock/gatelock/_window.py` (`class LockConfig`) | int ms fields — **only if meaningful**; see `must not` |
|
||||
|
||||
There are **three** code stacks plus the prose freeze. Do not go hunting for a
|
||||
fourth — it does not exist.
|
||||
|
||||
## must
|
||||
|
||||
- Define a **small** scale. Recommended, but use judgement:
|
||||
`instant 0ms · fast 120ms · base 200ms · slow 320ms`, and easing
|
||||
`standard (0.2, 0, 0, 1)` · `decelerate (0, 0, 0, 1)` · `accelerate (0.3, 0, 1, 1)`.
|
||||
Justify each value in `motion.md` in one line — the file is a freeze, so the
|
||||
reasoning has to survive without you.
|
||||
- Include a **haptic** vocabulary mapped to Flutter's `HapticFeedback` API:
|
||||
which semantic event gets `selectionClick` vs `lightImpact` vs `mediumImpact`.
|
||||
This is the highest-value part — `HapticFeedback` needs no dependency, so
|
||||
three of four apps can adopt it immediately.
|
||||
- Include a **sound** vocabulary: named semantic cues (`confirm`, `complete`,
|
||||
`error`) with the rule that sound ships **on** (opt-out) per app, and that
|
||||
each app owns its own asset files.
|
||||
- State the reduced-motion contract in `motion.md`: web uses
|
||||
`@media (prefers-reduced-motion: reduce)`, Flutter uses
|
||||
`MediaQuery.of(context).disableAnimations`. Motion tokens collapse to `0ms`
|
||||
under it; **haptics and sound are unaffected** (they are not motion).
|
||||
- Keep every file at or under **250 lines** (`~/src/utils/file_length/config.py`,
|
||||
`MAX_LINES = 250`). `.md` and `.py` are capped; `.css` is not.
|
||||
- **Cut tags at the end** — this is the step that makes the work reach consumers:
|
||||
- `design_system-v0.2.0` (consumed by `~/src/todo`, currently on `v0.1.0`)
|
||||
- `web_ui-v0.3.2` (consumed by `~/src/dufs-cloud/web`, currently on `v0.3.1`)
|
||||
Print both tag names at the end of the session; prompts 06, 07 and 08 need them.
|
||||
|
||||
- must not: add motion values to the Tkinter `LockConfig` just for symmetry.
|
||||
Tkinter has no animation framework. If a duration has no meaning there, mark
|
||||
the row `n/a (tk)` in `motion.md` and leave the Python alone. An honest `n/a`
|
||||
beats a dead constant.
|
||||
- must not: express any motion token as a hex-looking value. The existing
|
||||
`palette_check.py` parses `#RRGGBB` and would either ignore it or trip on it.
|
||||
- must not: touch any colour token, or add a colour alongside the motion work.
|
||||
That *would* break `palette_check.py`'s completeness half.
|
||||
- must not: add `# noqa` or `type: ignore` anywhere.
|
||||
|
||||
- optional: a `prefers-reduced-motion` helper in
|
||||
`~/src/utils/design_system/lib/src/` and/or `web_ui/src/` so consumers get the
|
||||
collapse behaviour without reimplementing it. Nice, not required.
|
||||
|
||||
## done
|
||||
|
||||
All four hold:
|
||||
|
||||
1. `~/src/utils/unified-design-system/motion.md` exists, is ≤250 lines, and defines
|
||||
duration, easing, haptic and sound vocabularies with a one-line rationale each.
|
||||
2. `python3 ~/src/utils/file_length/check.py` (or
|
||||
`~/src/utils/scripts/check_file_length.sh --all`) reports **no new** violations.
|
||||
`tokens.md` (260), `nielsen-audit.md` (258) and `README.md` (257) are
|
||||
pre-existing failures — do not fix them here, but do not add a fourth.
|
||||
3. `python3 ~/src/utils/unified-design-system/scripts/palette_check.py` still exits 0.
|
||||
4. Both tags exist: `git -C ~/src/utils tag | grep -E 'design_system-v0.2.0|web_ui-v0.3.2'`
|
||||
prints two lines.
|
||||
|
||||
## verify
|
||||
|
||||
Desktop, any way you like — this prompt ships no UI. Run the two gate commands in
|
||||
`done` and paste their output. Then confirm the token names you chose are what
|
||||
prompts 03–09 will reference by printing the Dart class and the CSS custom-prop
|
||||
block.
|
||||
|
||||
## read first
|
||||
|
||||
- `~/src/utils/unified-design-system/tokens.md` — the existing freeze; match its
|
||||
table format and tone exactly. Note its length problem before editing.
|
||||
- `~/src/utils/unified-design-system/screen-size.md` — the precedent for a sibling
|
||||
file split out of `tokens.md` (32 lines; short and self-contained).
|
||||
- `~/src/utils/design_system/lib/src/tokens.dart` — `AppPalette`, `AppSpacing`,
|
||||
`AppRadius`, `AppTextSize`. Your `AppDuration`/`AppCurve` sit alongside these.
|
||||
- `~/src/utils/web_ui/src/tokens.css` — the full custom-prop list.
|
||||
- `~/src/utils/design_system/lib/src/feedback.dart` — `showToast`/`showError` and
|
||||
`_show`. `confirm.dart` next to it **already imports
|
||||
`package:flutter/services.dart`**, so `HapticFeedback` is one call away with no
|
||||
new import. This is the natural home for a shared haptic helper.
|
||||
- `~/src/utils/unified-design-system/scripts/palette_check.py` — read the four
|
||||
`parse_*` regexes to see why motion tokens are invisible to it. Prompt 02
|
||||
builds the checker that covers them; **do not extend this script here.**
|
||||
|
||||
## context you would otherwise rediscover
|
||||
|
||||
- **Green CI does not mean no drift for these tokens.** `palette_check.py` only
|
||||
matches `#RRGGBB`, so a `--duration-fast: 120ms` is invisible to every one of
|
||||
its parsers. `palette_map.py:159` claims structural values are "checked by the
|
||||
scale check" — **no such script exists**. Prompt 02 writes it.
|
||||
- `~/src/utils/gatelock/` is a package inside the `~/src/utils` monorepo, not a
|
||||
standalone repo. It is consumed as a pinned git dependency.
|
||||
- Only `~/src/todo` depends on `design_system`; diet-guard, workout_app and
|
||||
wake_alarm hand-transcribe the token values into local `lib/ui/theme.dart`
|
||||
copies. So tokens added here reach exactly one app automatically — the others
|
||||
are handled per-prompt.
|
||||
|
||||
REMOVE ME AFTER FINISH
|
||||
Loading…
Reference in New Issue
Block a user