dashboard-ui-components

star 0

Use when building new UI in packages/fern-dashboard/, adding interactive elements, or choosing between raw HTML and existing components. Covers shadcn/ui component catalog, import patterns, variants, and design tokens.

alecharmon By alecharmon schedule Updated 3/4/2026

name: dashboard-ui-components description: Use when building new UI in packages/fern-dashboard/, adding interactive elements, or choosing between raw HTML and existing components. Covers shadcn/ui component catalog, import patterns, variants, and design tokens.

Dashboard UI Components

Overview

The Fern dashboard (packages/fern-dashboard/) uses shadcn/ui (new-york style) with Radix primitives, CVA variants, and Tailwind CSS v4. Always check src/components/ui/ before building custom UI.

Component Catalog

Component File Export Variants
Button button.tsx Button, buttonVariants variant: default destructive destructiveOutline outline secondary ghost link linkUnderlined dark / size: default xs sm lg icon iconSm
Badge Badge.tsx Badge variant: info success warning (required prop)
StatusBadge StatusBadge.tsx StatusBadge status: live unpublished loading uncommitted open closed merged draft preview
Card card.tsx default export No variants — simple wrapper
Dialog dialog.tsx Dialog DialogTrigger DialogContent DialogHeader DialogTitle DialogDescription DialogBody DialogFooter DialogClose DialogOverlay DialogPortal persistent prop on DialogContent hides close button
Input input.tsx Input No variants — uses forwardRef
Select select.tsx Select SelectTrigger SelectValue SelectContent SelectItem SelectGroup SelectLabel SelectSeparator SelectScrollUpButton SelectScrollDownButton SelectTrigger size: default sm / SelectItem description prop / checkOnLeft on SelectContent
Tooltip tooltip.tsx Tooltip TooltipProvider All-in-one wrapper (not separate primitives). Pass content, side, sideOffset
DropdownMenu dropdown-menu.tsx DropdownMenu + sub-parts Standard Radix compound pattern
Tabs tabs.tsx Tabs TabsList TabsTrigger TabsContent Standard compound pattern
Table table.tsx Table TableHeader TableBody TableRow TableHead TableCell Standard compound pattern
Label label.tsx Label
Switch switch.tsx Switch
RadioGroup radio-group.tsx RadioGroup RadioGroupItem
Textarea textarea.tsx Textarea
Skeleton skeleton.tsx Skeleton
Popover popover.tsx Popover PopoverTrigger PopoverContent
Pagination pagination.tsx Pagination parts
Sonner sonner.tsx Toaster Toast notifications
Note Note.tsx Note Callout/admonition component
Kbd kbd.tsx Kbd Keyboard shortcut display
SearchableDropdown SearchableDropdown.tsx SearchableDropdown Generic <T> — searchable select
CopyableText CopyableText.tsx CopyableText Click-to-copy
Steps steps.tsx Steps Step indicator

Import Patterns

// Always import cn from this path
import { cn } from "@/utils/utils";

// Named exports from individual files (no barrel index.ts)
import { Button } from "@/components/ui/button";
import {
    Dialog, DialogBody, DialogClose, DialogContent, DialogDescription,
    DialogFooter, DialogHeader, DialogTitle, DialogTrigger
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";

// Card is the ONLY default export
import Card from "@/components/ui/card";

// Icons from lucide-react
import { Plus, XIcon, ChevronDown } from "lucide-react";

// Type-only React import
import type * as React from "react";

Component Patterns

CVA Variants (Button pattern)

import { cva, type VariantProps } from "class-variance-authority";

const myVariants = cva("base-classes", {
    variants: {
        variant: { default: "...", outline: "..." },
        size: { default: "h-9 px-4", sm: "h-8 px-3" }
    },
    defaultVariants: { variant: "default", size: "default" }
});

// Usage: cn(myVariants({ variant, size, className }))

Compound Components (Dialog, Select, Tabs)

<Dialog>
    <DialogTrigger asChild>
        <Button variant="outline">Open</Button>
    </DialogTrigger>
    <DialogContent>
        <DialogHeader>
            <DialogTitle>Title</DialogTitle>
            <DialogDescription>Description</DialogDescription>
        </DialogHeader>
        <DialogBody>
            {/* content */}
        </DialogBody>
        <DialogFooter>
            <DialogClose asChild><Button variant="outline">Cancel</Button></DialogClose>
            <Button variant="destructive">Delete</Button>
        </DialogFooter>
    </DialogContent>
</Dialog>

Required Directives

  • "use client" on all interactive components (button, dialog, select, tooltip, dropdown-menu, tabs, switch, popover)
  • data-slot="component-name" on Radix-based wrappers

asChild Pattern

Use asChild to render a different element while keeping component behavior:

<DialogTrigger asChild>
    <Button variant="outline">Click me</Button>
</DialogTrigger>

Loading State (Button)

<Button loading>Saving...</Button>
// Renders children invisible + centered Loader2 spinner
// Automatically sets disabled={true}

Design Tokens

Semantic Colors (use these first)

Token Tailwind Class Purpose
--primary bg-primary text-primary Fern green (#008700 light, #70e155 dark)
--destructive bg-destructive text-destructive Error/delete actions
--muted-foreground text-muted-foreground Secondary text
--background bg-background Page background
--foreground text-foreground Primary text
--border border-border Default borders
--card bg-card Card backgrounds
--accent bg-accent Hover/active states
--sidebar bg-sidebar Sidebar background

Color Scale (100-1200)

Available for: gray, green, blue, purple, yellow

bg-gray-100 … bg-gray-1200
text-green-1100  (brand green in light mode)
border-blue-900
  • 100-400: Backgrounds, surfaces
  • 500-700: Borders, separators
  • 800-1000: Icons, secondary elements
  • 1100-1200: Text, primary elements

Dark Mode

Class-based: .dark on parent element. All tokens automatically remap. Never hardcode light/dark-specific hex values — use the semantic tokens or color scale.

Decision Flow

Need UI element?
├── Check src/components/ui/ first
│   ├── Component exists → Use it with correct variant
│   └── Component doesn't exist
│       ├── Can shadcn generate it? → npx shadcn add <component>
│       └── Truly custom → Create in src/components/ui/ following patterns above
└── Styling only? → Use semantic tokens, then color scale, never arbitrary hex

Common Mistakes

Mistake Fix
import Card from "@/components/ui/Card" Card file is lowercase: card.tsx
import { cn } from "@/lib/utils" Correct path: @/utils/utils
Using forwardRef everywhere Only Input uses it; others are plain function components
Separate Tooltip primitives Dashboard Tooltip is an all-in-one wrapper: <Tooltip content="text">
Missing "use client" Required on all interactive components
Hardcoded hex colors Use --primary, --destructive, or gray/green/blue/purple/yellow scale
className={...} without cn() Always merge with cn() for Tailwind class deduplication
Install via CLI
npx skills add https://github.com/alecharmon/fern-platform --skill dashboard-ui-components
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator