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

Overview
Add the CSS animation layer to the picture password login grid and sign-in page across PicturePasswordGrid, PicturePasswordOption, and SignInPage/index.vue. All animations are implemented using CSS @keyframes and Vue <transition>. This issue does not cover the burst animation on the submit button or the confirmation modal button transitions. A prototype of animations can be found below. To view the successful authentication animations, select the sequence moon, water, bird:
Picture login animation prototype
Complexity: Medium
Target branch: develop
Context
The motion behaviors for the picture login grid are deferred to this issue so that the structural and behavioral changes can be reviewed and merged first.
All animations must respect the prefers-reduced-motion: reduce media query. When reduced motion is preferred, all animations must be suppressed.
The Change
1. Shake animation — SignInPage/PictureSignInPage.vue
When the session API returns an authentication error for a submitted picture sequence and wrongSequence becomes true, apply a brief horizontal shake animation to the grid container before clearing the selections. Implement as a CSS @keyframes animation class toggled via a data property, removed after the animation completes.
2. Elastic scale-in on progress bar icon — PicturePasswordGrid
When an icon is added to the progress bar, it should scale in with an elastic overshoot ease rather than appearing instantly. Implement using a Vue <transition> with a CSS @keyframes animation on enter, using a cubic-bezier that produces a visible overshoot and settle.
Animation specifications:
- Starting state: Icon begins at 50% of its intended size, centered in its slot
- Overshoot: Scales past 100% to ~108% of final size
- Settle: Eases back down to 100%
- Duration: 380ms
- Easing: ease-out
3. Overfill expand/contract nudge — PicturePasswordGrid and PicturePasswordOption
When all 3 slots are filled and the learner taps a dimmed icon, the tapped icon should briefly scale up then contract back to its original size to acknowledge the tap without modifying the sequence. Implement as a CSS @keyframes animation on transform: scale, triggered by toggling a class on the tapped PicturePasswordOption. The animation must not retrigger if the learner taps the same icon before the previous animation completes — ignore repeat triggers until the animation completes.
4. Submit button pulse — PicturePasswordGrid
Once the learner has chosen 3 icons and the other icons become disabled, after the learner taps at least 3 greyed-out icons, the submit button should pulse continuously to draw the learner's attention toward it. Implement as a CSS @keyframes animation class toggled via a data property. The pulse continues looping until the sequence is changed or the submit button is clicked.
5. Icon bounces on successful submit — PicturePasswordGrid
When the session API returns a successful authentication response, all 3 selected icons should briefly scale up and bounce back to their original size before the confirmation modal opens. The icons should bounce sequentially in selection order — first, second, then third — with a brief stagger delay between each. Implement as a CSS @keyframes animation on transform: scale. The bounce must play to completion before the confirmation modal is shown — use a Promise or setTimeout matching the total animation duration to sequence the two events. This animation must only play after confirmed successful authentication, never optimistically on submit tap.
6. Arrow button scales on successful submit — PicturePasswordGrid
At the same moment as the last icon in the sequence bounces, the submit arrow button should scale up and return to its original size. This can share the same keyframe definition as the icon bounce and be triggered at the same time.
7. Parent integration — SignInPage/PictureSignInPage.vue
The parent needs to coordinate the success animation with the confirmation modal that is implemented in #14428 (in-progress, this change can be implemented after that issue is completed). In createSession, after a successful picture login API response, do not immediately display the confirmation modal. Instead, trigger the authentication success flow to PicturePasswordGrid and wait for the grid to emit a submitAnimationComplete event after the animations finish. Only then allow the confirmation modal to be displayed.
Out of Scope
- The animated burst over the submit button on successful authentication
- Confirmation modal button transitions
- Any changes to component structure or non-animation behaviour
- Accessibility behavior changes
Acceptance Criteria
General
Accessibility
Testing
References
AI usage
🤖 This issue was written with AI assistance, under supervision, review and final edits by [@LianaHarris360] 🤖
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
Add the CSS animation layer to the picture password login grid and sign-in page across
PicturePasswordGrid,PicturePasswordOption, andSignInPage/index.vue. All animations are implemented using CSS@keyframesand Vue<transition>. This issue does not cover the burst animation on the submit button or the confirmation modal button transitions. A prototype of animations can be found below. To view the successful authentication animations, select the sequence moon, water, bird:Picture login animation prototype
Complexity: Medium
Target branch: develop
Context
The motion behaviors for the picture login grid are deferred to this issue so that the structural and behavioral changes can be reviewed and merged first.
All animations must respect the
prefers-reduced-motion: reducemedia query. When reduced motion is preferred, all animations must be suppressed.The Change
1. Shake animation —
SignInPage/PictureSignInPage.vueWhen the session API returns an authentication error for a submitted picture sequence and
wrongSequencebecomestrue, apply a brief horizontal shake animation to the grid container before clearing the selections. Implement as a CSS@keyframesanimation class toggled via a data property, removed after the animation completes.2. Elastic scale-in on progress bar icon —
PicturePasswordGridWhen an icon is added to the progress bar, it should scale in with an elastic overshoot ease rather than appearing instantly. Implement using a Vue
<transition>with a CSS@keyframesanimation on enter, using acubic-bezierthat produces a visible overshoot and settle.Animation specifications:
3. Overfill expand/contract nudge —
PicturePasswordGridandPicturePasswordOptionWhen all 3 slots are filled and the learner taps a dimmed icon, the tapped icon should briefly scale up then contract back to its original size to acknowledge the tap without modifying the sequence. Implement as a CSS
@keyframesanimation ontransform: scale, triggered by toggling a class on the tappedPicturePasswordOption. The animation must not retrigger if the learner taps the same icon before the previous animation completes — ignore repeat triggers until the animation completes.4. Submit button pulse —
PicturePasswordGridOnce the learner has chosen 3 icons and the other icons become disabled, after the learner taps at least 3 greyed-out icons, the submit button should pulse continuously to draw the learner's attention toward it. Implement as a CSS
@keyframesanimation class toggled via a data property. The pulse continues looping until the sequence is changed or the submit button is clicked.5. Icon bounces on successful submit —
PicturePasswordGridWhen the session API returns a successful authentication response, all 3 selected icons should briefly scale up and bounce back to their original size before the confirmation modal opens. The icons should bounce sequentially in selection order — first, second, then third — with a brief stagger delay between each. Implement as a CSS
@keyframesanimation ontransform: scale. The bounce must play to completion before the confirmation modal is shown — use aPromiseorsetTimeoutmatching the total animation duration to sequence the two events. This animation must only play after confirmed successful authentication, never optimistically on submit tap.6. Arrow button scales on successful submit —
PicturePasswordGridAt the same moment as the last icon in the sequence bounces, the submit arrow button should scale up and return to its original size. This can share the same keyframe definition as the icon bounce and be triggered at the same time.
7. Parent integration —
SignInPage/PictureSignInPage.vueThe parent needs to coordinate the success animation with the confirmation modal that is implemented in #14428 (in-progress, this change can be implemented after that issue is completed). In
createSession, after a successful picture login API response, do not immediately display the confirmation modal. Instead, trigger the authentication success flow toPicturePasswordGridand wait for the grid to emit asubmitAnimationCompleteevent after the animations finish. Only then allow the confirmation modal to be displayed.Out of Scope
Acceptance Criteria
General
Accessibility
prefers-reduced-motion: reduceis setTesting
prefers-reduced-motion: reduceis enabled in the browser or OS settingsReferences
kolibri/plugins/user_auth/frontend/views/SignInPage/PictureSignInPage.vueprefers-reduced-motion: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motionAI usage
🤖 This issue was written with AI assistance, under supervision, review and final edits by [@LianaHarris360] 🤖