Skip to content

[Remove Vuetify from Studio] 'Reset password' page - #6145

Open
LightCreator1007 wants to merge 1 commit into
learningequality:unstablefrom
LightCreator1007:remove-vuetify-reset-password
Open

LightCreator1007 wants to merge 1 commit into
learningequality:unstablefrom
LightCreator1007:remove-vuetify-reset-password

Conversation

@LightCreator1007

Copy link
Copy Markdown
Contributor

Summary

Replace the four Vuetify-backed pieces of the reset password page with their Studio/KDS equivalents.
Minor Visual differences due to KDS itself.

References

Closes #5931

Reviewer guidance

Screen.Recording.2026-09-18.at.1.25.13.AM.mov

AI usage

I used claude code to scope the current state of tests and the component. Made it write a plan by mapping out the vuetify dependencies. Replaced them and then verified the UI manually, audited the changes to code to the best of my abilities.

Replace the four Vuetify-backed pieces of the reset password page with
their Studio/KDS equivalents, per learningequality#5931:

  MessageLayout  -> StudioMessageLayout
  VForm          -> <form> + generateFormMixin
  Banner         -> StudioBanner
  PasswordField  -> StudioPasswordField

All four replacements already existed and are in use by sibling pages;
no new components are introduced. The remaining pages under
pages/resetPassword/ were migrated earlier, so this brings the last
Vuetify page in that directory into line.

Two details preserve existing behaviour:

  - The submit handler validates and submits the raw this.form values
    rather than formMixin's clean(), which trims every field. Passwords
    must keep any leading or trailing spaces the user typed.
  - A touched map gates error display until blur, since formMixin's
    setters otherwise flag an error on every keystroke, where the
    VForm version validated on blur.

Strings, submit payload, redirect target, and the length and match
rules are unchanged. resetPassword.spec.js required no changes and
still passes.
@learning-equality-bot

Copy link
Copy Markdown
Contributor

👋 Hi @LightCreator1007, thanks for contributing!

For the review process to begin, please verify that the following is satisfied:

  • Contribution is aligned with our contributing guidelines

  • Pull request description has correctly filled AI usage section & follows our AI guidance:

    AI guidance

    State explicitly whether you didn't use or used AI & how.

    If you used it, ensure that the PR is aligned with Using AI as well as our DEEP framework. DEEP asks you:

    • Disclose — Be open about when you've used AI for support.
    • Engage critically — Question what is generated. Review code for correctness and unnecessary complexity.
    • Edit — Review and refine AI output. Remove unnecessary code and verify it still works after your edits.
    • Process sharing — Explain how you used the AI so others can learn.

    Examples of good disclosures:

    "I used Claude Code to implement the component, prompting it to follow the pattern in ComponentX. I reviewed the generated code, removed unnecessary error handling, and verified the tests pass."

    "I brainstormed the approach with Gemini, then had it write failing tests for the feature. After reviewing the tests, I used Claude Code to generate the implementation. I refactored the output to reduce verbosity and ran the full test suite."

Also check that issue requirements are satisfied & you ran pre-commit locally.

Pull requests that don't follow the guidelines will be closed.

Reviewer assignment can take up to 2 weeks.

@learning-equality-bot

Copy link
Copy Markdown
Contributor

📢✨ Before we assign a reviewer, we'll turn on @rtibblesbot to pre-review. Its comments are generated by an LLM, and should be evaluated accordingly.

@rtibblesbot

rtibblesbot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

🟡 Waiting for changes

Last updated: 2026-09-30 07:37 UTC

@rtibblesbot rtibblesbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #6145: four regressions block merge. The migration follows the sign-in page's form pattern. The happy path, bad-token banner, whitespace preservation and RTL all work in the browser.

CI passing. Manual QA: axe AA finds 0 violations on every state. No console errors.

  • blocking: blurring an empty field shows no "required" error (inline)
  • blocking: editing the first password doesn't re-check the confirmation (inline)
  • blocking: form overflows a 360px viewport (inline)
  • blocking: resetPassword.spec.js not updated, which the AC requires (inline)
  • suggestion: move focus to the first invalid field on a failed submit (inline)
  • nitpick: trim the process context from the touched comment (inline)

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

How was this generated?

Ran a phased review pipeline over the pull request diff:

  • Classified the diff to select review passes (core, frontend, backend) and whether manual QA was required
  • Core review pass checked correctness, design, architecture, testing, completeness, and DRY/SRP/Rule-of-Three principles
  • Specialized frontend/backend review passes applied framework-specific lenses where those files changed
  • For UI changes: manual QA and an accessibility audit against a live dev server, when available
  • Checked CI status and linked issue acceptance criteria
  • Synthesized one review from those passes and chose the verdict from the findings, CI status, and QA evidence

:errorMessages="
touched.new_password1 && errors.new_password1 ? [new_password1ErrorText] : []
"
@blur="touched.new_password1 = true"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: Blurring an empty field shows no "This field is required" error. Unstable's validate-on-blur showed it.

The blur handler only marks the field touched. Errors are only computed on input or on submit.

Run the field's validator on blur, or compute the errors from form instead of storing them.

},
new_password2: {
required: true,
validator: (v, vm) => Boolean(v) && v === vm.form.new_password1,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: Editing the first password doesn't re-check the confirmation.

  • Type abcdefgh in both, change field 1 to abcdefghZZ, Tab: no mismatch error until Submit.
  • The reverse also fails: after fixing a mismatch in field 1, the stale "Passwords don't match" stays.

Unstable re-ran the confirmation check whenever the first password changed. The mixin's setter only validates the field being set.

Add a watcher on form.new_password1 that re-runs the new_password2 check once that field is touched. Create.vue has the same gap.

<style lang="scss" scoped>

.reset-password-form {
width: 400px;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: The form overflows a 360px viewport. Fields, Submit and the banner are clipped at the end edge ("…Please try agai") in both LTR and RTL.

The cause is .message-slot-container in StudioMessageLayout. It has no width, so it shrink-wraps to this form's 400px. The form's max-width: 100% then resolves against 400px.

Add width: 100% to .message-slot-container. Verified: the form then renders at 328px. This also fixes RequestNewActivationLink, which overflows the same way.

methods: {
...mapActions('account', ['setPassword']),
submit() {
resetPassword() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: accounts/pages/__tests__/resetPassword.spec.js is unchanged. The AC requires the existing unit suite to be meaningfully updated.

Add tests for the new behavior:

  • the role="alert" banner when setPassword rejects
  • the required error on empty submit, for both fields
  • errors hidden while typing and shown on blur
  • leading/trailing spaces reaching setPassword untrimmed. A later switch to clean() would break this most easily.

The AccountsMain VTL tests from #6056 show the banner and blur patterns.

// Validate against this.form rather than formMixin's clean(), which
// trims every field. Passwords must keep the leading/trailing spaces
// the user typed, both here and in the payload below.
if (!this.validate(this.form)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: A failed submit announces nothing to screen-reader users. Focus stays where it was. KTextbox doesn't wire invalidText to aria-describedby or aria-invalid, so the errors are never read.

Move focus to the first invalid field with a ref and KTextbox's focus(). This isn't a regression: the old Vuetify form and AccountsMain.vue have the same gap.

new_password1: '',
new_password2: '',
error: false,
// Gates error display until blur, since formMixin's setters otherwise

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: This comment's Create.vue/#5060 sentences will go stale once #5060 is decided. Cut them and keep the first sentence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Remove Vuetify from Studio] 'Reset password' page

3 participants