Skip to content

[QTI] Delay validation messages until the author has engaged with the question #6107

Open

Description

@AlexVelezLl

❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.

Overview

Validation runs on every state change, so a question that has just been created shows its error messages immediately — before the author has had a chance to fill anything in. Validation should keep running as it does; what should change is when its messages are shown. An author should see a message only once they have engaged with the thing it is about, or once they have finished with the question.

Complexity: Medium
Target branch: unstable

Context

Every interaction editor validates on each state change and renders the resulting messages inline — under the question prompt, under an individual answer row, and under the answer list. Because a newly created question is empty, it is also invalid, so the messages are on screen from the moment the card opens.

A question that was saved empty earlier is a different case: its author already had the chance to fill it in, so its messages are not premature.

The Change

Messages should be revealed rather than suppressed — validation still runs, and an author who has engaged with a field still sees what is wrong with it immediately.

For a question created in the current session, each message waits for the author to touch what it is about:

  • "Question is required" appears once the question prompt editor has been blurred.
  • The answer-list messages — "Choose a correct answer" for choice questions, "At least 2 items are required for an ordering question." for ordering — appear once any answer row's editor has been blurred.
  • A row's own messages — the blank and duplicate errors on a choice, an ordering item, or a text entry answer — appear once that row's editor has been blurred.

Closing the question card reveals every message the question has, whether or not anything was touched. Once a message has been revealed it stays revealed while the error lasts.

A question that already existed before the author opened it shows all of its messages from the first render. Only a question created in the current session starts out quiet.

How to Get There

Open a channel for editing and go to /channels/<channel_id>/#/qti-demo. Adding a question exercises the new-question case; the fixture items, which are already saved, exercise the existing-question case.

Acceptance Criteria

  • A question created in the current session shows no validation messages when it opens
  • "Question is required" appears after the question prompt editor is blurred
  • "Choose a correct answer" appears after any answer row's editor is blurred, for choice questions
  • "At least 2 items are required for an ordering question." appears after any item row's editor is blurred
  • A row's blank and duplicate messages appear after that row's own editor is blurred, and not before — for choices, ordering items and text entry answers
  • Blurring one row does not reveal another row's messages
  • Closing the question card reveals every message the question has
  • A message that has been revealed stays revealed while its error lasts
  • A question that existed before the author opened it shows all its messages from the first render
  • Tests cover that a newly created question starts with no messages and that each blur reveals the messages it should

AI usage

I used Claude Code to draft this issue. It read the validation strings and interaction editors to confirm the current messages; I defined the reveal behavior and reviewed every section.

Activity

  1. changed the title [-]Delay validation messages until the author has engaged with the question[/-] [+][QTODelay validation messages until the author has engaged with the question[/+] on Aug 26, 2026
  2. changed the title [-][QTODelay validation messages until the author has engaged with the question[/-] [+][QTI] Delay validation messages until the author has engaged with the question[/+] on Aug 26, 2026
  3. self-assigned this
    on Sep 30, 2026
  4. rtibblesbot commented on Sep 30, 2026

    @rtibblesbot
    Contributor

    Plan: A question created in the current session shows each validation message only after the author blurs what it is about, or closes the card.

    • Emit blur from TipTapEditor
    • useMessageReveal composable
    • Card provides the state
    • Choice editor renders through the reveal
    • /simplify pass — Phase 1
    • Ordering editor
    • Text entry editor
    • /simplify pass — Phase 2
    • QTIEditor marks the questions it creates
    • Manual check on the demo page
    • /simplify pass — Phase 3, then self-review of the branch

    Assumptions — the issue did not settle these; say so if one is wrong.

    • Match and associate editors are left eager, since the issue names only choice, ordering and text entry; if wrong, they show messages immediately on a new question.
    • The "N incomplete" header indicator in QTIItemEditor stays eager, since it is not one of the listed messages; if wrong, it needs the same gate.
    • A row's red border and error icon follow its message's reveal, so no error styling shows before its message; if wrong, borders show error state early.
    • "No correct answer" on text entry and "Too many correct answers" on choice count as answer-list messages, revealed by any row blur; if wrong, they need their own trigger.
    • A touched field stays touched: an error that clears and returns shows at once; if wrong, it must wait for another blur.
    • Revealing on the mousedown blur is not held until pointer release, unlike match/Editor.vue:491; if it shifts a click target in practice, add a hold.
    • A card remounted as a whole (e.g. the tab re-opened) counts as pre-existing and shows everything; if wrong, new-ness must persist outside the editor.

    @rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly

    How was this generated?
    • Implemented code following the pre-approved plan using test-driven development (red-green-refactor)
    • Ran the project's full test suite and linter before committing
    • For UI changes: captured live screenshots to verify rendering
    • For backend changes: verified with example API/CLI output
  5. rtibblesbot commented on Sep 30, 2026

    @rtibblesbot
    Contributor

    @AlexVelezLl Blocked on Phase 1: the agent's sandbox has no Node, pnpm or node_modules, so I cannot run Jest and so cannot watch any test fail (RED) or pass (GREEN). I have not implemented anything. Can the environment provide a Node/pnpm toolchain with installed dependencies?

  6. AlexVelezLl commented on Oct 1, 2026

    @AlexVelezLl
    MemberAuthor

    You shouldn't have assigned this issue to you @rtibblesbot :)

  7. added theissue type on Oct 2, 2026
  8. self-assigned this
    on Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions