Notivue Versions Save

:bell: Powerful toast notification system for Vue and Nuxt.

v2.4.4

3 weeks ago

Release Notes

Fix regression introduced in v2.3.0 where an unnecessary key was added to the Notifications' dynamic icon component prevented the switch when using custom icons on promise-resolve/reject types - Thanks @BayBreezy, #55

v2.4.0

3 weeks ago

Release Notes

The next minor release brings a new exciting feature, plently of improvements and a non-breaking but important change to the API.

At this point, I believe Notivue is feature-complete and most likely there won't be new features in future releases besides improvements and fixes.


New: useNotivueInstance

Consumers can now fully control the Notivue instance by stopping and restarting it.

In .vue components:

<script setup lang="ts">
import { useNotivueInstance } from 'notivue'

const { isRunning, startInstance, stopInstance } = useNotivueInstance()
</script>

In any other module:

import { startInstance, stopInstance } from 'notivue'

This allows the users of an app, for example, to properly enable and disable notifications in total autonomy.

Before this release, this was not "officially" supported and it could be achieved for example, by mounting/unmounting <Notivue /> (e.g. using v-if) but this was not optimal as it would have not stopped the store from "working" in the background, processing unwanted notifications and wasting resources.

This is now done the right way: when the instance is stopped, the whole store is reset, any watcher is detached, any update to the config either via direct setter or via update() is gracefully proxied without throwing errors. Same for push, which is made no-op when the instance is stopped.

Finally, notivue can now be initialized with a startOnCreation option (which defaults to true):

import { createNotivue } from 'notivue'

const notivue = createNotivue({
   startOnCreation: false,
   // Other options
})

If set to false, Notivue won't be started when the app is mounted.

This can be useful to make sure that for some users Notivue is never enabled or to only start it when the environment is ready:

import { updateConfig, startInstance } from 'notivue'

fetch('/api/user-preferences')
   .then((res) => res.json())
   .then((data) => {
      if (data.notifications.isEnabled) {
         startInstance()
         updateConfig(data.notifications.config)
      }
   })

Change: Add transition config property and disable automatic transition property detection

Before this release Notivue automatically computed the transition property added to the containers when repositioning them by "reading" the animationDuration and animationTimingFunction properties of the enter animation as soon as the first notification was rendered.

This logic required about 100 lines of code and added some complexity that could definitely be avoided as the majority of users are not customizing animations at all. This also made the package smaller and more efficient.

Starting from this release, Notivue won't compute anymore the transition property automatically, instead it should be defined manually in the configuration if using custom animations.

const notivue = createNotivue({
  transition: 'transform 200ms ease-out',
})

Check the docs website for more info.

Improvement: Fine-tune repositioning

Notivue handles repositioning of the notifications using a custom approach via CSS transitions and inline styles. Internally, the store includes a method named updatePositions that is called to compute and apply those styles everytime the notifications must be repositioned (creation, clearing, destroy, size-change, etc).

Before this release, such method was called a couple of times more than necessary on both creation and clearing, creating some unnecessary overhead.

By adding a tiny logic that keeps track of the lifecycle events (creation, clearing and destruction), I was able to move the updatePositions logic to a single place of the store in order to make sure that repositoning now happens only once per each of those events.

Improvement: Fine-tune ResizeObserver

Notivue uses the ResizeObserver API to keep track of the size of the containers and to reposition them if needed, for example, when the content of a notification is updated dynamically, all the notifications must be repositioned.

Before this release, the ResizeObserver callback would have repositioned the notifications when they were about to be destroyed, if their size never changed. This was totally unnecessary as it was already handled (as explained in the previous section) and it has been taken care of.

Improvement: Fine-tune pauseOnTabChange: false

Before this release, if pauseOnTabChange was disabled in the config, the notifications would have been immediately destroyed when the window was blurred.

I realized that this not optimal as an user would expect the notifications timeouts to be kept alive and running.

This has been taken care of and the behavior when pauseOnTabChange is disabled is now basically the same as if the user din't left the app.

