UI Components

SaaSForge Core ships ~32 shadcn/ui primitives plus dozens of higher-order components organized by domain. This guide is the map: where each component lives, how to edit it, and how to add new ones.

Where components live

src/components/
├── ui/                  shadcn primitives (32 files: Button, Card, Dialog, Input, ...)
├── marketing/           Hero, CTA, integrations, generic marketing helpers
├── hero2/               Alternate hero layouts
├── features/            Features grid sections
├── pricing/             Pricing tables (multi-variant)
├── testimonials/        Testimonial carousels and grids
├── faq/                 FAQ accordions
├── footer/, header/     Layout chrome
├── dashboard/           KPI cards, charts, activity widgets
├── data-table/          Reusable table with pagination, filters, bulk actions
├── activity-feed/       Per-entity activity timeline
├── attachments/         File upload + listing
├── comments/            Threaded comments component
├── tags/                Tag picker + chips
├── custom-fields/       Generic dynamic field renderer
├── rbac/                Permission gates and role-aware controls
├── presence/            "Who's here" presence indicators
├── command-palette/     Cmd-K palette
├── onboarding/          Multi-step onboarding wizard
├── sidebar/             App sidebar
├── theme/               next-themes provider + toggle
├── docs/, mdx/          In-product docs renderer
└── usage-meter.tsx      Plan-usage meter

The shadcn primitives (src/components/ui/)

FilePurpose
accordion.tsxCollapsible panels (FAQ, settings sections)
alert-dialog.tsxDestructive confirmations
avatar.tsxUser and workspace avatars
badge.tsx, status-badge.tsx, section-badge.tsxInline labels, status, section tags
button.tsxAll button variants and sizes
card.tsxContainer with header/content/footer slots
carousel.tsxEmbla-based slider
chart.tsxRecharts wrapper used by dashboard widgets
checkbox.tsx, select.tsx, input.tsx, label.tsxForm controls
command.tsxCmd-K command list (used by command-palette)
confirm-dialog.tsxGeneric yes/no modal
dialog.tsx, sheet.tsx, popover.tsx, tooltip.tsxOverlays
dropdown.tsx, dropdown-menu.tsxMenus
empty-state.tsx, loading-state.tsx, skeleton.tsxAsync-state placeholders
heading.tsxTypography wrapper
message-bubble.tsxChat / notification bubble
pagination.tsxNumeric pagination control
section.tsxPage section with consistent padding
sonner.tsxToast provider (Sonner)
table.tsxLow-level table primitives
tabs.tsxTabs/tab-list/tab-trigger

All primitives use class-variance-authority for variants and clsx for composition. They are owned source: edit them like any other file.

Editing an existing primitive

Open the file under src/components/ui/ and adjust either:

  1. Tailwind classes in the base template literal: visual-only changes.
  2. cva() definitions: add/remove variants and sizes.

Example: add a new xl size to button.tsx:

const buttonVariants = cva(
  "inline-flex items-center justify-center ...",
  {
    variants: {
      size: {
        default: "h-9 px-4 py-2",
        sm: "h-8 px-3 text-xs",
        lg: "h-10 px-8",
        xl: "h-12 px-10 text-base",  // new
        icon: "size-9",
      },
    },
  },
);

Then <Button size="xl"> is available everywhere with no other change.

Adding a brand-new primitive

The repo uses the standard shadcn CLI workflow. To add, for example, the slider component:

pnpm dlx shadcn@latest add slider

The generator drops the component into src/components/ui/slider.tsx using your existing Tailwind config and CSS variables. No further wiring needed.

components.json at the repo root holds the CLI config (component path, alias, base color). Don't edit it unless you change the project structure.

Higher-order components

Beyond primitives, three sets of components do most of the heavy lifting:

Marketing sections

The landing page is composed from sections under src/components/:

  • hero2/: hero variants
  • features/: feature grids
  • pricing/: multi-tier pricing tables
  • testimonials/: quotes carousel/grid
  • faq/: FAQ accordion
  • cta/, integrations/, process/, readiness/, services/

Every section reads its content from a matching file in src/config/ui/ (e.g., pricing/Pricing2.tsx pulls from src/config/ui/pricing2.ts). See Content & Editing for the full mapping.

Dashboard widgets (src/components/dashboard/)

KPI cards, area/bar charts, recent-activity feeds. They wrap the chart.tsx primitive (Recharts) with sensible defaults and the project's color palette via CSS variables.

Data-table system (src/components/data-table/)

A reusable table built on @tanstack/react-table with:

  • Column sorting, filtering, hide/show
  • Row selection + bulk actions
  • Pagination (server- or client-side)
  • CSV import/export
  • Saved views
  • Soft-delete + restore

The Products module uses this stack end-to-end: copy that pattern when adding a new entity (see Adding Your Own Model).

Composing a new marketing section

If you need a one-off section that isn't in src/components/:

// src/components/cta/SimpleCTA.tsx
import { Section } from "@/components/ui/section";
import { Button } from "@/components/ui/button";

interface SimpleCTAProps {
  title: string;
  body: string;
  buttonLabel: string;
  buttonHref: string;
}

export function SimpleCTA({ title, body, buttonLabel, buttonHref }: SimpleCTAProps) {
  return (
    <Section className="text-center">
      <h2 className="text-3xl font-semibold">{title}</h2>
      <p className="mt-4 text-muted-foreground">{body}</p>
      <Button asChild className="mt-8">
        <a href={buttonHref}>{buttonLabel}</a>
      </Button>
    </Section>
  );
}

Drop it on a page and pass props from a config file in src/config/ui/.

When to edit a component vs. when to edit config

Want to change...Edit
Hero headline, button label, FAQ Q&AConfig file in src/config/ui/
Color of all primary buttonsCSS variable in src/app/globals.css
Layout/order of section contentSection component file
Add a new variant (e.g., button size)cva() block in the primitive
Add a brand-new primitivepnpm dlx shadcn@latest add ...

For brand basics (name, emails, logo paths) see Customization. For full theme work see Theming.