Skip to main content

React Components

Core UI components for building MCP applications. Built on shadcn/ui design system with MCP-specific enhancements.

Installation

npm install @leanmcp/ui
Import styles in your app:
import '@leanmcp/ui/styles.css';

Core Components

Button

Button component with multiple variants and loading state.
import { Button } from '@leanmcp/ui';

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

Props

variant
string
default:"primary"
Button style variantOptions: primary | secondary | ghost | destructive | outline
size
string
default:"md"
Button sizeOptions: sm | md | lg | icon
loading
boolean
default:false
Show loading spinner and disable button
asChild
boolean
default:false
Render as child component using Radix Slot
leftIcon
ReactNode
Icon to display on the left side
rightIcon
ReactNode
Icon to display on the right side
disabled
boolean
Disable the button
onClick
function
Click event handler

Examples

// Loading state
<Button loading>Loading...</Button>

// With icons
<Button leftIcon={<SearchIcon />}>Search</Button>

// Variants
<Button variant="destructive">Delete</Button>
<Button variant="ghost">Cancel</Button>

Card

Card container component with header, content, and footer sections.
import { Card, CardHeader, CardContent, CardFooter } from '@leanmcp/ui';

function MyComponent() {
  return (
    <Card variant="elevated">
      <CardHeader title="Settings" description="Manage your preferences" />
      <CardContent>
        {/* Content */}
      </CardContent>
      <CardFooter>
        <Button>Save</Button>
      </CardFooter>
    </Card>
  );
}

Card Props

variant
string
default:"default"
Card style variantOptions: default | outline | elevated
padding
string
default:"md"
Card padding sizeOptions: none | sm | md | lg
interactive
boolean
default:false
Enable hover effects for clickable cards

CardHeader Props

title
ReactNode
Header title text
description
ReactNode
Header description text
action
ReactNode
Right-side action element (e.g., button)

Input

Input component with label, validation, and icon support.
import { Input } from '@leanmcp/ui';

function MyComponent() {
  return (
    <Input
      label="Email"
      type="email"
      placeholder="Enter your email"
      error={errors.email}
      fullWidth
    />
  );
}

Props

label
string
Input label
helperText
string
Helper text displayed below input
error
string
Error message (displays in red)
size
string
default:"md"
Input sizeOptions: sm | md | lg
leftElement
ReactNode
Element to display on the left (e.g., icon)
rightElement
ReactNode
Element to display on the right (e.g., icon)
fullWidth
boolean
default:false
Expand to full width of container

Examples

// With icon
<Input
  leftElement={<SearchIcon />}
  placeholder="Search..."
/>

// With validation
<Input
  label="Username"
  value={username}
  error={username.length < 3 ? 'Too short' : undefined}
/>

Select

Dropdown select component.
import { Select } from '@leanmcp/ui';

function MyComponent() {
  return (
    <Select
      value={value}
      onChange={setValue}
      options={[
        { value: 'opt1', label: 'Option 1' },
        { value: 'opt2', label: 'Option 2' },
      ]}
    />
  );
}

Props

value
string
Currently selected value
options
SelectOption[]
required
Array of options
interface SelectOption {
  value: string;
  label: string;
  disabled?: boolean;
}
placeholder
string
default:"Select..."
Placeholder text when no value selected
disabled
boolean
default:false
Disable the select
onChange
(value: string) => void
Change event handler

Alert

Inline feedback messages with multiple variants.
import { Alert } from '@leanmcp/ui';

function MyComponent() {
  return (
    <Alert variant="success" title="Success">
      Your changes have been saved.
    </Alert>
  );
}

Props

variant
AlertVariant
default:"info"
Alert style variantOptions: info | success | warning | error
title
string
Alert title
children
ReactNode
Alert content/description
onDismiss
() => void
Dismiss handler. Shows close button if provided.

Examples

<Alert variant="error" title="Error" onDismiss={handleDismiss}>
  Failed to save changes. Please try again.
</Alert>

<Alert variant="warning">
  This action cannot be undone.
</Alert>

Layout Components

Dialog/modal component built on Radix UI.
import { Modal, Button } from '@leanmcp/ui';

function MyComponent() {
  const [open, setOpen] = useState(false);
  
  return (
    <Modal
      open={open}
      onOpenChange={setOpen}
      title="Confirm Delete"
      description="This action cannot be undone."
      trigger={<Button>Open Modal</Button>}
    >
      <Button onClick={() => setOpen(false)}>Cancel</Button>
      <Button variant="destructive" onClick={handleDelete}>Delete</Button>
    </Modal>
  );
}

Props

open
boolean
Controlled open state
defaultOpen
boolean
Uncontrolled default open state
onOpenChange
(open: boolean) => void
Open state change handler
title
string
Modal title
description
string
Modal description
trigger
ReactNode
Element that triggers the modal (e.g., button)
children
ReactNode
Modal content

Data Components

DataGrid

Sortable, filterable data table for displaying tool results.
import { DataGrid } from '@leanmcp/ui';
import { useTool } from '@leanmcp/ui';

function MyComponent() {
  const { result } = useTool<{ items: Item[] }>('get-items');
  
  return (
    <DataGrid
      data={result?.items ?? []}
      columns={[
        { key: 'name', header: 'Name', sortable: true },
        { key: 'price', header: 'Price', cell: (v) => `$${v}` },
        { key: 'status', header: 'Status' },
      ]}
      searchable
      onRowClick={(row) => console.log(row)}
    />
  );
}

Props

data
T[]
required
Array of data objects to display
columns
DataGridColumn<T>[]
required
Column definitions
interface DataGridColumn<T> {
  key: keyof T | string;
  header: string;
  cell?: (value: unknown, row: T) => ReactNode;
  sortable?: boolean;
  width?: number | string;
}
searchable
boolean
default:false
Enable global search functionality
searchPlaceholder
string
default:"Search..."
Search input placeholder
onRowClick
(row: T) => void
Row click handler
loading
boolean
default:false
Show loading state
emptyMessage
string
default:"No data"
Message to display when data is empty

Examples

// Custom cell renderer
<DataGrid
  data={users}
  columns={[
    { key: 'name', header: 'Name' },
    { 
      key: 'email', 
      header: 'Email',
      cell: (value) => <a href={`mailto:${value}`}>{value}</a>
    },
    {
      key: 'role',
      header: 'Role',
      sortable: false,
      width: 100
    }
  ]}
/>

Type Reference

SelectOption

interface SelectOption {
  value: string;
  label: string;
  disabled?: boolean;
}

AlertVariant

type AlertVariant = 'info' | 'success' | 'warning' | 'error';

DataGridColumn

interface DataGridColumn<T> {
  key: keyof T | string;
  header: string;
  cell?: (value: unknown, row: T) => ReactNode;
  sortable?: boolean;
  width?: number | string;
}

See Also

Build docs developers (and LLMs) love