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)
Iconify icon name to display in the button
Position of the icon relative to button text
Render button as icon-only with padding adjustments
Shows loading spinner and hides children
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.
Flexible input component supporting text, password, textarea, and custom prefix/suffix elements.
Props
Label text displayed above the input
type
string | 'textarea'
default:"text"
Input type (text, password, email, date, etc.) or textarea
Error message or boolean to show error state
Disables input interaction
Content to display before the input field
Content to display after the input field
Number of rows for textarea type
Custom classes for the inner wrapper
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 text displayed above the select (on SelectTrigger)
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>
)}
/>
);
}
Modal
Animated modal dialog with center and side panel positions.
Props
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 displayed in modal header (required for side position)
Show close button (for center position)
Custom classes for the modal panel
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
Column definitions from TanStack Table
data
Record<string, unknown>[]
required
Array of data objects to display
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’
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
Callback for cancel action
Callback for confirm action
bodyText
string | React.ReactNode
required
Dialog body content
Icon to display in dialog
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
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: