Overview

Learn about Plainform's UI system built with Tailwind CSS 4 and shadcn/ui components

Plainform uses a modern UI system combining Tailwind CSS 4 with shadcn/ui-inspired components built on Radix UI primitives. This approach provides a flexible, accessible, and customizable design system.

What's Included

Tailwind CSS 4

Tailwind CSS 4 is the latest version featuring:

  • Native CSS imports with @import 'tailwindcss'
  • CSS-first configuration using @theme directive
  • Improved performance and smaller bundle sizes
  • Enhanced dark mode support with custom variants

UI Components

Plainform includes 25+ pre-built components in components/ui/:

  • Form Elements: Button, Input, Label, InputOTP
  • Layout: Card, Separator, Sheet, ScrollArea
  • Overlays: Dialog, Popover, DropdownMenu
  • Navigation: Tabs, TableOfContents, BackButton
  • Feedback: Skeleton, ProgressBar, Avatar
  • Advanced: Accordion, BentoGrid, Marquee, AnimatedShinyText

All components are built with:

  • Radix UI primitives for accessibility
  • TypeScript for type safety
  • forwardRef for ref forwarding
  • Tailwind CSS for styling

Design System

The design system uses CSS variables for theming:

components/styles/globals.css
:root {
  --color-surface: #fafafa;
  --color-foreground: #171717;
  --color-brand: #4153ff;
  --color-neutral: #e7e6e6;
}

.dark {
  --color-surface: #171717;
  --color-foreground: #fafafa;
  --color-brand: #4153ff;
  --color-neutral: #262626;
}

Component Architecture

Base Pattern

UI components follow standard React patterns with TypeScript:

components/ui/Card.tsx
import * as React from 'react';
import { cn } from '@/lib/utils';

function Card({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      className={cn(
        'bg-neutral/40 text-foreground flex flex-col gap-6 rounded-md border border-neutral py-6 shadow-sm',
        className
      )}
      {...props}
    />
  );
}

function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      className={cn('grid auto-rows-min items-start gap-1.5 px-6', className)}
      {...props}
    />
  );
}

export { Card, CardHeader };

Key Features

  • Composition: Components can be composed together
  • Customization: Override styles via className prop
  • Accessibility: Built-in ARIA attributes and keyboard navigation
  • Type Safety: Full TypeScript support with proper types

Styling Utilities

cn() Helper

The cn() utility merges Tailwind classes intelligently:

lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Usage:

components/Example.tsx
<div className={cn(
  'base-classes',
  variant === 'primary' && 'bg-brand',
  className
)} />

Typography System

Global typography styles are defined in globals.css:

components/styles/globals.css
@layer base {
  h1 {
    @apply text-5xl font-bold leading-normal max-md:text-[36px] font-poppins;
  }
  h2 {
    @apply text-[2.5rem] font-semibold leading-normal max-md:text-[32px] font-poppins;
  }
  p {
    @apply text-base font-normal leading-normal max-md:text-[15px];
  }
}

Responsive Design

All components are mobile-first and responsive:

components/Example.tsx
<div className="w-full md:w-1/2 lg:w-1/3">
  <p className="text-sm md:text-base lg:text-lg">
    Responsive text
  </p>
</div>

Custom breakpoints:

components/Example.tsx
<div className="max-[1000px]:hidden">
  Desktop only content
</div>

Dark Mode

Dark mode is handled automatically using CSS variables:

components/Card.tsx
<div className="bg-card text-card-foreground border-border">
  <h2 className="text-foreground">Title</h2>
  <p className="text-muted-foreground">Description</p>
</div>

The theme provider handles mode switching:

components/providers/ThemeProvider.tsx
import { ThemeProvider } from 'next-themes';

<ThemeProvider attribute="class" defaultTheme="system">
  {children}
</ThemeProvider>

Next Steps

How is this guide ?

Last updated on

On this page