# Atrium — Tailwind CRM Dashboard Template

> For sales teams that need one view of the pipeline: a Tailwind CRM dashboard template with drag-and-drop deals, account flows, forecast and reports. 10 pages.

- Price: $39, one-time
- License: Standard
- Version: 2.6.2
- Category: Dashboard
- Editions: React, HTML
- Dark mode: Yes
- Stack: Next.js >=15, React >=19, Tailwind CSS >=4
- Dependencies: `lucide-react`, `recharts`

## What's inside

- 10 pages
- 37 components
- 58 design tokens plus 58 dark overrides

## Pages

| Path | Sections |
| --- | --- |
| `/` | `app-shell`, `page-heading`, `kpi-row`, `bookings-chart`, `stage-breakdown`, `deal-table`, `activity-timeline` |
| `/pipeline` | `app-shell`, `page-heading`, `filter-bar`, `pipeline-board`, `stage-breakdown`, `activity-timeline` |
| `/accounts` | `app-shell`, `page-heading`, `filter-bar`, `accounts-table`, `record-panel`, `coverage-map` |
| `/forecast` | `app-shell`, `page-heading`, `forecast-table`, `bookings-chart`, `funnel-chart`, `deal-table` |
| `/calendar` | `app-shell`, `page-heading`, `calendar-view`, `deal-table` |
| `/activity` | `app-shell`, `page-heading`, `filter-bar`, `activity-timeline` |
| `/reports` | `app-shell`, `page-heading`, `reports-workspace` |
| `/new-deal` | `app-shell`, `page-heading`, `record-form` |
| `/new-account` | `app-shell`, `page-heading`, `record-form` |
| `/components` | `app-shell`, `page-heading`, `filter-bar`, `kpi-row`, `bookings-chart`, `stage-breakdown`, `deal-table`, `activity-timeline`, `pipeline-board`, `accounts-table`, `record-panel`, `forecast-table`, `calendar-view`, `funnel-chart`, `coverage-map`, `reports-workspace`, `record-form` |

## Components

| Name | What it renders |
| --- | --- |
| `app-shell` | The console frame every page composes into: a labelled rail from lg (208px, 240px at 2xl) on its own tone off the ground, carrying a workspace identity plate that states rather than opens, two nav groups whose rows state the count they resolve to, a this-week strip tallied from the log and an account row anchored to the rail's foot; below lg the same body opens from the top bar's menu. Plus a one-row top bar with search, a light/dark toggle and a deliberately secondary global action that stands down on the create routes, and a status bar that carries the demo's reset |
| `page-heading` | In-console page opener: breadcrumb, the page's single h1 (demotable via headingLevel), a one-line lede, and the route's figures read from the console state rather than typed — an optional hero at the top of the display ladder with the page facts demoted beneath it as its supporting line |
| `filter-bar` | The single toolbar above everything it scopes: a segmented scope control on a bordered inset track whose options carry the count each resolves to, an owner select with a real caret, a clear-filters action that appears once a filter is on, and the page's own primary action; scope and owner are live and the surfaces below render what they leave |
| `kpi-row` | Three stat tiles as one framed sheet divided by hairlines: the weighted forecast and target meter derive from console state, while win-rate and cycle-time use authored twelve-week trend examples; every signed delta carries its own arrow and words, each sparkline uses its own [dataMin, dataMax] range with a ringed end dot, and the overview's headline number is not repeated here |
| `bookings-chart` | An authored closed-won history example against target by month as a recharts composed chart: sample columns plus a dashed target rule on one shared axis, token-coloured, legend, custom tooltip, the canonical quarter target stated as a badge and an exact table twin under it |
| `stage-breakdown` | Open pipeline by stage as a horizontal recharts bar chart, one series and no legend, every row on a recess track so an empty stage reads as $0 rather than as a row that failed to render, direct value labels at each tip, drawn from the same stage totals the board columns sum to, with the weighted table twin below it and open by default |
| `deal-table` | The deals whose close date falls in the current month, as a semantic table with stage chips, owner avatars, tabular values, close dates and health, closing on a computed total row |
| `forecast-table` | The quarter split by the rep carrying it: deals, open value, weighted at the stage odds and contract-stage commit, sorted by weighted, with the order stated in the caption rather than claimed by an aria-sort no control can change, closing on a tfoot totals row that is the board regrouped rather than a second fixture |
| `activity-timeline` | Ordered list of calls, stage moves, proposals, records created and system flags, each with an icon, an account link and a machine-readable time; the console writes to it as you work, the panel variant is this week beside the dashboard, the log variant is the /activity surface with the week before under its own hairline head |
| `pipeline-board` | Five-stage kanban board with working drag and drop — pointer via native HTML5 DnD, keyboard via arrow keys on each card's grip, with focus following the card into its new column, a polite live region announcing the move, and every column count and total recomputing from the deals themselves; columns share hairlines rather than gaps, and the empty column names the gesture |
| `accounts-table` | The dense table and the console's read, update and delete: eight data columns of px-3 py-2 cells, a header that sticks to the page, a pinned account column, the console mono on every numeric column, edit opening the row into a form in place, delete confirming in the row it is about to remove, bulk selection, and three distinct row grounds for hover, selection and the open record |
| `record-panel` | The account the table has open, expanded into three columns: facts read from the record, contacts with working create, edit and delete on reserved .example addresses, and next steps derived from that account's own open deals with a designed empty state for an account that has none |
| `record-form` | The console's create surface as a three-step wizard: a headline field at the top of the display ladder, set to its own measure rather than to the panel, that stays on screen through every step and doubles as the panel's header so the page title is never printed twice, per-step validation that names the field, a review step, and an on-save column stating the exact before and after of every total the draft would touch — which then comes true, because saving writes to the same state the board reads; ships deal and account field sets via the variant prop |
| `calendar-view` | The quarter's close dates as a month grid with weekday column heads, a marked today cell, a chip per closing deal linking to the board, month navigation bounded by the quarter, and the same month repeated underneath in date order as the reading a phone and a screen reader get |
| `funnel-chart` | How much of the pipeline has reached each stage or gone past it, as a recharts funnel drawn from the live stage totals — cumulative so the shape falls by construction rather than drawing a bowtie out of honest data, one series and one colour with the stage named inside each band, and a table twin carrying both the reached and the standing figure |
| `coverage-map` | Where the accounts are, as an authored SVG cartogram: eight regions on a lattice arranged west to east and north to south, tokens for fill, no tiles and no network, with the same regions repeated as a table whose rows light their tile — position carries geography, area carries nothing, and the footer says so |
| `reports-workspace` | Period, owner, stage, status and comparison controls over canonical report selectors; Q3 bounded to the canonical quarter; one balanced summary sheet; a Recharts stage comparison with solid-current and dashed-prior shapes plus an exact table twin; zero values left on the neutral track; keyboard-sortable record evidence linked to focusable Pipeline cards; WebKit-safe CSV export; validated, unique, renameable personal views; scoped storage recovery; dismissible receipts with deterministic focus; explicit missing-comparison and filter-empty recovery; and a team baseline bound to Elena's read access |
| `ui/button` | Shared primitive: Button and ButtonLink in primary/secondary/ghost variants and sm/md/lg/icon sizes, plus the buttonClasses helper; pressed is a background step, never a bounce |
| `ui/badge` | Shared primitives: Badge pill (neutral/tint/spot/outline), StatusBadge for deal health (on track, watch, at risk) which always pairs colour with an icon and a word, the statusInk helper for the line that states why, and the Eyebrow label |
| `ui/panel` | Shared primitive: Panel container (with the bleed variant that gives up its corners so a page can run it to the gutters) plus PanelHeader (title, meta, actions, demotable heading) and PanelFooter — the console's only grouping device |
| `ui/avatar` | Shared primitive: the owner mark. The five Marlow seats carry generated portraits keyed by name; every other person keeps initials, because a CRM holds a profile for its own seats and not for someone else's employee. Plus OwnerCell, pairing the mark with the full name for table rows |
| `ui/icons` | Shared primitive: the bespoke MarlowMark brand glyph (currentColor, strokeWidth 1.5) — every other icon in the theme is a named lucide-react import |
| `ui/chart` | Shared primitive: the chart chrome the five Recharts sections share — series variables, axis and grid styling, the token-styled tooltip and the &lt;details&gt; table twin |
| `ui/control` | Shared primitive: the form-control layer — Field with its label, help and one error line, TextField, TextArea, a Select that draws its own lucide caret because the platform will not draw one inside a bordered box, and SegmentedControl on a bordered inset track with per-option counts, controlled or native |
| `ui/console-state` | Shared primitive: the operational spine. Twelve deals, twelve accounts, ten contacts, the activity log, the quarter and Elena's report access declared once, with the reducer that moves, creates, edits and deletes records, selectors for every live pipeline and account total, and a seed snapshot so any section renders standalone outside a provider; authored history and trend examples remain local to their chart sections |
| `ui/mode-toggle` | Shared primitive: the top bar's light/dark switch — Sun and Moon, aria-pressed, flipping the mode class on the nearest theme wrapper or on the document when the theme is the whole app, remembered in localStorage; it forwards a ref and the rest of its props, so `ui/tooltip` can describe it from outside |
| `ui/dashboard-layout` | Shared primitive: slot-based dashboard geometry for sidebar, compact rail and top bar modes with mobile navigation, sticky header, content and footer ownership plus an accessible persisted layout picker; DashboardLayout and the living styleguide share DashboardLayoutGeometry, while Atrium product routes lock the labelled sidebar |
| `ui/dialog` | Shared primitive: the modal layer on tt-ui — DialogSurface (a panel that has left the sheet: same hairline, radius, p-4 body and quiet foot), Dialog with role=dialog, aria-modal, the scrim as a real dismissal target and the library's layer stack behind it, and ConfirmDialog whose safe answer comes first and takes focus, with the consequence stated on the critical band beside its glyph |
| `ui/dropdown-menu` | Shared primitive: the dropdown menu on tt-ui — role=menu at the rail's own metrics, rows declared as data so a check state lands on menuitemradio and never on a plain menuitem, a reserved check box that keeps every label on one x, and a disabled row that says why in words wired through aria-describedby; the list is one tab stop, arrows and Home and End move inside it, Tab out closes it, and the card grows out of the corner the anchor engine actually used |
| `ui/tooltip` | Shared primitive: the tooltip on tt-ui — 80ms of hover intent, immediate on keyboard focus, Escape through the layer stack so a tip over a dialog dismisses only itself; placement is measured, clamped and flipped, and the bubble is aria-describedby on a control that keeps its own accessible name, so it is never the only route to the words |
| `ui/toast` | Shared primitive: the receipt layer on tt-ui — a module-level queue so any section posts one without a provider, capped at three, the role following the tone, Escape reaching the newest card only when nothing is open above it, and the tone said in a word as well as drawn; receipts state what happened in the past tense and never offer an undo the console cannot honour |
| `ui/tabs` | Shared primitive: tabs on tt-ui, drawn on the panel's own hairline with an underline rather than pills, so the filtering vocabulary (SegmentedControl) and the switching vocabulary stay distinct; one tab stop with roving arrow keys, Home and End, selection follows focus, a disabled tab skipped by the arrows exactly as by Tab, and aria-selected stating it outright |
| `ui/skeleton` | Shared primitive: the wait — a held block in the muted plane with no shimmer and no pulse, a run of text lines that ends short the way a paragraph does, and a region that is aria-busy while it waits and speaks one sentence a screen reader hears each time it goes busy rather than a live region repeating itself |
| `ui/date-field` | Shared primitive: the date picker — an ISO text field first, with a keyboard-operable month grid beside it (arrows a day, up and down a week, PageUp and PageDown a month, Home and End the week, Enter picks, Escape closes); today is a ring rather than a fill so selected-and-today reads as both, and the console's own TODAY marks it rather than the wall clock |
| `ui/status` | Shared primitive: the two states a console explains in sentences rather than in shapes — Progress as a real progressbar carrying its three value attributes, and InlineNotice for info, warning, critical and denied, each with its own glyph and its own words so colour is never the only signal, and denied deliberately not painted red |
| `ui/sort-head` | Shared primitive: the sortable column head — the whole th is the part, so aria-sort and the control that changes it can never be wired to different columns; the button is the entire cell rather than six characters of text, the glyph states up, down or the two-headed arrow that means this column can sort and does not, and the sr-only sentence says what pressing it does |
| `ui/pagination` | Shared primitive: the page strip — a live range sentence stating the rows against the total rather than a page number about the control, a real list of destinations with aria-current on the one you are on, ends that disable rather than wrap, and a run that elides past seven targets with the first and last always reachable |
## Design tokens

