Skip to main content

Button

A versatile button component with multiple variants and sizes.
import { Button } from './components/ui/Button';

function MyComponent() {
  return (
    <Button variant="primary" onClick={handleClick}>
      Click me
    </Button>
  );
}

Props

Extends all standard HTML button attributes.
variant
'primary' | 'secondary' | 'danger' | 'ghost'
default:"'primary'"
Visual style variant of the button
  • primary - Blue background with white text
  • secondary - Surface background with border
  • danger - Red background for destructive actions
  • ghost - Transparent background, shows background on hover
size
'sm' | 'md' | 'lg'
default:"'md'"
Size of the button
  • sm - 32px height, 12px horizontal padding, 12px font
  • md - 40px height, 16px horizontal padding, 14px font
  • lg - 48px height, 32px horizontal padding, 16px font
isLoading
boolean
default:"false"
Shows a loading spinner and disables the button when true
icon
React.ReactNode
Icon element to display before the button text (typically from lucide-react)
children
React.ReactNode
Button content (text or other elements)

Examples

// Primary button
<Button variant="primary" onClick={handleSave}>
  Save Changes
</Button>

// Button with icon
<Button 
  variant="secondary" 
  icon={<Plus size={16} />}
  onClick={handleAdd}
>
  Add Item
</Button>

// Small danger button
<Button 
  variant="danger" 
  size="sm"
  onClick={handleDelete}
>
  Delete
</Button>

// Loading state
<Button isLoading={isSaving}>
  {isSaving ? 'Saving...' : 'Save'}
</Button>

// Ghost button (minimal style)
<Button 
  variant="ghost" 
  icon={<Trash2 size={14} />}
  aria-label="Remove"
/>

Styling

The button uses CSS custom properties for theming:
  • --color-primary - Primary button background
  • --color-primary-hover - Primary button hover state
  • --color-surface - Secondary button background
  • --color-surface-hover - Hover background for ghost/secondary
  • --color-danger - Danger button background
  • --color-border - Secondary button border
  • --radius-md - Border radius

Card

A container component with optional title and action button.
import { Card } from './components/ui/Card';

function MyComponent() {
  return (
    <Card title="Settings">
      {/* Card content */}
    </Card>
  );
}

Props

children
React.ReactNode
required
Content to display inside the card
title
string
Optional title displayed in the card header
action
React.ReactNode
Optional action element (typically a button) displayed in the header
className
string
Additional CSS class names

Examples

// Basic card with title
<Card title="Personal Information">
  <Input label="Name" />
  <Input label="Email" />
</Card>

// Card with action button
<Card 
  title="Experience" 
  action={
    <Button size="sm" onClick={addExperience}>
      Add
    </Button>
  }
>
  {/* Experience entries */}
</Card>

// Card without header
<Card>
  <p>Simple card content</p>
</Card>

Styling

The card uses CSS custom properties:
  • --color-surface - Card background
  • --color-border - Card border and header divider
  • --radius-lg - Border radius
  • --spacing-md - Internal padding

Input

A styled text input component with label and error support.
import { Input } from './components/ui/Input';

function MyComponent() {
  const [value, setValue] = React.useState('');
  
  return (
    <Input
      label="Email"
      type="email"
      value={value}
      onChange={(e) => setValue(e.target.value)}
      placeholder="[email protected]"
    />
  );
}

Props

Extends all standard HTML input attributes.
label
string
Label text displayed above the input
error
string
Error message displayed below the input in red
className
string
Additional CSS class names

Examples

// Basic input with label
<Input 
  label="Full Name" 
  value={name}
  onChange={(e) => setName(e.target.value)}
/>

// Email input
<Input 
  label="Email"
  type="email"
  value={email}
  onChange={(e) => setEmail(e.target.value)}
  placeholder="[email protected]"
/>

// Input with error
<Input 
  label="Password"
  type="password"
  value={password}
  onChange={(e) => setPassword(e.target.value)}
  error={passwordError}
/>

// Disabled input
<Input 
  label="End Date"
  value={endDate}
  disabled={isCurrentPosition}
/>

Styling

Inputs use CSS custom properties:
  • --color-surface - Input background
  • --color-border - Input border (changes to --color-primary on focus)
  • --color-primary - Border color when focused
  • --color-text - Input text color
  • --color-text-muted - Label color
  • --color-danger - Error text color
  • --radius-md - Border radius

TextArea

A multi-line text input component with label and error support.
import { TextArea } from './components/ui/Input';

function MyComponent() {
  const [value, setValue] = React.useState('');
  
  return (
    <TextArea
      label="Description"
      value={value}
      onChange={(e) => setValue(e.target.value)}
      placeholder="Enter description..."
    />
  );
}

Props

Extends all standard HTML textarea attributes.
label
string
Label text displayed above the textarea
error
string
Error message displayed below the textarea in red
className
string
Additional CSS class names

Examples

// Basic textarea
<TextArea 
  label="Description" 
  value={description}
  onChange={(e) => setDescription(e.target.value)}
  placeholder="• Led a team of..."
/>

// Textarea with custom rows
<TextArea 
  label="Summary" 
  value={summary}
  onChange={(e) => setSummary(e.target.value)}
  rows={6}
/>

// Textarea with error
<TextArea 
  label="Bio" 
  value={bio}
  onChange={(e) => setBio(e.target.value)}
  error="Bio must be at least 50 characters"
/>

Styling

TextArea uses the same CSS custom properties as Input, with these differences:
  • Minimum height of 5rem (80px)
  • Vertical resize enabled
  • Inherits font family from parent
  • Uses padding instead of inline padding

CSS Custom Properties Reference

All UI components rely on these CSS variables defined in your theme:
:root {
  /* Colors */
  --color-primary: /* Primary brand color */
  --color-primary-hover: /* Primary hover state */
  --color-surface: /* Card/input backgrounds */
  --color-surface-hover: /* Hover background */
  --color-border: /* Borders */
  --color-text: /* Primary text */
  --color-text-muted: /* Secondary text */
  --color-danger: /* Error/danger actions */
  
  /* Spacing */
  --spacing-sm: /* Small spacing */
  --spacing-md: /* Medium spacing */
  --spacing-lg: /* Large spacing */
  
  /* Radii */
  --radius-md: /* Medium border radius */
  --radius-lg: /* Large border radius */
}

Build docs developers (and LLMs) love