Repository navigation
Add the inline choice interaction editor - #6303
AlexVelezLl wants to merge 8 commits into
Conversation
🟡 Waiting for changesOutcome: skipped — no new commits since Last updated: 2026-10-23 14:50 UTC |
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: the inline choice editor works end to end in manual QA. The type selector, insert flows, options panel, Shuffle, copy/paste ids, save/reopen and view mode all behave as #6182 specifies. CI is passing.
QA ran in the qti-demo shell because the QA server returned Redis 500s. axe found no new violations.
Suggestions, all inline:
- Options panel focus: clicking non-focusable parts drops focus, and
aria-modalwhile the passage stays editable. - Validation goes stale after removing a chip as text.
- Accessible name for the passage editor.
isSupportedBodyaccepts bodies TipTap can't hold.- Chip and announcer changes outside #6182's scope.
- Toolbar CSS and narrow-width overflow of Insert.
- Tests that match text anywhere on the page, and focus-trap tests that don't check where focus lands.
Written by rtibblesbot, an LLM-based coding agent.
18fbfe8 to
6055318
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: 6 prior findings are still open; please fix or reply on each thread. 3 new suggestions below. 7 of 14 prior findings are resolved and 1 acknowledged.
CI passes. Manual QA ran 12 scenarios on the qti-demo shell, since Redis MISCONF blocked Django login. Scenarios: insert, options panel, keyboard/screen reader, undo/paste, shuffle, save/reopen, validation, RTL/touch. No regressions.
Still open:
aria-modalwhile the passage stays clickableisSupportedBodyaccepts bodies TipTap can't hold- chip behaviour that #6182 lists as out of scope
- undo restoring a chip isn't announced
- chip with options but no correct mark reads "Add answers"
- Insert overflows the passage toolbar below ~480px without touch. QA: 413px wide in a 301px toolbar at 375px.
- options use a bare
<input>, not the #5927 plain-text row - options-problem message shown for
NO_CORRECT_ANSWER(nitpick)
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — clicking heading/padding drops focus; Escape stops closing
UNADDRESSED — InlineChoiceOptions/index.vue:13 — aria-modal while passage stays interactive
RESOLVED — inlineChoice/Editor.vue:95 — validation stale after chip removed/restored
ACKNOWLEDGED — inlineChoice/Editor.vue:84 — passage editor indistinguishable from question field (separate issue under #6103)
UNADDRESSED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
UNADDRESSED — InlineChoiceChip/index.vue:24 — chip behaviour out of scope per #6182
UNADDRESSED — InlineChoiceChip/index.vue:32 — chip with no correct mark reads as "Add answers"
UNADDRESSED — EditorToolbar.vue — Insert pushed off narrow toolbar (styling now via appearanceOverrides)
RESOLVED — inlineChoice/tests/Editor.spec.js — focus-trap tests pass with handlers swapped
RESOLVED — inlineChoice/tests/Editor.spec.js — no-id error test passes wherever it renders
RESOLVED — TipTapEditor/tests/imageSrc.spec.js — duplicates toStoredImageSrcs cases via stub
UNADDRESSED — InlineChoiceOptions/index.vue:97 — bare <input>, not the #5927 plain-text row
UNADDRESSED — inlineChoice/Editor.vue:52 — options-problem message for NO_CORRECT_ANSWER (nitpick)
RESOLVED — InlineChoiceChip/index.vue:14 — green fill on chip with no correct answer
RESOLVED — useInlineChoicePassage.js:75 — praise: live sync keeps editor history
Written by rtibblesbot, an LLM-based coding agent.
79b7904 to
4ec7055
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: manual QA found two blocking bugs:
- Clicking another chip can miss when the page is scrolled to its end.
- Ctrl+Z in an option field types back what it undid.
16 of 17 prior findings are resolved or acknowledged. Please address the open Editor.vue:56 nitpick: its message blames the options for a missing correct answer.
The other comments are smaller. CI pending. QA covered insert, options editing, keyboard, click-outside, chip navigation, undo/copy/paste, shuffle, save/reopen, validation, view mode and RTL. axe found nothing new.
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — clicking heading/padding drops focus to <body>
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while the passage stays usable
RESOLVED — inlineChoice/Editor.vue:100 — validation stale after chip removed/restored
ACKNOWLEDGED — inlineChoice/Editor.vue:89 — passage editor indistinguishable from question field
ACKNOWLEDGED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — InlineChoiceChip/index.vue:24 — chip behaviour changes out of scope
ACKNOWLEDGED — InlineChoiceChip/index.vue:42 — chip without correct mark reads like an option
RESOLVED — EditorToolbar.vue — Insert pushed off the toolbar in narrow windows
RESOLVED — inlineChoice/tests/Editor.spec.js — focus-trap tests pass with handlers swapped
RESOLVED — inlineChoice/tests/Editor.spec.js — no-id error test passes wherever it renders
RESOLVED — TipTapEditor/tests/imageSrc.spec.js — repeats toStoredImageSrcs cases through a stub
ACKNOWLEDGED — InlineChoiceOptions/index.vue:97 — bare <input> instead of plain-text toolbar row
UNADDRESSED — inlineChoice/Editor.vue:56 — message blames options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — green fill on chip with no correct answer
RESOLVED — passageChips.js:45 — invalid chip marked by colour alone
RESOLVED — inlineChoice/Editor.vue:69 — helper text not referenced by the passage
RESOLVED — QTIItemEditor.spec.js:599 — findByText for the heading
Written by rtibblesbot, an LLM-based coding agent.
4ec7055 to
79fdd0b
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: two new keyboard gaps from routing undo through the passage's history (inline).
17 of 23 prior findings resolved; 6 acknowledged.
CI passing. Manual QA covered authoring, options, shuffle, validation, keyboard (LTR/RTL), screen reader, light dismiss and view mode. Axe found nothing new.
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — Clicking the panel's heading or padding drops focus to <body>
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal="true" while the passage stays clickable
RESOLVED — inlineChoice/Editor.vue:97 — Validation goes stale after a chip is removed or restored as text
ACKNOWLEDGED — inlineChoice/Editor.vue:86 — Screen readers can't tell the passage editor from the question field
ACKNOWLEDGED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — InlineChoiceChip/index.vue:24 — Chip behaviour changes listed as out of scope
ACKNOWLEDGED — InlineChoiceChip/index.vue:42 — Chip with no correct mark reads like an option named "Add answers"
RESOLVED — EditorToolbar.vue — Insert pushed off the toolbar in narrow windows
RESOLVED — inlineChoice/tests/Editor.spec.js — Focus-trap tests pass with first/last handlers swapped
RESOLVED — inlineChoice/tests/Editor.spec.js — No-id error test passes wherever the error renders
RESOLVED — TipTapEditor/tests/imageSrc.spec.js — Repeats toStoredImageSrcs cases through a stub
ACKNOWLEDGED — InlineChoiceOptions/index.vue:97 — Options use a bare <input>, not the plain-text toolbar row
ACKNOWLEDGED — inlineChoice/Editor.vue:53 — Message blames the options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — Show answers fills a chip with no correct answer green
RESOLVED — inlineChoice/passageChips.js:45 — Invalid chip marked by colour alone
RESOLVED — inlineChoice/Editor.vue:66 — Helper text not referenced by the passage
RESOLVED — QTIItemEditor/tests/QTIItemEditor.spec.js:599 — findByText instead of a heading role query
RESOLVED — inlineChoice/Editor.vue — Clicking another chip doesn't open it when scrolled to the end
RESOLVED — InlineChoiceOptions/index.vue:112 — Repeated Ctrl+Z in an option field types the undone text back
ACKNOWLEDGED — InlineChoiceChip/index.vue:33 — Error icon replaces the option count
RESOLVED — EditorToolbar.vue:402 — More menu may be clipped to the toolbar box
RESOLVED — useInlineChoicePassage.spec.js:218 — hasErrors branch of chipMessage untested
RESOLVED — InlineChoiceChip/index.vue — Selected chip doesn't take the selection's colour
Written by rtibblesbot, an LLM-based coding agent.
Superseded by my review of 79fdd0b: no blocking findings remain.
79fdd0b to
0c742cd
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: all 25 prior findings are resolved. Two new suggestions on the history shortcut are inline.
CI passes. Manual QA did not run. The UI is unverified.
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — Clicking heading/padding drops focus; Escape stops closing
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while the passage stays clickable
RESOLVED — inlineChoice/Editor.vue:97 — Validation goes stale after a chip is removed
RESOLVED — inlineChoice/Editor.vue:86 — Passage editor indistinguishable from question field
RESOLVED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — InlineChoiceChip/index.vue — Chip behaviour changes outside #6182 scope
RESOLVED — InlineChoiceChip/index.vue:42 — No-correct chip reads like option "Add answers"
RESOLVED — EditorToolbar.vue — Insert pushed off toolbar in narrow windows
RESOLVED — Editor.spec.js — Focus-trap tests pass with handlers swapped
RESOLVED — Editor.spec.js — No-id error test passes wherever it renders
RESOLVED — imageSrc.spec.js — Repeats toStoredImageSrcs cases through a stub
RESOLVED — InlineChoiceOptions/index.vue:97 — Options use a bare <input>
RESOLVED — inlineChoice/Editor.vue:53 — Message blames options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — Green fill on chip with no correct answer
RESOLVED — passageChips.js:45 — Invalid chip marked by colour alone
RESOLVED — inlineChoice/Editor.vue:66 — Helper text not referenced
RESOLVED — QTIItemEditor.spec.js:599 — findByText for card heading
RESOLVED — inlineChoice/Editor.vue — Clicking another chip fails when scrolled to end
RESOLVED — InlineChoiceOptions/index.vue:112 — Repeated Ctrl+Z types undone text back
RESOLVED — InlineChoiceChip/index.vue:33 — Error icon replaces option count
RESOLVED — EditorToolbar.vue:402 — More menu clipped to toolbar box
RESOLVED — useInlineChoicePassage.spec.js:218 — hasErrors branch of chipMessage untested
RESOLVED — InlineChoiceChip/index.vue — Selected chip lacks selection colour
RESOLVED — InlineChoiceOptions/index.vue — Undo/redo deletes focused option, focus to <body>
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z does nothing while a chip has focus
Written by rtibblesbot, an LLM-based coding agent.
0c742cd to
4ec4fa0
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: all 27 prior findings resolved or acknowledged; two new suggestions inline.
CI passing. Manual QA did not run, so the UI is unverified.
- suggestion: On macOS, Ctrl+Z undoes from a chip or the panel but not in the passage. Could the chip and panel reuse ProseMirror's keymap instead of
historyShortcut.js? - suggestion: The caret test never moves the caret. Could it assert the movement?
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — clicking heading/padding drops focus to <body>
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while passage stays clickable
RESOLVED — inlineChoice/Editor.vue:97 — validation stale after chip removed/restored
ACKNOWLEDGED — inlineChoice/Editor.vue:86 — passage editor indistinguishable from question field (separate issue)
ACKNOWLEDGED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold (general issue)
RESOLVED — InlineChoiceChip/index.vue — chip behaviour out of #6182 scope
ACKNOWLEDGED — InlineChoiceChip/index.vue:42 — chip with no correct mark reads like option "Add answers"
RESOLVED — EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — inlineChoice/tests/Editor.spec.js — focus-trap tests pass with handlers swapped
RESOLVED — inlineChoice/tests/Editor.spec.js — no-id error test passes wherever it renders
RESOLVED — TipTapEditor/tests/imageSrc.spec.js — repeats toStoredImageSrcs cases
ACKNOWLEDGED — InlineChoiceOptions/index.vue:98 — bare <input> instead of plain-text toolbar row
ACKNOWLEDGED — inlineChoice/Editor.vue:53 — message blames options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — green fill on chip with no correct answer
RESOLVED — passageChips.js:45 — invalid chip marked by colour alone
RESOLVED — inlineChoice/Editor.vue:66 — helper text not referenced
RESOLVED — QTIItemEditor.spec.js:599 — findByText instead of heading role
RESOLVED — inlineChoice/Editor.vue — clicking another chip fails when scrolled to end
RESOLVED — InlineChoiceOptions/index.vue:112 — repeated Ctrl+Z types undone text back
ACKNOWLEDGED — InlineChoiceChip/index.vue:33 — error icon replaces option count
RESOLVED — EditorToolbar.vue:402 — More menu clipped to toolbar box
RESOLVED — useInlineChoicePassage.spec.js:218 — hasErrors branch of chipMessage untested
RESOLVED — InlineChoiceChip/index.vue — selected chip doesn't take selection colour
RESOLVED — InlineChoiceOptions/index.vue — undo/redo deletes focused option, focus to <body>
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z does nothing while chip focused
RESOLVED — InlineChoiceOptions/index.vue — Ctrl+Z does nothing on panel radios/buttons
RESOLVED — historyShortcut.js — Ctrl+Z on chip fails with non-Latin layout
Written by rtibblesbot, an LLM-based coding agent.
4ec4fa0 to
8d74e78
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: 23 of 29 prior findings resolved; 6 acknowledged. One new suggestion inline.
CI passing. Manual QA covered insert/convert, marking, reorder, multiple dropdowns, Shuffle, save/reopen (XSD-valid), undo/redo, copy/paste ids, keyboard/screen reader, view mode and RTL. No new axe AA violations. QA ran the real channel_edit bundle in a static shell because Redis MISCONF blocked login. Server persistence via /api/sync/ was not checked.
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — clicking heading/padding drops focus to <body>
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while passage stays clickable
RESOLVED — inlineChoice/Editor.vue:97 — validation stale after chip removed/restored
ACKNOWLEDGED — inlineChoice/Editor.vue:86 — passage editor indistinguishable from question field
ACKNOWLEDGED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — InlineChoiceChip/index.vue — chip behaviour changes out of #6182 scope
ACKNOWLEDGED — InlineChoiceChip/index.vue:42 — unmarked chip reads like option "Add answers"
RESOLVED — EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — inlineChoice/tests/Editor.spec.js — focus-trap tests pass with handlers swapped
RESOLVED — inlineChoice/tests/Editor.spec.js — no-id error test passes wherever it renders
RESOLVED — TipTapEditor/tests/imageSrc.spec.js — repeats toStoredImageSrcs cases
ACKNOWLEDGED — InlineChoiceOptions/index.vue:98 — bare <input> instead of plain-text toolbar
ACKNOWLEDGED — inlineChoice/Editor.vue:53 — message blames options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — green fill on chip with no correct answer
RESOLVED — passageChips.js:45 — invalid chip marked by colour alone
RESOLVED — inlineChoice/Editor.vue:66 — helper text not referenced
RESOLVED — QTIItemEditor.spec.js:599 — findByText instead of heading role
RESOLVED — inlineChoice/Editor.vue — clicking another chip fails when scrolled to end
RESOLVED — InlineChoiceOptions/index.vue:112 — repeated Ctrl+Z retypes undone text
ACKNOWLEDGED — InlineChoiceChip/index.vue:33 — error icon replaces option count
RESOLVED — EditorToolbar.vue:402 — More menu clipped
RESOLVED — useInlineChoicePassage.spec.js:218 — hasErrors branch untested
RESOLVED — InlineChoiceChip/index.vue — selected chip lacks selection colour
RESOLVED — InlineChoiceOptions/index.vue — undo/redo deletes focused option
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z does nothing on focused chip
RESOLVED — InlineChoiceOptions/index.vue — Ctrl+Z does nothing on radios/buttons
RESOLVED — historyShortcut.js — Ctrl+Z fails on non-Latin layout
RESOLVED — historyShortcut.js — macOS Ctrl+Z undoes from chip but not passage
RESOLVED — InlineChoiceChip.spec.js:144 — test never moves the caret
Written by rtibblesbot, an LLM-based coding agent.
8d74e78 to
f51a09a
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: no new findings. 25 of 31 prior findings are resolved. The maintainer acknowledged the other 6.
Prior-finding status
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:9 — Clicking heading or padding drops focus to
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:13 — aria-modal while the passage stays clickable
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:97 — Validation goes stale after a chip is removed or restored
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:86 — Passage editor indistinguishable from the question field (separate issue)
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold (general issue)
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Chip behaviour changes outside #6182 scope
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:42 — Chip with no correct mark reads like an "Add answers" option
RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue — Insert pushed off the toolbar in narrow windows
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/Editor.spec.js — Focus-trap tests pass with handlers swapped
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/Editor.spec.js — No-id error test passes wherever it renders
RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/tests/imageSrc.spec.js — Repeats toStoredImageSrcs cases through a stub
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:98 — Options use a bare
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:53 — Message blames options for NO_CORRECT_ANSWER
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:14 — Green fill on a chip with no correct answer
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/useInlineChoicePassage.js:114 — Live sync keeps editor history (praise)
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/passageChips.js:45 — Invalid chip marked by colour alone
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:66 — Helper text not referenced
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/tests/QTIItemEditor.spec.js:599 — findByText instead of heading role
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue — Clicking another chip fails when scrolled to the end
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:112 — Repeated Ctrl+Z types undone text back
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:33 — Error icon replaces the option count
RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue:402 — More menu may be clipped
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/useInlineChoicePassage.spec.js:218 — hasErrors branch of chipMessage untested
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Selected chip lacks the selection colour
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue — Undo/redo deletes the focused option
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Ctrl+Z does nothing on a focused chip
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue — Ctrl+Z does nothing on panel radios/buttons
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/historyShortcut.js — Ctrl+Z fails on non-Latin layouts
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/historyShortcut.js — macOS Ctrl+Z works from chip/panel but not the passage
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/InlineChoiceChip.spec.js:144 — Test never moves the caret
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:263 — Ctrl+Z in one panel undoes another chip's edit unseen
Written by rtibblesbot, an LLM-based coding agent.
f51a09a to
bceea4a
Compare
rtibbles
left a comment
There was a problem hiding this comment.
From manual QA; screenshots of the first two in the next comment.
| return { label, optionCount, hasAnswer, accessibleName: name({ label, count: optionCount }) }; | ||
| } | ||
|
|
||
| const label = hasAnswer ? correctText : addAnswers$(); |
There was a problem hiding this comment.
The chip says "Add answers" while the panel says "Choose a correct answer". We should make them match.
| :aria-label="editQuestionLabel$()" | ||
| @click="openPrompt" | ||
| > | ||
| <TipTapEditor |
There was a problem hiding this comment.
Pasting a dropdown here gives satstoodlay. We should strip it, or keep only the correct answer.
| idsWith(ValidationError.NO_CORRECT_ANSWER).has(props.dropdown.responseIdentifier), | ||
| ); | ||
|
|
||
| const isOnlyOption = computed(() => props.dropdown.options.length <= 1); |
There was a problem hiding this comment.
A dropdown with one option passes validation. We should report TOO_FEW_CHOICES.
| .has-errors & { | ||
| background-color: v-bind('$themeTokens.error'); | ||
| color: var(--tokens-textInverted); | ||
| background-color: var(--tokens-correct); |
There was a problem hiding this comment.
The chip stays green when answers are hidden. We should use neutral colours when isConcealed.
| const prevDoc = editor.state.doc; | ||
| isSteppingFromOutside = true; | ||
| try { | ||
| editor.commands[direction](); |
There was a problem hiding this comment.
Undo from the panel scrolls the page. We should use undoNoScroll/redoNoScroll.
| /** Every dropdown in the passage, in document order. */ | ||
| const dropdowns = computed(() => getDropdowns(state.value.passage)); | ||
|
|
||
| function setPrompt(html) { |
There was a problem hiding this comment.
A cleared question is saved as <p data-studio-prompt=""/>. We should normalize it with hasRichTextContent.
7be483c to
1c82782
Compare
There was a problem hiding this comment.
PR #6303: 30 of 33 prior findings resolved or acknowledged; 3 still open on their threads (out-of-scope chip changes, imageSrc.spec.js duplication, More menu clipping).
CI pending. Manual QA covered all 12 scenarios, including RTL and 375px. Nothing blocking turned up. axe found one new violation (chip name).
- suggestion:
TOO_FEW_CHOICESadds a publish gate that #6180 doesn't specify. - suggestion: removing Vuetify's
::selectionchanges selection colour app-wide. - suggestion: opening the panel fires up to two alerts.
- suggestion: the chip's visible text isn't in its accessible name.
- suggestion: toolbar Copy leaves out the chip's answer in plain text.
I dropped QA's report that Insert starts out of view at phone widths. The test browser had no touch support. Touch devices get the mobile toolbar.
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — panel heading/padding click drops focus
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while passage clickable (outside click closes the panel)
RESOLVED — Editor.vue:97 — stale validation after chip removed/restored
ACKNOWLEDGED — Editor.vue:86 — passage editor not distinguishable from question field (separate issue under #6103)
ACKNOWLEDGED — Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold (general issue)
UNADDRESSED — InlineChoiceChip/index.vue — chip behaviour changes #6182 lists out of scope
ACKNOWLEDGED — InlineChoiceChip/index.vue:43 — chip with no correct mark reads like "Add answers"
RESOLVED — EditorToolbar.vue — Insert pushed off narrow toolbar (icon-only + overflow-x)
RESOLVED — Editor.spec.js — focus-trap tests pass with first/last swapped
RESOLVED — Editor.spec.js — no-id error test not pinned to passage editor
UNADDRESSED — imageSrc.spec.js — repeats toStoredImageSrcs cases through a stub
ACKNOWLEDGED — InlineChoiceOptions/index.vue:102 — bare input instead of plain-text toolbar
ACKNOWLEDGED — Editor.vue:53 — message blames options for NO_CORRECT_ANSWER (strings review)
RESOLVED — InlineChoiceChip/index.vue:14 — green fill on chip with no correct answer
RESOLVED — useInlineChoicePassage.js:116 — live sync keeps editor history (praise)
RESOLVED — passageChips.js:62 — invalid chip marked by colour alone
RESOLVED — Editor.vue:66 — helper text not referenced
RESOLVED — QTIItemEditor.spec.js:599 — findByText not scoped to heading
RESOLVED — Editor.vue — clicking another chip at page end doesn't open it
RESOLVED — InlineChoiceOptions/index.vue:116 — repeated Ctrl+Z types undone text back
ACKNOWLEDGED — InlineChoiceChip/index.vue:34 — error icon replaces option count
UNADDRESSED — EditorToolbar.vue:402 — More menu may be clipped by overflow-y: hidden
RESOLVED — useInlineChoicePassage.spec.js:225 — hasErrors branch of chipMessage untested
RESOLVED — InlineChoiceChip/index.vue — selected chip colour comment mismatch
RESOLVED — InlineChoiceOptions/index.vue — undo/redo deletes focused option
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z inert while chip focused
RESOLVED — InlineChoiceOptions/index.vue — Ctrl+Z inert on radios/buttons
RESOLVED — historyShortcut.js — non-Latin keyboard layout
RESOLVED — historyShortcut.js — macOS Ctrl+Z in passage
RESOLVED — InlineChoiceChip.spec.js:156 — test never moves the caret
RESOLVED — InlineChoiceOptions/index.vue:265 — Ctrl+Z undoes another chip's edit
RESOLVED — InlineChoiceChip/index.vue — selected chips #b3d4fc blue (Vuetify's ::selection overrode KDS's; see vuetify.scss)
ACKNOWLEDGED — package.json:83 — KDS bump not in PR body (lands after #6317)
After this review: Full code review, then manual QA once the reviewer sets Needs QA.
- User-visible files changed:
.stylelintrc.js,contentcuration/contentcuration/frontend/shared/styles/vuetify.scss,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/composables/useInlineChoiceInteraction.js,contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/descriptors.js…. - Decide whether a one-option dropdown should block publishing (
TOO_FEW_CHOICES), since #6180 doesn't specify it. - Sign off on removing Vuetify's global
::selection, which changes selection colour and text colour on every Studio page. - Check text selection on dark toolbars (channel list, edit modal, settings) for contrast once the selection decision is made.
QA captures (50)
Add a new exercise question and switch it to Inline choice in the type selector — option label and description, card type label, optional question field, passage editor label and helper text, Shuffle setting off by default in the choice editor's settings slot
| Step | Screenshot |
|---|---|
| Card collapsed type label | ![]() |
| Inline choice edit mode | ![]() |
| Type dropdown open | ![]() |
| Type selector dialog | ![]() |
1-switch-to-inline-choice.webm
Insert a blank dropdown with Insert, then convert highlighted passage text into a dropdown — the panel opens on each with focus inside, Insert's look while unavailable (no hover change, not-allowed cursor), the converted text becomes an option, the chip's label and count
| Step | Screenshot |
|---|---|
| Blank insert panel open | ![]() |
| Convert over chip | ![]() |
| Converted text panel open | ![]() |
| Insert unavailable hover | ![]() |
2-insert-and-convert.webm
In an open chip's options panel add, edit, remove and reorder options by drag and by move up / move down, and mark the correct one — chip label and count update immediately, the correct mark stays on its option after reorder, the only option's remove control is disabled, removing the correct option gives the dashed "Add answer" chip, the markers act as one labelled single-select group
| Step | Screenshot |
|---|---|
| After drag | ![]() |
| Correct moved up | ![]() |
| Correct option duplicate | ![]() |
| Correct removed | ![]() |
| Only option remove disabled | ![]() |
| Option errors | ![]() |
| Panel initial | ![]() |
3-drag-reorder.webm
3-edit-options.webm
Drive the options panel from the keyboard only — Enter / Space on a chip opens it as a labelled role=dialog aria-modal panel, Tab and Shift+Tab stay inside, Escape and the close control return focus to the chip and the next Tab moves on, opening a second chip shows its options, clicking the passage closes the panel, the passage editor stays open while the panel is used
| Step | Screenshot |
|---|---|
| Escape focus on chip | ![]() |
| Panel closed by passage click | ![]() |
| Panel open via enter | ![]() |
| Second chip options | ![]() |
4-keyboard-options-panel.webm
Turn Shuffle on and off on a question with several dropdowns, then save and reopen — drag handles and move up / move down hidden on every chip's panel while on and back when off, the setting survives reopening, every qti-inline-choice-interaction in the saved XML carries it
| Step | Screenshot |
|---|---|
| Shuffle off handles shown | ![]() |
| Shuffle on after reopen | ![]() |
| Shuffle on handles hidden | ![]() |
5-shuffle-toggle.webm
Move the caret through a passage with several dropdowns and delete them — arrow keys step past a chip without selecting it, Backspace / Delete beside a chip removes it, Left / Right on a focused chip returns the caret to the text, live-region announcements for crossing and removing chips, a text selection spanning a chip restyles it and selection colours look right
| Step | Screenshot |
|---|---|
| Caret after trailing chip | ![]() |
| Rtl selection | ![]() |
| Select all | ![]() |
| Selection spanning chips | ![]() |
| Three chips deleted | ![]() |
6-caret-and-delete-chips.webm
Undo and redo option edits and chip removals with the shortcuts in the passage, on a chip and inside the panel, then copy, cut and paste dropdowns within the passage and into the question field — the open panel always matches the chip, pasted chips get fresh unique response and choice identifiers, pasting outside a passage leaves only the correct answer text
| Step | Screenshot |
|---|---|
| Pasted chip in passage | ![]() |
| Undo in panel opens changed chip | ![]() |
Break an inline choice question in each way validation catches — no dropdown, a dropdown with no correct answer, one option only, an empty option, duplicate options — each error appears on the option row, the chip or the passage as it belongs, the question is marked incomplete, and fixing each clears it
| Step | Screenshot |
|---|---|
| All fixed | ![]() |
| Collapsed incomplete | ![]() |
| Dropdown removed | ![]() |
| Dropdown restored | ![]() |
| Duplicate options | ![]() |
| Empty correct option | ![]() |
| Empty option | ![]() |
| New blank errors | ![]() |
| No dropdown error | ![]() |
| One option only | ![]() |
8-fix-and-remove-dropdown.webm
Save an inline choice question with several dropdowns, some without a correct answer, reload the page and reopen it — question, passage, every chip's options and correct answer restored, which chip was open is not saved, the saved XML has response processing only once every dropdown is scorable and no console warning is written
| Step | Screenshot |
|---|---|
| After reload reopened | ![]() |
| All dropdowns scorable | ![]() |
| Before reload chip2 open | ![]() |
Written by rtibblesbot, an LLM-based coding agent.
cf5c162 to
65380dc
Compare
There was a problem hiding this comment.
PR #6303: the More menu now runs off the viewport, and Add option reads the new field's error twice.
Most prior findings are resolved or acknowledged. New commits landed after these passes ran and are unreviewed.
CI passing. Manual QA covered 12 scenarios. Only the two findings below came up.
- blocking: the More menu now runs off the viewport (inline).
- suggestion: Add option reads the new field's error twice (inline).
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — panel heading/padding click drops focus
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while passage clickable
RESOLVED — Editor.vue:97 — validation stale while passage open
ACKNOWLEDGED — Editor.vue:86 — passage editor not distinguishable from question field
ACKNOWLEDGED — Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
ACKNOWLEDGED — InlineChoiceChip/index.vue — chip behaviour out of #6182 scope
ACKNOWLEDGED — InlineChoiceChip/index.vue:46 — "Add answers" reads as option name
RESOLVED — EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — Editor.spec.js — focus-trap tests pass with handlers swapped
RESOLVED — Editor.spec.js — no-id error not pinned to passage editor
RESOLVED — imageSrc.spec.js — repeats toStoredImageSrcs cases
ACKNOWLEDGED — InlineChoiceOptions/index.vue:105 — bare input for options
ACKNOWLEDGED — Editor.vue:53 — message blames options
RESOLVED — InlineChoiceChip/index.vue:14 — green fill with no correct answer
RESOLVED — useInlineChoicePassage.js:116 — live sync keeps history (praise)
RESOLVED — passageChips.js:62 — invalid chip marked by colour alone
RESOLVED — Editor.vue:66 — helper text unreferenced
RESOLVED — QTIItemEditor.spec.js:599 — findByText not scoped to heading
RESOLVED — Editor.vue — clicking another chip at page end
RESOLVED — InlineChoiceOptions/index.vue:119 — repeated Ctrl+Z retypes text
ACKNOWLEDGED — InlineChoiceChip/index.vue:36 — error icon replaces count
RESOLVED — EditorToolbar.vue:404 — More menu clipped (fix regressed; see new blocking finding)
RESOLVED — useInlineChoicePassage.spec.js:225 — hasErrors branch untested
RESOLVED — InlineChoiceChip/index.vue — selected chip colour vs comment
RESOLVED — InlineChoiceOptions/index.vue — undo deletes focused option
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z on focused chip
RESOLVED — InlineChoiceOptions/index.vue — Ctrl+Z on radios/buttons
RESOLVED — historyShortcut.js — non-Latin layouts
RESOLVED — historyShortcut.js — macOS Ctrl+Z
RESOLVED — InlineChoiceChip.spec.js:156 — test never moves caret
RESOLVED — InlineChoiceOptions/index.vue:292 — Ctrl+Z undoes another chip's edit
ACKNOWLEDGED — InlineChoiceChip/index.vue — selected chip blue vs yellow
ACKNOWLEDGED — package.json:83 — KDS bump not in PR body
RESOLVED — validation.js:14 — one-option dropdown fails validation (withdrawn: #6182 lists TOO_FEW_CHOICES)
ACKNOWLEDGED — vuetify.scss:2482 — rule removal affects all pages
RESOLVED — InlineChoiceOptions/index.vue:22 — up to two alerts on open
RESOLVED — InlineChoiceChip/index.vue:106 — accessible name omits badge text
RESOLVED — InlineChoiceNode.js — toolbar Copy drops chip
After this review: Full code review, then manual QA once the reviewer sets Needs QA.
- User-visible files changed:
.stylelintrc.js,contentcuration/contentcuration/frontend/shared/styles/vuetify.scss,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/ValidationMessage/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/composables/useInlineChoiceInteraction.js…. - Confirm the chip behaviour changes beyond #6182's stated scope (chip labels, error icon, selection colour) are wanted product-wide.
- Confirm removing the vuetify.scss
::selectionrule is acceptable across all Studio pages. - Re-run the More menu and Add option screen-reader checks once fixed.
QA captures (50)
Add a new question in the exercise editor and switch it to Inline choice — type selector entry, card type label, question field, passage helper text, Insert button in the passage toolbar, Shuffle setting off by default in the settings slot
| Step | Screenshot |
|---|---|
| Card collapsed type label | ![]() |
| Inline choice card initial | ![]() |
| Passage open insert button | ![]() |
| Type info modal inline choice | ![]() |
| Type selector inline choice entry | ![]() |
1-switch-to-inline-choice.webm
Build a passage with two dropdowns, one inserted blank and one converted from highlighted text, fill each in, then save, close and reopen the item — panel opens on insert, chip labels and counts, correct answers, saved XML has every declaration and no open-chip state
| Step | Screenshot |
|---|---|
| Card closed two chips | ![]() |
| Panel open on insert | ![]() |
| Reopened dropdown 2 | ![]() |
| Two dropdowns filled | ![]() |
2-build-save-reopen.webm
Edit one dropdown's options panel end to end — add, type in, remove (last option's remove disabled), reorder by drag and by move up/down, mark correct and move the mark, remove the correct option to reach the dashed Add answer state; chip label and count update after each step
| Step | Screenshot |
|---|---|
| Blank options errors | ![]() |
| Correct moved to green | ![]() |
| Correct removed no answer | ![]() |
| Four options blank error | ![]() |
| No answer chip closed | ![]() |
| One option delete disabled | ![]() |
3-drag-reorder.webm
Open one chip, then click another chip, then click into the passage text, then click outside the editor — panel switches to the second chip's options, closes on passage click, rich text editor stays open while the panel is open and closes after
| Step | Screenshot |
|---|---|
| Chip1 panel open | ![]() |
| Chip2 panel switched | ![]() |
| Outside click editor closed | ![]() |
| Outside click with panel open | ![]() |
| Passage click panel closed | ![]() |
| Passage open no panel | ![]() |
4-chip-switch-and-dismiss.webm
Operate the options panel by keyboard only — open a chip with Enter and with Space, focus lands in the list, Tab and Shift+Tab stay trapped, correct markers act as one radio group, move up/down, Escape and the close button return focus to the chip and the next Tab moves on
| Step | Screenshot |
|---|---|
| Focus on correct radio | ![]() |
| Focus on move down | ![]() |
| Panel opened by enter focus in list | ![]() |
| Panel opened by space dropdown 2 | ![]() |
5-keyboard-only-panel.webm
Move the caret through a passage with dropdowns using arrow keys, Backspace and Delete, and Left/Right from a focused chip — caret skips over chips, Backspace/Delete beside a chip removes it, chip-to-text return, live region announcements for crossed and removed chips
| Step | Screenshot |
|---|---|
| After undo | ![]() |
| Backspace removed chip | ![]() |
| Caret after chip | ![]() |
| Rtl passage | ![]() |
6-caret-and-chip-keys.webm
Edit options and remove chips, then undo and redo repeatedly with toolbar buttons and keyboard shortcuts — options panel always matches the passage, the open chip survives or the panel closes when its chip is gone, no stale or duplicated option ids
| Step | Screenshot |
|---|---|
| History fully undone | ![]() |
| Panel after edits | ![]() |
| Panel after undo | ![]() |
7-undo-redo-panel-sync.webm
Copy and paste dropdowns — chip into the same passage, into a second inline choice question, and into the question field or another question type's rich text — pasted chip keeps its options with fresh identifiers, plain-text targets get only the correct answer text
| Step | Screenshot |
|---|---|
| Question field paste correct answer | ![]() |
| Same passage pasted chip panel | ![]() |
| Second question pasted chip | ![]() |
| Single choice paste correct answer | ![]() |
| Toolbar and cut paste chips | ![]() |
Toggle Shuffle on and off with several chips, then save and reopen — drag handles and move up/down hide and return on every chip's panel, setting persists, every qti-inline-choice-interaction in the XML carries shuffle
| Step | Screenshot |
|---|---|
| Reopened shuffle persisted | ![]() |
| Shuffle off panel reorderable | ![]() |
| Shuffle on panel no reorder | ![]() |
9-shuffle-toggle-save-reopen.webm
Trigger each validation error — empty option text, dropdown with no correct answer, dropdown with one option, passage with no dropdowns — error shown on the option row, chip and panel top, or passage editor; question marked incomplete; Add option does not double-announce the empty error
| Step | Screenshot |
|---|---|
| Collapsed cards incomplete | ![]() |
| Empty option row errors | ![]() |
Written by rtibblesbot, an LLM-based coding agent.
65380dc to
b3705ba
Compare
There was a problem hiding this comment.
PR #6303: the toolbar More menu still opens off-screen on a phone. The other 40 prior findings are resolved or acknowledged.
- blocking: More menu runs off the viewport at phone width (
EditorToolbar.vue:106). - CI passing.
- Manual QA passed insert, options panel, reorder/shuffle, keyboard, undo/redo, paste, validation, save/reload, RTL and selection colour.
- Commits pushed after these passes ran are not reviewed here.
Prior-finding status
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:9 — Panel heading/padding click drops focus to body
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:13 — aria-modal while passage is clickable
RESOLVED — QTIEditor/interactions/inlineChoice/Editor.vue:97 — Validation stale after chip removed or restored
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/Editor.vue:86 — Passage editor indistinguishable from question field
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Chip behaviour changes out of scope for #6182 (withdrawn: later changes came from review asks)
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:46 — "Add answers" reads like an option
RESOLVED — TipTapEditor/TipTapEditor/components/EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — QTIEditor/interactions/inlineChoice/tests/Editor.spec.js — Focus-trap tests survive swapped handlers
RESOLVED — QTIEditor/interactions/inlineChoice/tests/Editor.spec.js — No-id error test not tied to passage editor
RESOLVED — TipTapEditor/tests/imageSrc.spec.js — Duplicated toStoredImageSrcs cases
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:105 — Bare input instead of plain-text toolbar
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/Editor.vue:53 — Message blames options for NO_CORRECT_ANSWER
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:14 — Show-answers fill with no correct answer
RESOLVED — QTIEditor/interactions/inlineChoice/passageChips.js:62 — Invalid chip marked by colour alone
RESOLVED — QTIEditor/interactions/inlineChoice/Editor.vue:66 — Helper text unreferenced
RESOLVED — QTIEditor/components/QTIItemEditor/tests/QTIItemEditor.spec.js:751 — findByText not scoped to heading
RESOLVED — QTIEditor/interactions/inlineChoice/Editor.vue — Another chip doesn't open at page end
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:119 — Repeated Ctrl+Z types text back
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:36 — Error icon replaces option count
RESOLVED — TipTapEditor/TipTapEditor/components/EditorToolbar.vue:404 — More menu clipped to toolbar
RESOLVED — QTIEditor/interactions/inlineChoice/tests/useInlineChoicePassage.spec.js:225 — hasErrors branch untested
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Selected chip doesn't take selection colour
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue — Undo/redo deletes focused option
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Ctrl+Z does nothing on a focused chip
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue — Ctrl+Z does nothing on radios/buttons
RESOLVED — QTIEditor/interactions/inlineChoice/historyShortcut.js — Ctrl+Z fails on non-Latin layouts
RESOLVED — QTIEditor/interactions/inlineChoice/historyShortcut.js — macOS Ctrl+Z inconsistent in passage
RESOLVED — QTIEditor/interactions/inlineChoice/tests/InlineChoiceChip.spec.js:156 — Test never moves the caret
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:292 — Ctrl+Z crosses chips
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Selected chips blue vs yellow selection
ACKNOWLEDGED — package.json:84 — KDS bump not in PR body
RESOLVED — QTIEditor/interactions/inlineChoice/validation.js:14 — One-option dropdown fails validation (withdrawn: #6180 rule 8 requires it)
RESOLVED — styles/vuetify.scss:2482 — Removed selection rule changes selection app-wide
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:22 — Two alerts on opening an incomplete chip
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:106 — Accessible name omits count badge text
ACKNOWLEDGED — QTIEditor/interactions/inlineChoice/InlineChoiceNode.js — Toolbar Copy drops chip from plain text
UNADDRESSED — TipTapEditor/TipTapEditor/components/EditorToolbar.vue:106 — More menu runs off viewport
RESOLVED — QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:252 — Add option reads blank error twice
After this review: Full code review, then manual QA once the reviewer sets Needs QA.
- User-visible files changed:
.stylelintrc.js,contentcuration/contentcuration/frontend/shared/styles/vuetify.scss,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/ValidationMessage/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/composables/useInlineChoiceInteraction.js…. - Confirm the shared EditorToolbar changes (Insert icon-only,
overflow-x: auto, More menu positioning) suit every TipTap editor, not just the passage. - Confirm dropping Vuetify's global
::selectionoverride for KDS's yellow is wanted app-wide. - QA the More menu and toolbar on a phone-width window in LTR and RTL once the off-screen fix lands.
QA captures (50)
Add a new exercise question, switch its type to Inline choice, write a question and a passage, insert a blank dropdown and convert highlighted text into a dropdown — question type label, helper text, Insert opening the options panel with focus inside it, the chip label and count after each insert
1-insert-flow.webm
Fill a dropdown's options in its panel: add options, edit their text, mark one correct then mark another, remove the correct one, try removing the last remaining option — chip label and count update live, single-select correct markers, disabled remove on the only option, dashed "Add answer" state after removing the correct option
2-options-panel-flow.webm
Reorder a dropdown's options with drag and drop and with move up / move down, then turn Shuffle on and off — correct mark follows its option, Shuffle checkbox sits where the choice question's does and starts off, handles and move controls hide on every chip's panel while Shuffle is on and return when off
3-reorder-shuffle-flow.webm
Operate the options panel by keyboard only: Tab to a chip, open it with Enter and with Space, Tab and Shift+Tab around the panel, mark correct and reorder by keyboard, close with Escape and with the close control, open a second chip while one is open — focus trapped in the dialog, dialog role/aria-modal/label naming the dropdown, focus returns to the chip and the next Tab moves on, the second chip's options replace the first's
| Step | Screenshot |
|---|---|
| Marked correct and moved | ![]() |
| Panel open by enter | ![]() |
| Second chip replaces first | ![]() |
4-keyboard-panel-flow.webm
Move the caret through a passage with several dropdowns using arrow keys, delete a dropdown with Backspace and with Delete beside it, press Left/Right on a focused chip, then click the passage while a panel is open — caret skips chips rather than selecting them, chip removed in one keystroke, caret returns to the text, panel closes on passage click while the editor stays open, screen reader live-region announcements for crossed and removed dropdowns
| Step | Screenshot |
|---|---|
| Caret before chip | ![]() |
| Panel closed after passage click | ![]() |
| Panel open | ![]() |
5-caret-delete-flow.webm
Edit options, insert and delete dropdowns, then undo and redo each step with keyboard shortcuts and the toolbar history buttons — the open panel's list always matches the chip after every undo/redo, no stale panel for a removed chip, each edit is one undo step
| Step | Screenshot |
|---|---|
| Start | ![]() |
| Undo switches panel to changed chip | ![]() |
6-insert-delete-undo-redo.webm
Copy passage text holding dropdowns with Ctrl+C and with the toolbar Copy, paste it back into the passage, into the question field, into a hint and as plain text — pasted chips come back whole with fresh identifiers (check saved XML for duplicate ids), the question gets only the correct answer text or nothing without one, plain-text paste drops the dropdown
Leave an inline choice question with validation problems — no dropdown in the passage, a dropdown with no correct answer, a dropdown with too few options, an option with empty text — each error shows on the passage, the chip and the panel top, or the option row as appropriate, the question is marked incomplete, and errors clear once fixed
| Step | Screenshot |
|---|---|
| Blank dropdown errors | ![]() |
Written by rtibblesbot, an LLM-based coding agent.
rtibblesbot
left a comment
There was a problem hiding this comment.
PR #6303: 38 of 41 prior findings resolved or acknowledged; 3 still open.
- suggestion (
vuetify.scss:2482thread): removing Vuetify's global::selectionrule recolours text selection on every Studio page. Vuetify's#b3d4fcoverrode KDS's, hence the bluish selection on unstable. Get design sign-off, or scope it to the editor. - suggestion (
EditorToolbar.vue:106, both threads): the More menu still runs off the viewport in narrow non-touch windows. Downgraded from blocking: touch devices get the mobile toolbar. Fix it, or get a maintainer to defer it to KDS. - Withdrawn: chip changes outside #6182's scope; I requested most.
- Withdrawn: the one-option dropdown validation finding. #6182 names
TOO_FEW_CHOICES.
CI passing. Manual QA did not run.
Prior-finding status
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:9 — Panel heading click drops focus
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:13 — aria-modal while the passage is clickable
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:97 — Stale validation after a chip is removed
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:86 — Passage editor indistinguishable from question field
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Chip behaviour outside #6182 scope (withdrawn)
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:46 — Chip with no correct mark reads like an option
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/Editor.spec.js — Focus-trap tests pass with handlers swapped
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/Editor.spec.js — No-id error test not tied to passage editor
RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/tests/imageSrc.spec.js — Duplicate toStoredImageSrcs cases
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:105 — Options use a bare <input>
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:53 — Message blames options for NO_CORRECT_ANSWER
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:14 — Green fill on chip with no correct answer
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/useInlineChoicePassage.js:116 — Praise: live sync keeps history
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/passageChips.js:62 — Invalid chip marked by colour alone
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue:66 — Helper text not referenced
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/tests/QTIItemEditor.spec.js:751 — findByText for card label
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/Editor.vue — Clicking another chip fails at page end
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:119 — Repeated Ctrl+Z types undone text back
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:36 — Error icon replaces option count
RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue:404 — More menu clipped to toolbar box
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/useInlineChoicePassage.spec.js:225 — hasErrors branch untested
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Selected chip doesn't take selection colour
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue — Undo/redo deletes the focused option
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Ctrl+Z does nothing on a focused chip
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue — Ctrl+Z does nothing on radios/buttons
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/historyShortcut.js — Ctrl+Z on non-Latin layouts
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/historyShortcut.js — macOS Ctrl+Z in the passage
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/tests/InlineChoiceChip.spec.js:156 — Test never moves the caret
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:300 — Ctrl+Z undoes another chip's edit
ACKNOWLEDGED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue — Selected chips #b3d4fc blue
ACKNOWLEDGED — package.json:84 — KDS bump not in PR body
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/validation.js:14 — One-option dropdown fails validation (withdrawn)
UNADDRESSED — contentcuration/contentcuration/frontend/shared/views/../styles/vuetify.scss:2482 — Global ::selection rule removed
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:22 — Up to two alerts on opening an incomplete chip
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceChip/index.vue:106 — Accessible name lacks visible text
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/InlineChoiceNode.js — Toolbar Copy drops chip from plain text
RESOLVED — contentcuration/contentcuration/frontend/shared/views/QTIEditor/interactions/inlineChoice/components/InlineChoiceOptions/index.vue:254 — Add option announces blank error twice
CONTESTED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue:106 — More menu runs off the viewport
CONTESTED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue:106 — More menu opens above the viewport on a phone
After this review: Full code review, then manual QA once the reviewer sets Needs QA.
- User-visible files changed:
.stylelintrc.js,contentcuration/contentcuration/frontend/shared/styles/vuetify.scss,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/ValidationMessage/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/composables/useInlineChoiceInteraction.js…. - Decide whether dropping Vuetify's global
::selectionrule, which recolours text selection across Studio, is acceptable. - Decide whether the More menu running off the viewport in narrow non-touch windows can wait for a KDS fix.
- In the running app, check the chip and options panel with keyboard, screen reader and Ctrl+Z, because manual QA did not run.
Written by rtibblesbot, an LLM-based coding agent.
Superseded by my review of b3705ba: no blocking findings remain.
An item with several responses gets no response processing while any of them has nothing to score it by, such as an inline choice dropdown with no correct answer yet. That is an unfinished item, which validation already reports to the author, so it is not logged as well. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An unavailable action now fades as the toolbar's disabled buttons do, with a not-allowed cursor, and no longer changes on hover or press as if it could be used. In a small window it shows only its icon, keeping its name for assistive technology, since its full label ran past the toolbar's edge in a narrow window or at a high zoom. As a last resort, a toolbar still too wide for its editor scrolls. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The editor stays open on a click outside it while any trigger inside it has aria-haspopup and aria-expanded="true". The toolbar's menus rely on that, and so does a node view that opens a panel beside the editor, such as the inline choice chip's options. It is now stated in the consumer docs and tested for a popup opened from the content, so a change to the check cannot silently close the editor while such a panel is in use. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A chip is not a place to type, and its button is how the keyboard reaches its options, so it is no longer selectable as a node: the arrow keys move past it rather than onto it. ProseMirror leaves Backspace and Delete beside such a node to the browser, which handles them unevenly, so they remove the chip themselves, in one undoable step. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The stored form of an editor's HTML, with images back to their stored filenames, is now `storedHTML` in `utils/imageSrc.js`. `TipTapEditor` reads its content out through it, and so can a consumer that reads an editor directly, without repeating how that form is made. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
b3705ba to
f144867
Compare
There was a problem hiding this comment.
PR #6303: 31 of 41 prior findings are resolved and 8 acknowledged. The More menu placement (2 threads) is still open, now as a suggestion.
CI passing. Manual QA covered create/save/reopen, option editing, validation, keyboard, undo/redo, copy/paste, view mode, RTL, the toolbar and legacy items. The saved XML passes the QTI 3 XSD. axe found only pre-existing violations.
- suggestion: More menu opens off-screen (inline).
- suggestion: Add option still sets off a section-level alert (inline).
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — Clicking panel padding drops focus
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while the passage is clickable
RESOLVED — Editor.vue:97 — Validation stale after a chip is removed
ACKNOWLEDGED — Editor.vue:86 — Passage editor indistinguishable from question field
ACKNOWLEDGED — Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — InlineChoiceChip/index.vue — Chip changes out of #6182's scope (withdrawn: later rounds asked for most of them)
ACKNOWLEDGED — InlineChoiceChip/index.vue:46 — "Add answers" reads like an option
RESOLVED — EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — Editor.spec.js — Focus-trap tests pass with handlers swapped
RESOLVED — Editor.spec.js — No-id error not pinned to passage editor
RESOLVED — imageSrc.spec.js — Repeats toStoredImageSrcs cases
ACKNOWLEDGED — InlineChoiceOptions/index.vue:105 — Bare input instead of plain-text toolbar
ACKNOWLEDGED — Editor.vue:53 — Message blames options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — Green fill on chip with no correct answer
ACKNOWLEDGED — useInlineChoicePassage.js:116 — Live sync keeps history (praise)
RESOLVED — passageChips.js:62 — Invalid chip marked by colour alone
RESOLVED — Editor.vue:66 — Helper text not referenced
RESOLVED — QTIItemEditor.spec.js:751 — findByText instead of heading role
RESOLVED — Editor.vue — Chip click fails when scrolled to page end
RESOLVED — InlineChoiceOptions/index.vue:119 — Repeated Ctrl+Z retypes undone text
ACKNOWLEDGED — InlineChoiceChip/index.vue:36 — Error icon replaces option count
RESOLVED — EditorToolbar.vue:404 — More menu clipped to toolbar box
RESOLVED — useInlineChoicePassage.spec.js:225 — hasErrors branch untested
RESOLVED — InlineChoiceChip/index.vue — Selected chip ignores selection colour
RESOLVED — InlineChoiceOptions/index.vue — Undo deletes focused option
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z does nothing on a chip
RESOLVED — InlineChoiceOptions/index.vue — Ctrl+Z does nothing on radios/buttons
RESOLVED — historyShortcut.js — Non-Latin layout
RESOLVED — historyShortcut.js — macOS Ctrl+Z in passage
RESOLVED — InlineChoiceChip.spec.js:156 — Test never moves the caret
RESOLVED — InlineChoiceOptions/index.vue:300 — Undo touches another chip's edit
RESOLVED — InlineChoiceChip/index.vue — Selected chips blue (the removed vuetify.scss rule was the blue; chips now take KDS's yellow)
ACKNOWLEDGED — package.json:84 — KDS bump not in PR body
RESOLVED — validation.js:14 — One-option dropdown fails validation (withdrawn: #6182 lists TOO_FEW_CHOICES)
RESOLVED — vuetify.scss:2482 — Global selection change (withdrawn: every page now uses KDS's selection colour)
RESOLVED — InlineChoiceOptions/index.vue:22 — Two alerts on open
RESOLVED — InlineChoiceChip/index.vue:106 — Accessible name lacks badge text
RESOLVED — InlineChoiceNode.js — Plain-text copy drops chip (withdrawn: #6274 specifies it)
RESOLVED — InlineChoiceOptions/index.vue:254 — Add option double announcement
CONTESTED — EditorToolbar.vue:106 — More menu runs off the viewport (now suggestion)
CONTESTED — EditorToolbar.vue:106 — More menu opens above the viewport on a phone (now suggestion)
Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.
- User-visible files changed:
.stylelintrc.js,contentcuration/contentcuration/frontend/shared/styles/vuetify.scss,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/ValidationMessage/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/composables/useInlineChoiceInteraction.js…. - Decide whether the off-viewport More menu at small window widths can wait on a KDS change.
- The vuetify.scss removal changes text selection colour on every Studio page; confirm that is wanted.
- Check the chip, panel and toolbar against the Figma spec in a running app before release.
QA captures (50)
Create an inline choice question from scratch in the exercise editor — pick Inline choice in the question type selector, write an optional question and a passage, insert a blank dropdown and one converted from highlighted text, add options, mark the correct one, close the panel, save, then reopen the item and check the dropdowns, options and correct answers persisted and the saved XML is valid QTI with unique identifiers
1-create-inline-choice.webm
Edit options in the dropdown's options panel — add, edit, delete and reorder options, change the correct answer, then turn Shuffle on and check reordering is hidden and the setting persists after save and reopen
| Step | Screenshot |
|---|---|
| Panel after edits | ![]() |
| Panel initial | ![]() |
| Reopened shuffle persisted | ![]() |
| Shuffle on no reorder | ![]() |
2-edit-options-and-shuffle.webm
Validation on an inline choice question — a passage with no dropdown, a dropdown with no correct answer, one with fewer than 2 options, duplicate options; check each error shows on the option, the chip (error icon in place of the count) and the passage, clears when fixed, and an incomplete question is flagged in the exercise
3-fix-errors-one-by-one.webm
Options panel as a modal dialog with the keyboard — open a chip with Enter, Tab stays inside the panel, Escape and the close button return focus to the chip, clicking in the passage closes it, and messages are not all read out as alerts on open
| Step | Screenshot |
|---|---|
| Panel open by enter | ![]() |
| Panel open dropdown 2 | ![]() |
| Panel reopened with errors | ![]() |
4-keyboard-modal-flow.webm
Keyboard caret movement around dropdown chips in the passage — arrow keys move past a chip without selecting it, Left/Right from a focused chip return the caret beside it (also in an RTL language), Backspace and Delete beside a chip remove it in one step, and screen reader live-region announcements for crossed and removed chips
| Step | Screenshot |
|---|---|
| Caret beside chip | ![]() |
| Rtl caret after chip | ![]() |
5-backspace-delete-chip.webm
5-rtl-arabic-passage-arrows.webm
Undo and redo in an inline choice question — undo/redo option edits from inside the options panel and on a focused chip, undo a chip removal and redo it; check the panel and validation follow each step and the page does not scroll away
| Step | Screenshot |
|---|---|
| Blank option error | ![]() |
| Chip removal undone | ![]() |
| Chip removed | ![]() |
| Panel before edit | ![]() |
| Redo removes open chip | ![]() |
| Undo switches to chip 2 | ![]() |
| Undo while scrolled | ![]() |
6-undo-redo-flow.webm
Copy and paste dropdown chips — copy a chip within a passage and into another inline choice question (comes back whole with options and new unique ids), into the question field or another rich text editor (only its correct answer, nothing without one), and as plain text
| Step | Screenshot |
|---|---|
| Chip copied within passage | ![]() |
| Chip pasted into question field | ![]() |
| Chips pasted into other question | ![]() |
| Plain text paste drops chips | ![]() |
View mode of an inline choice question in the exercise list/preview — with Show answers on each chip shows its correct answer, with it off each shows "Choose…" in neutral colours, and a chip needing attention is named as such
| Step | Screenshot |
|---|---|
| Needs attention answers off | ![]() |
| Needs attention answers on | ![]() |
| Rtl answers off | ![]() |
| Rtl answers on | ![]() |
Written by rtibblesbot, an LLM-based coding agent.
f144867 to
f3ca0f9
Compare
There was a problem hiding this comment.
PR #6303: 40 of 43 prior findings resolved; 3 acknowledged, none open.
The two More-menu threads at EditorToolbar.vue:106 are no longer blocking. Only narrow non-touch windows hit them; touch devices get the mobile toolbar. The fix is deferred to KDS #1384.
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — panel heading or padding click drops focus
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while passage is clickable
RESOLVED — inlineChoice/Editor.vue:103 — validation stale after chip removed
RESOLVED — inlineChoice/Editor.vue:92 — passage editor indistinguishable from question field
RESOLVED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — InlineChoiceChip/index.vue — chip behaviour changes out of scope
RESOLVED — InlineChoiceChip/index.vue:46 — "Add answers" reads like an option
RESOLVED — EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — inlineChoice/tests/Editor.spec.js — focus-trap tests pass if handlers swapped
RESOLVED — inlineChoice/tests/Editor.spec.js — no-id error not tied to passage editor
RESOLVED — TipTapEditor/tests/imageSrc.spec.js — repeats toStoredImageSrcs cases
RESOLVED — InlineChoiceOptions/index.vue:105 — bare <input> for options
RESOLVED — inlineChoice/Editor.vue — message blames options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — green fill with no correct answer
RESOLVED — inlineChoice/useInlineChoicePassage.js:116 — praise: live sync keeps history
RESOLVED — inlineChoice/passageChips.js:62 — invalid chip marked by colour alone
RESOLVED — inlineChoice/Editor.vue:72 — helper text not referenced
RESOLVED — QTIItemEditor/tests/QTIItemEditor.spec.js:751 — findByText not scoped to heading
RESOLVED — inlineChoice/Editor.vue — clicking another chip at page end doesn't open it
RESOLVED — InlineChoiceOptions/index.vue:119 — repeated Ctrl+Z types undone text back
RESOLVED — InlineChoiceChip/index.vue:36 — error icon replaces option count
RESOLVED — EditorToolbar.vue:404 — More menu clipped to toolbar box
RESOLVED — inlineChoice/tests/useInlineChoicePassage.spec.js:225 — hasErrors branch untested
RESOLVED — InlineChoiceChip/index.vue — selected chip doesn't take selection colour
RESOLVED — InlineChoiceOptions/index.vue — undo or redo deletes focused option
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z does nothing with chip focused
RESOLVED — InlineChoiceOptions/index.vue — Ctrl+Z does nothing on radios or buttons
RESOLVED — inlineChoice/historyShortcut.js — non-Latin layout
RESOLVED — inlineChoice/historyShortcut.js — macOS Ctrl+Z in passage
RESOLVED — inlineChoice/tests/InlineChoiceChip.spec.js:156 — test never moves caret
RESOLVED — InlineChoiceOptions/index.vue:305 — Ctrl+Z undoes another chip's edit
RESOLVED — InlineChoiceChip/index.vue — selected chips #b3d4fc blue
RESOLVED — package.json:84 — KDS bump not in PR body
RESOLVED — inlineChoice/validation.js:14 — one-option dropdown fails validation
RESOLVED — shared/styles/vuetify.scss:2482 — removed ::selection rule is global
RESOLVED — InlineChoiceOptions/index.vue:22 — incomplete chip fires two alerts
RESOLVED — InlineChoiceChip/index.vue:106 — accessible name omits badge text
RESOLVED — inlineChoice/InlineChoiceNode.js — toolbar Copy drops chip from plain text
RESOLVED — InlineChoiceOptions/index.vue:257 — Add option reads "Answer cannot be blank" twice
RESOLVED — inlineChoice/Editor.vue — Add option fires role="alert"
ACKNOWLEDGED — EditorToolbar.vue:106 — More menu runs off the viewport (severity withdrawn; KDS #1384)
ACKNOWLEDGED — EditorToolbar.vue:106 — More menu opens above the viewport on a phone (severity withdrawn; KDS #1384)
ACKNOWLEDGED — EditorToolbar.vue:106 — More menu partly off-screen (KDS #1384)
Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.
- User-visible files changed:
.stylelintrc.js,contentcuration/contentcuration/frontend/shared/styles/vuetify.scss,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/ValidationMessage/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/composables/useInlineChoiceInteraction.js…. - Removing Vuetify's
::selectionrule invuetify.scsschanges the text-selection colour on every Studio page. EditorToolbar.vuesets:constrainToScrollParent="false", which pushes the More menu off-screen in every rich text editor at narrow non-touch widths until KDS #1384 lands.- The KDS bump in
package.jsonassumes this merges after #6317.
QA captures (50)
Add a new question in the exercise editor and switch it to Inline choice — type selector offers it, card label, optional question field, passage editor with helper text and the prominent Insert button (unavailable look, hover, tooltip), Shuffle setting off by default
Write a passage, insert a blank dropdown and convert highlighted text into a dropdown — the panel opens on insert with focus inside, add/edit/remove options, remove disabled on the last option, mark the correct option and see the chip label and count update, removing the correct option leaves the dashed "Add answer" chip
| Step | Screenshot |
|---|---|
| Correct option marked | ![]() |
| Correct option removed | ![]() |
| Highlight converted | ![]() |
| Panel closed no correct | ![]() |
| Panel opens on insert | ![]() |
2-options-add-mark-remove.webm
Build a passage with two or more dropdowns and switch between them — clicking or Enter/Space on another chip shows that chip's options, panel dialog label names the dropdown, clicking the passage closes the panel, no duplicated option or response identifiers across chips
| Step | Screenshot |
|---|---|
| Click switches to dropdown 2 | ![]() |
| Passage click closes panel | ![]() |
| Pasted chip own ids | ![]() |
| Space opens dropdown 4 | ![]() |
| Three chips dropdown 2 open | ![]() |
3-switch-between-dropdowns.webm
Reorder options in a dropdown with drag and drop and with move up / move down — correct mark stays on the same option, then turn Shuffle on and confirm handles and move controls disappear on every chip's panel, and return when it is turned off
| Step | Screenshot |
|---|---|
| After drag correct follows | ![]() |
| After move up correct follows | ![]() |
| Panel before reorder | ![]() |
| Shuffle off handles return | ![]() |
| Shuffle on chip1 no handles | ![]() |
| Shuffle on chip4 no handles | ![]() |
4-drag-reorder.webm
Drive the options panel by keyboard only — open a chip with Enter and Space, Tab/Shift+Tab stay trapped in the panel, correct-answer markers act as a single-select group with option names, Escape and the close control return focus to the chip and the next Tab moves on
| Step | Screenshot |
|---|---|
| Close control focused | ![]() |
| Panel opened by enter | ![]() |
| Panel opened by space | ![]() |
5-keyboard-panel-flow.webm
Move the caret through a passage with dropdowns using the arrow keys, Backspace and Delete — caret steps past chips without selecting them, Left/Right from a focused chip return to the text, Backspace/Delete beside a chip removes it, screen reader live-region announcements for crossed and removed chips, selected text over a chip uses the pale yellow KDS selection colour
| Step | Screenshot |
|---|---|
| Rtl selection over chips | ![]() |
| Selection over chips | ![]() |
6-caret-past-chips.webm
Undo and redo options edits, chip insertions and chip removals in the passage — the open panel's list always matches the chip, toolbar and Ctrl+Z/Ctrl+Y both work, removal announcements on redo
| Step | Screenshot |
|---|---|
| Redo removed chip | ![]() |
| Undo switches panel to changed chip | ![]() |
7-undo-redo-options-and-chips.webm
Copy passage text containing dropdowns and paste it into the same passage, another inline choice question's passage, and the question field — whole dropdowns with fresh ids in passages, only the correct answer (or nothing) in the question field, toolbar Copy and plain-text paste leave the chip out
| Step | Screenshot |
|---|---|
| Pasted into question field | ![]() |
| Pasted into same passage | ![]() |
| Pasted into second question passage | ![]() |
Leave an inline choice question incomplete in each way (no dropdown, a dropdown with no correct answer, too few options, an empty option) — errors appear on the option row, the chip and the panel top or the passage editor, and the question is marked incomplete; fix each and see it clear
| Step | Screenshot |
|---|---|
| All errors cleared | ![]() |
| Blank dropdown all errors | ![]() |
| Chip error panel closed | ![]() |
| Collapsed card incomplete | ![]() |
| Correct option blanked | ![]() |
| Fixed card closed | ![]() |
| No dropdown error | ![]() |
| Only no correct answer | ![]() |
9-fix-too-few-options.webm
Finish an inline choice question with several dropdowns and Shuffle on, close the editor and view it — view mode shows the question and passage with correct answers when Show answers is on and "Choose…" when off; reopen and confirm question, passage, every chip's options, correct answers and Shuffle are restored, and the saved XML puts shuffle on every dropdown and no open-chip state
| Step | Screenshot |
|---|---|
| Reopened panel dropdown 3 | ![]() |
| Rtl view show answers on | ![]() |
Written by rtibblesbot, an LLM-based coding agent.
Turns on the Inline choice question type: an optional question, the passage holding the dropdown chips, and a modal options panel for the open chip, trapping focus with KFocusTrap and returning it to the chip on close. A press in the passage closes it, as the passage is then in use. Option edits go through the chip node's commands, so each is one step of the passage's history, and the passage is synced while a chip is open so the panel always matches the saved state. A change to the chips syncs it too, so validation follows a chip removed or restored without waiting for the passage to lose focus. A dropdown needs a correct answer and at least two options, and its panel lists what it lacks. Shuffle is the choice interaction's AnswerSettings, and hides reordering while on. The chips follow the design, and take the selection colour as a whole when a selection covers them. A preview without Show answers shows "Choose…" in neutral colours in place of each answer. A copied chip pastes into another passage whole, and into an editor without chips as its correct answer alone. A cleared question is saved as no question. The descriptor accepts any item body, since parse() splits every body into question and passage. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Left and Right on a focused chip put the caret back in the passage beside it, following the text direction, as they move past the chip there. - A chip the caret crosses is announced by its accessible name, since a screen reader reads out the text the caret crosses and a chip has none. Removing chips is announced too. Both use KDS's assertive live region, so they are read as a crossed character would be. - A chip that needs attention shows the error icon in place of its option count, as an option row does, so colour is not all that marks it. Its name says so in a preview that hides the answers too. - The passage editor is described by its helper text. - A chip without a correct answer shows what its options panel says is missing, such as "Choose a correct answer", so the two always match. A chip with one shows it, its error icon saying if it needs work. - Undo and redo from the options panel or a focused chip don't scroll the page away from the panel. - The options panel's messages are no alerts, which would all be read at once each time it opens. Those it opens with describe the dialog and its fields; one that appears while it is open is announced once, through KDS's live region. - A chip's count badge is hidden from assistive technology, which hears the count in its name, so that the name starts with the text it shows. The chip's label and accessible name move to passageChips.js, so the chip and the announcements name it the same way. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
f3ca0f9 to
30149d8
Compare
There was a problem hiding this comment.
PR #6303: the More menu still runs off the viewport (blocking, inline at EditorToolbar.vue:106).
41 of 43 prior findings are resolved. The 2 contested ones are both this menu.
CI pending. Manual QA ran 11 scenarios across the inline choice editor. Only the More menu regression comes from this PR.
- blocking: More menu off-viewport at desktop widths (inline,
EditorToolbar.vue:106). - pre-existing:
InlineChoiceChip/index.vue:263— chips are cut off without an ellipsis at 360px.
Prior-finding status
RESOLVED — InlineChoiceOptions/index.vue:9 — Panel click drops focus, Escape stops working
RESOLVED — InlineChoiceOptions/index.vue:13 — aria-modal while passage is clickable
RESOLVED — inlineChoice/Editor.vue:103 — Validation stale while passage is open
RESOLVED — inlineChoice/Editor.vue:92 — Passage editor indistinguishable from question field
RESOLVED — inlineChoice/Descriptor.js:43 — isSupportedBody accepts bodies TipTap can't hold
RESOLVED — InlineChoiceChip/index.vue — Chip behaviour changes out of #6182 scope
RESOLVED — InlineChoiceChip/index.vue:46 — Options but no correct mark reads like "Add answers"
RESOLVED — EditorToolbar.vue — Insert pushed off narrow toolbar
RESOLVED — tests/Editor.spec.js — Focus-trap tests pass with handlers swapped
RESOLVED — tests/Editor.spec.js — No-id error test passes wherever it renders
RESOLVED — tests/imageSrc.spec.js — Repeats toStoredImageSrcs cases through a stub
RESOLVED — InlineChoiceOptions/index.vue:105 — Bare input instead of plain-text toolbar row
RESOLVED — inlineChoice/Editor.vue — Message blames options for NO_CORRECT_ANSWER
RESOLVED — InlineChoiceChip/index.vue:14 — Green fill on chip with no correct answer
RESOLVED — useInlineChoicePassage.js:116 — Live sync keeps editor history (praise)
RESOLVED — passageChips.js:63 — Invalid chip marked by colour alone
RESOLVED — inlineChoice/Editor.vue:72 — Helper text not referenced
RESOLVED — QTIItemEditor.spec.js:751 — findByText instead of heading role
RESOLVED — inlineChoice/Editor.vue — Clicking another chip fails when scrolled to end
RESOLVED — InlineChoiceOptions/index.vue:119 — Repeated Ctrl+Z types undone text back
RESOLVED — InlineChoiceChip/index.vue:36 — Error icon replaces option count
RESOLVED — EditorToolbar.vue:404 — More menu clipped to toolbar box
RESOLVED — useInlineChoicePassage.spec.js:225 — hasErrors branch of chipMessage untested
RESOLVED — InlineChoiceChip/index.vue — Selected chip doesn't take selection colour
RESOLVED — InlineChoiceOptions/index.vue — Undo/redo deletes focused option
RESOLVED — InlineChoiceChip/index.vue — Ctrl+Z does nothing on a focused chip
RESOLVED — InlineChoiceOptions/index.vue — Ctrl+Z does nothing on radios/buttons
RESOLVED — historyShortcut.js — Ctrl+Z fails on non-Latin layouts
RESOLVED — historyShortcut.js — macOS Ctrl+Z mismatch with passage
RESOLVED — InlineChoiceChip.spec.js:156 — Caret test never moves the caret
RESOLVED — InlineChoiceOptions/index.vue:305 — Ctrl+Z silently undoes another chip's edit
RESOLVED — InlineChoiceChip/index.vue — Selected chips still #b3d4fc blue
RESOLVED — package.json:84 — KDS bump not in PR body
RESOLVED — inlineChoice/validation.js — One-option dropdown fails validation
RESOLVED — styles/vuetify.scss:2482 — Removed ::selection rule affects every page
RESOLVED — InlineChoiceOptions/index.vue:22 — Opening incomplete chip fires extra alerts
RESOLVED — InlineChoiceChip/index.vue:106 — Accessible name omits visible badge text
RESOLVED — inlineChoice/InlineChoiceNode.js — Toolbar Copy drops chip from plain text
RESOLVED — InlineChoiceOptions/index.vue:257 — Add option announces blank error twice
RESOLVED — EditorToolbar.vue:106 — More menu partly off-screen (suggestion)
RESOLVED — inlineChoice/Editor.vue — Add option fires role=alert while focus moves
CONTESTED — EditorToolbar.vue:106 — More menu runs off the viewport (blocking, re-raised)
CONTESTED — EditorToolbar.vue:106 — More menu opens above the viewport on a phone (blocking, re-raised)
Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.
- User-visible files changed:
.stylelintrc.js,contentcuration/contentcuration/frontend/shared/styles/vuetify.scss,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/QTIItemEditor/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/components/ValidationMessage/index.vue,contentcuration/contentcuration/frontend/shared/views/QTIEditor/composables/useInlineChoiceInteraction.js…. - Decide whether the More menu running off-screen below 600px can wait on kolibri-design-system#1384 or must be fixed before merge.
- The toolbar changes (icon-only Insert,
overflow-x: auto, unconstrained More) reach every TipTap editor, not just inline choice. - Run the inline choice editor end to end, especially undo/redo across the panel, chips and passage.
QA captures (50)
Add a new question in the exercise editor, switch its type to Inline choice, write a question and a passage, insert a blank dropdown with Insert and convert highlighted text into a second one — the question field, passage helper text, the options panel opening on insert, the card's Inline choice type label
| Step | Screenshot |
|---|---|
| Blank dropdown panel open | ![]() |
| Closed card type label | ![]() |
| Converted dropdown panel open | ![]() |
| Highlighted text | ![]() |
| Inline choice empty | ![]() |
| Insert over selection with chips | ![]() |
| Passage open toolbar | ![]() |
1-create-inline-choice.webm
Build a dropdown's options in its panel — Add option, edit option text, mark one correct then move the mark, remove options down to the last (remove disabled), remove the correct one (chip goes to dashed "Add answer"), move up / move down and drag reorder keeping the correct mark; chip label and count update after each edit
| Step | Screenshot |
|---|---|
| After drag correct last | ![]() |
| Correct removed chip | ![]() |
| Last option remove disabled | ![]() |
| Move button focused | ![]() |
| New dropdown panel | ![]() |
| Three options correct marked | ![]() |
2-build-options.webm
2-reorder-keeps-correct.webm
Open one dropdown, then another, then delete the open dropdown from the passage — the panel switches to the other chip's options, closes when its chip is gone with focus back in the editor, and closes when the passage is clicked
| Step | Screenshot |
|---|---|
| First chip open | ![]() |
| Open chip deleted | ![]() |
| Passage click closes panel | ![]() |
| Switched to second chip | ![]() |
3-switch-then-delete-open-chip.webm
Edit a dropdown's options, then undo and redo with the toolbar and Ctrl+Z / Ctrl+Shift+Z — the options list and the chip label match the passage after each step, and removing a dropdown with Backspace or Delete beside it undoes cleanly
| Step | Screenshot |
|---|---|
| After edits | ![]() |
| After redo | ![]() |
| Chip removed backspace | ![]() |
| Chip restored undo | ![]() |
| Panel open initial | ![]() |
| Undo opens other chip | ![]() |
4-undo-redo.webm
Toggle Shuffle on an inline choice question, save, close and reopen the exercise — Shuffle sits where the choice question's does and starts off, drag handles and move up / move down vanish on every dropdown while on and return when off, and the setting survives the reopen
| Step | Screenshot |
|---|---|
| Shuffle click with panel open | ![]() |
| Shuffle off again handles back | ![]() |
| Shuffle off initial | ![]() |
| Shuffle off panel handles | ![]() |
| Shuffle on panel no handles | ![]() |
5-shuffle-toggle-handles.webm
Save an inline choice question with several dropdowns, close and reopen it, and inspect the saved raw_data via the sync API — question, passage, every dropdown's options, correct answers and shuffle restored; no open-chip state and no duplicate identifiers in the XML
| Step | Screenshot |
|---|---|
| Closed card four dropdowns | ![]() |
| Passage three dropdowns | ![]() |
| Reopened after reload | ![]() |
Leave validation errors on an inline choice question (no dropdown, a dropdown with no correct answer, an empty option) and close the card — each error shows on the passage, the chip, the panel top or the option row, and the question is marked incomplete; fix each and see it clear
7-fix-errors.webm
Close the editing card of a filled inline choice question and toggle Show answers — view mode shows the question and the passage with each chip's correct answer when on and "Choose…" when off, and a chip needing attention is named as such
| Step | Screenshot |
|---|---|
| Filled question answers on | ![]() |
8-close-card-toggle-show-answers.webm
Written by rtibblesbot, an LLM-based coding agent.
| <!-- Not kept inside the toolbar, which scrolls when too narrow, as its other menus --> | ||
| <KDropdownMenu | ||
| :options="flatOverflowOptions(overflowItems)" | ||
| :constrainToScrollParent="false" |
There was a problem hiding this comment.
blocking: The More menu still runs off the viewport, and not only on phones. My :404 suggestion caused this. :constrainToScrollParent="false" fixed the clipping but lets the menu overflow the viewport.
- New since the author's reply: it happens at 599×800 on a non-touch window. The menu spans y −278 to 284. Copy, Paste, Paste without formatting, Align right, Clear formatting and Bullet list are unreachable. The page doesn't scroll.
- At 360px, ArrowDown focuses "Italic" at y −334. Keyboard users lose sight of focus.
- A legacy answer editor and RTL fail the same way. Every TipTap editor regresses, not just the passage.
- With this prop false,
UiPopover.vue:170-172turns off popper's overflow prevention entirely. KDS has no viewport-boundary option; kolibri-design-system#1384 tracks that.
Drop this prop and keep the More button outside the overflow-x: auto box, so its scroll parent is the dialog, as on unstable. Or hold merge until #1384 lands. A maintainer can accept the regression instead. The author's reply alone doesn't settle a blocking regression.
11-more-menu-offscreen-360.webm
There was a problem hiding this comment.
This will be fixed when learningequality/kolibri-design-system#1384 is implemented. I just assigned that issue, so it will be in the next KDS release.







































































































































































































































































Summary
TipTapEditor, not only the passage.::selectioninvuetify.scss), so selected text on every Studio page now uses KDS's selection colour, pale yellow instead of light blue, and a dropdown covered by a selection matches the text around it..stylelintrc.js, for KDS theme variables such asvar(--tokens-fineLine). The rule applies to the whole repo.References
Fixes #6182.
Fixes #6274.
Beyond #6182's scope
#6182 leaves the dropdown chip and Insert to #6181, but this PR also changes the chip. No #6182 acceptance criterion requires these changes; each came up while building, testing or reviewing the editor:
InlineChoiceNode.js). The arrow keys stopped on each dropdown to select it before moving past, and Backspace selected it rather than removing it.leaveForText). A dropdown is a focusable button in the text, and the arrow keys did nothing on it.useKLiveRegion, with two new strings. A screen reader said nothing in either case, since a dropdown has no text to read out.InlineChoiceNode.js,parse.js). Pasted into another passage it comes back whole; pasted into an editor without dropdowns, such as the question, it is its correct answer, or nothing without one, rather than every option run together. Plain text leaves it out, since a dropdown read as text could set off TipTap's typing shortcuts.These can move to their own PR if preferred.
Still open: undoing a removal brings the dropdown back without an announcement, while redo announces the removal.
Reviewer guidance
Demo
Grabacion.de.pantalla.2026-10-07.a.las.4.02.52.p.m.mov
AI usage
Claude Code implemented this from the issue and design screenshots, with tests, then self-reviewed it. I reviewed the changes and steered the design and accessibility decisions.
🤖 Generated with Claude Code