You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
Build the inline choice chip: the TipTap node that represents one dropdown inside the passage, its node view, and the Insert action that places it. The chip is contributed to TipTapEditor from the QTI editor through the seams added in #6176, and TipTapEditor stays free of QTI vocabulary.
Complexity: High Target branch: unstable
Context
In the design, the passage is a rich text editor with dropdowns inline as chips. Its toolbar shows history, clipboard, a prominent, labelled Insert button, and a More menu. The helper text reads "Inline choice widgets can be inserted blank or converted from highlighted text."
A chip shows:
a badge with its number of options
the text of its correct option as its label (e.g. 3 Moon), in a solid style
when it has no correct option: a dashed style with the label "Add answer" ("Add answers" when it has no options, e.g. 0 Add answers)
a selected state for the chip whose options are being edited below the passage
#6176 adds the pieces this builds on: the extensions prop, the @ready event, insertActions descriptors with a prominent desktop treatment, the selection / canInsertNode facts, the transformPasted guidance, and reading consumer state from a node view via provide / inject.
A chip's options travel with the chip. Undo and redo restore the passage document, and copy / paste moves document content. If a chip's options and correct answer lived only in the interaction's Vue state, undoing a chip deletion would bring back an empty chip, and a pasted chip would arrive with no options. So the node carries its dropdown's data, and the editor UI edits it through the node.
The Change
An inline choice node and node view under interactions/inlineChoice/, registered on the passage's TipTapEditor through the extensions prop. The node is an inline atom whose attributes hold its dropdown's response identifier, options and correct answer.
The node view renders the chip as described above, and shows it as selected when it is the dropdown the options list is editing (read through provide / inject). Clicking or keyboard-selecting a chip makes it the selected dropdown.
An Insert action contributed through insertActions, with the prominent (labelled) desktop treatment:
with an empty selection, it inserts a blank chip (no options) at the cursor and selects it
with text highlighted within one paragraph, it replaces that text with a chip whose single option is that text, marked correct, and selects it. The passage is rich text but options are plain text, so any styling in the selection (bold, italic, links, etc.) is dropped and only its text is kept
it is unavailable when the selection spans more than one block (selection.spansBlocks), or where the node cannot be inserted (canInsertNode)
A pasted or duplicated chip gets a fresh response identifier and fresh choice identifiers (in transformPasted), so an item never carries two dropdowns with the same identifier. Cut and paste within the same passage should keep the chip's identity, since it is a move rather than a copy.
Existing inline atom for reference: shared/views/TipTapEditor/TipTapEditor/extensions/Math.js
AI usage
I used Claude Code to draft this issue from the Figma design and #6176, which it read alongside the existing TipTap extensions. I decided how to split the work and reviewed and edited the text.
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
Build the inline choice chip: the TipTap node that represents one dropdown inside the passage, its node view, and the Insert action that places it. The chip is contributed to
TipTapEditorfrom the QTI editor through the seams added in #6176, andTipTapEditorstays free of QTI vocabulary.Complexity: High
Target branch: unstable
Context
In the design, the passage is a rich text editor with dropdowns inline as chips. Its toolbar shows history, clipboard, a prominent, labelled Insert button, and a More menu. The helper text reads "Inline choice widgets can be inserted blank or converted from highlighted text."
A chip shows:
3 Moon), in a solid style0 Add answers)#6176 adds the pieces this builds on: the
extensionsprop, the@readyevent,insertActionsdescriptors with a prominent desktop treatment, theselection/canInsertNodefacts, thetransformPastedguidance, and reading consumer state from a node view viaprovide/inject.A chip's options travel with the chip. Undo and redo restore the passage document, and copy / paste moves document content. If a chip's options and correct answer lived only in the interaction's Vue state, undoing a chip deletion would bring back an empty chip, and a pasted chip would arrive with no options. So the node carries its dropdown's data, and the editor UI edits it through the node.
The Change
interactions/inlineChoice/, registered on the passage'sTipTapEditorthrough theextensionsprop. The node is an inline atom whose attributes hold its dropdown's response identifier, options and correct answer.provide/inject). Clicking or keyboard-selecting a chip makes it the selected dropdown.insertActions, with the prominent (labelled) desktop treatment:selection.spansBlocks), or where the node cannot be inserted (canInsertNode)transformPasted), so an item never carries two dropdowns with the same identifier. Cut and paste within the same passage should keep the chip's identity, since it is a move rather than a copy.Out of Scope
TipTapEditorseams themselves ([QTI] Update TipTapEditor to support custom insert node behavior defined on parent component #6176).TipTapEditorother than the inline choice passage.Acceptance Criteria
General
0 Add answers, dashed) at the cursor and selects itshared/views/TipTapEditorimports from or refers to the QTI editorAccessibility and i18n
qtiEditorStringsTesting
Testing
References
docs/rich_text_editor.md, the rich text editor developer guide (updated by [QTI] Update TipTapEditor to support custom insert node behavior defined on parent component #6176)shared/views/TipTapEditor/TipTapEditor/extensions/Math.jsAI usage
I used Claude Code to draft this issue from the Figma design and #6176, which it read alongside the existing TipTap extensions. I decided how to split the work and reviewed and edited the text.