Repository navigation
Edit the whole form as one document (part 1) - #268
PhilReinking wants to merge 22 commits into
Conversation
The question list and the workbench become one column. Each question is a compact row (number, type icon, text on up to 2 lines, a meta line with Required, rules, Hidden and the identifier), groups are sections. The open question is a card in place: text with its format toolbar, choices, then answer type, Required, Settings (this type's settings inline), Rules and a menu. A new question opens with the cursor in its text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Delete and the drag grip showed only on hover, 96 px left of the row and
outside the tab order. Now they sit at the end of the row, always visible;
delete is a named button ("Delete choice “Yes”").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The toolbar buttons had their name only in a tooltip. They now have an aria-label, aria-pressed and type="button", in a group named "Text format". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After Try again loads the questions, the cursor goes into the open question's text (or onto Add question); when it fails again, back onto Try again. Before, focus fell to the page. A question load that answers after the editor closed or switched forms no longer fills the store or opens a question (which also changed the next page's address). A question opened by click or added now takes the cursor through one shared value, because its text editor shows up a moment after the card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PhilReinking
left a comment
There was a problem hiding this comment.
Changes at d32d1cd. No CI (stacked): Vitest, lint, vue-tsc and the build pass locally.
Must: when a question gets a type with an input field (text, email, number, file, rating, date), the field is only made once Settings is opened. Until then the live form shows nothing to answer.
Held: every setting of every answer type is still reachable, the 4 new loading tests fail without the fixes, and the closed row shows plain text only.
| </div> | ||
|
|
||
| <QuestionSettings | ||
| v-if="settingsOpen" |
There was a problem hiding this comment.
The Configure* parts create the answer field when they mount. Today they mount as soon as the question opens. Here they mount only with Settings open, so a new "Short text" question has no field in the live form. Keeping the panel mounted fixes it for every type.
| v-if="settingsOpen" | |
| v-show="settingsOpen" |
| <div | ||
| role="group" |
There was a problem hiding this comment.
id is a prop here, so it never lands on the element, and the Settings button's aria-controls points at nothing.
| <div | |
| role="group" | |
| <div | |
| :id="id" | |
| role="group" |
| class="rounded-lg border border-grey-200 bg-grey-50 py-2 pr-2" | ||
| :class="isOpen && 'ring-1 ring-blue-500'" | ||
| > | ||
| <div class="flex flex-wrap items-center gap-x-2 gap-y-1 pb-2 pl-3"> |
There was a problem hiding this comment.
Groups can't be moved any more. The list only starts a drag on .document-grip, and the group header has none. Today a group can be dragged. Can the header get a grip like the questions, or does a later part bring it?
| </div> | ||
| </section> | ||
| <ChoiceRowActions | ||
| :label="label ? `choice “${label}”` : `choice ${index + 1}`" |
There was a problem hiding this comment.
This delete button is new to the keyboard, but after it the row is gone and focus falls to the page. Cmd+Backspace moves focus to a neighbor choice first. The same goes for the policy delete in ConsentInteraction.
The Configure* parts create the block's interaction when they mount. Keep QuestionSettings mounted (v-show) so a new Short text, Email, Number, Long text, File, Rating, Scale or Date question gets its field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The row's Delete button and Cmd+Backspace now ask the list to delete. Once the row is gone, focus moves to the row above, the new first row, or the Add button. A failed delete leaves focus where it was. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PhilReinking
left a comment
There was a problem hiding this comment.
OK at e4fc5f5 (a7fa8d5 plus the updated base; this PR's own changes are the same). No CI (stacked): Vitest, lint, vue-tsc and the build pass locally.
All 5 items from the last review are fixed, and the 6 new tests fail on d32d1cd. A failed choice delete keeps focus on its button. One should inline: with a custom answer on, focus still drops after a delete.
| // a failed delete keeps the row, and focus stays in it | ||
| if (editableInteractions.value?.includes(item)) return; | ||
|
|
||
| if (!(await focusNeighborItem(index))) { |
There was a problem hiding this comment.
With a custom answer on, the list useKeyboardNavigation gets (activeInteractions) also holds that hidden row, but index counts only the visible choices. So after a delete, focus can land on the hidden row and falls to the page. Enter on the last choice also throws when the custom answer is last, so "Enter adds a choice" adds nothing. Both work with the visible list:
-const { activeInteractions, editableInteractions } = useActiveInteractions(
+const { editableInteractions } = useActiveInteractions(
...
-} = useKeyboardNavigation(activeInteractions, async () => {
+} = useKeyboardNavigation(editableInteractions, async () => {The keyboard helper got the list with the hidden custom answer row, but row numbers count only the visible choices. Focus after a delete could land on the hidden row, and Enter on the last choice threw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Editor gets a bare prop: no border around the toolbar and the text. The card uses it and drops the word counter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One border around the key, the text, the grip and delete. Screen readers now say "Choice 2" and "Reply for choice 2" instead of the placeholder "Label". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PhilReinking
left a comment
There was a problem hiding this comment.
OK at 3938f6b. No CI (stacked): Vitest, lint, vue-tsc and the build pass locally.
The should from the last review is fixed, and the 5 new tests fail on e4fc5f5. Beyond the PR text: without bare the editor gets the same classes as before, so the completion page's editor is unchanged. A second click on Add choice makes no second choice.
# Conflicts: # CHANGELOG.md
PhilReinking
left a comment
There was a problem hiding this comment.
OK at 18c92f9, a merge of 3938f6b and the stack at 2f7ecf9. No CI (stacked), local runs: Vitest 294, lint, vue-tsc, build.
The diff to the stack equals the reviewed one at 3938f6b byte for byte, except #268's own changelog line. PHP is unchanged. The full PHP suite had one failure in a test outside this PR that depends on database order. It passes alone and in a feature-only run.
Brings in the delete dialogs (#269) and the save status (#267). Conflicts: the old Workbench, Sidebar Block and Group stay deleted. Choice and policy rows keep their in-row delete button, which now asks first through useDeleteChoice; the list still does the delete so it can move focus once the row is gone (useDeleteChoice takes that delete). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PhilReinking
left a comment
There was a problem hiding this comment.
OK at 0f2f881 (the stack with #269 and #267 merged in). No CI (stacked), local runs: Vitest 333, lint, vue-tsc, build.
The merge keeps part a's diff, except the choice and policy rows, which now ask through #269's step before the list deletes. Held: a choice people picked asks first, one nobody picked goes at once, a failed count asks anyway, focus lands where part a's tests say, and a failed delete keeps the row and its focus.
|
Landed in main with #282 (the editor rebuild as one PR); this PR's commits are part of it. |
The editor shows the whole form as one column of short questions. The question you work on opens in place as a card, so a phone can edit questions too. This is the first of several stacked parts. Part of BITS-282.
Tested: Vitest, lint, vue-tsc and
npm run buildlocally (stacked PR, no CI). By hand at 1440, 1024, 390 and 360: no sideways scroll, every answer type, drag saved.Not tested: a screen reader by hand.
Known gap: Delete still asks with the browser dialog, and Duplicate, Move, the outline and a phone bottom sheet come in the next parts.
🤖 Generated with Claude Code