Skip to content

Notification Badge

A small count badge or unread dot for signalling new activity on avatars and channels.

A small count badge or unread dot for signalling new activity on avatars and channels. Compose it from the exported registry parts so local content and behaviour stay in the application while the visual contract stays token-driven.

Root class newt-notif-badge
import { Avatar } from "@/registry/bases/newt/ui/avatar"
import { NotifBadge } from "@/registry/bases/newt/ui/notif-badge"

export default function NotifBadgeDemo() {
  return (
    <div className="flex items-center gap-8">
      <div className="relative inline-block">
        <Avatar>U</Avatar>
        <NotifBadge className="absolute -right-1 -top-1">3</NotifBadge>
      </div>

      <NotifBadge variant="unread" aria-label="Unread" />
    </div>
  )
}
<script setup lang="ts">
import { Avatar } from "~~/registry/bases/newt/ui/avatar"
import { NotifBadge } from "~~/registry/bases/newt/ui/notif-badge"
</script>

<template>
  <div class="flex items-center gap-8">
    <div class="relative inline-block">
      <Avatar>U</Avatar>
      <NotifBadge class="absolute -right-1 -top-1">3</NotifBadge>
    </div>

    <NotifBadge variant="unread" aria-label="Unread" />
  </div>
</template>

Installation

pnpm dlx newtui@latest add notif-badge
npx newtui@latest add notif-badge
yarn dlx newtui@latest add notif-badge
bunx newtui@latest add notif-badge

Install the dependencies

pnpm dlx --yes class-variance-authority
npx --yes class-variance-authority
yarn dlx --yes class-variance-authority
bunx --yes class-variance-authority

Add the components it builds on

Copy the source into your project

import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react"

import { cn } from "@/lib/utils"

const notifBadgeVariants = cva(
  "inline-flex items-center justify-center rounded-full border-2 border-newt-bg-base text-[11px] font-bold leading-none text-white",
  {
    variants: {
      variant: {
        default: "h-4 min-w-4 bg-newt-dnd px-1",
        mention: "h-4 min-w-4 bg-newt-dnd px-1",
        unread: "h-2 w-2 min-w-0 bg-newt-text-primary p-0",
      },
    },
    defaultVariants: {
      variant: "default",
    },
  }
)

export interface NotifBadgeProps
  extends
    React.ComponentProps<"span">,
    VariantProps<typeof notifBadgeVariants> {}

const NotifBadge = React.forwardRef<HTMLSpanElement, NotifBadgeProps>(
  ({ className, variant, ...props }, ref) => (
    <span
      ref={ref}
      className={cn(notifBadgeVariants({ variant }), className)}
      {...props}
    />
  )
)
NotifBadge.displayName = "NotifBadge"

export { NotifBadge, notifBadgeVariants }
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

import { cn } from "@/lib/utils"

import { notifBadgeVariants, type NotifBadgeVariants } from "."

const props = defineProps<{
  class?: HTMLAttributes["class"]
  variant?: NotifBadgeVariants["variant"]
}>()
</script>

<template>
  <span
    :class="cn(notifBadgeVariants({ variant: props.variant }), props.class)"
  >
    <slot />
  </span>
</template>
import { cva, type VariantProps } from "class-variance-authority"

export { default as NotifBadge } from "./NotifBadge.vue"

export const notifBadgeVariants = cva(
  "inline-flex items-center justify-center rounded-full border-2 border-newt-bg-base text-[11px] font-bold leading-none text-white",
  {
    variants: {
      variant: {
        default: "h-4 min-w-4 bg-newt-dnd px-1",
        mention: "h-4 min-w-4 bg-newt-dnd px-1",
        unread: "h-2 w-2 min-w-0 bg-newt-text-primary p-0",
      },
    },
    defaultVariants: {
      variant: "default",
    },
  }
)

export type NotifBadgeVariants = VariantProps<typeof notifBadgeVariants>

Update the import paths

The files import @/lib/utils and sibling components through the aliases in your components.json. Point them at wherever those live in your project.

Usage

import { NotifBadge } from "@/components/ui/notif-badge"

export function Example() {
  return <NotifBadge />
}
<script setup lang="ts">
import { NotifBadge } from "@/components/ui/notif-badge"
</script>

<template>
  <NotifBadge />
</template>

API reference

NotifBadge

PropType
children / default slot?React.ReactNode / Vue slot

Content rendered inside the component.

TypeReact.ReactNode / Vue slot
className / class?string

Additional classes merged with the component defaults.

Typestring

The registry exports NotifBadge. Parts without a table accept the native attributes for the element they render; React uses className, while Vue uses class and fallthrough attributes.

Accessibility

Preserve the native semantics of the rendered elements and pass through ARIA attributes when the surrounding context needs a label or description. Any interactive child needs a visible focus indicator, and meaning must not rely on colour alone.

Tokens

Notification Badge reads its colours, radii and motion from the --newt-* tokens installed with the library. Override a token and every component that reads it follows, including this one — see the token layer. In the plain HTML and CSS distribution the same component is newt-notif-badge.