# Dashboard preview

> A layered app dashboard with a floating notification.

A shadcn/ui block from the [@flx](https://ui.flexnative.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/flx/scene-01).

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

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/flx/scene-01.json
```

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

## Dependencies

- npm packages: `motion`
- Registry items: `card`, `badge`, `button`, `avatar`

## Files

### `registry/illustrations/scene/scene-01.tsx`

```tsx
'use client'

import { Activity, Bell, LayoutGrid, Settings, Users } from 'lucide-react'
import { motion, useReducedMotion } from 'motion/react'

import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'

const nav = [
  { icon: LayoutGrid, active: true },
  { icon: Activity, active: false },
  { icon: Users, active: false },
  { icon: Settings, active: false },
]

const stats = [
  { label: 'Revenue', value: '$48.2k', trend: '+12%' },
  { label: 'Users', value: '2,318', trend: '+4%' },
  { label: 'Churn', value: '1.4%', trend: '-2%' },
]

export function Scene01() {
  const reduce = useReducedMotion()

  return (
    <motion.div
      className="relative w-full max-w-xl"
      initial={reduce ? false : { opacity: 0, filter: 'blur(6px)' }}
      animate={{ opacity: 1, filter: 'blur(0px)' }}
      transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
    >
      <Card className="bg-card w-full gap-0 overflow-hidden p-0 shadow-sm">
        <div className="flex items-center gap-2 border-b px-3 py-2">
          <div className="flex shrink-0 gap-1.5">
            <span className="size-2.5 rounded-full bg-red-400/70" />
            <span className="size-2.5 rounded-full bg-amber-400/70" />
            <span className="size-2.5 rounded-full bg-emerald-400/70" />
          </div>
          <div className="bg-muted mx-auto h-4 w-full max-w-36 min-w-0 rounded-md" />
          <Avatar className="size-5 shrink-0">
            <AvatarImage
              src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=64&q=80"
              alt=""
            />
            <AvatarFallback className="text-[9px]">JD</AvatarFallback>
          </Avatar>
        </div>

        <div className="flex">
          <div className="flex w-11 shrink-0 flex-col items-center gap-2.5 border-r py-3 sm:w-12">
            <div className="bg-primary/80 size-5 rounded-lg" />
            {nav.map(({ icon: Icon, active }, i) => (
              <div
                key={i}
                className={`flex size-7 items-center justify-center rounded-lg ${
                  active ? 'bg-muted text-foreground' : 'text-muted-foreground'
                }`}
              >
                <Icon className="size-3.5" />
              </div>
            ))}
          </div>

          <div className="flex min-w-0 flex-1 flex-col gap-2.5 p-3">
            <div className="flex items-center justify-between gap-2">
              <div className="flex min-w-0 flex-col gap-0.5">
                <span className="truncate text-sm font-semibold tracking-tight">
                  Overview
                </span>
                <span className="text-muted-foreground truncate text-[10px]">
                  Last 30 days
                </span>
              </div>
              <Button size="xs" variant="outline" className="shrink-0">
                Export
              </Button>
            </div>

            <div className="grid grid-cols-3 gap-2">
              {stats.map((s) => (
                <div key={s.label} className="min-w-0 rounded-lg border p-2">
                  <span className="text-muted-foreground block truncate text-[9px]">
                    {s.label}
                  </span>
                  <div className="mt-0.5 flex flex-wrap items-baseline justify-between gap-x-1">
                    <span className="text-xs font-semibold tabular-nums sm:text-[13px]">
                      {s.value}
                    </span>
                    <span className="text-[9px] font-medium text-emerald-600 dark:text-emerald-400">
                      {s.trend}
                    </span>
                  </div>
                </div>
              ))}
            </div>

            <div className="rounded-lg border p-2.5">
              <div className="flex items-center justify-between gap-2">
                <div className="bg-foreground/10 h-1.5 w-14 max-w-full rounded-full" />
                <div className="flex shrink-0 gap-1">
                  <span className="bg-primary/70 size-1.5 rounded-full" />
                  <span className="bg-muted-foreground/30 size-1.5 rounded-full" />
                </div>
              </div>
              <svg
                viewBox="0 0 320 44"
                className="mt-1.5 h-10 w-full"
                preserveAspectRatio="none"
                aria-hidden
              >
                <defs>
                  <linearGradient id="scene-01-fill" x1="0" y1="0" x2="0" y2="1">
                    <stop
                      offset="0%"
                      className="text-primary"
                      stopColor="currentColor"
                      stopOpacity="0.24"
                    />
                    <stop
                      offset="100%"
                      className="text-primary"
                      stopColor="currentColor"
                      stopOpacity="0"
                    />
                  </linearGradient>
                </defs>
                <path
                  d="M0 33 C 34 30, 52 14, 84 18 S 150 7, 184 21 S 250 4, 288 12 S 312 10, 320 9 L 320 44 L 0 44 Z"
                  fill="url(#scene-01-fill)"
                />
                <path
                  d="M0 33 C 34 30, 52 14, 84 18 S 150 7, 184 21 S 250 4, 288 12 S 312 10, 320 9"
                  className="text-primary stroke-current"
                  strokeWidth="2"
                  fill="none"
                  strokeLinecap="round"
                />
              </svg>
            </div>
          </div>
        </div>
      </Card>

      <div className="absolute right-1 bottom-1 max-w-[calc(100%-0.5rem)] sm:-right-2 sm:-bottom-3">
        <Card className="flex-row items-center gap-2 p-2 shadow-md sm:gap-2.5 sm:p-2.5">
          <div className="bg-primary/15 text-primary relative flex size-8 shrink-0 items-center justify-center rounded-lg">
            <Bell className="size-4" />
            <span className="border-card absolute -top-0.5 -right-0.5 size-2 rounded-full border-2 bg-emerald-500" />
          </div>
          <div className="flex min-w-0 flex-col">
            <span className="truncate text-xs leading-tight font-medium">
              New signup
            </span>
            <span className="text-muted-foreground truncate text-[10px] leading-tight">
              Acme Inc. joined your plan
            </span>
          </div>
          <Badge variant="secondary" className="ml-1 shrink-0 text-[10px]">
            Live
          </Badge>
        </Card>
      </div>
    </motion.div>
  )
}
```
