Notification Stack
beui/notification-stackFreeBlock
Compact notification cards that spring from a stacked summary into a readable list on hover, focus or tap.
Install it
npx shadcn@latest add https://beui.dev/r/notification-stack.jsonSource
1"use client";2// beui.dev/components/blocks/notification-stack34import { ArrowUpRight, BellOff } from "lucide-react";5import { motion, useReducedMotion, type Transition } from "motion/react";6import {7 useCallback,8 useRef,9 useState,10 type FocusEvent,11 type KeyboardEvent,12 type ReactNode,13} from "react";14import { ActionSwapText } from "@/components/motion/action-swap";15import { EASE_OUT, SPRING_LAYOUT } from "@/lib/ease";16import { useHoverCapable } from "@/lib/hooks/use-hover-capable";17import { cn } from "@/lib/utils";1819export type NotificationStackItem = {20 id: string;21 title: ReactNode;22 description?: ReactNode;23 trailing?: ReactNode;24};2526export type NotificationStackClassNames = {27 stack?: string;28 card?: string;29 content?: string;30 title?: string;31 description?: string;32 trailing?: string;33 footer?: string;34 count?: string;35};3637export interface NotificationStackProps {38 items: NotificationStackItem[];39 expanded?: boolean;40 defaultExpanded?: boolean;41 onExpandedChange?: (expanded: boolean) => void;42 onViewAll?: () => void;43 maxVisible?: number;44 collapsedLabel?: string;45 expandedLabel?: string;46 emptyLabel?: string;47 className?: string;48 classNames?: NotificationStackClassNames;49}5051const STACK_PEEK = 8;52const STACK_INSET = 12;5354function useControllableExpanded({55 expanded,56 defaultExpanded,57 onExpandedChange,58}: {59 expanded?: boolean;60 defaultExpanded: boolean;61 onExpandedChange?: (expanded: boolean) => void;62}) {63 const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);64 const isControlled = expanded !== undefined;65 const value = expanded ?? internalExpanded;6667 const setValue = useCallback(68 (next: boolean) => {69 if (!isControlled) setInternalExpanded(next);70 onExpandedChange?.(next);71 },72 [isControlled, onExpandedChange],73 );7475 return [value, setValue] as const;76}7778function NotificationCardContent({79 item,80 classNames,81}: {82 item: NotificationStackItem;83 classNames?: NotificationStackClassNames;84}) {85 return (86 <span87 className={cn(88 "flex min-w-0 flex-col gap-1.5 py-4",89 classNames?.content,90 )}91 >92 <span className="flex min-w-0 items-start justify-between gap-3">93 <span94 className={cn(95 "min-w-0 text-sm font-medium leading-snug",96 classNames?.title,97 )}98 >99 {item.title}100 </span>101 {item.trailing ? (102 <span103// … truncated
What it pulls in
npm packages
Files it writes
More from beui
All 104 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| File Upload Attachment Uploadattachment-upload | beui | Blocks | Free | 4 deps · 5 files | |
| Availability Scheduleravailability-scheduler | beui | Blocks | Free | 4 deps · 15 files | |
| Bloom Menubloom-menu | beui | Blocks | Free | 4 deps · 3 files | |
| Command Palettecommand-palette | beui | Blocks | Free | 4 deps · 3 files | |
| Dynamic Islanddynamic-island | beui | Blocks | Free | 3 deps · 3 files | |
| Expandable Action Barexpandable-action-bar | beui | Blocks | Free | 3 deps · 2 files | |
| Expandable Tabsexpandable-tabs | beui | Blocks | Free | 3 deps · 3 files | |
| Feedback Widgetfeedback-widget | beui | Blocks | Free | 4 deps · 9 files |
