Docs
Components

Data

Components for displaying and managing data

Data Components

Components for displaying and managing tabular data.

Table

Display data in a table with sorting.

Basic Usage

import { Table } from '@/components/ui/Table'

<Table
  columns={[
    { key: 'name', label: 'Name' },
    { key: 'email', label: 'Email' },
  ]}
  data={users}
/>

Props

PropTypeDefaultDescription
columnsColumn[]-Table columns
dataany[]-Table data
loadingbooleanfalseShow loading state
onRowClick(row) => void-Row click handler

Examples

const columns = [
  { key: 'id', label: 'ID' },
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'status', label: 'Status' },
]

const users = [
  { id: 1, name: 'John Doe', email: 'john@example.com', status: 'active' },
  { id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'inactive' },
]

// Basic table
<Table 
  columns={columns}
  data={users}
/>

// With loading state
<Table 
  columns={columns}
  data={users}
  loading={isLoading}
/>

// With row click
<Table 
  columns={columns}
  data={users}
  onRowClick={(user) => router.push(`/users/${user.id}`)}
/>

// Custom cell rendering
const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { 
    key: 'status', 
    label: 'Status',
    render: (value) => (
      <StatusBadge 
        status={value} 
        variant={value === 'active' ? 'success' : 'ghost'}
      />
    )
  },
  {
    key: 'actions',
    label: 'Actions',
    render: (_, row) => (
      <div className="flex gap-2">
        <Button size="sm" onClick={() => handleEdit(row)}>Edit</Button>
        <Button size="sm" variant="error" onClick={() => handleDelete(row)}>Delete</Button>
      </div>
    )
  },
]

Pagination

Navigate through pages of data.

Basic Usage

import { Pagination } from '@/components/ui/Pagination'

<Pagination
  currentPage={page}
  totalPages={totalPages}
  onPageChange={setPage}
/>

Props

PropTypeDefaultDescription
currentPagenumber-Current page number
totalPagesnumber-Total number of pages
onPageChange(page) => void-Page change handler
showFirstLastbooleantrueShow first/last buttons

Examples

const [page, setPage] = useState(1)
const pageSize = 10
const totalItems = 100
const totalPages = Math.ceil(totalItems / pageSize)

// Basic pagination
<Pagination
  currentPage={page}
  totalPages={totalPages}
  onPageChange={setPage}
/>

// Without first/last buttons
<Pagination
  currentPage={page}
  totalPages={totalPages}
  onPageChange={setPage}
  showFirstLast={false}
/>

Display content in a modal dialog.

Basic Usage

import { Modal } from '@/components/ui/Modal'

<Modal 
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
  title="Modal Title"
>
  <p>Modal content</p>
</Modal>

Props

PropTypeDefaultDescription
isOpenboolean-Control modal visibility
onClose() => void-Close handler
titlestring-Modal title
size'sm' | 'md' | 'lg' | 'xl''md'Modal size
showCloseButtonbooleantrueShow close button

Examples

const [isOpen, setIsOpen] = useState(false)

// Basic modal
<Modal 
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
  title="Confirm Action"
>
  <p>Are you sure you want to continue?</p>
  <div className="flex gap-2 mt-4">
    <Button onClick={() => setIsOpen(false)}>Cancel</Button>
    <Button variant="primary" onClick={handleConfirm}>Confirm</Button>
  </div>
</Modal>

// Large modal
<Modal 
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
  title="User Details"
  size="lg"
>
  <div className="space-y-4">
    <Input label="Name" value={user.name} />
    <Input label="Email" value={user.email} />
    <Button>Save Changes</Button>
  </div>
</Modal>

// Form modal
<Modal 
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
  title="Create User"
>
  <form onSubmit={handleSubmit} className="space-y-4">
    <Input 
      label="Name" 
      value={name}
      onChange={(e) => setName(e.target.value)}
      required
    />
    <Input 
      label="Email"
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
      required
    />
    <div className="flex gap-2">
      <Button type="submit">Create</Button>
      <Button type="button" variant="ghost" onClick={() => setIsOpen(false)}>
        Cancel
      </Button>
    </div>
  </form>
</Modal>

Complete Data Table Example

Full example with table, pagination, and modal:

import { useState } from 'react'
import { Table } from '@/components/ui/Table'
import { Pagination } from '@/components/ui/Pagination'
import { Modal } from '@/components/ui/Modal'
import { Button } from '@/components/ui/Button'
import { Input } from '@/components/ui/Input'
import { StatusBadge } from '@/components/ui/StatusBadge'

export function UserTable() {
  const [page, setPage] = useState(1)
  const [isModalOpen, setIsModalOpen] = useState(false)
  const [selectedUser, setSelectedUser] = useState(null)
  const pageSize = 10
  
  const { data: users, isLoading } = useUsers({ page, pageSize })
  const totalPages = Math.ceil(users?.total / pageSize)
  
  const columns = [
    { key: 'id', label: 'ID' },
    { key: 'name', label: 'Name' },
    { key: 'email', label: 'Email' },
    { 
      key: 'status', 
      label: 'Status',
      render: (value) => (
        <StatusBadge 
          status={value} 
          variant={value === 'active' ? 'success' : 'ghost'}
          label={value}
        />
      )
    },
    {
      key: 'actions',
      label: 'Actions',
      render: (_, row) => (
        <div className="flex gap-2">
          <Button 
            size="sm" 
            onClick={() => {
              setSelectedUser(row)
              setIsModalOpen(true)
            }}
          >
            Edit
          </Button>
          <Button 
            size="sm" 
            variant="error" 
            onClick={() => handleDelete(row.id)}
          >
            Delete
          </Button>
        </div>
      )
    },
  ]
  
  return (
    <div className="space-y-4">
      <div className="flex justify-between items-center">
        <h2 className="text-2xl font-bold">Users</h2>
        <Button onClick={() => {
          setSelectedUser(null)
          setIsModalOpen(true)
        }}>
          Add User
        </Button>
      </div>
      
      <Table 
        columns={columns}
        data={users?.items || []}
        loading={isLoading}
      />
      
      <Pagination
        currentPage={page}
        totalPages={totalPages}
        onPageChange={setPage}
      />
      
      <Modal
        isOpen={isModalOpen}
        onClose={() => setIsModalOpen(false)}
        title={selectedUser ? 'Edit User' : 'Create User'}
      >
        <UserForm 
          user={selectedUser}
          onSuccess={() => {
            setIsModalOpen(false)
            refetch()
          }}
        />
      </Modal>
    </div>
  )
}

Next Steps

Data | Tikship