Click UICommon patterns

Common patterns

Real-world examples showing how Click UI components work together to build common UI patterns. These examples are designed to be copy-paste ready for AI tools and developers.

Table with pagination and title

This is the most common pattern: a data table with pagination controls and a page title.

User Management

Name
Email
Role
Name
John Doe
Email
john@example.com
Role
Admin
Name
Jane Smith
Email
jane@example.com
Role
User
Name
Bob Johnson
Email
bob@example.com
Role
User
100 rows
of 10

Complete code example

import { Table, Pagination, Title, Container } from '@clickhouse/click-ui'
import { useState } from 'react'

function UserTable() {
  const [currentPage, setCurrentPage] = useState(1)
  const [pageSize, setPageSize] = useState(10)
  
  const headers = [
    { label: 'Name' },
    { label: 'Email' },
    { label: 'Role' },
  ]
  
  const rows = [
    {
      id: 1,
      items: [
        { label: 'John Doe' },
        { label: 'john@example.com' },
        { label: 'Admin' },
      ],
    },
    {
      id: 2,
      items: [
        { label: 'Jane Smith' },
        { label: 'jane@example.com' },
        { label: 'User' },
      ],
    },
  ]
  
  const totalPages = Math.ceil(100 / pageSize)
  
  return (
    <Container orientation='vertical' gap='md'>
      <Title size='lg' type='h1'>User Management</Title>
      <Table headers={headers} rows={rows} />
      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        onChange={setCurrentPage}
        rowCount={100}
        pageSize={pageSize}
        maxRowsPerPageList={[10, 25, 50, 100]}
        onPageSizeChange={setPageSize}
      />
    </Container>
  )
}

Form in dialog

A common pattern for creating or editing data: a form displayed in a modal dialog.

Complete code example

import { Dialog, Button, TextField, Label, Container } from '@clickhouse/click-ui'
import { useState } from 'react'

function AddUserDialog() {
  const [open, setOpen] = useState(false)
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
  
  return (
    <>
      <Button label='Add User' onClick={() => setOpen(true)} />
      <Dialog open={open} onOpenChange={setOpen}>
        <Dialog.Content title='Add New User' showClose onClose={() => setOpen(false)}>
          <Container orientation='vertical' gap='md'>
            <Label htmlFor='name-input'>Name</Label>
            <TextField
              id='name-input'
              value={name}
              onChange={(value) => setName(value)}
              placeholder='Enter name'
            />
            <Label htmlFor='email-input'>Email</Label>
            <TextField
              id='email-input'
              value={email}
              onChange={(value) => setEmail(value)}
              placeholder='Enter email'
            />
            <Container orientation='horizontal' gap='sm' justifyContent='end'>
              <Button label='Cancel' onClick={() => setOpen(false)} />
              <Button type='primary' label='Save' onClick={() => {
                // Handle save logic
                setOpen(false)
              }} />
            </Container>
          </Container>
        </Dialog.Content>
      </Dialog>
    </>
  )
}

Search with filters

A search interface with filters and results display.

Search Users

Results for "" with filter: all

Complete code example

import { Container, Title, TextField, Button, Text } from '@clickhouse/click-ui'
import { useState } from 'react'

function SearchInterface() {
  const [searchQuery, setSearchQuery] = useState('')
  
  return (
    <Container orientation='vertical' gap='md'>
      <Title size='lg' type='h1'>Search Users</Title>
      <Container orientation='horizontal' gap='sm'>
        <TextField
          id='search-input'
          value={searchQuery}
          onChange={(value) => setSearchQuery(value)}
          placeholder='Search...'
        />
        <Button type='primary' label='Search' />
      </Container>
    </Container>
  )
}

Filter bar with multiple filters

A comprehensive filter bar with multiple filter types for advanced data filtering.

Filtered Results

Showing results for: all | Status: all | Date: all

Complete code example

import { Container, Title, SearchField, Select, DateRangePicker, Button, Text } from '@clickhouse/click-ui'
import { useState } from 'react'

function FilterBar() {
  const [status, setStatus] = useState('all')
  const [dateRange, setDateRange] = useState(null)
  const [searchQuery, setSearchQuery] = useState('')
  
  return (
    <Container orientation='vertical' gap='md'>
      <Title size='lg' type='h1'>Filtered Results</Title>
      <Container orientation='horizontal' gap='sm' wrap='wrap' alignItems='end'>
        <SearchField
          id='search-filter'
          value={searchQuery}
          onChange={(value) => setSearchQuery(value)}
          placeholder='Search...'
        />
        <Select
          id='status-filter'
          label='Status'
          value={status}
          onSelect={setStatus}
          options={[
            { label: 'All', value: 'all' },
            { label: 'Active', value: 'active' },
          ]}
        />
        <DateRangePicker
          id='date-filter'
          label='Date Range'
          value={dateRange}
          onChange={setDateRange}
        />
        <Button type='secondary' label='Clear Filters' />
      </Container>
    </Container>
  )
}

