- Accordion
- Agent Thinking
- Alert
- Alert Dialog
- Announcement
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Checkbox Card
- Code Block
- Collapsible
- Color Picker
- Combobox
- Command
- Composer
- Composer Loader
- Context Menu
- Data Grid
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- File Upload
- Hover Card
- Input
- Input Group
- Input Otp
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Meter
- Native Select
- Navigation Menu
- Number Field
- Pagination
- Period Switcher
- Popover
- Progress
- Questionnaire
- Radio Card
- Radio Group
- Resizable
- Reveal
- Scroll Area
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Social Button
- Sonner
- Spinner
- Status Dot
- Switch
- Switch Card
- Table
- Tabs
- Tag Group
- Textarea
- Theme Toggle
- Time Field
- Toggle
- Toggle Group
- Tooltip
- Trace
- Tree View
- Agent Creator 01
- Agent Limits Card 01
- Agent Progress 01
- AI Chat 01
- AI Image Generation 01
- AI Profile 01
- Alerts Card 01
- Auth Card 01
- Calendar 01
- Composer 01
- Composer Attachments 01
- Composer Panel 01
- Finance Dashboard 01
- Home Dashboard 01
- Marketing Dashboard 01
- Medical Profile 01
- Meeting Scheduler 01
- Multi Agent Chat 01
- Notification Center 01
- Patient Info Card 01
- Project Board 01
- Questionnaire 01
- Settings Modal 01
- Sidebar 01
- Stat Cards 01
- Task List 01
- Web Search 01
- Activity Rings Card 01
- Area Chart Card 01
- Bar List Card 01
- Combo Chart Card 01
- Contributions Card 01
- Earnings Chart Card 01
- Funnel Chart Card 01
- Heatmap Chart Card 01
- Line Chart Card 01
- Most Active Days Card 01
- Orders Chart Card 01
- Radar Chart Card 01
- Radial Chart Card 01
- Revenue Chart Card 01
- Sankey Chart Card 01
- Scatter Chart Card 01
- Sleep Score Card 01
- Stage Bars Card 01
- Steps Card 01
Marketing
Investment
$24,380
+8.4%Views
1.94M
+12.6%Sign-ups
1,286
+5.2%Cost per visit
$1.24
-3.1%Audience journey
96,400+5.8%
- Reached
- 96,400
- Engaged
- 38,600
- Visited
- 14,100
- Signed up
- 5,200
Channel investment
24,380+8.4%
Sessions
- Search40%
- Social25%
- Partners14%
- Direct8%
- Email7%
Investment · Return 3.3x
$230.0K
+9.4%30K20K10K0
JanFebMarAprMayJunJulAugSepOctNovDec
6.0x4.0x2.0x0.0x
Investment · total
$230.0K
Return · average
3.3x
Visitors
177,100
+8.8%Search
92,000Social
55,200Email
29,900Total Results
80 campaigns
| Delivery | Objective | Actions | ||||
|---|---|---|---|---|---|---|
| Spring discovery 1 | Awareness | Jan 01, 2026 | $320 | |||
| New arrivals 1 | Leads | Feb 06, 2026 | $1,237 | |||
| Community stories 1 | Traffic | Mar 11, 2026 | $2,154 | |||
| Summer interest 1 | Retargeting | Apr 16, 2026 | $3,071 | |||
| Back to routine 1 | Conversions | May 21, 2026 | $0 | |||
| Holiday preview 1 | Awareness | Jun 26, 2026 | $4,905 | |||
| Loyalty thanks 1 | Leads | Jul 04, 2026 | $5,822 | |||
| Weekend flash 1 | Traffic | Aug 09, 2026 | $6,739 | |||
| Maker spotlight 1 | Retargeting | Sep 14, 2026 | $7,656 | |||
| Field notes 1 | Conversions | Oct 19, 2026 | $1,173 |
Page 1 of 8
…
Installation
Set up the @cobalt registry first, as described in Installation, then add the block:
$ pnpm dlx shadcn@latest add @cobalt/marketing-dashboard-01
The dashboard uses local sample data. Pass popupClassName to scope the theme on chart menus rendered outside the dashboard.
Source
"use client";
import {
RiCursorLine,
RiEyeLine,
RiGlobalLine,
RiGroupLine,
RiLayoutLine,
RiMailLine,
RiMoneyDollarCircleLine,
RiSearchLine,
RiShareForwardLine,
RiWindowLine,
RiMegaphoneLine,
RiFileTextLine,
} from "@remixicon/react";
import { cn } from "cn";
import * as React from "react";
import { AreaChartCard } from "@/components/blocks/area-chart-card-01/components/area-chart-card";
import { BarListCard } from "@/components/blocks/bar-list-card-01/components/bar-list-card";
import { ComboChartCard } from "@/components/blocks/combo-chart-card-01/components/combo-chart-card";
import { FunnelChartCard } from "@/components/blocks/funnel-chart-card-01/components/funnel-chart-card";
import { CampaignsTable } from "@/components/blocks/marketing-dashboard-01/components/marketing-dashboard-campaigns-table";
import {
investment,
listTabs,
monthly,
stages,
} from "@/components/blocks/marketing-dashboard-01/components/marketing-dashboard-data";
import { RadialChartCard } from "@/components/blocks/radial-chart-card-01/components/radial-chart-card";
import { StatCards } from "@/components/blocks/stat-cards-01/components/stat-cards";
import type { Stat } from "@/components/blocks/stat-cards-01/components/stat-cards";
import { Checkbox } from "@/components/ui/checkbox";
import {
Collapsible,
CollapsibleContent,
} from "@/components/ui/collapsible";
import { Label } from "@/components/ui/label";
import { Reveal } from "@/components/ui/reveal";
const stats: Stat[] = [
{
icon: RiMoneyDollarCircleLine,
label: "Investment",
value: `$${investment.reduce((sum, channel) => sum + channel.value, 0).toLocaleString("en-US")}`,
delta: "+8.4%",
deltaColor: "lime",
},
{
icon: RiEyeLine,
label: "Views",
value: "1.94M",
delta: "+12.6%",
deltaColor: "lime",
},
{
icon: RiGroupLine,
label: "Sign-ups",
value: "1,286",
delta: "+5.2%",
deltaColor: "lime",
},
{
icon: RiCursorLine,
label: "Cost per visit",
value: "$1.24",
delta: "-3.1%",
deltaColor: "rose",
},
];
const channelIcon = [
RiSearchLine,
RiShareForwardLine,
RiGroupLine,
RiGlobalLine,
RiMailLine,
RiWindowLine,
];
const withIcons = (
items: { label: string; value: number }[],
icons: React.ElementType[]
) =>
items.map((item, index) => {
const Icon = icons[index % icons.length];
return { ...item, icon: <Icon aria-hidden /> };
});
// The chart cards draw in with a left-to-right wipe on their charts and bars.
const charts = "marketing-dashboard-01-draw";
// Inline panels fade in from just above, so a toggle never pops open.
const banner = "marketing-dashboard-01-banner";
/**
* The body of a marketing overview: four KPI cards, a funnel, channel spend,
* a ranked list, two charts and a campaign table. It carries no navigation or
* heading, so it drops into an app shell or any page. A page can open the
* filters panel and the new-campaign dialog from its own header with
* `filtersOpen` and `newCampaignOpen`. Pass `popupClassName` (a theme scope)
* so menus and tooltips rendered outside the block pick up the same tokens.
*/
export function MarketingDashboard({
className,
popupClassName,
filtersOpen = false,
newCampaignOpen,
onNewCampaignOpenChange,
}: {
className?: string;
popupClassName?: string;
filtersOpen?: boolean;
newCampaignOpen?: boolean;
onNewCampaignOpenChange?: (open: boolean) => void;
}) {
const [activeOnly, setActiveOnly] = React.useState(false);
const lists = [
{
id: "channels",
label: "Channels",
items: withIcons(listTabs.channels, channelIcon),
},
{
id: "campaigns",
label: "Campaigns",
items: withIcons(listTabs.campaigns, [RiMegaphoneLine]),
},
{
id: "pages",
label: "Landing pages",
items: withIcons(listTabs.pages, [RiFileTextLine, RiLayoutLine]),
},
];
return (
<div className={cn("@container flex min-w-0 flex-col gap-4", className)}>
<Collapsible open={filtersOpen} className="contents">
<CollapsibleContent>
<div
className={cn(
"flex w-fit items-center gap-2 rounded-[8px] bg-muted px-3 py-2.5",
banner
)}
>
<Label variant="inline">
<Checkbox
checked={activeOnly}
onCheckedChange={(checked) => setActiveOnly(checked)}
/>
Active campaigns only
</Label>
</div>
</CollapsibleContent>
</Collapsible>
<StatCards stats={stats} popupClassName={popupClassName} />
<Reveal delay={160} blur>
<div className={cn(charts, "grid grid-cols-1 gap-4 @5xl:grid-cols-3")}>
<FunnelChartCard
title="Audience journey"
stages={stages}
delta={0.058}
ranges={[
{ label: "Last 30 days", stages, delta: 0.058 },
{
label: "Last 90 days",
stages: stages.map((s) => ({ ...s, value: s.value * 3 })),
delta: 0.081,
},
]}
popupClassName={popupClassName}
/>
<RadialChartCard
title="Channel investment"
data={investment}
variant="stacked"
delta="+8.4%"
ranges={[
{ label: "Last 30 days", data: investment, delta: "+8.4%" },
{
label: "Last 90 days",
data: investment.map((c) => ({ ...c, value: c.value * 3 })),
delta: "+9.1%",
},
]}
popupClassName={popupClassName}
className="max-w-none"
/>
<BarListCard
title="Traffic sources"
metricLabel="Sessions"
tabs={lists}
/>
</div>
</Reveal>
<Reveal delay={200} blur>
<div className={cn(charts, "grid grid-cols-1 gap-4 @4xl:grid-cols-2")}>
<ComboChartCard
title="Investment"
tiles
data={monthly}
bar={{
key: "spend",
label: "Investment",
format: (n) => `$${(n / 1000).toFixed(1)}K`,
}}
line={{
key: "return",
label: "Return",
color: "var(--funnel-chart-2, var(--primary))",
format: (n) => `${n.toFixed(1)}x`,
}}
delta={0.094}
ranges={[
{ id: "year", label: "This year", data: monthly },
{ id: "half", label: "Last 6 months", data: monthly.slice(6) },
]}
popupClassName={popupClassName}
/>
<AreaChartCard
title="Visitors"
tiles
data={monthly}
series={[
{
key: "search",
label: "Search",
color: "var(--funnel-chart-1, var(--chart-1))",
},
{
key: "social",
label: "Social",
color: "var(--funnel-chart-2, var(--chart-4))",
},
{
key: "email",
label: "Email",
color: "var(--funnel-chart-3, var(--chart-5))",
},
]}
delta={0.088}
ranges={[
{ id: "year", label: "This year", data: monthly },
{ id: "half", label: "Last 6 months", data: monthly.slice(6) },
]}
popupClassName={popupClassName}
/>
</div>
</Reveal>
<Reveal delay={240} blur>
<CampaignsTable
popupClassName={popupClassName}
activeOnly={activeOnly}
newOpen={newCampaignOpen}
onNewOpenChange={onNewCampaignOpenChange}
/>
</Reveal>
</div>
);
} On this page