@bastani/atomic 0.9.11-alpha.6 → 0.9.11-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/package.json +1 -1
  5. package/dist/builtin/web-access/package.json +1 -1
  6. package/dist/builtin/workflows/package.json +1 -1
  7. package/dist/builtin/workflows/skills/impeccable/SKILL.md +33 -129
  8. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_asset_producer.toml +11 -3
  9. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_documenter.toml +26 -0
  10. package/dist/builtin/workflows/skills/impeccable/agents/impeccable_finish_reviewer.toml +35 -0
  11. package/dist/builtin/workflows/skills/impeccable/reference/android.md +1 -1
  12. package/dist/builtin/workflows/skills/impeccable/reference/animate.md +72 -189
  13. package/dist/builtin/workflows/skills/impeccable/reference/audit.md +10 -9
  14. package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +2 -2
  15. package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +19 -108
  16. package/dist/builtin/workflows/skills/impeccable/reference/clarify.md +59 -253
  17. package/dist/builtin/workflows/skills/impeccable/reference/colorize.md +51 -222
  18. package/dist/builtin/workflows/skills/impeccable/reference/craft-floor.md +45 -0
  19. package/dist/builtin/workflows/skills/impeccable/reference/craft.md +3 -121
  20. package/dist/builtin/workflows/skills/impeccable/reference/critique.md +28 -20
  21. package/dist/builtin/workflows/skills/impeccable/reference/degraded/asset-producer.md +97 -0
  22. package/dist/builtin/workflows/skills/impeccable/reference/degraded/documenter.md +23 -0
  23. package/dist/builtin/workflows/skills/impeccable/reference/degraded/finish-reviewer.md +32 -0
  24. package/dist/builtin/workflows/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
  25. package/dist/builtin/workflows/skills/impeccable/reference/delight.md +47 -279
  26. package/dist/builtin/workflows/skills/impeccable/reference/distill.md +2 -2
  27. package/dist/builtin/workflows/skills/impeccable/reference/doctor.md +53 -0
  28. package/dist/builtin/workflows/skills/impeccable/reference/document.md +60 -73
  29. package/dist/builtin/workflows/skills/impeccable/reference/harden.md +1 -12
  30. package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +17 -4
  31. package/dist/builtin/workflows/skills/impeccable/reference/init.md +64 -163
  32. package/dist/builtin/workflows/skills/impeccable/reference/ios.md +1 -1
  33. package/dist/builtin/workflows/skills/impeccable/reference/layout.md +52 -153
  34. package/dist/builtin/workflows/skills/impeccable/reference/live.md +44 -32
  35. package/dist/builtin/workflows/skills/impeccable/reference/new-work.md +105 -0
  36. package/dist/builtin/workflows/skills/impeccable/reference/{product.md → operate.md} +6 -5
  37. package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +4 -4
  38. package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +1 -4
  39. package/dist/builtin/workflows/skills/impeccable/reference/polish.md +68 -212
  40. package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +3 -3
  41. package/dist/builtin/workflows/skills/impeccable/reference/routing.md +18 -0
  42. package/dist/builtin/workflows/skills/impeccable/reference/shape.md +38 -144
  43. package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +48 -269
  44. package/dist/builtin/workflows/skills/impeccable/reference/visualize.md +38 -0
  45. package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +1 -1
  46. package/dist/builtin/workflows/skills/impeccable/scripts/concept-seed.mjs +584 -0
  47. package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +117 -9
  48. package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +486 -59
  49. package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +16 -45
  50. package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +96 -10
  51. package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +143 -26
  52. package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +181 -12
  53. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +3187 -182
  54. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +102 -7
  55. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +282 -70
  56. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +183 -15
  57. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +22 -7
  58. package/dist/builtin/workflows/skills/impeccable/scripts/detector/findings.mjs +7 -1
  59. package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +16 -2
  60. package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +155 -42
  61. package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +2988 -155
  62. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/constants.mjs +11 -0
  63. package/dist/builtin/workflows/skills/impeccable/scripts/doctor.mjs +336 -0
  64. package/dist/builtin/workflows/skills/impeccable/scripts/generate-image.mjs +232 -0
  65. package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +90 -10
  66. package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +410 -78
  67. package/dist/builtin/workflows/skills/impeccable/scripts/hook.mjs +25 -8
  68. package/dist/builtin/workflows/skills/impeccable/scripts/lib/artifact-schema.mjs +93 -0
  69. package/dist/builtin/workflows/skills/impeccable/scripts/lib/composition-catalog.mjs +165 -0
  70. package/dist/builtin/workflows/skills/impeccable/scripts/lib/concept-catalog.mjs +329 -0
  71. package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +20 -5
  72. package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-paths.mjs +16 -8
  73. package/dist/builtin/workflows/skills/impeccable/scripts/lib/provider.mjs +1 -0
  74. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness-deep.mjs +455 -0
  75. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness-notice.mjs +169 -0
  76. package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness.mjs +457 -0
  77. package/dist/builtin/workflows/skills/impeccable/scripts/lib/surface-briefs.mjs +151 -0
  78. package/dist/builtin/workflows/skills/impeccable/scripts/lib/target-slug.mjs +33 -0
  79. package/dist/builtin/workflows/skills/impeccable/scripts/lib/template-extensions.mjs +146 -0
  80. package/dist/builtin/workflows/skills/impeccable/scripts/live/completion.mjs +10 -1
  81. package/dist/builtin/workflows/skills/impeccable/scripts/live/event-validation.mjs +15 -0
  82. package/dist/builtin/workflows/skills/impeccable/scripts/live/generation-preflight.mjs +149 -0
  83. package/dist/builtin/workflows/skills/impeccable/scripts/live/poll-lanes.mjs +14 -0
  84. package/dist/builtin/workflows/skills/impeccable/scripts/live/session-store.mjs +109 -32
  85. package/dist/builtin/workflows/skills/impeccable/scripts/live/source-lock.mjs +105 -0
  86. package/dist/builtin/workflows/skills/impeccable/scripts/live/source-search.mjs +105 -0
  87. package/dist/builtin/workflows/skills/impeccable/scripts/live/sveltekit-adapter.mjs +8 -6
  88. package/dist/builtin/workflows/skills/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
  89. package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +208 -68
  90. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +563 -112
  91. package/dist/builtin/workflows/skills/impeccable/scripts/live-commit-manual-edits.mjs +3 -0
  92. package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +198 -13
  93. package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +24 -6
  94. package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edit-evidence.mjs +6 -1
  95. package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +44 -14
  96. package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +398 -33
  97. package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +9 -5
  98. package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +81 -67
  99. package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +7 -2
  100. package/dist/builtin/workflows/skills/impeccable/scripts/palette.mjs +76 -81
  101. package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +2 -2
  102. package/dist/builtin/workflows/skills/impeccable/scripts/serve-question.mjs +890 -0
  103. package/dist/builtin/workflows/skills/impeccable/scripts/surface-brief.mjs +74 -0
  104. package/dist/builtin/workflows/src/extension/index.bundle.mjs +201 -22
  105. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +23 -9
  106. package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +1 -0
  107. package/dist/builtin/workflows/src/runs/foreground/postmortem-stage-chat.ts +20 -5
  108. package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +10 -0
  109. package/dist/builtin/workflows/src/runs/foreground/stage-delivery-activity.ts +86 -0
  110. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +6 -2
  111. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +19 -13
  112. package/dist/builtin/workflows/src/runs/foreground/stage-runner-send-user-message.ts +8 -0
  113. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +16 -0
  114. package/dist/builtin/workflows/src/tui/stage-chat-view-delivery-activity.ts +121 -0
  115. package/dist/builtin/workflows/src/tui/stage-chat-view-live-events.ts +42 -0
  116. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +16 -0
  117. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +4 -0
  118. package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
  119. package/dist/modes/interactive/components/chat-session-host-actions.js +2 -14
  120. package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
  121. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/chat-session-host-events.js +9 -0
  123. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  124. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts +25 -0
  125. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts.map +1 -1
  126. package/dist/modes/interactive/components/chat-session-host-runtime.js +53 -0
  127. package/dist/modes/interactive/components/chat-session-host-runtime.js.map +1 -1
  128. package/dist/modes/interactive/components/chat-session-host.d.ts +13 -0
  129. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/chat-session-host.js +22 -1
  131. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  132. package/dist/modes/interactive/interactive-agent-events.js +9 -3
  133. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  134. package/docs/tui.md +7 -2
  135. package/docs/workflows.md +1 -1
  136. package/npm-shrinkwrap.json +23 -23
  137. package/package.json +2 -2
  138. package/dist/builtin/workflows/skills/impeccable/reference/brand.md +0 -108
  139. package/dist/builtin/workflows/skills/impeccable/reference/codex.md +0 -105
  140. package/dist/builtin/workflows/skills/impeccable/reference/interaction-design.md +0 -189
