Overview
aSaaSin’s UI is built on shadcn/ui. We keep thin wrappers in components/ui/*
and compose them into higher-level pieces in components/*
. Some wrappers also sit on top of focused libraries:
- Chart - shadcn/ui’s Chart wrapper (internally uses Recharts).
- Carousel - shadcn/ui’s carousel (internally Embla).
- Data Table - our table primitives + TanStack Table.
- Drawer / Sheet - Vaul.
- Flow Canvas - XYFlow.
- Icons - Lucide.
- Animations - Lottie (where used).
- Color Picker - react-colorful.
Use our wrappers instead of importing these libraries directly - props, styles, and dark mode are unified.
Component Architecture
- Primitives (
components/ui/*
)Button, Dialog, Input, Table, Tabs, Toast, Tooltip, Chart, Carousel, etc. These expose consistent props (variant
,size
,className
) and tie into our theme tokens. - Composite components (
components/*
)Dashboard cards, forms, dialogs, data tables, marketing sections - built by composing primitives with app logic. - ChartsWe use shadcn/ui’s Chart (not bare Recharts). Series are mapped to CSS variables so you don’t hardcode colors.
- CarouselBuilt on Embla for smooth touch/scroll. You configure slides/spacing, we provide sane defaults.
- Data TableBuilt on TanStack Table. Our wrappers handle markup, sorting headers, empty states, you define columns/cells.
Variants
Most primitives accept variant
and size
props (via CVA). Common options you’ll see:
variant
:default
,highlight
,outline
,destructive
,ghost
,link
,icon
size
:sm
,md
,lg
,icon
Use className
for small local tweaks. Colors and dark mode come from tokens - no hardcoded hex.
Composition pattern
Many primitives support asChild
(Radix Slot) so you can keep behavior/styling while rendering a different tag (e.g., render Button
as a Next.js Link
) without losing focus rings or variants.
Client vs server
Some components are client-only (Chart, Carousel, interactive Data Tables, Drawers). Others render on the server. If a component needs the browser, its file starts with use client
. Refer to each component’s page for specifics.