Insert dialog: list allowed elements first, reveal refused ones on demand #333

Closed
opened 2026-10-21 09:45:52 +02:00 by dominik.polakovics · 0 comments

Problem

The insert dialog (web/src/components/ElementPicker.tsx, issue #171) lists every insertable element and disables the ones the target refuses. The rationale was sound: an editor should see what exists and why it cannot go here instead of a list that silently shrinks. The cost is paid on every insert, and in the common cases it dominates:

  • inside an Accordion, one enabled tile sits among ~50 dimmed ones;
  • on a Form page (allowlist: the form fields), ~10 enabled tiles sit among ~40 dimmed ones;
  • disabled tiles are interleaved in catalogue order with the enabled ones, so the eye scans past every ghost;
  • the reason lives in a tooltip, and the tile is at 50% opacity, so even the "Not allowed here" marker is hard to read.

Design (settled)

  1. Allowed elements only by default. Categories, counts and order stay as they are (counts were already allowed-only).
  2. One line under the grid when the current category hides refused elements: "N more elements are not allowed here." with a ghost button "Show them" / "Hide them". The toggle is per open: every insert starts clean.
  3. Revealed tiles come after the allowed ones, not interleaved, and carry the reason on the tile (the text insertRefusal already produces) instead of a tooltip and an uppercase marker.
  4. Search always reveals a refused match, dimmed with its reason, whether or not the toggle is on. A search for "hero" never comes back empty just because Hero is refused here: that is the silent-shrink failure the original design guarded against.
  5. Nothing allowed at all (a page type with elements: [], a slot that admits nothing): a note explains it and the catalogue is revealed so each tile shows its reason. The existing slot note stays and takes precedence when the slot is what refuses.

Rules and owners

  • The refusal rule stays with insertRefusal / pickerEntries in web/src/elementcrud.ts. No new derivation; the dialog only partitions the entries it already gets.
  • Nothing is served or re-derived from the server.

Styleguide

  • Shared pieces used: .btn.btn--xs.btn--ghost for the toggle. No new token, no new shared component, no new status; styleguide.html is unchanged. The picker's own classes (.epick__*, .etile*) are product-only.
  • The disabled tile keeps disabled and its opacity rule (the one place opacity is allowed); the reason text replaces the uppercase marker.

Docs and skills

  • scaffold/site/AGENTS.md describes the picker only as "limited to what the container's placement allows" (Children section) and the insertable/hidden keys; both stay true. No skill walks through the dialog's rendering. No doc change.
  • i18n: new keys in en.json and de.json; insert.notAllowedHere goes away.

Tests

  • web/src/test/ElementPicker.test.tsx: default hides refused, toggle reveals after the allowed ones with the reason, search reveals a refused match, empty allowlist reveals with the note, Enter still picks the first enabled tile, toggle resets per open.
  • ElementCrud.test.tsx and LayoutGrid.test.tsx assert on the tooltip and marker today; they move to the tile text.
## Problem The insert dialog (`web/src/components/ElementPicker.tsx`, issue #171) lists every insertable element and disables the ones the target refuses. The rationale was sound: an editor should see what exists and why it cannot go here instead of a list that silently shrinks. The cost is paid on every insert, and in the common cases it dominates: - inside an Accordion, one enabled tile sits among ~50 dimmed ones; - on a Form page (allowlist: the form fields), ~10 enabled tiles sit among ~40 dimmed ones; - disabled tiles are interleaved in catalogue order with the enabled ones, so the eye scans past every ghost; - the reason lives in a tooltip, and the tile is at 50% opacity, so even the "Not allowed here" marker is hard to read. ## Design (settled) 1. **Allowed elements only by default.** Categories, counts and order stay as they are (counts were already allowed-only). 2. **One line under the grid** when the current category hides refused elements: "N more elements are not allowed here." with a ghost button "Show them" / "Hide them". The toggle is per open: every insert starts clean. 3. **Revealed tiles come after the allowed ones**, not interleaved, and carry **the reason on the tile** (the text `insertRefusal` already produces) instead of a tooltip and an uppercase marker. 4. **Search always reveals a refused match**, dimmed with its reason, whether or not the toggle is on. A search for "hero" never comes back empty just because Hero is refused here: that is the silent-shrink failure the original design guarded against. 5. **Nothing allowed at all** (a page type with `elements: []`, a slot that admits nothing): a note explains it and the catalogue is revealed so each tile shows its reason. The existing slot note stays and takes precedence when the slot is what refuses. ## Rules and owners - The refusal rule stays with `insertRefusal` / `pickerEntries` in `web/src/elementcrud.ts`. No new derivation; the dialog only partitions the entries it already gets. - Nothing is served or re-derived from the server. ## Styleguide - Shared pieces used: `.btn.btn--xs.btn--ghost` for the toggle. No new token, no new shared component, no new status; `styleguide.html` is unchanged. The picker's own classes (`.epick__*`, `.etile*`) are product-only. - The disabled tile keeps `disabled` and its opacity rule (the one place opacity is allowed); the reason text replaces the uppercase marker. ## Docs and skills - `scaffold/site/AGENTS.md` describes the picker only as "limited to what the container's placement allows" (Children section) and the `insertable`/`hidden` keys; both stay true. No skill walks through the dialog's rendering. No doc change. - i18n: new keys in `en.json` and `de.json`; `insert.notAllowedHere` goes away. ## Tests - `web/src/test/ElementPicker.test.tsx`: default hides refused, toggle reveals after the allowed ones with the reason, search reveals a refused match, empty allowlist reveals with the note, Enter still picks the first enabled tile, toggle resets per open. - `ElementCrud.test.tsx` and `LayoutGrid.test.tsx` assert on the tooltip and marker today; they move to the tile text.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle#333
No description provided.