amend D-88: shared base + content components per surface (not one ClideMenu)
Record the decomposition: ClideAnchoredOverlay is the shared base every anchored surface adopts; content matches the surface — ClideMenu for menus, a new ClideTypeahead for the slash/@ typeaheads, bespoke for quick-open and the theme picker. Re-scopes T-288 accordingly. The base blockers (focus race, follower untappable in the test harness) are what to fix first. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,3 +11,9 @@ widget primitives.
|
||||
- **Rationale:** Nine surfaces had hand-rolled the same anchored-overlay + row-list + barrier + keyboard-nav pattern (menu-bar dropdowns, theme picker, slash + @ typeaheads, quick-open, three modal pickers), each re-deriving positioning, dismissal, and nav — divergent a11y, inconsistent dismissal, and a `pumpAndSettle`-hostile spread of ad-hoc overlays. Owning one primitive (per "own the rendering stack", [D-5](architecture.md#d-5-dart-core-sidecar-dissolved-ptyc-as-pql-peer)) makes the behaviour uniform and testable once, and turns the tenth surface (the T-275 permission-mode picker) into a few lines instead of another hand-roll.
|
||||
- **Cost:** A migration sweep across the existing surfaces (menu bar, theme picker, typeaheads, quick-open); the typeaheads keep their text-completion/key pipeline and only delegate anchoring + body, so the primitive must stay composable (a bare lifecycle wrapper + an optional turnkey menu), not a monolith. New UI authors must reach for the primitive rather than rolling another overlay.
|
||||
- **Raised by:** 2026-06-08 — user, while building the T-275 permission-mode picker: "since we don't do Material doesn't mean we can't make components of our own." Realises the "own the rendering stack" guardrail at the component level. Tracked by epic T-286.
|
||||
- **Amendment (2026-06-08):** The shared piece is `ClideAnchoredOverlay` (positioning + lifecycle) — that is what every anchored surface adopts. Content is **NOT** universally `ClideMenu`; it matches the surface's shape, to avoid bending divergent surfaces into a menu (the theme-picker migration was reverted for exactly this friction):
|
||||
- **`ClideMenu`** — selectable-list menus only (menu bar, permission picker).
|
||||
- **`ClideTypeahead`** (a second shared content component, to add) — the slash and @ typeaheads are near-duplicate caret-anchored completion surfaces; they share *this*, not `ClideMenu`.
|
||||
- **Quick-open / command palette** — bespoke content (centred filter + fuzzy + two-column rows); uses only the `ClideAnchoredOverlay` base.
|
||||
- **Theme picker** — toggle + live-apply list; its own small content (or `ClideMenu` if it ever fits cleanly), on the base.
|
||||
Revised goal: *everything anchored shares `ClideAnchoredOverlay`; content components match the surface.* The blockers to clear first (focus capture racing content autofocus; follower content untappable in the `canSizeOverlay` test harness) live in the base, not in any content component. Tracked by T-288. Raised by the user: "should those then not just be a different shared component from the others?"
|
||||
|
||||
Reference in New Issue
Block a user