From f4e39426b7e07f48e557c0824d55da34cfd43a70 Mon Sep 17 00:00:00 2001 From: John Leider Date: Thu, 9 Jul 2026 15:04:33 -0500 Subject: [PATCH 01/16] docs: add Phase A key-lifecycle expansion spec --- ...-09-devkey-phase-a-key-lifecycle-design.md | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-09-devkey-phase-a-key-lifecycle-design.md diff --git a/docs/superpowers/specs/2026-07-09-devkey-phase-a-key-lifecycle-design.md b/docs/superpowers/specs/2026-07-09-devkey-phase-a-key-lifecycle-design.md new file mode 100644 index 0000000..157af44 --- /dev/null +++ b/docs/superpowers/specs/2026-07-09-devkey-phase-a-key-lifecycle-design.md @@ -0,0 +1,204 @@ +# DevKey Expansion — Phase A: Key Lifecycle + +**Date:** 2026-07-09 +**Status:** Approved design, pending implementation plan +**Scope:** Phase A of the DevKey coverage-expansion roadmap (below). + +## Context + +DevKey is a Vuetify0 reference project — an "API key dashboard" whose real job is +to demonstrate idiomatic v0 patterns in a realistic app. Today it exercises ~5 of +40 v0 components (`Button`, `Toggle`, `Tabs`, `Collapsible`, `Input`) plus +`createDataTable`, `createFilter`, `useVirtualFocus`, `useHotkey`, and 5 plugins. +Most product surfaces are stubs: New Key / Rotate / Revoke are `alert()` calls, and +the Analytics and Settings tabs say "coming soon." + +The expansion goal chosen with the user is **breadth-first coverage** organized as a +**hybrid**: map every primitive that plausibly fits the dashboard into real product +flows, and reserve a later `/components` gallery route for primitives with no honest +product home. The overriding constraint: every primitive must be used the **canonical, +documented way** — DevKey is held up as reference, so no contrived usage and no +hand-rolled logic where a v0 primitive exists. + +### House pattern (the "parameters" to stay within) + +- Thin `Dk*` wrapper components over v0 **compound** primitives (Root + sub-components). +- ` + + + + +``` + +- [ ] **Step 3: Mount `DkSnackbar` in `DkLayout.vue`** + +Edit `src/components/DkLayout.vue`. Add the import and render `` at the end of the root `
`: + +```vue + + + +``` +(Styles unchanged from current file.) + +- [ ] **Step 4: Type-check** + +Run: `pnpm type-check` +Expected: no errors. + +- [ ] **Step 5: Manual check** + +Run `pnpm dev`. In the browser console on the dashboard, run `window.__vue_app__` is not needed — instead temporarily add a button or use the command palette after Task 7. For now confirm no runtime errors on load and the snackbar container mounts (empty). + +- [ ] **Step 6: Commit** + +```bash +git add src/plugins/devkey.ts src/components/DkSnackbar.vue src/components/DkLayout.vue +git commit -m "chore(components): add notifications plugin and DkSnackbar" +``` + +--- + +## Task 3: `DkDialog` wrapper + +**Files:** +- Create: `src/components/DkDialog.vue` + +**Interfaces:** +- Produces: `` with default (body) slot and `actions` slot (receives `{ close }`). + +- [ ] **Step 1: Create `DkDialog.vue`** + +```vue + + + + + +``` + +- [ ] **Step 2: Type-check** + +Run: `pnpm type-check` +Expected: no errors. + +- [ ] **Step 3: Commit** + +```bash +git add src/components/DkDialog.vue +git commit -m "chore(components): add DkDialog wrapper" +``` + +--- + +## Task 4: Form field wrappers (`DkForm`, `DkSelect`, `DkSwitch`, `DkNumberField`) + +**Files:** +- Create: `src/components/DkForm.vue` +- Create: `src/components/DkSelect.vue` +- Create: `src/components/DkSwitch.vue` +- Create: `src/components/DkNumberField.vue` + +**Interfaces:** +- Produces: `` (submit payload `{ valid: boolean }`, default slot receives `{ valid }`). +- Produces: ``. +- Produces: `label`. +- Produces: ``. + +- [ ] **Step 1: Create `DkForm.vue`** + +```vue + + + + + +``` + +- [ ] **Step 2: Create `DkSelect.vue`** + +```vue + + + + + +``` + +- [ ] **Step 3: Create `DkSwitch.vue`** + +```vue + + + + + +``` + +- [ ] **Step 4: Create `DkNumberField.vue`** + +```vue + + + + + +``` + +- [ ] **Step 5: Type-check** + +Run: `pnpm type-check` +Expected: no errors. If `data-state` attribute names differ for Switch, adjust CSS selectors after visual check (Task 6) — do not change the component logic. + +- [ ] **Step 6: Commit** + +```bash +git add src/components/DkForm.vue src/components/DkSelect.vue src/components/DkSwitch.vue src/components/DkNumberField.vue +git commit -m "chore(components): add DkForm, DkSelect, DkSwitch, DkNumberField wrappers" +``` + +--- + +## Task 5: `DkCreateKeyDialog` + dashboard create wiring + +**Files:** +- Create: `src/components/DkCreateKeyDialog.vue` +- Modify: `src/pages/DashboardPage.vue` + +**Interfaces:** +- Consumes: `useKeys().add` (Task 1), `DkDialog` (Task 3), `DkForm`/`DkSelect`/`DkSwitch`/`DkNumberField` (Task 4), `DkInput` (existing), `useNotifications` (Task 2). +- Produces: ``. + +- [ ] **Step 1: Create `DkCreateKeyDialog.vue`** + +```vue + + + + + +``` + +> Note: `DkButton` prop/slot API is assumed to accept native `type`. If `DkButton` does not forward `type`, use plain `