frontend/src/components/ui/Rocket/README.md
Rocket is ToolJet's component library built on a 3-layer architecture: shadcn/Radix primitives, Rocket HOCs with CVA + ToolJet design tokens, and composed Blocks/Features.
┌─────────────────────────────────────────────────────┐
│ Blocks / Features (composed UI + state) │
├─────────────────────────────────────────────────────┤
│ Rocket HOCs (CVA + ToolJet tokens) │
│ src/components/ui/Rocket/{Name}/{Name}.jsx │
├─────────────────────────────────────────────────────┤
│ shadcn primitives (Radix, never edited) │
│ src/components/ui/Rocket/shadcn/ │
└─────────────────────────────────────────────────────┘
shadcn/ARCHITECTURE.md.className override using CVA variants + ToolJet token classes + tailwind-merge. This is where all visual styling lives.| Component | Sub-components | Key features |
|---|---|---|
| Button | — | 6 variants, 3 sizes, danger, icon-only, loading |
| Avatar | — | 7 sizes (xs–2xl), image + fallback initials |
| InlineInfo | — | 3 types (info/warning/danger) × 4 variants |
| Input | — | 3 sizes, error/disabled, browser resets |
| Field | FieldLabel, FieldDescription, FieldError, FieldGroup + 5 more | Form field composition |
| InputGroup | InputGroupAddon, InputGroupButton, InputGroupInput + 3 more | Grouped input pattern |
| Select | SelectTrigger, SelectContent, SelectItem + 4 more | Native-feel dropdown |
| Combobox | ComboboxInput, ComboboxContent, ComboboxItem + 8 more | Searchable, filterable |
| Toggle | — | ghost/outline × 4 sizes |
| ToggleGroup | ToggleGroupItem | Segmented control |
| Pagination | PaginationContent, PaginationLink + 4 more | 3 sizes via context |
| Tooltip | TooltipTrigger, TooltipContent, TooltipArrow | Side, align, custom content |
| Label | — | default/description variants |
| DropdownMenu | 10 sub-components | Checkbox/radio items, sub-menus |
| Dialog | DialogContent, DialogHeader, DialogBody, DialogFooter + 6 more | 5 sizes + fullscreen |
| Empty | EmptyHeader, EmptyMedia, EmptyTitle + 3 more | SVG illustrations, page-level states |
| Breadcrumb | BreadcrumbList, BreadcrumbLink, BreadcrumbPage + 3 more | Ellipsis, custom separator |
| Tabs | TabsList, TabsTrigger, TabsContent | 3 variants × 3 sizes |
import { Button, Input, Field, FieldLabel, FieldError } from '@/components/ui/Rocket';
Always import from the barrel (Rocket/index.js), never from individual component directories.
cd frontend && npm run storybook
All 18 components have stories demonstrating variants, sizes, states, and composition patterns.
# This runs the full workflow: Figma spec → shadcn install → HOC + stories
/create-rocket-component Badge
.claude/skills/create-rocket-component/shadcn-reference.mdnpx shadcn@latest add <name>, then convert with the shadcn-to-v3 skill.spec.md from Figma (see any existing component's spec as reference).claude/skills/create-rocket-component/hoc-template.md.claude/skills/create-rocket-component/story-template.mdRocket/index.js| File | Purpose |
|---|---|
tailwind.config.js | All available token classes |
src/_styles/componentdesign.scss | Token source of truth (CSS vars, light + dark) |
src/lib/utils.js | cn() — prefix-aware tailwind-merge |
components.json | shadcn CLI config |
src/components/ui/Rocket/index.js | Barrel — all public exports |
.claude/skills/create-rocket-component/hoc-template.md | CVA shape patterns A–E with examples |
.claude/skills/create-rocket-component/shadcn-reference.md | Which components have shadcn primitives |
Any component's .spec.md | Example design spec format |
tw- prefix. Modifiers (hover:, dark:, focus-visible:) never do.!tw-h-8 not tw-h-8!tw-bg-button-primary). Never use shadcn semantic tokens (tw-bg-primary).tw-border-solid is required alongside border color (preflight is off).Rocket/shadcn/ are CLI-managed. Regenerate, don't edit.small | default | large — not sm | md | lg.tw-font-* plugin utilities, never manual font combos.cn() from @/lib/utils for class merging.import React, { forwardRef } from 'react';
import { cva } from 'class-variance-authority';
import { cn } from '@/lib/utils';
import { Button as ShadcnButton } from '@/components/ui/Rocket/shadcn/button';
const buttonVariants = cva(
['tw-border-0 tw-border-solid ...base classes...'],
{
variants: {
variant: {
primary: ['tw-bg-button-primary tw-text-text-on-solid ...'],
secondary: ['tw-bg-button-secondary ...'],
},
size: {
default: ['tw-h-9 tw-px-4 tw-font-body-default'],
small: ['tw-h-7 tw-px-3 tw-font-body-small'],
large: ['tw-h-11 tw-px-5 tw-font-body-large'],
},
},
defaultVariants: { variant: 'primary', size: 'default' },
}
);
const Button = forwardRef(({ variant, size, className, ...props }, ref) => (
<ShadcnButton
ref={ref}
className={cn(buttonVariants({ variant, size }), className)}
{...props}
/>
));
Button.displayName = 'Button';
export { Button, buttonVariants };
Each component has a .spec.md co-located with its source. These are machine-readable specs extracted from Figma containing:
Spec files serve as the contract between design (Figma) and code.