# Stacked

> A list of dismissible notices, each removed on its own.

A shadcn/ui block from the [@flx](https://ui.flexnative.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/flx/banner-12).

- Page, with a live preview: https://shadcn.exchange/r/flx/banner-12
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/flx/banner-12-light-8cbb7421e04ae211.png
- Registry item: https://ui.flexnative.com/r/banner-12.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://ui.flexnative.com/r/banner-12.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `button`

## Files

### `registry/patterns/banner/banner-12.tsx`

```tsx
'use client'

import { useState } from 'react'
import {
  AlertTriangle,
  CheckCircle2,
  Info,
  X,
  type LucideIcon,
} from 'lucide-react'

import { Button } from '@/components/ui/button'
import { cn } from '@/lib/utils'

type Notice = {
  id: number
  icon: LucideIcon
  title: string
  body: string
  accent: string
}

const initial: Notice[] = [
  {
    id: 1,
    icon: CheckCircle2,
    title: 'Backup complete',
    body: 'Your workspace was backed up 5 minutes ago.',
    accent: 'text-emerald-600 dark:text-emerald-400',
  },
  {
    id: 2,
    icon: AlertTriangle,
    title: 'Seat limit reached',
    body: 'Invite more members by upgrading your plan.',
    accent: 'text-amber-600 dark:text-amber-400',
  },
  {
    id: 3,
    icon: Info,
    title: 'API keys rotated',
    body: 'Two keys were rotated automatically for security.',
    accent: 'text-blue-600 dark:text-blue-400',
  },
]

export function Banner12() {
  const [notices, setNotices] = useState(initial)

  if (notices.length === 0) {
    return (
      <button
        type="button"
        onClick={() => setNotices(initial)}
        className="text-muted-foreground hover:text-foreground text-sm underline-offset-4 hover:underline"
      >
        Restore notifications
      </button>
    )
  }

  return (
    <div className="flex w-full flex-col gap-2">
      {notices.map((notice) => {
        const Icon = notice.icon
        return (
          <div
            key={notice.id}
            className="bg-card relative flex items-start gap-3 rounded-lg border px-4 py-3 pr-11 text-sm shadow-sm"
          >
            <Icon className={cn('mt-0.5 size-5 shrink-0', notice.accent)} />
            <div className="flex flex-col gap-0.5">
              <p className="font-medium">{notice.title}</p>
              <p className="text-muted-foreground">{notice.body}</p>
            </div>
            <Button
              variant="ghost"
              size="icon-sm"
              aria-label={`Dismiss ${notice.title}`}
              onClick={() =>
                setNotices((prev) => prev.filter((n) => n.id !== notice.id))
              }
              className="text-muted-foreground absolute top-2 right-2"
            >
              <X />
            </Button>
          </div>
        )
      })}
    </div>
  )
}
```
