Appearance
Snackbar Plugin ​
File Information ​
- Path:
app/plugins/snackbar.client.ts - Purpose: Global snackbar notification system
- Type: Client-only (runs only in browser)
- Provides:
$snackbar(viaprovide: { snackbar })
Overview ​
The plugin renders notifications as plain DOM elements appended to document.body (not through a Vue component tree). Each call to show() builds a div.snackbar-plugin.snackbar-plugin-<color>, optionally mounts an icon component into it with its own small createApp(), slides it in, and removes it after the timeout. The older Snackbar.vue / useSnackbar state is kept only for type compatibility; useSnackbar() now delegates every call to this plugin.
Key Features ​
- Four colors -
success,error,warning,info(SnackbarColor), each with a default icon component loaded lazily (SnackbarSuccess,SnackbarError,SnackbarWarning,SnackbarInfofrom~/components/svg/). - Duplicate suppression (added in ee26b58) -
show()returns early when a snackbar of the same color with exactly the same text is already on screen. - Long default timeout - 300000 ms (5 minutes) when no timeout is passed to the plugin directly.
- Multiple snackbars - different messages, or the same text in a different color, still stack.
Code Structure ​
typescript
export default defineNuxtPlugin((nuxtApp) => {
const snackbar: SnackbarMethods = {
show(message, icon = null, color = 'success', timeout = 300000),
hideSnackbar(snackbarEl),
getBackgroundColor(color),
success(message, icon?, timeout?),
error(message, icon?, timeout?),
warning(message, icon?, timeout?),
info(message, icon?, timeout?),
}
return { provide: { snackbar } }
})Methods ​
show(message, icon?, color?, timeout?) ​
| Param | Type | Default |
|---|---|---|
message | string | required |
icon | Component | null | null (no icon) |
color | SnackbarColor | 'success' |
timeout | number (ms) | 300000 |
Order of work:
- Query
.snackbar-plugin-<color> .snackbar-plugin-message; if any element'stextContent === message, return without rendering. - Create the wrapper and set
--snackbar-color(fromSNACKBAR_COLORS[color], falling back to success) and--snackbar-bg-color(fromgetBackgroundColor(color)). - If
iconis given, mount it withcreateApp(h(icon, { color }))and keep the app on the element (__iconApp) for cleanup. - Append
span.snackbar-plugin-message, append todocument.body, addsnackbar-plugin-visibleon the next animation frame. - If
timeout > 0, callhideSnackbar()aftertimeoutms. A timeout of0keeps it on screen.
The dedupe landed in the same commit (ee26b58) that made the collage and folder detail pages show "Collage not found." / "Folder not found." from more than one code path, so the same message can be requested twice in quick succession.
success(message, icon?, timeout?) / error(...) / warning(...) / info(...) ​
Shortcuts for show(). icon defaults to the matching Snackbar* icon when undefined or null; timeout defaults to 300000. Note the second argument is the icon, not the timeout.
hideSnackbar(snackbarEl) ​
Removes snackbar-plugin-visible, then after 300 ms unmounts the icon app (if any) and removes the element.
getBackgroundColor(color) ​
Returns the background for a color, falling back to success.
Usage Examples ​
Success Notification ​
typescript
const { $snackbar } = useNuxtApp()
$snackbar.success('Operation completed successfully!')Error Notification ​
typescript
const { $snackbar } = useNuxtApp()
$snackbar.error('Collage not found.')Custom Timeout ​
typescript
const { $snackbar } = useNuxtApp()
// icon argument comes before timeout
$snackbar.info('Saved', undefined, 5000)Using Composable ​
typescript
const snackbar = useSnackbar()
snackbar.showSuccess('Success!')
snackbar.showError('Folder not found.')useSnackbar().addSnackbar() uses options.duration || options.timeout || 5000, so calls through the composable auto-hide after 5 s unless a duration is passed, while direct $snackbar.* calls default to 300000 ms.
Notification Colors ​
| Color | Text/border (SNACKBAR_COLORS) | Background (getBackgroundColor) |
|---|---|---|
success | #256029 | #E5F6EB |
error | #B00020 | #FFEEF1 |
warning | #856404 | #FFF2ED |
info | #0C5460 | #EEFFFD |
Styling ​
From app/assets/scss/components/_snackbar.scss: fixed at top: 16px; right: 16px, max-width: 600px, min-height: 70px, border-radius: 8px, border widths 1px 1px 1px 3px in var(--snackbar-color), z-index: 9999.
Animation ​
Hidden state is transform: translateX(100%); opacity: 0; .snackbar-plugin-visible sets translateX(0) and opacity: 1. Removal waits 300 ms for the transition.
Auto-Dismiss ​
- Plugin default: 300000 ms. Composable default: 5000 ms.
timeout = 0disables auto-dismiss.
Close Button ​
The plugin does not render a close button; snackbars leave only through the timeout.
Dependencies ​
- Vue -
createApp,h,defineAsyncComponentfor icons ~/types-SnackbarColor,SnackbarMethods,SNACKBAR_COLORS
Notes for Development ​
- Client-only plugin (
.client.tssuffix); it touchesdocumentdirectly. - Dedupe compares exact
textContentwithin the same color class only. - Stacked snackbars all use the same fixed position, so they overlap rather than list.
Related Documentation ​
- useSnackbar Composable - Snackbar composable
- Snackbar styles