@@ -1,105 +0,0 @@
1
- # Codex: Visual Direction & Asset Production
2
-
3
- This file is loaded by `$impeccable craft` when the harness has native image generation (currently Codex via `image_gen`). Other harnesses skip it. It covers the two craft steps that depend on real image generation: landing the visual direction, and producing the raster assets the implementation will compose.
4
-
5
- Read this *before* generating any images. The order matters, and the per-step user pauses are what keep generated imagery from drifting away from the brief.
6
-
7
- ### Four stop points before code
8
-
9
- Steps A through D each end with the user. Do not advance past any of them on your own read of the situation.
10
-
11
- 1. **STOP after Step A questions.** Wait for answers.
12
- 2. **STOP after Step B palette generation.** Wait for "confirm palette."
13
- 3. **STOP after Step C mocks.** Wait for direction approval or delegation.
14
- 4. **Only after Step D approves a direction** do you return to craft.md Step 4 and write code.
15
-
16
- Prior shape approval does **not** satisfy any of these. Shape's "confirm or override" advances you into Step A; it is not a substitute for it.
17
-
18
- ## Step A: Explore Directions with the User
19
-
20
- Before generating anything, run a brief direction conversation grounded in the shape brief.
21
-
22
- **Step A is required even when shape just produced a confirmed brief.** The shape questions and Step A questions cover different ground: shape pins purpose, content, scope; Step A pins palette, atmosphere, and named visual references for the comps you're about to generate. The only time you can skip Step A is when the user has already answered these exact palette/atmosphere/reference questions in the same session.
23
-
24
- Ask **2-3 targeted questions** about visual lane, color strategy, atmosphere, and named anchor references. Don't enumerate generic menus; tie each question to the shape brief's answers. Example shape-grounded questions:
25
-
26
- - "Brief says 'specimen-page restraint.' Are we closer to a quiet typographic page or a wider editorial spread with hero imagery?"
27
- - "Palette strategy from shape was 'Committed.' Which one color carries the surface (a brand-driven pick rather than a default warm-or-cool framing)? (And no, the answer isn't a cream/sand body bg; that's the saturated AI default.)"
28
-
29
- **STOP and wait for answers.** These pin the palette before any pixel gets generated. Do not proceed to Step B until the user has responded.
30
-
31
- ## Step B: Generate the Brand Palette First
32
-
33
- Generate **one** palette artifact before any mocks. This is a small, focused image: typography pairing on the chosen background, primary + accent color swatches, one signature ornament or motif. Single image, single pass.
34
-
35
- Why palette first: mocks generated against a vague color sense produce noise that drowns out the structural decisions. A confirmed palette is the first concrete contract for everything downstream.
36
-
37
- Show the palette to the user. Ask one question: "This is the palette I'm locking in for the mocks. Confirm, or call out what to shift?"
38
-
39
- **STOP and wait for confirmation.** Do not generate mocks against an unconfirmed palette. "Probably good enough" is the wrong call here; the palette is the contract for everything downstream.
40
-
41
- ## Step C: Generate 1-3 Visual Mocks Against the Palette
42
-
43
- Once the palette is confirmed, generate **1 to 3** high-fidelity north-star comps. Each mock must use the confirmed palette and typography. Mocks differ in *structural* direction (hierarchy, topology, density, composition), not in color or motif.
44
-
45
- - Brand work: push visual identity, composition, mood, and signature motifs.
46
- - Product work: push hierarchy, topology, density, tone, grounded in realistic product structure.
47
- - Landing pages and long-form brand surfaces: show enough of the second fold to establish the system beyond the hero.
48
-
49
- Use the `image_gen` tool directly (or via the imagegen skill when available). Don't ask the user to install anything.
50
-
51
- ## Step D: Approval Loop
52
-
53
- Show the comps. Ask what carries forward. Iterate until **one direction is approved** or the user explicitly delegates.
54
-
55
- **STOP and wait for the approval or the delegation.** Do not begin Step E or return to craft.md Step 4 until a single direction is named. If the user delegates, pick the strongest direction and explain it from the brief, not personal taste.
56
-
57
- Before moving to assets, summarize what to carry into code and what *not* to literalize from the mock. This is the handoff between visual exploration and semantic implementation.
58
-
59
- ## Step E: Mock Fidelity Inventory
60
-
61
- Inventory the approved mock's major visible ingredients. For each, decide implementation: semantic HTML/CSS/SVG, generated raster, sourced raster, icon library, canvas/WebGL, or accepted omission.
62
-
63
- Common ingredients to inventory:
64
-
65
- - Hero silhouette and dominant composition
66
- - Signature motifs (planets, devices, portraits, charts, route lines, insets, badges, etc.)
67
- - Nav and primary CTA treatment
68
- - Section sequence, especially the second fold
69
- - Image-native content the concept depends on
70
- - Typography, density, color/material treatment, motion cues
71
-
72
- Treat the mock as a north star, not a screenshot to trace. Don't rasterize core UI text. But if the live result lacks the mock's major ingredients, the implementation is wrong.
73
-
74
- If a photographic, architectural, product, or place-led mock becomes generic CSS scenery, decorative diagrams, bullets, or copy, stop and fix it. That's a broken implementation, not a harmless interpretation.
75
-
76
- Don't substitute a different hero composition or visual driver post-approval without user sign-off.
77
-
78
- ## Step F: Asset Slicing via the Asset Producer
79
-
80
- Raster ingredients identified in Step E need clean production assets. Use the bundled `impeccable_asset_producer` subagent rather than producing inline.
81
-
82
- Spawn it as a scoped subagent. If you do not have explicit permission to use agents, stop and ask:
83
-
84
- ```text
85
- Asset production will work better as a scoped subagent job. Should I spawn the Impeccable asset producer subagent for this step?
86
- ```
87
-
88
- Pass to the agent:
89
-
90
- - Approved mock path or screenshot reference
91
- - Crop paths or a contact sheet with crop ids
92
- - Output directory
93
- - Required dimensions, format, transparency needs
94
- - Avoid list
95
- - Notes on what should remain semantic HTML/CSS/SVG instead of raster
96
-
97
- Attach image generation capability to the spawned agent when the harness supports it. Do **not** load image-generation reference material into the parent thread.
98
-
99
- Inline asset production is allowed only if the user declines subagents, the harness cannot spawn the authorized agent, or the user explicitly asks for single-thread mode.
100
-
101
- Prefer HTML/CSS/SVG/canvas when they can credibly reproduce an ingredient; reach for real, generated, or stock imagery when the mock or subject matter calls for actual visual content.
102
-
103
- ## After This File
104
-
105
- Once Steps A through F are complete, return to `craft.md` Step 5 (Build to Production Quality). The implementation builds against the confirmed palette, approved mock, and the assets the producer wrote.
@@ -1,189 +0,0 @@
1
- # Interaction Design
2
-
3
- ## The Eight Interactive States
4
-
5
- Every interactive element needs these states designed:
6
-
7
- | State | When | Visual Treatment |
8
- |-------|------|------------------|
9
- | **Default** | At rest | Base styling |
10
- | **Hover** | Pointer over (not touch) | Subtle lift, color shift |
11
- | **Focus** | Keyboard/programmatic focus | Visible ring (see below) |
12
- | **Active** | Being pressed | Pressed in, darker |
13
- | **Disabled** | Not interactive | Reduced opacity, no pointer |
14
- | **Loading** | Processing | Spinner, skeleton |
15
- | **Error** | Invalid state | Red border, icon, message |
16
- | **Success** | Completed | Green check, confirmation |
17
-
18
- **The common miss**: Designing hover without focus, or vice versa. They're different. Keyboard users never see hover states.
19
-
20
- ## Focus Rings: Do Them Right
21
-
22
- **Never `outline: none` without replacement.** It's an accessibility violation. Instead, use `:focus-visible` to show focus only for keyboard users:
23
-
24
- ```css
25
- /* Hide focus ring for mouse/touch */
26
- button:focus {
27
- outline: none;
28
- }
29
-
30
- /* Show focus ring for keyboard */
31
- button:focus-visible {
32
- outline: 2px solid var(--color-accent);
33
- outline-offset: 2px;
34
- }
35
- ```
36
-
37
- **Focus ring design**:
38
- - High contrast (3:1 minimum against adjacent colors)
39
- - 2-3px thick
40
- - Offset from element (not inside it)
41
- - Consistent across all interactive elements
42
-
43
- ## Form Design: The Non-Obvious
44
-
45
- **Placeholders aren't labels.** They disappear on input. Always use visible `<label>` elements. **Validate on blur**, not on every keystroke (exception: password strength). Place errors **below** fields with `aria-describedby` connecting them.
46
-
47
- ## Loading States
48
-
49
- **Optimistic updates**: Show success immediately, rollback on failure. Use for low-stakes actions (likes, follows), not payments or destructive actions. **Skeleton screens > spinners**: they preview content shape and feel faster than generic spinners.
50
-
51
- ## Modals: The Inert Approach
52
-
53
- Focus trapping in modals used to require complex JavaScript. Now use the `inert` attribute:
54
-
55
- ```html
56
- <!-- When modal is open -->
57
- <main inert>
58
- <!-- Content behind modal can't be focused or clicked -->
59
- </main>
60
- <dialog open>
61
- <h2>Modal Title</h2>
62
- <!-- Focus stays inside modal -->
63
- </dialog>
64
- ```
65
-
66
- Or use the native `<dialog>` element:
67
-
68
- ```javascript
69
- const dialog = document.querySelector('dialog');
70
- dialog.showModal(); // Opens with focus trap, closes on Escape
71
- ```
72
-
73
- ## The Popover API
74
-
75
- For tooltips, dropdowns, and non-modal overlays, use native popovers:
76
-
77
- ```html
78
- <button popovertarget="menu">Open menu</button>
79
- <div id="menu" popover>
80
- <button>Option 1</button>
81
- <button>Option 2</button>
82
- </div>
83
- ```
84
-
85
- **Benefits**: Light-dismiss (click outside closes), proper stacking, no z-index wars, accessible by default.
86
-
87
- ## Dropdown & Overlay Positioning
88
-
89
- Dropdowns rendered with `position: absolute` inside a container that has `overflow: hidden` or `overflow: auto` will be clipped. This is the single most common dropdown bug in generated code.
90
-
91
- ### CSS Anchor Positioning
92
-
93
- The modern solution uses the CSS Anchor Positioning API to tether an overlay to its trigger without JavaScript:
94
-
95
- ```css
96
- .trigger {
97
- anchor-name: --menu-trigger;
98
- }
99
-
100
- .dropdown {
101
- position: fixed;
102
- position-anchor: --menu-trigger;
103
- position-area: block-end span-inline-end;
104
- margin-top: 4px;
105
- }
106
-
107
- /* Flip above if no room below */
108
- @position-try --flip-above {
109
- position-area: block-start span-inline-end;
110
- margin-bottom: 4px;
111
- }
112
- ```
113
-
114
- Because the dropdown uses `position: fixed`, it escapes any `overflow` clipping on ancestor elements. The `@position-try` block handles viewport edges automatically. **Browser support**: Chrome 125+, Edge 125+. Not yet in Firefox or Safari - use a fallback for those browsers.
115
-
116
- ### Popover + Anchor Combo
117
-
118
- Combining the Popover API with anchor positioning gives you stacking, light-dismiss, accessibility, and correct positioning in one pattern:
119
-
120
- ```html
121
- <button popovertarget="menu" class="trigger">Open</button>
122
- <div id="menu" popover class="dropdown">
123
- <button>Option 1</button>
124
- <button>Option 2</button>
125
- </div>
126
- ```
127
-
128
- The `popover` attribute places the element in the **top layer**, which sits above all other content regardless of z-index or overflow. No portal needed.
129
-
130
- ### Portal / Teleport Pattern
131
-
132
- In component frameworks, render the dropdown at the document root and position it with JavaScript:
133
-
134
- - **React**: `createPortal(dropdown, document.body)`
135
- - **Vue**: `<Teleport to="body">`
136
- - **Svelte**: Use a portal library or mount to `document.body`
137
-
138
- Calculate position from the trigger's `getBoundingClientRect()`, then apply `position: fixed` with `top` and `left` values. Recalculate on scroll and resize.
139
-
140
- ### Fixed Positioning Fallback
141
-
142
- For browsers without anchor positioning support, `position: fixed` with manual coordinates avoids overflow clipping:
143
-
144
- ```css
145
- .dropdown {
146
- position: fixed;
147
- /* top/left set via JS from trigger's getBoundingClientRect() */
148
- }
149
- ```
150
-
151
- Check viewport boundaries before rendering. If the dropdown would overflow the bottom edge, flip it above the trigger. If it would overflow the right edge, align it to the trigger's right side instead.
152
-
153
- ## Destructive Actions: Undo > Confirm
154
-
155
- **Undo is better than confirmation dialogs.** Users click through confirmations mindlessly. Remove from UI immediately, show undo toast, actually delete after toast expires. Use confirmation only for truly irreversible actions (account deletion), high-cost actions, or batch operations.
156
-
157
- ## Keyboard Navigation Patterns
158
-
159
- ### Roving Tabindex
160
-
161
- For component groups (tabs, menu items, radio groups), one item is tabbable; arrow keys move within:
162
-
163
- ```html
164
- <div role="tablist">
165
- <button role="tab" tabindex="0">Tab 1</button>
166
- <button role="tab" tabindex="-1">Tab 2</button>
167
- <button role="tab" tabindex="-1">Tab 3</button>
168
- </div>
169
- ```
170
-
171
- Arrow keys move `tabindex="0"` between items. Tab moves to the next component entirely.
172
-
173
- ### Skip Links
174
-
175
- Provide skip links (`<a href="#main-content">Skip to main content</a>`) for keyboard users to jump past navigation. Hide off-screen, show on focus.
176
-
177
- ## Gesture Discoverability
178
-
179
- Swipe-to-delete and similar gestures are invisible. Hint at their existence:
180
-
181
- - **Partially reveal**: Show delete button peeking from edge
182
- - **Onboarding**: Coach marks on first use
183
- - **Alternative**: Always provide a visible fallback (menu with "Delete")
184
-
185
- Don't rely on gestures as the only way to perform actions.
186
-
187
- ---
188
-
189
- **Avoid**: Removing focus indicators without alternatives. Using placeholder text as labels. Touch targets <44x44px. Generic error messages. Custom controls without ARIA/keyboard support.