Fix: syncTransitionStyles edge case failure

Notivue automatically syncs the transition duration and easing used for repositioning with your enter animation duration and easing. Before this release the approach used was too optimistica and could fail in some edge cases. This has been fixed by using requestAnimationFrame.

v2.3.0

1 month ago

Release notes

The next minor release of Notivue introduces a couple of cool features plus some improvements:

  • New (Core): Add avoidDuplicates config option
  • New (Core): Expose isStreamPaused internal signal
  • New (Built-in Notifications): Add NotificationProgress drop-in component
  • Refactor (Core): Use window's focus/blur events instead of visibilityChange
  • Improve (Core): Remove workaround for lightningcss keyframes minification (fixed upstream)
  • Improve (Core): Add singular-named import aliases for any exported CSS file
  • Fix (Built-in Notifications): Fix setting fallback accent color when computing --nv-accent CSS variable

The above new features can be summarized in this short video:

https://github.com/smastrom/notivue/assets/60471784/0835175d-131c-4e47-82c5-b100859d018e


avoidDuplicates config option

It is now possible to prevent the creation of notifications already displayed in the stream or already awaiting in the queue (duplicates).

I've found this feature extremely useful in scenarios where the same notification might be repeatedly created (external services errors, frequently updated settings), creating unnecessary noise in the UI.

Since the whole implementation required just a few lines of code, I believed it was a good trade-off implementing it.

While this option is disabled by default, it can be enabled by setting avoidDuplicates to true in Notivue's config:

const notivue = createNotivue({
   avoidDuplicates: true
})

Once enabled, if a notification like the following is pushed to the stream:

push.error({
  title: 'Error',
  message: 'There was an error sending your message, please try again.'
})

...and a notification with the same title, message and type is already displayed, Notivue will immediately make screen readers announce it again without rendering a new one.

Then, it will replace the remaining duration of the visible notification with the duration of the duplicate one (like "restarting" it).

:bulb: By design, this feature only supports static notification types (success, error, warning, info) and not dynamic types (promise, promise-resolve, promise-reject).

If using Custom Components, it is possible to "detect" when a duplicate is pushed by watching the duplicateCount property of the notification item (in your custom component setup function):

watch(
   () => props.item.duplicateCount,
   (newVal) => {
      console.log(`Total duplicates: ${newVal}`)
   }
)

For example, the above property could be used as component key to play/restart an animation everytime a duplicate of that notification is pushed (and its duration is updated).

Expose isStreamPaused internal signal

Notivue now exposes a readonly reactive proxy of its internal isStreamPaused signal, enabling consumers using Custom Components to create progress bars and advanced side-effects.

Check the docs website on how to implement a progress bar in your custom notification.

Wrapping up: <NotificationProgress /> drop-in component

Notivue's built-in Notifications now accept a default slot which can be used to add a new drop-in component named NotificationProgress (and anything else you'd like to) which fully leverages the new APIs introduced above.

All you have to do is to import it and pass the notification item to the item prop:

<script setup>
import { Notivue, Notification, NotificationProgress } from 'notivue'

import 'notivue/notification-progress.css'
</script>

<template>
  <Notivue v-slot="item">
    <Notification :item="item">
      <NotificationProgress :item="item" />
    </Notification>
  </Notivue>

  <!-- RouterView, etc. -->
</template>

:bulb: Please note that the CSS must also be imported either in app.vue or your app entry point.

v2.2.1

3 months ago

Release notes

This release brings few minor improvements to <Notifications /> and <NotivueSwipe />.

Notifications

  • Add Notification export as alias of Notifications in order to use it as the new default import mentioned in the documentation. I have come to the conclusion that users may think they're importing a list, whereas they're actually importing a single notification.
  • Replace SVG spinner <animate> with pure CSS keyframes animation.
  • Add --nv-y-align-has-title theme variable. It is now possible to set a different vertical align that only applies to notifications with title. The variable is set to center by default.
