Inline shortcode chips in the RTE: button and icon with param popovers #8
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle#8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
Inline shortcodes as first-class RTE citizens (docs/DECISIONS.md D5, D12): inline elements (
button,icon) declared in the field'sallowedInlinelist appear as atomic, non-editable chips in the text flow. Inserting or clicking a chip opens a popover form generated from the element's sidecar schema. Serialization emits inline shortcode syntax inside the markdown body and parses it back into chips.Acceptance criteria
allowedInlineelementsallowedInlineshow no insert affordance and refuse pasted chipsBlocked by
Agent Brief
Category: enhancement
Summary: Inline shortcodes as first-class rich-text citizens: inline elements (
button,icon) declared in a field'sallowedInlinelist render as atomic, non-editable chips in the RTE text flow, with a sidecar-schema-generated popover form for their params, and serialize losslessly to inline shortcode syntax inside the markdown body.Dependency note: this issue is hard-blocked by #7 (the TipTap Solid wrapper and markdown round-trip); the scheduler handles ordering — do not start until #7 is merged. #7 provides the editor, the rte body policy in the sidecar, the allowlist enforcement, and the markdown ⇄ editor conversion layer; #7 explicitly left inline shortcodes as inert non-corrupted placeholders — this issue upgrades them to chips. #3 (transitively) provides the schema-driven form generator the popover reuses. The issue body's
docs/DECISIONS.md D5, D12references point at a file that is not committed — this brief is self-contained.Current behavior:
After #7, element bodies are edited in a rich-text editor with an allowlist, but inline shortcodes appearing in a body are only guaranteed to survive: they show as inert placeholders, cannot be inserted, moved deliberately, or configured, and their params are invisible to the author. There is no notion of which inline elements a given rich-text field permits. The round-trip engine from #2 already represents inline shortcodes as self-closing shortcode nodes (name, markup flag, named typed params) among the text nodes of a body, and its serializer emits the canonical inline syntax (
{{< name k=v />}}/{{% ... /%}}) — and rejects raw{{</{{%inside text nodes, so shortcodes can never be flattened into text.Desired behavior:
Field configuration. The rte body policy from #7 gains an
allowedInlinelist naming the inline element types the field permits (e.g.button,icon). Each named type must have a sidecar schema (from #3); naming an element without a sidecar is a schema-load error surfaced like #3's other sidecar errors. An absent or emptyallowedInlinemeans the field permits no inline chips.Insertion. The editor's insert affordance (toolbar and/or slash command) offers exactly the field's
allowedInlineelements, each shown with its sidecarlabelandicon. Inserting one places a chip at the cursor with the element's schema defaults and opens its popover so required params can be filled. Fields withoutallowedInlineshow no insert affordance at all.Chips. A chip renders inline in the text flow with the sidecar label and icon, visibly distinct from text. Its text is not editable in place. It behaves as one atom: arrow keys skip over it as a unit, selection includes or excludes it whole, backspace/delete removes it whole, and copy/paste within the editor carries the chip with all its params. Pasting content containing a chip into a field whose
allowedInlinedoes not permit that element drops the chip while pasting the surrounding text normally — a disallowed chip can never enter a field, by any route.Popover. Clicking a chip opens a popover form generated purely from the element's sidecar schema — the same schema-driven form generation as #3 (labels, defaults, required, field types), no per-element form code. Validation matches #3's rules: required-missing or type-invalid values block the popover's save and show inline on the field. Saving the popover updates the chip's params and flows into the body's serialized form; cancelling leaves the chip unchanged.
Serialization. The markdown ⇄ editor conversion from #7 maps inline shortcode nodes to chip nodes and back. The round-trip is lossless: a body mixing text, formatting marks, and inline shortcodes — including chips directly adjacent to or inside bold/italic/link/list/heading constructs, chips back-to-back, and chips at the very start or end of the body — parses into the same chips and serializes back to the identical canonical form. Param types (string/bool/int/float) and each shortcode's markup flag (
{{<vs{{%) survive the round-trip. Chips are always serialized as shortcode nodes in the element tree, never as literal text.Key interfaces:
allowedInline(list of inline element names); validated at schema load with actionable errors.allowedInlineworks with zero editor code changes.Acceptance criteria:
allowedInlineelements with sidecar label and icon; a field withoutallowedInlineshows no insert affordanceallowedInlineyields an actionable schema-load errorbuttonandiconinline elements (shortcode template + sidecar each) and a page whose rich-text body uses them next to formatted text; the behaviors above are covered by testsOut of scope:
buttonandicon, with minimal templatesClosing as superseded: the maintainer has decided on a clean-slate reset of the project (issue #29, PR #30). The v1 implementation this issue builds on is being removed and the plan will be re-drawn from scratch; this spec is retired rather than actioned.