Form with validation

A complete form with validation, error states, and submission handling.

User Registration

Complete code example

import { Container, Title, TextField, NumberField, PasswordField, Button, Alert } from '@clickhouse/click-ui'
import { useState } from 'react'

function FormWithValidation() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    age: '',
    password: '',
  })
  const [errors, setErrors] = useState({})

  const validate = () => {
    const newErrors = {}
    if (!formData.name.trim()) newErrors.name = 'Name is required'
    if (!formData.email.trim()) newErrors.email = 'Email is required'
    // Add more validation...
    setErrors(newErrors)
    return Object.keys(newErrors).length === 0
  }

  const handleSubmit = () => {
    if (validate()) {
      // Handle submission
    }
  }

  return (
    <Container orientation='vertical' gap='md'>
      <Title size='lg' type='h1'>User Registration</Title>
      <TextField
        id='name-field'
        label='Name'
        value={formData.name}
        onChange={(value) => setFormData({ ...formData, name: value })}
        error={!!errors.name}
        errorText={errors.name}
      />
      <Button type='primary' label='Submit' onClick={handleSubmit} />
    </Container>
  )
}

Card grid layout

A responsive grid of cards displaying data in a card-based layout.

Dashboard

1,234

Total Users

98%

Success Rate

$12,345

Revenue

567

Active Sessions

Complete code example

import { Container, Title, GridContainer, CardPrimary } from '@clickhouse/click-ui'

function CardGrid() {
  const stats = [
    { title: '1,234', description: 'Total Users', icon: 'users' },
    { title: '98%', description: 'Success Rate', icon: 'check-in-circle' },
    { title: '$12,345', description: 'Revenue', icon: 'payment' },
    { title: '567', description: 'Active Sessions', icon: 'activity' },
  ]

  return (
    <Container orientation='vertical' gap='lg'>
      <Title size='lg' type='h1'>Dashboard</Title>
      <GridContainer gridTemplateColumns='repeat(auto-fit, minmax(250px, 1fr))' gap='lg'>
        {stats.map((stat, index) => (
          <CardPrimary
            key={index}
            title={stat.title}
            description={stat.description}
            icon={stat.icon}
            alignContent='center'
          />
        ))}
      </GridContainer>
    </Container>
  )
}

Action bar with buttons

A common pattern for action bars with primary and secondary actions.

Items

Click "Add New" to create an item, or select items to see bulk actions.

Complete code example

import { Container, Title, Button, Text, Separator } from '@clickhouse/click-ui'
import { useState } from 'react'

function ActionBar() {
  const [selectedCount, setSelectedCount] = useState(0)
  
  return (
    <Container orientation='horizontal' justifyContent='space-between' alignItems='center'>
      <Title size='lg' type='h1'>Items</Title>
      <Container orientation='horizontal' gap='sm'>
        {selectedCount > 0 && (
          <>
            <Text size='sm' color='muted'>{selectedCount} selected</Text>
            <Separator orientation='vertical' />
            <Button type='secondary' label='Delete Selected' />
          </>
        )}
        <Button type='primary' label='Add New' iconLeft='plus' />
      </Container>
    </Container>
  )
}

Status indicators with badges

Displaying status information with badges and icons.

Service Status

Service A

Operational

Service B

Degraded

Service C

Down

Service D

Healthy

Complete code example

import { Container, Title, Text, Badge } from '@clickhouse/click-ui'

function StatusIndicators() {
  const items = [
    { name: 'Service A', status: 'active', badge: 'Operational' },
    { name: 'Service B', status: 'warning', badge: 'Degraded' },
  ]

  return (
    <Container orientation='vertical' gap='md'>
      <Title size='lg' type='h1'>Service Status</Title>
      {items.map((item, index) => (
        <Container key={index} orientation='horizontal' justifyContent='space-between' alignItems='center'>
          <Text>{item.name}</Text>
          <Badge text={item.badge} state={item.status === 'active' ? 'success' : 'warning'} />
        </Container>
      ))}
    </Container>
  )
}

© 2026 ClickHouse, Inc. HQ in the Bay Area, CA and Amsterdam, NL.