<Notification
   :item="item"
   :theme="{ ...lightTheme, '--nv-y-align-has-title': 'flex-start' }"
/>

Screenshot 2024-02-05 alle 19 06 19

Screenshot 2024-02-05 alle 19 06 52

In addition to that, it is now possible to conditionally style the notification elements by using the attribute data-notivue-has-title,

.Notivue__notification[data-notivue-has-title='true'] {
   /* */
}

NotivueSwipe

  • Add a side-effect to move back the notification to its initial position if while dragging a new notification is pushed to the stream.
  • Remove some unnecessary code related to state checks and timeouts clearing which was not removed in a previous release.

v2.2.0

3 months ago

Release notes

What's new

Disable Teleport

It is now possible to disable the built-in Teleport feature by passing false to the teleportTo config option:

const notivue = createNotivue({
  teleportTo: false
})

Stream elements custom styles

<Notivue /> renders three elements with the following structure:

List container — ol
└── List items — li[]
    └── Item container - div
        └── Notification - slot

In order to orchestrate the stream according to your config, Notivue computes and adds some inline styles to the ol, li and div elements. No classes nor other magic is involved, just those styles.

Since this release, it is now possible to define your own styles that take precedence over the default ones by passing a styles object to the omonimous <Notivue /> prop:

<Notivue
  :styles="{
    list: {
      position: 'relative'
      height: '100%'
    },
    listItem: {},
    itemContainer: {}
  }"
  v-slot="item"
>
  <Notifications :item="item" />
</Notivue>

Both new features give you total control over the positioning, allowing, for example to render the stream relatevely to a specific container with a position other than fixed.

What's improved

Refactor timeouts handling

The way Notivue handles pause and resume timeouts has been rewritten from scratch. The 60% of the involved code has been removed resulting in a much cleaner and clearer codebase.

The timeouts clearing logic has also been refactored. Compared to the previous releases, when a notification is about to be cleared, all the timeouts related to it are now cleared before triggering the leave animation and destroying the notification.

v2.1.1

4 months ago

Release notes

  • Use same type aliases mentioned in the documentation for exported composables
  • Add additional type aliases mentioned in the documentation
  • Remove useless key on Notivue's default slot

v2.1.0

4 months ago

Release notes

The first minor release of Notivue v2, ships a new feature, fixes a NotivueSwipe bug and brings various improvements to the built-in notifications component.

What's new

useNotivue update method

The object returned by useNotivue now includes an update method that can be used to update the configuration. Before this release it was only possible to update it by directly assigning a value to each returned ref:

Pre v2.1.0

const config = useNotivue()

config.postion.value = 'bottom-right'
config.enqueue.value = true

v2.1.0

const config = useNotivue()

config.update({
  position: 'bottom-right',
  enqueue: true,
})

New options will be merged to your initial configuration and so on. Alternatively, the same method also accepts a function that returns new options and exposes the current configuration as argument:

config.update((currConfig) => ({
  enqueue: !currConfig.enqueue
}))

To update the configuration from outside the setup context, you can use the updateConfig utility which has the same signature of the above-mentioned update method:

import { updateConfig } from 'notivue'

What's fixed

NotivueSwipe - Fixed a bug where the computation of isPointerInside was not performed correctly.

What's Improved

Notifications

  • Add a tiny and light transition on promise-resolve and promise-reject icons appear using Vue Transition component.
  • Reduced the font-size from 1rem to 0.925rem.
  • Disabled spinner animation when prefers-reduced-motion is set to reduce
  • Lowered by little the saturation of the slateTheme foreground color.
  • Improved rendering performance by avoiding unnecessary computed properties to tracked.

Nuxt Module

  • Add auto-imports for any theme and icon set.

Other

  • Did a huge rename refactoring to the demo source files for better user inspection.
  • Set the Vue compiler version to the latest 3.3.x release.

v2.0.0

4 months ago

Before wishing happy new year to everyone and going for a bit off until the beginning of January, I wanted to release Notivue v2.0.0.

