Components
Reference for the bundled shadcn/ui (Base UI) kit and the composite dashboard components.
Vantage ships shadcn/ui as-is. Nothing to install, nothing to copy — just import. There are three public entry points, and the sidebar is sectioned by those three.
| Subpath | What’s in it | Count |
|---|---|---|
@squadbase/vantage/ui |
The shadcn/ui primitives (Base UI build) plus utilities like cn() |
37 |
@squadbase/vantage/components |
Dashboard parts composed from them | 15 |
@squadbase/vantage/markdown |
Markdown rendering alone (kept apart — it’s heavy) | 1 |
import { Button, Card, Badge } from "@squadbase/vantage/ui";
import { PageShell, DashboardCardPreset, EChart } from "@squadbase/vantage/components";
import { MarkdownRenderer } from "@squadbase/vantage/markdown";
It’s the Base UI build
What ships is the Base UI variant of shadcn/ui. In July 2026 shadcn/ui switched its default primitives from Radix UI to Base UI, and Vantage follows the new one. Coming from the Radix build, four differences matter.
-
There is no
asChild. Pass an element to therenderprop instead.// Radix build <PopoverTrigger asChild><Button>Open</Button></PopoverTrigger> // Base UI build (Vantage) <PopoverTrigger render={<Button />}>Open</PopoverTrigger> -
Checkbox’scheckedis strictly a boolean. The mixed state is the separateindeterminateprop. -
ToggleGroup’svalueis an array. For single choice, useSegmentedControl. -
Select’sonValueChangegivesstring | null. You need anullguard. The value-to-labelitemsmap is derived from yourSelectItems automatically, so you rarely write it (only when a separate component returns the options).
State is expressed as data-open / data-checked rather than data-state="open". Vantage’s
theme.css declares custom variants that accept both spellings, so classes like
data-open:animate-in work either way.
@squadbase/vantage/ui
The shadcn/ui primitives. The names and props are shadcn/ui’s own, so their docs apply directly. The sidebar is alphabetical; here they’re grouped by what they’re for.
Forms and input
Button ·
Input ·
InputGroup ·
Textarea ·
Label ·
Select ·
Checkbox ·
Switch ·
Slider ·
Toggle ·
ToggleGroup ·
Calendar ·
Command
Layout and navigation
Card ·
Tabs ·
Separator ·
ScrollArea ·
Sidebar ·
Breadcrumb ·
Accordion ·
Collapsible
Data display
Overlays
Dialog ·
Sheet ·
Popover ·
Tooltip ·
DropdownMenu
States
Alert ·
Skeleton ·
Spinner ·
Loading ·
Empty ·
ErrorState
Loading / Empty / ErrorState are the only three that aren’t shadcn/ui — Vantage adds them.
Utilities
@squadbase/vantage/components
Dashboard parts composed from ui/.
| Component | What it is |
|---|---|
PageShell |
The page frame: header band, summary, content |
AppShell |
The app frame — hand it your nav |
SectionHeader |
A section heading with actions |
DashboardCard |
The dashboard tile, with preset and skeleton |
DataTable |
Sorting, search, pagination, selection |
EChart |
The Apache ECharts wrapper |
FunnelSteps |
A funnel drawn as bars |
Sparkline |
An inline trend chart for cells and tiles |
FilterBar |
A row of filters driven by one value |
DateRangePicker |
Date range with presets |
SegmentedControl |
Single-choice segments |
SearchableSelect |
Single choice with search |
MultiSelect |
Multiple choice with search |
MetricValue |
A KPI’s number and unit |
TrendIndicator |
An arrow and a percentage |
StatusBadge |
A dot-and-label status badge |
Placeholder |
An inline marker for sample data |
@squadbase/vantage/markdown
A subpath holding only MarkdownRenderer. Markdown
rendering carries Shiki with every language grammar; mixed into the components barrel it would add
over 10 MB to every build, so it is deliberately kept apart.
Putting it together
import { Button } from "@squadbase/vantage/ui";
import {
PageShell,
PageShellHeader,
PageShellHeading,
PageShellTitle,
PageShellDescription,
PageShellHeaderEnd,
PageShellActions,
PageShellContent,
DashboardCardPreset,
MetricValue,
TrendIndicator,
EChart,
type EChartsOption,
} from "@squadbase/vantage/components";
const option: EChartsOption = {
xAxis: { type: "category", data: monthly.map((m) => m.month) },
yAxis: { type: "value" },
series: [{ type: "bar", data: monthly.map((m) => m.revenue) }],
};
export default function Overview() {
return (
<PageShell>
<PageShellHeader>
<PageShellHeading>
<PageShellTitle>Sales dashboard</PageShellTitle>
<PageShellDescription>The last six months</PageShellDescription>
</PageShellHeading>
<PageShellHeaderEnd>
<PageShellActions>
<Button variant="outline">Export</Button>
</PageShellActions>
</PageShellHeaderEnd>
</PageShellHeader>
<PageShellContent>
<div className="grid gap-4 md:grid-cols-3">
<DashboardCardPreset title="Revenue">
<MetricValue className="my-0">$12,400</MetricValue>
<TrendIndicator value={12.4} direction="up" />
</DashboardCardPreset>
<DashboardCardPreset title="New customers">
<MetricValue className="my-0">128</MetricValue>
<TrendIndicator value={3.1} direction="down" />
</DashboardCardPreset>
<DashboardCardPreset title="Churn">
<MetricValue className="my-0">2.1%</MetricValue>
</DashboardCardPreset>
</div>
<DashboardCardPreset title="Monthly revenue" className="mt-4">
<EChart option={option} height={320} />
</DashboardCardPreset>
</PageShellContent>
</PageShell>
);
}
Theming
The look is decided by CSS variables (design tokens). To change colours or radii, override just the
variables in a styles.css placed on the same side as your pages (src/styles.css when the project
has a src/) — see UI & theming.
When you want to edit the source
To change a component’s internals, pull an editable copy.
vantage add ui data-table # an editable DataTable into components/
vantage add block sales-overview
How to read these pages
Every component page pairs a live preview with its source, in tabs. The
export const client = "only"; at the top of each source is this documentation site’s own directive
— your app doesn’t need it.