Setup Guide
One-time setup for using PILOT // NEXT components. Add these to your project, then copy any component from the theme.
The cn() utility combines clsx and tailwind-merge for conditional class names. Install both packages.
npm install clsx tailwind-mergeCreate lib/utils.ts with the cn() helper. Every component imports this for class name merging.
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]): string {
return twMerge(clsx(inputs))
}Add the PILOT // NEXT design tokens to your globals.css. These define colors, fonts, and animation tokens used by every component in the theme.
@theme {
/* ── Colors ──────────────────────────────────────────────────────────── */
--color-pilot-bg: #0d0f14;
--color-pilot-surface: #12151c;
--color-pilot-elevated: #181c26;
--color-pilot-hover: #1e2230;
--color-pilot-input: #0f1118;
--color-pilot-border: #1f2333;
--color-pilot-border-soft: #191d28;
--color-pilot-accent: #7c3aed;
--color-pilot-accent-dim: #5b21b6;
--color-pilot-text: #e2e4ed;
--color-pilot-secondary: #8891a8;
--color-pilot-muted: #4f5769;
--color-pilot-green: #22c55e;
--color-pilot-red: #ef4444;
--color-pilot-yellow: #eab308;
--color-pilot-cyan: #06b6d4;
/* ── Fonts ───────────────────────────────────────────────────────────── */
--font-display: var(--font-space-grotesk);
--font-mono: var(--font-jetbrains-mono);
/* ── Layout ──────────────────────────────────────────────────────────── */
--sidebar-w: 220px;
--topbar-h: 52px;
/* ── Radius ──────────────────────────────────────────────────────────── */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 10px;
}Each component may need its own CSS classes in your globals.css. Copy the styles for the components you use.
.pilot-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 7px 14px;
border-radius: var(--radius-md);
font-family: var(--font-space-grotesk), system-ui, sans-serif;
font-size: 12px;
font-weight: 600;
cursor: pointer;
border: none;
outline: none;
letter-spacing: 0.01em;
white-space: nowrap;
text-decoration: none;
transition: opacity 0.15s, background 0.15s;
}
.pilot-btn:focus-visible {
outline: 2px solid var(--color-pilot-accent);
outline-offset: 2px;
}
.pilot-btn:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.pilot-btn-primary {
background: var(--accent);
color: #fff;
border: 1px solid transparent;
}
.pilot-btn-primary:hover:not(:disabled) {
background: var(--accent-dim);
}
.pilot-btn-secondary {
background: var(--bg-elevated);
color: var(--text-primary);
border: 1px solid var(--border);
}
.pilot-btn-secondary:hover:not(:disabled) {
background: var(--bg-hover);
border-color: var(--accent);
}
.pilot-btn-ghost {
background: transparent;
color: var(--text-secondary);
border: 1px solid var(--border);
}
.pilot-btn-ghost:hover:not(:disabled) {
background: var(--bg-elevated);
color: var(--text-primary);
}
.pilot-btn-sm {
padding: 4px 10px;
font-size: 11px;
}
.pilot-btn-lg {
padding: 10px 20px;
font-size: 14px;
}
/* ── Settings ────────────────────────────────────────────────────────────── */
.pilot-btn-danger {
background: transparent;
color: var(--color-pilot-red);
border: 1px solid rgba(239, 68, 68, 0.3);
border-radius: var(--radius-md);
padding: 6px 14px;
font-size: 0.75rem;
font-weight: 500;
cursor: pointer;
transition: all 0.15s;
}
.pilot-btn-danger:hover {
background: var(--red-bg);
border-color: var(--color-pilot-red);
}
/* ── Dropdowns ──────────────────────────────────────────────────────────── */
.pilot-btn-danger:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.pilot-btn.pilot-btn-primary:disabled {
opacity: 0.4;
cursor: not-allowed;
}/* ── Dropdowns ──────────────────────────────────────────────────────────── */
.pilot-copy-field {
display: flex;
align-items: center;
gap: 10px;
background: var(--color-pilot-input);
border: 1px solid var(--color-pilot-border);
border-radius: var(--radius-md);
padding: 10px 12px;
}
.pilot-copy-value {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--color-pilot-text);
flex: 1;
word-break: break-all;
min-width: 0;
}
.pilot-copy-btn {
display: flex;
align-items: center;
gap: 5px;
flex-shrink: 0;
font-family: var(--font-display);
font-size: 0.75rem;
font-weight: 500;
color: var(--color-pilot-secondary);
background: transparent;
border: 1px solid var(--color-pilot-border);
border-radius: var(--radius-sm);
padding: 4px 8px;
cursor: pointer;
transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.pilot-copy-btn:hover {
color: var(--color-pilot-text);
background: var(--color-pilot-hover);
}
.pilot-copy-btn--copied {
color: var(--color-pilot-green);
border-color: color-mix(in srgb, var(--color-pilot-green) 30%, transparent);
}/* ── Dropdowns ──────────────────────────────────────────────────────────── */
.pilot-dropdown-wrap {
position: relative;
flex-shrink: 0;
display: inline-block;
}
.pilot-dropdown-overlay {
position: fixed;
inset: 0;
z-index: 99;
}
.pilot-dropdown-wrap--full {
width: 100%;
}
.pilot-daterange-chevron {
transition: transform 0.15s;
color: var(--color-pilot-muted);
}
.pilot-daterange-chevron.open {
transform: rotate(180deg);
}
.pilot-daterange-option {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
padding: 9px 12px;
background: transparent;
border: none;
border-radius: var(--radius-md);
cursor: pointer;
text-align: left;
transition: background 0.1s;
}
.pilot-daterange-option:hover {
background: var(--color-pilot-hover);
}
.pilot-daterange-option.active {
background: color-mix(in srgb, var(--color-pilot-accent) 10%, transparent);
}
.pilot-daterange-option-label {
font-size: 0.8125rem;
font-weight: 500;
color: var(--color-pilot-text);
flex: 1;
}
.pilot-daterange-option.active .pilot-daterange-option-label {
color: var(--color-pilot-accent);
}
.pilot-daterange-option-display {
font-family: var(--font-mono);
font-size: 0.6875rem;
color: var(--color-pilot-muted);
}
.pilot-daterange-option svg {
color: var(--color-pilot-accent);
flex-shrink: 0;
}Button
Dashboard button with primary, secondary, and ghost variants in three sizes. Handles disabled links by rendering an aria-disabled span instead of a Link.
CopyField
Read-only code field with a one-click copy-to-clipboard button. Shows a checkmark and "Copied!" confirmation for 2 seconds after copying. Client component.
DateRangePicker
Dropdown date range selector with preset intervals (7, 14, 30, 90 days). Displays the computed date range in the trigger button and closes on route change. Client component.