Release notes

This release unifies usage between Vite, Nuxt and Astro setups by bringing an isomorphic API that deprecates usePush and exports push from notivue by finally allowing it to be called from anywhere no matter what framework is being used.

Upgrade guide

While usePush has been deprecated, it is still exported from notivue to facilitate the migration. For Nuxt setups, upgrading to v2.0.0 shouldn't break your code at all.

Unfortunately, for Vite-based setups an edit in both your main.js and any file where you imported push is required.

Vite

main.js

import { createNotivue } from 'notivue'
import { createApp } from 'vue'

import App from './App.vue'

+ const notivue = createNotivue(/* options */)
const app = createApp(App)

- export const push = createNotivue(app, /* options */)
+ app.use(notivue)

app.mount('#app')

In any of your files:

- import { push } from '@/main'
+ import { push } from 'notivue'

push.success('Hello from Notivue 2.0.0')

Nuxt

All you have to do is to remove this statement from anywhere in your code:

- const push = usePush()

push is now auto-imported directly from notivue and can be called from anywhere without worrying about the setup context.


What's new

notivue/astro

This package now exports Astro-dedicated versions of Notivue and push from notivue/astro meant to connect the Notivue store to Astro client code using Custom Events.

This makes possible to push notifications from anywhere: script tags, React components, Vue components, you name it. Persistence of the notification stream across page navigation is also supported when using View Transitions.

Check the installation guide in the docs.

Promise Aliases

Promise-based notifications can now be pushed using the load method alternatively to the promise one and updated using success and error methods alternatively to resolve and reject. After using this package for a bit in my professional work, I realized that calling promise, resolve and reject was a bit odd.

let notification = push.promise('Loading...')
notification.resolve('Done!')

// Same
let notification = push.load('Loading...')
notification.success('Done!')
let notification = push.promise('Loading...')
notification.reject('Error!')

// Same
let notification = push.load('Loading...')
notification.error('Error!')

What's fixed

  • Improve repositioning performance by avoiding calling triggerRef when not necessary
  • Remove animation enterClass when completed. This prevents the enter animation to be played again when navigating between pages using Astro View Transitions.

What's changed

  • Definitely remove deprecated notivue plugin. The compatibility fallback released in v1 is not anymore exported.
  • Definitely remove deprecated useNotivueConfig composable alias.
  • Remove popIn animation applied to built-in notifications icon.

v1.4.5

4 months ago

Release notes

  • Import Nuxt composables from #imports instead of #app. Thanks @danielroe - #32
  • Fix teleportTo prop not working with HTML elements. Thanks @luxterful - #33

v1.4.3

6 months ago

Release notes - v1.4.3

What's changed

NotivueSwipe - Improved stream pausing/resuming after touch interactions. Interactions that may trigger a clear or a position reset will now schedule the resumal using debounce instead of immediately performing it.

This gives an overall better UX by avoiding that:

  • Siblings notifications are cleared just right after releasing or clearing the target notification via swipe (if their duration expires at that moment).
  • Siblings notifications are cleared while clicking a target's excluded element (close button).

While this behavior worked great with mouse interactions because the stream is always paused on hover, it wasn't really suitable for touch interactions.

Affected interactions and debounce timings:

  • Tapping on excluded elements (close buttons) will now pause and resume the stream after 1.4s.
  • Swiping and releasing a notification not enough to be cleared will resume timeouts after 1s.
  • Tapping and releasing a notification will now pause an resume timeouts after 1s.

NotivueSwipe - Fix isPointerInside computation, which paused the stream after releasing a notification if the mouse pointer was still hovering a notification.

NotivueCore - Added will-change: transform when repositioning the notifications. This improves performance on Android Firefox which was the only environment "suffering" from it since the last minor release.

Release notes - v1.4.4

Fixed a regression introduced in v1.4.3 where the transition data computation failed in nuxt middlewares or initial page load.

Time elapsed between v1.4.3 and v1.4.4: 1 hour and 30 minutes.