Repository navigation
Add questions anywhere with a grouped type picker - #276
PhilReinking wants to merge 16 commits into
Conversation
Short text, Long text, Email, Link, Phone, Number, Hidden text; Single choice, Checkboxes; Rating, Scale; Date, File upload, Consent; Text only. Text only no longer shares the envelope icon with Email. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A search field filters the types; arrow keys move, Enter adds, Esc closes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Add question" adds after the open question; "+ Add question here" between questions (hover and keyboard focus), the + in a question's gutter and "Add question below" add right there. The new question opens with the cursor in its text. An empty form shows "Add your first question" with the picker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to feat/bits-283-type-picker
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PhilReinking
left a comment
There was a problem hiding this comment.
OK at e710ffd. No CI (stacked): Vitest 312, lint, vue-tsc and the build pass locally. 9 new tests fail on 711992e.
Should: when a new question opens under the mouse, a toolbar tooltip takes the focus, so the cursor isn't in its text. #275's tooltip fix in app.ts solves it; with the mouse away, the cursor lands in the text. Creates send the picked type, and into an empty group the group as scope.
| - The API can copy a question (`POST /api/blocks/{block}/duplicate`) with its text, settings, answers and Required, but not its rules. The copy goes right after the original. (#262) | ||
| - The form's team can try a form in preview mode, also while it's a draft. Answers in preview mode are never stored or counted and send no webhooks or emails. (#266) | ||
| - Add `?preview=1` to your form's link to try it as a member of its team. Nothing is stored, files aren't uploaded and the form doesn't redirect at the end. (#270) | ||
| - Add a question right where you need it: between questions, from a question's menu or with "/" in an empty question. A picker groups the answer types as Text, Choice, Rating, Other and Content, and the new question opens ready to type. The answer types have new names, like Single choice, Short text and Text only. (#276) |
There was a problem hiding this comment.
Nit: "/" doesn't add a question, it picks the type of the empty one.
| - Add a question right where you need it: between questions, from a question's menu or with "/" in an empty question. A picker groups the answer types as Text, Choice, Rating, Other and Content, and the new question opens ready to type. The answer types have new names, like Single choice, Short text and Text only. (#276) | |
| - Add a question right where you need it: between questions or from a question's menu, and type "/" in an empty question to pick its answer type. A picker groups the answer types as Text, Choice, Rating, Other and Content, and the new question opens ready to type. The answer types have new names, like Single choice, Short text and Text only. (#276) |
…icker Keeps both: the type picker opens from the menu, the group and the gutter +, and Alt+Up/Down and Move up/down move a block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Multiple Choice is Single choice, Secret is Hidden text, Information Block is Text only, Phone Number is Phone. Adding a question names the add line, the menu and the picker. Page links stay the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The line, the gutter + and the menu add after a given question. The end button always adds after the last block, also while a question is open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d down Opened low on the screen, the picker sat partly below the fold. It now scrolls into view; on a phone its top goes to the top, since the list never fits. Below lg the title takes the focus instead of the search, so the screen keyboard doesn't cover the list. Esc closes from anywhere in the picker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Grey on white was about 1.1:1 and looked like hover. The ring shows while you type in the search, where Enter adds that type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PhilReinking
left a comment
There was a problem hiding this comment.
OK at 17d4bd1. No CI (stacked), local runs: Vitest 367, lint, vue-tsc, build and the docs build pass. On the merged head, Alt+Up/Down moves keep the right order after reload (4 of 4), the picker creates with the right type, place and group, and the end button adds at the end, also after reload. A new question that opens under the mouse keeps the cursor in its text.
| }; | ||
| const closeTypes = () => { | ||
| typesOpen.value = false; | ||
| editor.value?.focus(); |
There was a problem hiding this comment.
Should: with this picker open, a click on the end "Add question" opens the end picker, but the cursor comes back into this text a frame later (tiptap focuses on the next animation frame). Typing then goes into the question text and saves it. Maybe refocus only after Esc or a pick, not after a click outside. Not run.
Closing it by a click elsewhere put the cursor back into the question a frame later, so typing in the end picker's search landed in the question text. Only Esc and a pick give the cursor back now. 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 17d3ccc. No CI (stacked), local runs: Vitest 368, lint, vue-tsc, build and the docs build pass. The new QuestionCard test fails on 17d4bd1. In the browser, a click on the end "Add question" while the "/" picker is open now leaves the cursor in the end picker's search, and Esc or a pick still give it back to the text.
| export function closePicker() { | ||
| const spot = addAt.value; | ||
| addAt.value = null; | ||
|
|
||
| if (opener?.isConnected) { | ||
| opener.focus(); | ||
| } else if (spot) { | ||
| focusBlock(spot.after); | ||
| } | ||
| } |
There was a problem hiding this comment.
Should: the other pickers have the same slip. With the end picker open, a click into the open question's text puts the cursor back on "Add question", so typing goes nowhere. TypePicker already sends false here. Tested: Vitest, lint, vue-tsc, and in the browser the click keeps the cursor in the text while Esc still returns to the button.
| export function closePicker() { | |
| const spot = addAt.value; | |
| addAt.value = null; | |
| if (opener?.isConnected) { | |
| opener.focus(); | |
| } else if (spot) { | |
| focusBlock(spot.after); | |
| } | |
| } | |
| export function closePicker(returnFocus = true) { | |
| const spot = addAt.value; | |
| addAt.value = null; | |
| // a click elsewhere leaves the focus where the click put it | |
| if (!returnFocus) { | |
| return; | |
| } | |
| if (opener?.isConnected) { | |
| opener.focus(); | |
| } else if (spot) { | |
| focusBlock(spot.after); | |
| } | |
| } |
With the end "Add question" picker open, a click into the open question's text put the cursor back on "Add question", so typing went nowhere. Only Esc and a pick give the cursor back now, as in the "/" picker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Landed in main with #282 (the editor rebuild as one PR); this PR's commits are part of it. |
"Add question" now opens a picker with the answer types grouped as Text, Choice, Rating, Other and Content. The new question opens where you asked for it, with the cursor in its text. Fixes BITS-283.
Heads-up: the answer types have new names in the editor and the docs: Multiple Choice is now Single choice, Short Answer is Short text, No Input is Text only, Secret is Hidden text. Docs links stay the same.
Tested: Vitest (new tests fail without the change), lint, vue-tsc, build. By hand at 1440 and 390 on my own server.
Not tested: real touch devices. Stacked on #275, so CI runs once this targets main.
🤖 Generated with Claude Code