Skip to content

feat: Add KSnackbar component and useKSnackbar composable#1205

Open
Prashant-thakur77 wants to merge 36 commits intolearningequality:developfrom
Prashant-thakur77:ksnackbar
Open

feat: Add KSnackbar component and useKSnackbar composable#1205
Prashant-thakur77 wants to merge 36 commits intolearningequality:developfrom
Prashant-thakur77:ksnackbar

Conversation

@Prashant-thakur77
Copy link
Contributor

@Prashant-thakur77 Prashant-thakur77 commented Feb 14, 2026

Description

Part Of learningequality/studio#5445

This PR implements the core KSnackbar component and the useKSnackbar composable. This is Part 1 of the migration strategy, focusing on logic, accessibility, and unit testing. (Visual tests and documentation will follow in a subsequent PR).
I have followed the design descriptions given in https://design-system.learningequality.org/snackbars/

Key Features

  1. KSnackbar Component (lib/KSnackbar/KSnackbar.vue):
  • Accessibility: Implements role="alert", dynamic aria-live ('polite'/'assertive'), and focus trapping when the backdrop is active.
  • Responsiveness: Uses useKResponsiveWindow to handle mobile vs desktop positioning.
  • Interactions: Supports action buttons, auto-hide timers, and manual dismissal.
  1. Composable (lib/composables/useKSnackbar/index.js):
  • Implements a singleton state pattern for global snackbar management.
  • Includes forceReuse logic for instant content updates.
  1. Added comprehensive Unit Tests using @testing-library/vue.

Before/after screenshots

This is the testing that i have done in Playground.
Screencast From 2026-02-14 23-41-29.webm

Changelog

  • Description: Add KSnackbar component and useKSnackbar composable for globally-managed notifications with action buttons, auto-hide, backdrop mode, and full keyboard accessibility
  • Products impact: new API
  • Addresses: [Remove Vuetify from Studio] Snackbar studio#5445
  • Components: KSnackbar, useKSnackbar
  • Breaking: no
  • Impacts a11y: yes
  • Guidance: Import and use KSnackbar with the useKSnackbar composable to display global notifications. Place a single KSnackbar component at the root level of your app and bind it to snackbarState from useKSnackbar. Call createSnackbar() from anywhere to display notifications. The component uses useKLiveRegion for screen reader announcements, supports keyboard navigation, and includes focus management with backdrop mode.

(optional) Implementation notes

At a high level, how did you implement this?

Does this introduce any tech-debt items?

Testing checklist

  • Contributor has fully tested the PR manually
  • If there are any front-end changes, before/after screenshots are included
  • Critical and brittle code paths are covered by unit tests
  • The change is described in the changelog section above

Reviewer guidance

  • Is the code clean and well-commented?
  • Are there tests for this change?
  • Are all UI components LTR and RTL compliant (if applicable)?
  • Add other things to check for here

Comments

@learning-equality-bot
Copy link

👋 Thanks for contributing!

We will assign a reviewer within the next two weeks. In the meantime, please ensure that:

  • You ran pre-commit locally
  • All issue requirements are satisfied
  • The contribution is aligned with our Contributing guidelines. Pay extra attention to Using generative AI. Pull requests that don't follow the guidelines will be closed.

We'll be in touch! 😊

Copy link
Member

Choose a reason for hiding this comment

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

Nice, thanks

queue.value = [];
}

function initVuexBridge(store) {
Copy link
Member

Choose a reason for hiding this comment

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

What was the reason for this logic?

Asking because I wouldn't expect Vuex-compatibility to be needed ~ the idea is to migrate both Studio and Kolibri to KSnackbar + useKSnackbar where useKSnacbkar is the place which will keep the state rather than relying on Vuex. During migration, we'll cleanup all obsolete Vuex code from Kolibri and Studio.

Copy link
Member

Choose a reason for hiding this comment

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

Here's an example of a composable acting as global store

https://github.com/learningequality/kolibri/blob/develop/packages/kolibri/composables/useSnackbar.js#L4-L12

You may need to tweak to fit all features of this KDS implementation, but the main idea is same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

ref="snackbarElement"
class="k-snackbar"
:class="$computedClass(focusStyles)"
role="alert"
Copy link
Member

@MisRob MisRob Feb 23, 2026

Choose a reason for hiding this comment

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

Can you please remove alert role and aria-live from everywhere here and instead use https://design-system.learningequality.org/usekliveregion?

You can see 'The Value Add' section of #668 to understand its benefit over having multiple live regions on a page.

Copy link
Member

Choose a reason for hiding this comment

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

To explain, this role would create a live region too

Alerts are assertive live regions. Setting role="alert" is equivalent to setting aria-live="assertive" and aria-atomic="true".

https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/alert_role

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

},
},

computed: {
Copy link
Member

@MisRob MisRob Feb 23, 2026

Choose a reason for hiding this comment

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

Since most of the logic already is placed in setup, it may make more sense to also move computed + methods there.

And generally we're trying to move towards Composition API setup in all new features, even though I admit we're not always diligent in that regard, myself included :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

addresed

@MisRob
Copy link
Member

MisRob commented Feb 23, 2026

Hi @Prashant-thakur77, wonderful work as always & I enjoyed watching the recording. I left a few higher-level notes. We'll proceed as discussed here ~ let me know any time you're ready. Thanks a lot.

@Prashant-thakur77
Copy link
Contributor Author

@MisRob Sure, currently working on it and will also work on your review.;)

- Move snackbars.vue to design guidelines only (like buttons.vue)
- Create new ksnackbar.vue for component-specific documentation
- Remove KSnackbar example and useKSnackbar logic from snackbars.vue
- Add complete props, events, and usage examples to ksnackbar.vue
- Update related section to link to both KSnackbar component and useKSnackbar composable
- Add KSnackbar to Code library components section
- Add useKSnackbar to Composables section
- Both sections use autoSort, so entries will be alphabetically sorted
@Prashant-thakur77
Copy link
Contributor Author

@AlexVelezLl @MisRob I have created the visual tests and documentation and pushed it,the talk on slack related to specifications i have currently used the one given by kds (and took care for the colors --used the one mentioned in kds color section). I have also tried implementing the ksnackbar in studio and it is working as expected.I think the review can be started after the specifications are confirmed.do tell if any other changes are needed to be addressed.

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.

3 participants