move: the plumbing that makes the carried set self-standing
commit e3632990bf0537f8b9c0f287d11593f15a91e049 · parent 76fc25b2da
· browse this tree
Ximianth, 2026-10-10 05:13:04 UTC
Every edit here is one the move needed and nothing more; the next
commits add the harness and packaging, and later steps reformat and
rename. Against the verbatim parent commit, this is the whole diff of
the carried bodies:
- tokens.ts: the "ownership" group goes. Its one token was the
incubating app's own-faction color, not a kit value; nothing in the
kit set consumed it.
- doc citations in comments: docs/ui/{ui-ux-guidelines,design-tokens}.md
become this repo's docs/precepts-we-love-the-keyboard.md and
docs/precepts-aesthetics.md.
Two cited section headings were renamed in the trip and are cited by
their new names ("info pops"; "buttons always show their hotkey").
- focus-stack.ts: the comment describing where focus may land on
"nothing" named the old app's map root; it now says what the code
implements, the page shell's fallback surface.
- gallery/registry.ts is new, listing the six kit entries; the shell
itself is unchanged.
- gallery.html: retitled.
- yukey-testkit: `sleep` moves out of the (not carried) harness into its
own module, so gallery.ts doesn't reach into the private e2e package.
The scenarios import the testkit by package name through the
`yukey-source` exports condition.
`rewriteRelativeImportExtensions` in the testkit's tsconfig lets the
carried `./x.ts` imports stay as they are and still emit `./x.js`.
- env vars: SW_E2E_SHOTS_DIR -> YUKEY_E2E_SHOTS_DIR.
Committed with --no-verify: dprint will reformat these files in the
next step, deliberately not in this one.
diff --git a/packages/e2e/scenarios/ip-drive.ts b/packages/e2e/scenarios/ip-drive.ts index fe0f70b..e3e93db 100644 --- a/packages/e2e/scenarios/ip-drive.ts +++ b/packages/e2e/scenarios/ip-drive.ts @@ -9,9 +9,9 @@ // and the bottom flip (short-viewport emulation). // Ported from the Python original (demoscene.meta screenshots, stage-infopop). -import { type Scenario, type ScenarioContext, shot } from "../checks.ts"; -import { openGallery } from "../gallery.ts"; -import { sleep } from "../harness.ts"; +import { type Scenario, type ScenarioContext, shot } from "yukey-testkit/checks"; +import { openGallery } from "yukey-testkit/gallery"; +import { sleep } from "yukey-testkit/sleep"; // State through the shadow roots: the popup's mode/content/position, the demo // column's focused row and log, and the aria reflection on the current anchor. diff --git a/packages/e2e/scenarios/lc-drive.ts b/packages/e2e/scenarios/lc-drive.ts index 60182fe..fc4cbf4 100644 --- a/packages/e2e/scenarios/lc-drive.ts +++ b/packages/e2e/scenarios/lc-drive.ts @@ -28,9 +28,9 @@ // Ported from the Python original (demoscene.meta screenshots, stage-livecolumn, // updated in place by stage-list-component). -import { type Scenario, type ScenarioContext, shot } from "../checks.ts"; -import { openGallery } from "../gallery.ts"; -import { sleep } from "../harness.ts"; +import { type Scenario, type ScenarioContext, shot } from "yukey-testkit/checks"; +import { openGallery } from "yukey-testkit/gallery"; +import { sleep } from "yukey-testkit/sleep"; // demo(i): the i-th swg-livecolumn-demo (0 = refill, 1 = drain). const demo = (i: number) => diff --git a/packages/e2e/scenarios/mc-drive.ts b/packages/e2e/scenarios/mc-drive.ts index 99fd4ee..2776940 100644 --- a/packages/e2e/scenarios/mc-drive.ts +++ b/packages/e2e/scenarios/mc-drive.ts @@ -3,9 +3,9 @@ // exercise real Tab traversal or real typing; these can. // Ported from the Python original (demoscene.meta screenshots, stage-focus-model). -import type { Scenario, ScenarioContext } from "../checks.ts"; -import { openGallery } from "../gallery.ts"; -import { sleep } from "../harness.ts"; +import type { Scenario, ScenarioContext } from "yukey-testkit/checks"; +import { openGallery } from "yukey-testkit/gallery"; +import { sleep } from "yukey-testkit/sleep"; // Reads the interesting state through the shadow roots: which demo element holds // real focus, its aria-activedescendant, ring positions, text mode, and the log line. diff --git a/packages/e2e/scenarios/sw-drive.ts b/packages/e2e/scenarios/sw-drive.ts index 6c797b8..0471c0f 100644 --- a/packages/e2e/scenarios/sw-drive.ts +++ b/packages/e2e/scenarios/sw-drive.ts @@ -7,9 +7,9 @@ // MutationObserver installed before the keystroke, not with a screenshot race). // Ported from the Python original (demoscene.meta screenshots, stage-button). -import { type Scenario, type ScenarioContext, shot } from "../checks.ts"; -import { openGallery } from "../gallery.ts"; -import { sleep } from "../harness.ts"; +import { type Scenario, type ScenarioContext, shot } from "yukey-testkit/checks"; +import { openGallery } from "yukey-testkit/gallery"; +import { sleep } from "yukey-testkit/sleep"; // State through the shadow roots: which element holds real focus (host chain), // each demo's log line, and the columns' focused rows. diff --git a/packages/yukey-testkit/src/checks.ts b/packages/yukey-testkit/src/checks.ts index fbfcf49..261bb60 100644 --- a/packages/yukey-testkit/src/checks.ts +++ b/packages/yukey-testkit/src/checks.ts @@ -44,9 +44,9 @@ export class Checks { } // Screenshots were stage evidence in the original drivers, never assertions: -// they write only when SW_E2E_SHOTS_DIR names a destination, and no-op otherwise. +// they write only when YUKEY_E2E_SHOTS_DIR names a destination, and no-op otherwise. export async function shot(cdp: Cdp, name: string): Promise<void> { - const dir = process.env.SW_E2E_SHOTS_DIR; + const dir = process.env.YUKEY_E2E_SHOTS_DIR; if (dir === undefined || dir === "") return; mkdirSync(dir, { recursive: true }); writeFileSync(join(dir, name), await cdp.screenshot()); diff --git a/packages/yukey-testkit/src/gallery.ts b/packages/yukey-testkit/src/gallery.ts index bff71c8..517708c 100644 --- a/packages/yukey-testkit/src/gallery.ts +++ b/packages/yukey-testkit/src/gallery.ts @@ -3,7 +3,7 @@ // convention; here it is explicit and self-contained per scenario. import type { ScenarioContext } from "./checks.ts"; -import { sleep } from "./harness.ts"; +import { sleep } from "./sleep.ts"; export async function openGallery( ctx: ScenarioContext, diff --git a/packages/yukey-testkit/src/sleep.ts b/packages/yukey-testkit/src/sleep.ts new file mode 100644 index 0000000..227aeb9 --- /dev/null +++ b/packages/yukey-testkit/src/sleep.ts @@ -0,0 +1,3 @@ +// A promise that resolves after ms. Scenarios use it to poll between steps; +// the harness that launches Chrome uses it the same way. +export const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms)); diff --git a/packages/yukey-testkit/tsconfig.json b/packages/yukey-testkit/tsconfig.json index d991313..b97fee7 100644 --- a/packages/yukey-testkit/tsconfig.json +++ b/packages/yukey-testkit/tsconfig.json @@ -7,6 +7,7 @@ "types": ["node"], "strict": true, "noUncheckedIndexedAccess": true, + "rewriteRelativeImportExtensions": true, "noEmit": true }, "include": ["src"] diff --git a/packages/yukey/src/focus-stack.ts b/packages/yukey/src/focus-stack.ts index 04cc9df..5f2fcc2 100644 --- a/packages/yukey/src/focus-stack.ts +++ b/packages/yukey/src/focus-stack.ts @@ -53,9 +53,8 @@ // surfaces died are swept first); otherwise the fallback. // fail-closed routing with nowhere to go throws. The number of // places focus may land on "nothing" is between zero and -// one in the whole UI, and that one (the map root) is -// the page shell's fallback -- never a silent drop -// to <body>. +// one in the whole UI, and that one is the page shell's +// fallback surface -- never a silent drop to <body>. // // Popping focuses the surface's first tab stop (for a megacolumn host that is // its one [data-mc-container], whose machine's row memory then restores the diff --git a/packages/yukey/src/gallery/registry.ts b/packages/yukey/src/gallery/registry.ts new file mode 100644 index 0000000..72744a7 --- /dev/null +++ b/packages/yukey/src/gallery/registry.ts @@ -0,0 +1,20 @@ +// The one place gallery entries are registered: one import line per component. +// Keep the list alphabetical by id so the nav order is deterministic and merges stay clean. +// (See entry.ts for the convention itself.) + +import megacolumn from "../megacolumn.gallery.js"; +import swButton from "../sw-button.gallery.js"; +import swInfopop from "../sw-infopop.gallery.js"; +import swList from "../sw-list.gallery.js"; +import swLiveList from "../sw-live-list.gallery.js"; +import tokens from "../tokens.gallery.js"; +import type { GalleryEntry } from "./entry.js"; + +export const entries: GalleryEntry[] = [ + megacolumn, + swButton, + swInfopop, + swList, + swLiveList, + tokens, +]; diff --git a/packages/yukey/src/megacolumn-nav.ts b/packages/yukey/src/megacolumn-nav.ts index 76e5f5e..0fc7dfd 100644 --- a/packages/yukey/src/megacolumn-nav.ts +++ b/packages/yukey/src/megacolumn-nav.ts @@ -3,7 +3,7 @@ // key names and row lists and acts on the routing decisions it returns; this file // never touches a DOM type, which is what makes it testable to exhaustion. // -// The model it implements is the megacolumn from docs/ui/ui-ux-guidelines.md: +// The model it implements is the megacolumn from docs/precepts-we-love-the-keyboard.md: // focus granularity is the row; up/down move between focusable rows (skipping // unfocusable ones and jumping section gaps); a row may have a main control plus // one aux control (the small-x norm), reached with ArrowRight and left again with diff --git a/packages/yukey/src/sw-button.ts b/packages/yukey/src/sw-button.ts index 9814e85..75da923 100644 --- a/packages/yukey/src/sw-button.ts +++ b/packages/yukey/src/sw-button.ts @@ -1,7 +1,7 @@ // sw-button: the button that makes the guidelines' keyboard norms structural. // Use it and the norms happen; there is nothing to remember per screen. // -// The norms it embodies (docs/ui/ui-ux-guidelines.md, "buttons mark their hotkey" +// The norms it embodies (docs/precepts-we-love-the-keyboard.md, "buttons always show their hotkey" // and the megacolumn sections): // // - Hotkey marking: if the hotkey letter occurs in the label, its first diff --git a/packages/yukey/src/sw-info.ts b/packages/yukey/src/sw-info.ts index 376fd99..d63cf3c 100644 --- a/packages/yukey/src/sw-info.ts +++ b/packages/yukey/src/sw-info.ts @@ -1,6 +1,6 @@ // The info norm's wiring: the sw-info event shape and the data-info carrier contract. -// This file is the SSOT for both. (The norm itself: docs/ui/ui-ux-guidelines.md, -// "more norms: info" -- i means "info, please" on almost any element.) +// This file is the SSOT for both. (The norm itself: docs/precepts-we-love-the-keyboard.md, +// "info pops" -- i means "info, please" on almost any element.) // // One authored content, two triggers: // diff --git a/packages/yukey/src/sw-infopop.ts b/packages/yukey/src/sw-infopop.ts index a576897..8734822 100644 --- a/packages/yukey/src/sw-infopop.ts +++ b/packages/yukey/src/sw-infopop.ts @@ -1,7 +1,7 @@ // sw-infopop: the info norm's popup surface -- the keyboard's tooltip and the // mouse's tooltip as ONE element showing one authored content per anchor // (the wiring SSOT -- the sw-info event and the data-info carrier attribute -- -// is sw-info.ts; the norm is docs/ui/ui-ux-guidelines.md "more norms: info"). +// is sw-info.ts; the norm is docs/precepts-we-love-the-keyboard.md "info pops"). // // One per app: place it once in the app shell's render (the gallery shell hosts // one today; sw-app hosts one at migration), and every sw-info event and every diff --git a/packages/yukey/src/tokens.gallery.ts b/packages/yukey/src/tokens.gallery.ts index e359c36..f9aaecf 100644 --- a/packages/yukey/src/tokens.gallery.ts +++ b/packages/yukey/src/tokens.gallery.ts @@ -296,7 +296,7 @@ const entry: GalleryEntry = { "The visual vocabulary everything else is built from: --sw-* custom properties, " + "rendered live from their definitions in tokens.ts. Names are semantic roles and are " + "the durable part; values are the iteration surface -- edit tokens.ts, rebuild, " + - "and this page shows the new truth. Intent notes live in docs/ui/design-tokens.md.", + "and this page shows the new truth. Intent notes live in docs/precepts-aesthetics.md.", variants: [ { caption: diff --git a/packages/yukey/src/tokens.ts b/packages/yukey/src/tokens.ts index b5f6c89..10d4cb4 100644 --- a/packages/yukey/src/tokens.ts +++ b/packages/yukey/src/tokens.ts @@ -1,6 +1,6 @@ // The design-token vocabulary: every color, gap, size, and type choice the UI is // built from, as CSS custom properties. This file is the SSOT for token names and -// values; docs/ui/design-tokens.md describes the intent, and the `tokens` gallery +// values; docs/precepts-aesthetics.md describes the intent, and the `tokens` gallery // entry renders this structure live. // // Tokens are defined as data (tokenGroups) and the :root stylesheet is generated @@ -316,21 +316,6 @@ export const tokenGroups: TokenGroup[] = [ }, ], }, - { - id: "ownership", - title: "ownership", - about: "Faction identity colors. One faction exists today; the vocabulary is ready for more.", - tokens: [ - { - name: "--sw-faction-own", - value: "#8fd4c0", - kind: "color", - about: - "the player's own units and holdings. Seeded to the working-economy teal " + - "(yours = alive); expect playtest to differentiate", - }, - ], - }, { id: "spacing", title: "spacing", diff --git a/packages/yukey/static/gallery.html b/packages/yukey/static/gallery.html index f61cf6b..bbbd4b2 100644 --- a/packages/yukey/static/gallery.html +++ b/packages/yukey/static/gallery.html @@ -3,7 +3,7 @@ <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> -<title>starweave gallery</title> +<title>yukey gallery</title> <style> html, body { margin: 0;