Skip to main content

Button

Versatile button component with multiple variants, sizes, and states. Built with Class Variance Authority for type-safe variant management.

Props

variant
'primary' | 'outline' | 'danger' | 'secondary' | 'warning' | 'ghost'
default:"primary"
Visual style variant of the button
size
'small' | 'medium' | 'default'
default:"default"
Size of the button (height and padding)
icon
string
Iconify icon name to display in the button
iconPosition
'left' | 'right'
Position of the icon relative to button text
iconOnly
boolean
default:"false"
Render button as icon-only with padding adjustments
loading
boolean
default:"false"
Shows loading spinner and hides children
disabled
boolean
default:"false"
Disables button interaction
as
React.ElementType
default:"button"
Render button as a different element (e.g., Link)
permissions
PermissionType | PermissionType[]
Required permissions to render the button

Usage Examples

import { Button } from "@/components";

export function AssetForm() {
  return (
    <Button variant="primary" type="submit">
      Save Asset
    </Button>
  );
}
The Button component uses ComponentGuard internally for permission-based rendering.

Input

Flexible input component supporting text, password, textarea, and custom prefix/suffix elements.

Props

label
string
Label text displayed above the input
type
string | 'textarea'
default:"text"
Input type (text, password, email, date, etc.) or textarea
error
string | boolean
Error message or boolean to show error state
disabled
boolean
Disables input interaction
prefix
React.ReactNode
Content to display before the input field
suffix
React.ReactNode
Content to display after the input field
rows
number
Number of rows for textarea type
innerClassName
string
Custom classes for the inner wrapper
inputClassName
string
Custom classes for the input element itself

Usage Examples

import Input from "@/components/input/Input";
import { useForm } from "react-hook-form";

export function AssetForm() {
  const { register, formState: { errors } } = useForm();
  
  return (
    <Input
      label="Asset Name"
      {...register("name")}
      error={errors.name?.message}
    />
  );
}
Password inputs automatically show/hide toggle icon. The component uses forwardRef for form library compatibility.

Select

Accessible dropdown select component built on Radix UI primitives.

Components

The Select component is composed of multiple sub-components:
  • Select - Root component
  • SelectTrigger - Trigger button with label and error support
  • SelectValue - Displays selected value
  • SelectContent - Dropdown container
  • SelectItem - Individual option
  • SelectGroup - Groups related items
  • SelectLabel - Label for groups

Props

label
string
Label text displayed above the select (on SelectTrigger)
error
string | boolean
Error message or state (on SelectTrigger)
size
'sm' | 'default'
default:"default"
Size variant of the select trigger

Usage Examples

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components";
import { Controller } from "react-hook-form";

export function AssetTypeSelect({ control, errors }) {
  return (
    <Controller
      name="asset_type"
      control={control}
      render={({ field }) => (
        <Select value={field.value} onValueChange={field.onChange}>
          <SelectTrigger label="Asset Type" error={errors.asset_type?.message}>
            <SelectValue placeholder="Select asset type" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="pump">Pump</SelectItem>
            <SelectItem value="motor">Motor</SelectItem>
            <SelectItem value="compressor">Compressor</SelectItem>
            <SelectItem value="turbine">Turbine</SelectItem>
          </SelectContent>
        </Select>
      )}
    />
  );
}
Animated modal dialog with center and side panel positions.

Props

isOpen
boolean
required
Controls modal visibility
setIsOpen
(open: boolean) => void
required
Callback to change modal state
position
'center' | 'side'
default:"center"
Modal position - center overlay or side panel
title
string
Title displayed in modal header (required for side position)
showClose
boolean
Show close button (for center position)
panelClass
string
Custom classes for the modal panel
overflowHidden
boolean
Apply overflow hidden to panel

Usage Examples

import { Modal, Button } from "@/components";
import { useState } from "react";

export function DeleteAssetModal() {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <>
      <Button onClick={() => setIsOpen(true)}>Delete</Button>
      <Modal 
        isOpen={isOpen} 
        setIsOpen={setIsOpen}
        position="center"
        showClose
      >
        <div className="p-6">
          <h2 className="text-xl font-bold mb-4">Confirm Deletion</h2>
          <p className="mb-6">Are you sure you want to delete this asset?</p>
          <div className="flex gap-3">
            <Button variant="outline" onClick={() => setIsOpen(false)}>
              Cancel
            </Button>
            <Button variant="danger" onClick={handleDelete}>
              Delete
            </Button>
          </div>
        </div>
      </Modal>
    </>
  );
}
Modal uses Framer Motion for animations and Radix UI Dialog primitives for accessibility.

