Notifications Popover
A popover panel for displaying notifications, anchored to a customisable activator element.
Component
Props
| Props | Default | Type |
|---|---|---|
list | [] | AppNotificationItem[] |
limit | 10 | number |
title | 'Notifications' | string |
isLoading | false | boolean |
loadingText | 'Loading notifications' | string |
errorText | '' | string |
listEmptyText | 'No notifications available.' | string |
listMaxHeightClass | 'max-h-[400px]' | string |
isListIconContained | true | boolean |
listIconSize | IconSize.MD | IconSize |
listContainedIconSize | IconContainerSize.SM | IconContainerSize |
listContainedIconShape | IconContainerShape.CIRCLE | IconContainerShape |
listContainedStyleType | IconContainerStyleType.FLAT | IconContainerStyleType |
listTimeAgoIcon | 'mdi:clock-time-four-outline' | string |
listAuthorIcon | 'mdi:account-outline' | string |
listRemoveItemIcon | 'mdi:close' | string |
listRemoveItemAriaLabel | 'Remove notification' | string |
viewAllText | 'View all' | string |
viewAllLink | '' | string |
badgeColor | ColorAccent.SECONDARY_BRAND | ColorAccent |
badgeStyleType | BadgeStyle.FILLED | BadgeStyle |
badgeShape | BadgeShape.PILL | BadgeShape |
buttonAllReadText | 'Mark all as read' | string |
buttonAllReadIcon | 'mdi:check-all' | string |
buttonClearAllText | 'Clear all' | string |
buttonClearAllIcon | 'mdi:close-circle-outline' | string |
filterAllButtonText | 'All' | string |
filterUnreadButtonText | 'Unread' | string |
filterGroupStyle | ToggleButtonGroupStyle.GROUPED | ToggleButtonGroupStyle |
position | Position.BOTTOM | Position |
align | Align.RIGHT | Align |
trigger | Trigger.CLICK | Trigger |
popoverClass | 'min-w-[332px]' | string |
Slots
| Name | Description |
|---|---|
activator | The element that triggers the popover. Typically an icon button or action button. |
list | Overrides the default rendered list. When provided, NotificationListItem components are not rendered automatically. |
<template>
<NotificationsPopover :list="notifications">
<template #list>
<NotificationListItem
v-for="item in notifications"
:key="item.id"
:title="item.title"
:description="item.description"
:timeAgo="item.timeAgo"
:author="item.author"
/>
</template>
<template #activator>
<ActionIconButton icon="mdi:bell-outline" />
</template>
</NotificationsPopover>
</template>
Components
| Name | Description |
|---|---|
<NotificationsPopover> | The main popover container. Manages the internal list state, filtering, and emits events for remove, mark-all-read, and clear-all. |
<NotificationListItem> | Represents a single notification row. Handles click-to-read, item removal, and optional navigation via the to prop. |
Usage
list
The array of notification items to display. Each item must conform to the AppNotificationItem interface: id, read, title, description, timeAgo, author, link (required), plus optional icon and iconColor.
<template>
<NotificationsPopover :list="notifications">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
<script setup lang="ts">
const notifications: AppNotificationItem[] = [
{
id: '1',
read: false,
title: 'New message',
description: 'You have a new message from Alice.',
timeAgo: '2 minutes ago',
author: 'Alice',
link: '/messages/1',
icon: 'mdi:bell-outline',
iconColor: ColorAccent.PRIMARY_BRAND,
},
]
</script>
TypeScript interface
interface AppNotificationItem {
id: string;
read: boolean;
title: string;
description: string;
timeAgo: string;
author: string;
link: string;
icon?: string;
iconColor?: ColorAccent;
}
limit
Caps the number of notifications rendered in the list, applied after the read/unread filter. The unread count badge always reflects the full list, regardless of the limit.
<template>
<NotificationsPopover :list="notifications" :limit="5">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
title
Sets the heading text displayed at the top of the popover.
<template>
<NotificationsPopover title="Updates">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
isLoading
Shows a loading spinner and hides the list while notifications are being fetched.
<template>
<NotificationsPopover :isLoading="true">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
loadingText
The label shown next to the loading spinner when isLoading is true.
<template>
<NotificationsPopover :isLoading="true" loadingText="Fetching updates…">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
errorText
When non-empty, renders an error message and hides the list. Use this when the notification fetch fails.
<template>
<NotificationsPopover errorText="Could not load notifications.">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
listEmptyText
The message displayed when the list has no items to show.
<template>
<NotificationsPopover :list="[]" listEmptyText="You're all caught up!">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
listMaxHeightClass
A Tailwind max-h-* utility class applied to the scrollable list container.
<template>
<NotificationsPopover listMaxHeightClass="max-h-[600px]">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
isListIconContained
When true, each item's icon is wrapped in a ContainedIcon. When false, a plain Icon is rendered instead.
<template>
<NotificationsPopover :isListIconContained="false">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
listIconSize
Size of the plain icon rendered when isListIconContained is false. Uses the IconSize enum.
<template>
<NotificationsPopover :isListIconContained="false" :listIconSize="IconSize.LG">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
XS | Extra small icon. |
SM | Small icon. |
MD | Medium icon. |
LG | Large icon. |
XL | Extra large icon. |
listContainedIconSize
Size of the ContainedIcon container per list item when isListIconContained is true. Uses the IconContainerSize enum.
<template>
<NotificationsPopover :listContainedIconSize="IconContainerSize.MD">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
SM | 24 × 24 px container. |
MD | 32 × 32 px container. |
LG | 40 × 40 px container. |
XL | 48 × 48 px container. |
XXL | 56 × 56 px container. |
listContainedIconShape
Shape of the ContainedIcon container per list item. Uses the IconContainerShape enum.
<template>
<NotificationsPopover :listContainedIconShape="IconContainerShape.SQUARE">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
CIRCLE | Fully rounded container. |
SQUARE | Rounded-corner square container. |
listContainedStyleType
Visual style of the ContainedIcon container per list item. Uses the IconContainerStyleType enum.
<template>
<NotificationsPopover :listContainedStyleType="IconContainerStyleType.FILLED">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
FLAT | Subtle background tinted to match the icon colour. |
FILLED | Bold filled background with an on-filled icon colour. |
listTimeAgoIcon
Icon name rendered before the time-ago label on each list item.
<template>
<NotificationsPopover listTimeAgoIcon="mdi:timer-outline">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
listAuthorIcon
Icon name rendered before the author name on each list item.
<template>
<NotificationsPopover listAuthorIcon="mdi:account-circle-outline">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
listRemoveItemIcon
Icon used for the remove button on each list item.
<template>
<NotificationsPopover listRemoveItemIcon="mdi:trash-can-outline">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
listRemoveItemAriaLabel
Accessible label for the remove button on each list item.
<template>
<NotificationsPopover listRemoveItemAriaLabel="Dismiss notification">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
viewAllText
Label of the "view all" link displayed in the header.
<template>
<NotificationsPopover viewAllText="See all updates" viewAllLink="/notifications">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
viewAllLink
Route passed to the "view all" link in the header. Clicking the link always closes the popover; when this prop is empty, no navigation is triggered.
<template>
<NotificationsPopover viewAllLink="/notifications">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
badgeColor
Colour of the unread-count badge displayed next to the title. Uses the ColorAccent enum.
<template>
<NotificationsPopover :badgeColor="ColorAccent.DANGER">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
NEUTRAL | Neutral grey badge. |
PRIMARY_BRAND | Primary brand colour badge. |
SECONDARY_BRAND | Secondary brand colour badge. |
SUCCESS | Green success badge. |
WARNING | Yellow warning badge. |
DANGER | Red danger badge. |
INFO | Blue info badge. |
badgeStyleType
Visual style of the unread-count badge. Uses the BadgeStyle enum.
<template>
<NotificationsPopover :badgeStyleType="BadgeStyle.SOFT">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
FILLED | Solid background badge. |
SOFT | Tinted soft background badge. |
OUTLINED | Transparent badge with a border. |
badgeShape
Shape of the unread-count badge. Uses the BadgeShape enum.
<template>
<NotificationsPopover :badgeShape="BadgeShape.ROUNDED">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
PILL | Fully rounded pill shape. |
ROUNDED | Rounded-corner rectangle. |
buttonAllReadText
Label of the "mark all as read" footer button.
<template>
<NotificationsPopover buttonAllReadText="Read all">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
buttonAllReadIcon
Icon for the "mark all as read" footer button.
<template>
<NotificationsPopover buttonAllReadIcon="mdi:check">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
buttonClearAllText
Label of the "clear all" footer button.
<template>
<NotificationsPopover buttonClearAllText="Remove all">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
buttonClearAllIcon
Icon for the "clear all" footer button.
<template>
<NotificationsPopover buttonClearAllIcon="mdi:trash-can-outline">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
filterAllButtonText
Label of the toggle button that shows all notifications.
<template>
<NotificationsPopover filterAllButtonText="All items">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
filterUnreadButtonText
Label of the toggle button that shows only unread notifications.
<template>
<NotificationsPopover filterUnreadButtonText="New">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
filterGroupStyle
Visual style of the filter toggle buttons group. Uses the ToggleButtonGroupStyle enum.
<template>
<NotificationsPopover :filterGroupStyle="ToggleButtonGroupStyle.SEPARATED">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
GROUPED | Buttons share a single joined container. |
SEPARATED | Buttons are rendered individually with gaps. |
position
Determines the vertical position of the popover relative to the activator. Uses the Position enum.
<template>
<NotificationsPopover :position="Position.TOP">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
TOP | The popover appears above the activator. |
BOTTOM | The popover appears below the activator. |
align
Sets the horizontal alignment of the popover relative to the activator. Uses the Align enum.
<template>
<NotificationsPopover :align="Align.LEFT">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
LEFT | The popover aligns to the left edge of the activator. |
CENTER | The popover centers relative to the activator. |
RIGHT | The popover aligns to the right edge of the activator. |
trigger
Configures how the popover is opened. Uses the Trigger enum.
<template>
<NotificationsPopover :trigger="Trigger.HOVER">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
Options
| Value | Description |
|---|---|
CLICK | The popover opens on activator click. |
HOVER | The popover opens on activator hover. |
popoverClass
Overrides the popover panel's CSS class. Use it to set a custom minimum width or other layout styles.
<template>
<NotificationsPopover popoverClass="min-w-[420px]">
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
NotificationListItem
<NotificationListItem> represents a single row in the notifications list. It supports an optional icon, navigation link, read/unread state, and a remove action.
This is a notification description.
Props
| Props | Default | Type |
|---|---|---|
modelValue | false | booleanThe read status of the notification. Use v-model to keep the parent in sync. |
icon | — | string |
iconColor | ColorAccent.NEUTRAL | ColorAccent |
iconSize | IconSize.MD | IconSize |
isIconContained | true | boolean |
containedStyleType | IconContainerStyleType.FLAT | IconContainerStyleType |
containedIconShape | IconContainerShape.CIRCLE | IconContainerShape |
containedIconSize | IconContainerSize.XL | IconContainerSize |
to | — | string |
title | 'Title' | string |
description | 'Description' | string |
timeAgo | 'Time ago' | string |
timeAgoIcon | 'mdi:clock-time-four-outline' | string |
author | 'Author' | string |
authorIcon | 'mdi:account-outline' | string |
removeItemIcon | 'mdi:close' | string |
removeAriaLabel | 'Remove notification' | string |
modelValue
Controls the read state of the notification. Bind with v-model to keep the parent in sync. The item automatically emits update:modelValue with true when clicked.
<template>
<NotificationListItem
v-model="notification.read"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
icon
Icon name rendered on the left of the list item. When paired with isIconContained, it is displayed inside a ContainedIcon.
<template>
<NotificationListItem
icon="mdi:bell-outline"
:iconColor="ColorAccent.PRIMARY_BRAND"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
iconColor
Colour applied to the icon or its container. Uses the ColorAccent enum.
<template>
<NotificationListItem
icon="mdi:bell-outline"
:iconColor="ColorAccent.DANGER"
title="Alert"
description="Something needs your attention."
timeAgo="1 minute ago"
author="System"
/>
</template>
Options
| Value | Description |
|---|---|
NEUTRAL | Neutral grey. |
PRIMARY_BRAND | Primary brand colour. |
SECONDARY_BRAND | Secondary brand colour. |
SUCCESS | Green success colour. |
WARNING | Yellow warning colour. |
DANGER | Red danger colour. |
INFO | Blue info colour. |
iconSize
Size of the plain icon when isIconContained is false. Uses the IconSize enum.
<template>
<NotificationListItem
icon="mdi:bell-outline"
:isIconContained="false"
:iconSize="IconSize.LG"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
Options
| Value | Description |
|---|---|
XS | Extra small icon. |
SM | Small icon. |
MD | Medium icon. |
LG | Large icon. |
XL | Extra large icon. |
isIconContained
When true, the icon is wrapped inside a ContainedIcon component. When false, a plain Icon is rendered.
<template>
<NotificationListItem
icon="mdi:bell-outline"
:isIconContained="false"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
containedStyleType
Visual style of the ContainedIcon container. Uses the IconContainerStyleType enum.
<template>
<NotificationListItem
icon="mdi:bell-outline"
:containedStyleType="IconContainerStyleType.FILLED"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
Options
| Value | Description |
|---|---|
FLAT | Subtle tinted background matching the icon colour. |
FILLED | Bold filled background with an on-filled icon colour. |
containedIconShape
Shape of the ContainedIcon container. Uses the IconContainerShape enum.
<template>
<NotificationListItem
icon="mdi:bell-outline"
:containedIconShape="IconContainerShape.SQUARE"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
Options
| Value | Description |
|---|---|
CIRCLE | Fully rounded container. |
SQUARE | Rounded-corner square container. |
containedIconSize
Size of the ContainedIcon container. Uses the IconContainerSize enum.
<template>
<NotificationListItem
icon="mdi:bell-outline"
:containedIconSize="IconContainerSize.MD"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
Options
| Value | Description |
|---|---|
SM | 24 × 24 px container. |
MD | 32 × 32 px container. |
LG | 40 × 40 px container. |
XL | 48 × 48 px container. |
XXL | 56 × 56 px container. |
to
Navigation route for the item. When provided, clicking the content area navigates to this path.
<template>
<NotificationListItem
to="/messages/1"
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
/>
</template>
title
The main heading text of the notification.
<template>
<NotificationListItem
title="Deployment complete"
description="Your application was deployed successfully."
timeAgo="3 minutes ago"
author="CI System"
/>
</template>
description
The body text of the notification.
<template>
<NotificationListItem
title="New comment"
description="Bob left a comment on your post."
timeAgo="10 minutes ago"
author="Bob"
/>
</template>
timeAgo
The relative time string displayed below the description.
<template>
<NotificationListItem
title="New message"
description="You have a new message."
timeAgo="just now"
author="Alice"
/>
</template>
timeAgoIcon
Icon name rendered before the time-ago string.
<template>
<NotificationListItem
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
timeAgoIcon="mdi:timer-outline"
/>
</template>
author
The name of the notification's author, displayed below the description.
<template>
<NotificationListItem
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice Smith"
/>
</template>
authorIcon
Icon name rendered before the author name.
<template>
<NotificationListItem
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
authorIcon="mdi:account-circle-outline"
/>
</template>
removeItemIcon
Icon for the remove button.
<template>
<NotificationListItem
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
removeItemIcon="mdi:trash-can-outline"
/>
</template>
removeAriaLabel
Accessible label for the remove button.
<template>
<NotificationListItem
title="New message"
description="You have a new message."
timeAgo="2 minutes ago"
author="Alice"
removeAriaLabel="Dismiss this notification"
/>
</template>
Slots
| Name | Description |
|---|---|
content | Replaces the entire content area (icon excluded). Use this for fully custom layouts. |
description | Replaces only the description paragraph while keeping the title, timeAgo and author rows. |
<template>
<NotificationListItem
title="New message"
timeAgo="2 minutes ago"
author="Alice"
>
<template #description>
<p class="text-sm text-text-default">
Bob left a <strong>comment</strong> on your post.
</p>
</template>
</NotificationListItem>
</template>
Emits
| Value | Description |
|---|---|
update:modelValue | Emitted with true when an unread item is clicked. Use with v-model to keep read state in sync. |
remove | Emitted when the remove button is clicked. Clicking remove does not trigger update:modelValue. |
Emits
| Value | Description |
|---|---|
remove | Emitted when a list item's close button is clicked. Payload: { id: string }. |
markAllAsRead | Emitted when the 'Mark all as read' footer button is clicked. |
clearAll | Emitted when the 'Clear all' footer button is clicked. |
Example
<template>
<NotificationsPopover
:list="notifications"
@remove="onRemove"
@mark-all-as-read="onMarkAllAsRead"
@clear-all="onClearAll"
>
<template #activator>
<ActionButton text="Show notifications" />
</template>
</NotificationsPopover>
</template>
<script setup lang="ts">
const onRemove = ({ id }: { id: string }) => {
// Remove the notification with the given id from your data source
}
const onMarkAllAsRead = () => {
// Sync all-read state to your data source
}
const onClearAll = () => {
// Clear all notifications in your data source
}
</script>