| Token | Light | Dark override |
| --- | --- | --- |
| `--background` | `#f6f6f7` | `#0b0b0d` |
| `--foreground` | `#18181b` | `#e7e7ea` |
| `--card` | `#ffffff` | `#17171a` |
| `--card-foreground` | `#18181b` | `#e7e7ea` |
| `--primary` | `#6633b5` | `#a887f6` |
| `--primary-hover` | `#561da1` | `#b99eff` |
| `--primary-active` | `#46008b` | `#cab7ff` |
| `--primary-foreground` | `#ffffff` | `#140724` |
| `--secondary` | `#e4e4e7` | `#222226` |
| `--secondary-foreground` | `#27272a` | `#d4d4d8` |
| `--muted` | `#efeff1` | `#111114` |
| `--muted-foreground` | `#52525b` | `#a1a1aa` |
| `--accent` | `#a4610a` | `#c2843a` |
| `--accent-foreground` | `#ffffff` | `#1c1003` |
| `--border` | `#d4d4d8` | `#303036` |
| `--ring` | `#6633b5` | `#a887f6` |
| `--surface-tint` | `#e9e9ed` | `#29292f` |
| `--field` | `#f1f1f3` | `#08080a` |
| `--control-border` | `#b4b4bb` | `#4d4d55` |
| `--control-border-hover` | `#8f8f98` | `#63636d` |
| `--shadow-color` | `#09090b` | `#000000` |
| `--overlay` | `#ffffff` | `#1e1e22` |
| `--scrim` | `#18181bb3` | `#000000cc` |
| `--positive` | `#e2f2e9` | `#12241d` |
| `--positive-foreground` | `#10653f` | `#74cfa2` |
| `--warning` | `#fbeddb` | `#262015` |
| `--warning-foreground` | `#8a5210` | `#dfae6c` |
| `--critical` | `#fbe6e4` | `#2a1715` |
| `--critical-foreground` | `#a32218` | `#f08d84` |
| `--chart-1` | `#6633b5` | `#9273d9` |
| `--radius` | `0.5rem` | `0.5rem` |
| `--font-text` | `var(--font-inter-tight), ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif` | `var(--font-inter-tight), ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif` |
| `--font-sans` | `var(--font-text)` | `var(--font-text)` |
| `--font-mono` | `var(--font-red-hat-mono), ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace` | `var(--font-red-hat-mono), ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace` |
| `--text-d1` | `1.5rem` | `1.5rem` |
| `--leading-d1` | `1.25` | `1.25` |
| `--tracking-d1` | `-0.01em` | `-0.01em` |
| `--text-d2` | `1.6875rem` | `1.6875rem` |
| `--leading-d2` | `1.2` | `1.2` |
| `--tracking-d2` | `-0.01em` | `-0.01em` |
| `--text-d3` | `clamp(1.6875rem, 1.35rem + 1.1vw, 1.8984rem)` | `clamp(1.6875rem, 1.35rem + 1.1vw, 1.8984rem)` |
| `--leading-d3` | `1.15` | `1.15` |
| `--tracking-d3` | `-0.01em` | `-0.01em` |
| `--text-d4` | `clamp(1.6875rem, 1.2rem + 1.6vw, 2.1357rem)` | `clamp(1.6875rem, 1.2rem + 1.6vw, 2.1357rem)` |
| `--leading-d4` | `1.1` | `1.1` |
| `--tracking-d4` | `-0.01em` | `-0.01em` |
| `--text-lead` | `1.125rem` | `1.125rem` |
| `--leading-lead` | `1.6` | `1.6` |
| `--text-body` | `1rem` | `1rem` |
| `--leading-body` | `1.55` | `1.55` |
| `--text-small` | `0.875rem` | `0.875rem` |
| `--leading-small` | `1.45` | `1.45` |
| `--text-dense` | `0.8125rem` | `0.8125rem` |
| `--leading-dense` | `1.538` | `1.538` |
| `--text-caption` | `0.75rem` | `0.75rem` |
| `--leading-caption` | `1.4` | `1.4` |
| `--tracking-label` | `0.07em` | `0.07em` |
| `--display-weight` | `600` | `500` |
## Use it

- Registry: `bunx shadcn add https://tailthemes.com/r/atrium.json`
- MCP: [https://tailthemes.com/api/mcp](https://tailthemes.com/api/mcp)
- Download: [https://tailthemes.com/api/download/atrium](https://tailthemes.com/api/download/atrium)

## Links

- Product page: [https://tailthemes.com/themes/atrium](https://tailthemes.com/themes/atrium)
- Live preview: [https://tailthemes.com/preview/atrium](https://tailthemes.com/preview/atrium)
- Docs: [https://tailthemes.com/docs/atrium](https://tailthemes.com/docs/atrium)
- Manifest JSON: [https://tailthemes.com/api/themes/atrium](https://tailthemes.com/api/themes/atrium)
- Registry item: [https://tailthemes.com/r/atrium.json](https://tailthemes.com/r/atrium.json)