Table

Data table component powered by TanStack Table for flexible data display.

Props

columns
ColumnDef[]
required
Column definitions from TanStack Table
data
Record<string, unknown>[]
required
Array of data objects to display
onRowClick
(rowData) => void
Callback when a row is clicked

Usage Example

src/app/(home)/assets/components/AssetTable.tsx
import { Table } from "@/components";
import { createColumnHelper } from "@tanstack/react-table";

const columnHelper = createColumnHelper();

const columns = [
  columnHelper.accessor("name", {
    header: "Asset Name",
    cell: (info) => info.getValue(),
  }),
  columnHelper.accessor("type", {
    header: "Type",
    cell: (info) => info.getValue(),
  }),
  columnHelper.accessor("status", {
    header: "Status",
    cell: (info) => <StatusBadge status={info.getValue()} />,
  }),
];

export function AssetTable({ assets }) {
  const handleRowClick = (rowData) => {
    router.push(`/assets/${rowData.id}`);
  };
  
  return <Table columns={columns} data={assets} onRowClick={handleRowClick} />;
}

StatusBadge

Colored badge component for displaying status information.

Props

status
StatusBadgeStatus
required
Status value: ‘Active’ | ‘Inactive’ | ‘Pending’ | ‘Low’ | ‘Medium’ | ‘High’ | ‘Acknowledged’ | ‘Unacknowledged’
className
string
Additional CSS classes

Usage Example

import { StatusBadge } from "@/components";

export function AlarmRow({ alarm }) {
  return (
    <div className="flex items-center gap-3">
      <span>{alarm.name}</span>
      <StatusBadge status={alarm.severity} />
      <StatusBadge status={alarm.acknowledged ? "Acknowledged" : "Unacknowledged"} />
    </div>
  );
}

ConfirmDialog

Pre-styled confirmation dialog for delete and destructive actions.

Props

isOpen
boolean
required
Dialog visibility state
reject
() => void
required
Callback for cancel action
accept
() => void
required
Callback for confirm action
title
string
required
Dialog title
bodyText
string | React.ReactNode
required
Dialog body content
actionText
string
default:"Delete"
Text for confirm button
icon
IconNames
Icon to display in dialog
isLoading
boolean
Loading state for confirm button

Usage Example

import { ConfirmDialog } from "@/components";
import { useState } from "react";

export function DeleteAssetButton({ assetId }) {
  const [showConfirm, setShowConfirm] = useState(false);
  const [isDeleting, setIsDeleting] = useState(false);
  
  const handleDelete = async () => {
    setIsDeleting(true);
    await deleteAsset(assetId);
    setIsDeleting(false);
    setShowConfirm(false);
  };
  
  return (
    <>
      <Button variant="danger" onClick={() => setShowConfirm(true)}>
        Delete
      </Button>
      <ConfirmDialog
        isOpen={showConfirm}
        reject={() => setShowConfirm(false)}
        accept={handleDelete}
        title="Delete Asset"
        bodyText="Are you sure you want to delete this asset? This action cannot be undone."
        actionText="Delete"
        isLoading={isDeleting}
      />
    </>
  );
}

Tag

Small colored tag component for labels and categories.

Props

value
string
required
Text content of the tag
variant
'error' | 'warning' | 'success' | 'gray'
default:"gray"
Color variant

Usage Example

import { Tag } from "@/components";

export function AssetTags({ asset }) {
  return (
    <div className="flex gap-2">
      <Tag value={asset.type} variant="gray" />
      <Tag value={asset.criticality} variant="warning" />
    </div>
  );
}

Checkbox

Accessible checkbox component using Radix UI primitives.

Usage Example

import { Checkbox } from "@/components";
import { Controller } from "react-hook-form";

export function AcknowledgeCheckbox({ control }) {
  return (
    <Controller
      name="acknowledged_status"
      control={control}
      render={({ field }) => (
        <div className="flex items-center gap-2">
          <Checkbox
            checked={field.value}
            onCheckedChange={field.onChange}
            id="acknowledged"
          />
          <label htmlFor="acknowledged" className="text-sm">
            Mark as Acknowledged
          </label>
        </div>
      )}
    />
  );
}
For additional UI components, see:

Build docs developers (and LLMs) love