Files
igny8/frontend/src/pages/UIElements.tsx
2026-01-01 21:42:04 +00:00

738 lines
30 KiB
TypeScript

/**
* UI Elements Showcase Page
*
* Single source of truth for all UI components from components/ui/
* This page is non-indexable and serves as documentation/reference
*
* Route: /ui-elements
*/
import React, { useState } from 'react';
import PageMeta from '../components/common/PageMeta';
// ============================================================================
// UI COMPONENTS - All imports from components/ui/ (SINGLE SOURCE OF TRUTH)
// ============================================================================
// Accordion
import { Accordion, AccordionItem } from '../components/ui/accordion/Accordion';
// Alert
import Alert from '../components/ui/alert/Alert';
import AlertModal from '../components/ui/alert/AlertModal';
// Avatar
import Avatar from '../components/ui/avatar/Avatar';
// Badge
import Badge from '../components/ui/badge/Badge';
// Breadcrumb
import { Breadcrumb } from '../components/ui/breadcrumb/Breadcrumb';
// Button
import Button from '../components/ui/button/Button';
import ButtonWithTooltip from '../components/ui/button/ButtonWithTooltip';
import IconButton from '../components/ui/button/IconButton';
// Button Group
import { ButtonGroup, ButtonGroupItem } from '../components/ui/button-group/ButtonGroup';
// Card
import { Card, CardImage, CardTitle, CardContent, CardDescription, CardAction, CardIcon, HorizontalCard } from '../components/ui/card/Card';
// DataView
import { DataView, DataViewHeader, DataViewToolbar, DataViewEmptyState } from '../components/ui/dataview/DataView';
// Dropdown
import { Dropdown } from '../components/ui/dropdown/Dropdown';
import { DropdownItem } from '../components/ui/dropdown/DropdownItem';
// List
import { List, ListItem, ListDot, ListIcon, ListCheckboxItem, ListRadioItem } from '../components/ui/list/List';
// Modal
import { Modal } from '../components/ui/modal';
// Pagination
import { Pagination } from '../components/ui/pagination/Pagination';
import { CompactPagination } from '../components/ui/pagination/CompactPagination';
// Progress
import { ProgressBar } from '../components/ui/progress/ProgressBar';
// Ribbon
import { Ribbon } from '../components/ui/ribbon/Ribbon';
// Spinner
import { Spinner } from '../components/ui/spinner/Spinner';
// Table
import { Table, TableHeader, TableBody, TableRow, TableCell } from '../components/ui/table';
// Tabs
import { Tabs, TabList, Tab, TabPanel } from '../components/ui/tabs/Tabs';
// Toast
import { useToast } from '../components/ui/toast/ToastContainer';
// Tooltip
import { Tooltip } from '../components/ui/tooltip/Tooltip';
import { EnhancedTooltip } from '../components/ui/tooltip/EnhancedTooltip';
// Icons for demos
import {
CheckCircleIcon,
CloseIcon,
PlusIcon,
ArrowRightIcon,
GridIcon,
FileIcon,
BoltIcon,
} from '../icons';
// Component categories for navigation
const CATEGORIES = [
{ id: 'buttons', label: 'Buttons' },
{ id: 'badges', label: 'Badges' },
{ id: 'cards', label: 'Cards' },
{ id: 'alerts', label: 'Alerts' },
{ id: 'modals', label: 'Modals' },
{ id: 'tables', label: 'Tables' },
{ id: 'tabs', label: 'Tabs' },
{ id: 'accordion', label: 'Accordion' },
{ id: 'dropdown', label: 'Dropdown' },
{ id: 'pagination', label: 'Pagination' },
{ id: 'progress', label: 'Progress' },
{ id: 'spinner', label: 'Spinner' },
{ id: 'avatar', label: 'Avatar' },
{ id: 'breadcrumb', label: 'Breadcrumb' },
{ id: 'list', label: 'List' },
{ id: 'tooltip', label: 'Tooltip' },
{ id: 'ribbon', label: 'Ribbon' },
{ id: 'toast', label: 'Toast' },
{ id: 'dataview', label: 'DataView' },
];
// Section wrapper component
function Section({ id, title, children }: { id: string; title: string; children: React.ReactNode }) {
return (
<section id={id} className="mb-12 scroll-mt-24">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4 pb-2 border-b border-gray-200 dark:border-gray-700">
{title}
</h2>
<div className="space-y-6">
{children}
</div>
</section>
);
}
// Demo box component
function DemoBox({ label, children }: { label: string; children: React.ReactNode }) {
return (
<div className="p-4 bg-gray-50 dark:bg-gray-800/50 rounded-lg">
<p className="text-xs font-mono text-gray-500 dark:text-gray-400 mb-3">{label}</p>
<div className="flex flex-wrap items-center gap-3">
{children}
</div>
</div>
);
}
export default function UIElements() {
const toast = useToast();
// Modal states
const [showModal, setShowModal] = useState(false);
const [showAlertModal, setShowAlertModal] = useState(false);
// Dropdown state
const [dropdownOpen, setDropdownOpen] = useState(false);
const dropdownRef = React.useRef<HTMLButtonElement>(null);
// Pagination state
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
// Tabs state
const [activeTab, setActiveTab] = useState('tab1');
// List state
const [checkboxChecked, setCheckboxChecked] = useState(false);
const [radioValue, setRadioValue] = useState('option1');
// Button group state
const [activeButton, setActiveButton] = useState(0);
return (
<>
<PageMeta
title="UI Elements | IGNY8 Design System"
description="Component library reference - Single source of truth for all UI components"
noIndex={true}
/>
<div className="flex gap-8">
{/* Sticky Navigation */}
<nav className="hidden lg:block w-48 shrink-0">
<div className="sticky top-24 space-y-1">
<h3 className="font-semibold text-gray-900 dark:text-white mb-3">Components</h3>
{CATEGORIES.map(cat => (
<a
key={cat.id}
href={`#${cat.id}`}
className="block py-1.5 px-3 text-sm text-gray-600 dark:text-gray-400 hover:text-brand-600 dark:hover:text-brand-400 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-md transition-colors"
>
{cat.label}
</a>
))}
</div>
</nav>
{/* Main Content */}
<div className="flex-1 min-w-0">
<div className="mb-8">
<h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
UI Elements Library
</h1>
<p className="text-gray-600 dark:text-gray-400">
Single source of truth for all UI components. All components are imported from <code className="text-sm bg-gray-100 dark:bg-gray-800 px-1 rounded">components/ui/</code>
</p>
</div>
{/* ================================================================ */}
{/* BUTTONS */}
{/* ================================================================ */}
<Section id="buttons" title="Button">
<DemoBox label="variants: primary | secondary | outline | ghost | gradient">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="gradient">Gradient</Button>
</DemoBox>
<DemoBox label="tones: brand | success | warning | danger | neutral">
<Button tone="brand">Brand</Button>
<Button tone="success">Success</Button>
<Button tone="warning">Warning</Button>
<Button tone="danger">Danger</Button>
<Button tone="neutral">Neutral</Button>
</DemoBox>
<DemoBox label="sizes: xs | sm | md | lg | xl | 2xl">
<Button size="xs">XS</Button>
<Button size="sm">SM</Button>
<Button size="md">MD</Button>
<Button size="lg">LG</Button>
<Button size="xl">XL</Button>
</DemoBox>
<DemoBox label="shapes: rounded | pill">
<Button shape="rounded">Rounded</Button>
<Button shape="pill">Pill</Button>
</DemoBox>
<DemoBox label="with icons: startIcon | endIcon">
<Button startIcon={<PlusIcon className="w-4 h-4" />}>Add Item</Button>
<Button endIcon={<ArrowRightIcon className="w-4 h-4" />}>Continue</Button>
</DemoBox>
<DemoBox label="states: disabled | fullWidth">
<Button disabled>Disabled</Button>
</DemoBox>
<DemoBox label="ButtonWithTooltip (shows tooltip when disabled)">
<ButtonWithTooltip disabled tooltip="This action is not available">
Disabled with Tooltip
</ButtonWithTooltip>
</DemoBox>
<DemoBox label="ButtonGroup">
<ButtonGroup>
<ButtonGroupItem isActive={activeButton === 0} onClick={() => setActiveButton(0)}>Day</ButtonGroupItem>
<ButtonGroupItem isActive={activeButton === 1} onClick={() => setActiveButton(1)}>Week</ButtonGroupItem>
<ButtonGroupItem isActive={activeButton === 2} onClick={() => setActiveButton(2)}>Month</ButtonGroupItem>
</ButtonGroup>
</DemoBox>
<DemoBox label="IconButton - variants: solid | outline | ghost">
<IconButton icon={<PlusIcon />} variant="solid" tone="brand" title="Add" />
<IconButton icon={<PlusIcon />} variant="outline" tone="brand" title="Add" />
<IconButton icon={<PlusIcon />} variant="ghost" tone="brand" title="Add" />
</DemoBox>
<DemoBox label="IconButton - sizes: xs | sm | md | lg">
<IconButton icon={<CloseIcon />} size="xs" title="Close" />
<IconButton icon={<CloseIcon />} size="sm" title="Close" />
<IconButton icon={<CloseIcon />} size="md" title="Close" />
<IconButton icon={<CloseIcon />} size="lg" title="Close" />
</DemoBox>
<DemoBox label="IconButton - shapes: rounded | circle">
<IconButton icon={<CheckCircleIcon />} shape="rounded" variant="solid" tone="success" title="Approve" />
<IconButton icon={<CheckCircleIcon />} shape="circle" variant="solid" tone="success" title="Approve" />
</DemoBox>
<DemoBox label="IconButton - tones">
<IconButton icon={<BoltIcon />} variant="ghost" tone="brand" title="Brand" />
<IconButton icon={<BoltIcon />} variant="ghost" tone="success" title="Success" />
<IconButton icon={<BoltIcon />} variant="ghost" tone="warning" title="Warning" />
<IconButton icon={<BoltIcon />} variant="ghost" tone="danger" title="Danger" />
<IconButton icon={<BoltIcon />} variant="ghost" tone="neutral" title="Neutral" />
</DemoBox>
</Section>
{/* ================================================================ */}
{/* BADGES */}
{/* ================================================================ */}
<Section id="badges" title="Badge">
<DemoBox label="variants: solid | soft | outline | light">
<Badge variant="solid" tone="brand">Solid</Badge>
<Badge variant="soft" tone="brand">Soft</Badge>
<Badge variant="outline" tone="brand">Outline</Badge>
<Badge variant="light" tone="brand">Light</Badge>
</DemoBox>
<DemoBox label="tones: brand | success | warning | danger | info | neutral">
<Badge tone="brand">Brand</Badge>
<Badge tone="success">Success</Badge>
<Badge tone="warning">Warning</Badge>
<Badge tone="danger">Danger</Badge>
<Badge tone="info">Info</Badge>
<Badge tone="neutral">Neutral</Badge>
</DemoBox>
<DemoBox label="sizes: xs | sm | md">
<Badge size="xs">XS</Badge>
<Badge size="sm">SM</Badge>
<Badge size="md">MD</Badge>
</DemoBox>
<DemoBox label="with icons: startIcon | endIcon">
<Badge startIcon={<CheckCircleIcon className="w-3 h-3" />} tone="success">Completed</Badge>
<Badge endIcon={<CloseIcon className="w-3 h-3" />} tone="danger">Remove</Badge>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* CARDS */}
{/* ================================================================ */}
<Section id="cards" title="Card">
<DemoBox label="variants: surface | panel | frosted | borderless | gradient">
<Card variant="surface" className="w-48">
<CardContent>Surface Card</CardContent>
</Card>
<Card variant="panel" className="w-48">
<CardContent>Panel Card</CardContent>
</Card>
</DemoBox>
<DemoBox label="padding: none | sm | md | lg">
<Card padding="sm" className="w-48">
<CardContent>Small Padding</CardContent>
</Card>
<Card padding="lg" className="w-48">
<CardContent>Large Padding</CardContent>
</Card>
</DemoBox>
<DemoBox label="Card with components">
<Card className="w-64">
<CardIcon><FileIcon className="w-8 h-8 text-brand-500" /></CardIcon>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description text goes here</CardDescription>
<CardAction>View More</CardAction>
</Card>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* ALERTS */}
{/* ================================================================ */}
<Section id="alerts" title="Alert">
<DemoBox label="variants: success | error | warning | info">
<div className="space-y-3 w-full">
<Alert variant="success" title="Success" message="Operation completed successfully!" />
<Alert variant="error" title="Error" message="Something went wrong. Please try again." />
<Alert variant="warning" title="Warning" message="Please review before continuing." />
<Alert variant="info" title="Info" message="Here's some useful information." />
</div>
</DemoBox>
<DemoBox label="AlertModal">
<Button onClick={() => setShowAlertModal(true)}>Open Alert Modal</Button>
<AlertModal
isOpen={showAlertModal}
onClose={() => setShowAlertModal(false)}
variant="warning"
title="Confirm Action"
message="Are you sure you want to proceed?"
isConfirmation={true}
onConfirm={() => setShowAlertModal(false)}
/>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* MODALS */}
{/* ================================================================ */}
<Section id="modals" title="Modal">
<DemoBox label="Basic Modal">
<Button onClick={() => setShowModal(true)}>Open Modal</Button>
<Modal isOpen={showModal} onClose={() => setShowModal(false)}>
<div className="p-6">
<h3 className="text-lg font-semibold mb-4">Modal Title</h3>
<p className="text-gray-600 dark:text-gray-400 mb-4">
This is modal content. You can put any React components here.
</p>
<div className="flex justify-end gap-3">
<Button variant="outline" onClick={() => setShowModal(false)}>Cancel</Button>
<Button onClick={() => setShowModal(false)}>Confirm</Button>
</div>
</div>
</Modal>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* TABLES */}
{/* ================================================================ */}
<Section id="tables" title="Table">
<DemoBox label="Table components">
<Table className="w-full">
<TableHeader>
<TableRow>
<TableCell isHeader>Name</TableCell>
<TableCell isHeader>Status</TableCell>
<TableCell isHeader>Date</TableCell>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Item One</TableCell>
<TableCell><Badge tone="success">Active</Badge></TableCell>
<TableCell>Jan 1, 2024</TableCell>
</TableRow>
<TableRow>
<TableCell>Item Two</TableCell>
<TableCell><Badge tone="warning">Pending</Badge></TableCell>
<TableCell>Jan 2, 2024</TableCell>
</TableRow>
</TableBody>
</Table>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* TABS */}
{/* ================================================================ */}
<Section id="tabs" title="Tabs">
<DemoBox label="Tabs component">
<div className="w-full">
<Tabs defaultTab="tab1" onChange={setActiveTab}>
<TabList>
<Tab tabId="tab1">Tab One</Tab>
<Tab tabId="tab2">Tab Two</Tab>
<Tab tabId="tab3">Tab Three</Tab>
</TabList>
<TabPanel tabId="tab1">
<div className="py-4">Content for Tab One</div>
</TabPanel>
<TabPanel tabId="tab2">
<div className="py-4">Content for Tab Two</div>
</TabPanel>
<TabPanel tabId="tab3">
<div className="py-4">Content for Tab Three</div>
</TabPanel>
</Tabs>
</div>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* ACCORDION */}
{/* ================================================================ */}
<Section id="accordion" title="Accordion">
<DemoBox label="Accordion component">
<div className="w-full">
<Accordion>
<AccordionItem title="Section One" defaultOpen>
Content for section one goes here.
</AccordionItem>
<AccordionItem title="Section Two">
Content for section two goes here.
</AccordionItem>
<AccordionItem title="Section Three">
Content for section three goes here.
</AccordionItem>
</Accordion>
</div>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* DROPDOWN */}
{/* ================================================================ */}
<Section id="dropdown" title="Dropdown">
<DemoBox label="Dropdown component">
<div className="relative">
<Button ref={dropdownRef} onClick={() => setDropdownOpen(!dropdownOpen)}>
Open Dropdown
</Button>
<Dropdown
isOpen={dropdownOpen}
onClose={() => setDropdownOpen(false)}
anchorRef={dropdownRef}
>
<DropdownItem onClick={() => setDropdownOpen(false)}>Option One</DropdownItem>
<DropdownItem onClick={() => setDropdownOpen(false)}>Option Two</DropdownItem>
<DropdownItem onClick={() => setDropdownOpen(false)}>Option Three</DropdownItem>
</Dropdown>
</div>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* PAGINATION */}
{/* ================================================================ */}
<Section id="pagination" title="Pagination">
<DemoBox label="Pagination variants">
<Pagination
currentPage={currentPage}
totalPages={10}
onPageChange={setCurrentPage}
variant="text"
/>
</DemoBox>
<DemoBox label="CompactPagination (with page size)">
<CompactPagination
currentPage={currentPage}
totalPages={10}
pageSize={pageSize}
onPageChange={setCurrentPage}
onPageSizeChange={setPageSize}
/>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* PROGRESS */}
{/* ================================================================ */}
<Section id="progress" title="Progress">
<DemoBox label="ProgressBar colors">
<div className="space-y-3 w-full">
<ProgressBar value={75} color="primary" showLabel />
<ProgressBar value={60} color="success" showLabel />
<ProgressBar value={45} color="warning" showLabel />
<ProgressBar value={30} color="error" showLabel />
</div>
</DemoBox>
<DemoBox label="ProgressBar sizes: sm | md | lg">
<div className="space-y-3 w-full">
<ProgressBar value={50} size="sm" />
<ProgressBar value={50} size="md" />
<ProgressBar value={50} size="lg" />
</div>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* SPINNER */}
{/* ================================================================ */}
<Section id="spinner" title="Spinner">
<DemoBox label="sizes: sm | md | lg">
<Spinner size="sm" />
<Spinner size="md" />
<Spinner size="lg" />
</DemoBox>
<DemoBox label="colors: primary | success | error | warning | info">
<Spinner color="primary" />
<Spinner color="success" />
<Spinner color="error" />
<Spinner color="warning" />
<Spinner color="info" />
</DemoBox>
</Section>
{/* ================================================================ */}
{/* AVATAR */}
{/* ================================================================ */}
<Section id="avatar" title="Avatar">
<DemoBox label="sizes: xsmall | small | medium | large | xlarge | xxlarge">
<Avatar src="/images/user/user-01.jpg" size="xsmall" />
<Avatar src="/images/user/user-01.jpg" size="small" />
<Avatar src="/images/user/user-01.jpg" size="medium" />
<Avatar src="/images/user/user-01.jpg" size="large" />
<Avatar src="/images/user/user-01.jpg" size="xlarge" />
</DemoBox>
<DemoBox label="status: online | offline | busy | none">
<Avatar src="/images/user/user-01.jpg" status="online" />
<Avatar src="/images/user/user-01.jpg" status="offline" />
<Avatar src="/images/user/user-01.jpg" status="busy" />
<Avatar src="/images/user/user-01.jpg" status="none" />
</DemoBox>
</Section>
{/* ================================================================ */}
{/* BREADCRUMB */}
{/* ================================================================ */}
<Section id="breadcrumb" title="Breadcrumb">
<DemoBox label="Breadcrumb component">
<Breadcrumb items={[
{ label: 'Home', path: '/', icon: <GridIcon className="w-4 h-4" /> },
{ label: 'Category', path: '/category' },
{ label: 'Current Page' },
]} />
</DemoBox>
</Section>
{/* ================================================================ */}
{/* LIST */}
{/* ================================================================ */}
<Section id="list" title="List">
<DemoBox label="List variants">
<List variant="unordered">
<ListItem><ListDot />Item One</ListItem>
<ListItem><ListDot />Item Two</ListItem>
<ListItem><ListDot />Item Three</ListItem>
</List>
</DemoBox>
<DemoBox label="ListCheckboxItem">
<List variant="checkbox">
<ListCheckboxItem
id="check1"
label="Checkbox Option"
checked={checkboxChecked}
onChange={setCheckboxChecked}
/>
</List>
</DemoBox>
<DemoBox label="ListRadioItem">
<List variant="radio">
<ListRadioItem
id="radio1"
name="radioGroup"
value="option1"
label="Option One"
checked={radioValue === 'option1'}
onChange={setRadioValue}
/>
<ListRadioItem
id="radio2"
name="radioGroup"
value="option2"
label="Option Two"
checked={radioValue === 'option2'}
onChange={setRadioValue}
/>
</List>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* TOOLTIP */}
{/* ================================================================ */}
<Section id="tooltip" title="Tooltip">
<DemoBox label="placements: top | bottom | left | right">
<Tooltip text="Top tooltip" placement="top">
<Button variant="outline" size="sm">Top</Button>
</Tooltip>
<Tooltip text="Bottom tooltip" placement="bottom">
<Button variant="outline" size="sm">Bottom</Button>
</Tooltip>
<Tooltip text="Left tooltip" placement="left">
<Button variant="outline" size="sm">Left</Button>
</Tooltip>
<Tooltip text="Right tooltip" placement="right">
<Button variant="outline" size="sm">Right</Button>
</Tooltip>
</DemoBox>
<DemoBox label="EnhancedTooltip (supports ReactNode content)">
<EnhancedTooltip
content={
<div>
<strong>Rich Content</strong>
<p className="text-xs">With multiple lines</p>
</div>
}
>
<Button variant="outline" size="sm">Hover Me</Button>
</EnhancedTooltip>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* RIBBON */}
{/* ================================================================ */}
<Section id="ribbon" title="Ribbon">
<DemoBox label="Ribbon variants">
<Ribbon text="New" variant="rounded" color="primary">
<Card className="w-48 h-24">
<CardContent>Card with ribbon</CardContent>
</Card>
</Ribbon>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* TOAST */}
{/* ================================================================ */}
<Section id="toast" title="Toast">
<DemoBox label="Toast notifications (via useToast hook)">
<Button onClick={() => toast.success('Success', 'Operation completed!')}>
Show Success
</Button>
<Button onClick={() => toast.error('Error', 'Something went wrong!')} tone="danger">
Show Error
</Button>
<Button onClick={() => toast.warning('Warning', 'Please review!')} tone="warning">
Show Warning
</Button>
<Button onClick={() => toast.info('Info', 'Here is some information')} variant="outline">
Show Info
</Button>
</DemoBox>
</Section>
{/* ================================================================ */}
{/* DATAVIEW */}
{/* ================================================================ */}
<Section id="dataview" title="DataView">
<DemoBox label="DataView container">
<DataView className="w-full">
<DataViewHeader
title="Data View Title"
description="Description of the data view"
actions={<Button size="sm">Action</Button>}
/>
<DataViewToolbar>
<Button size="sm" variant="outline">Filter</Button>
<Button size="sm" variant="outline">Sort</Button>
</DataViewToolbar>
<div className="p-4 text-gray-500">Data content goes here...</div>
</DataView>
</DemoBox>
<DemoBox label="DataViewEmptyState">
<DataViewEmptyState
title="No Data Found"
description="Try adjusting your filters or add new items"
action={<Button size="sm">Add Item</Button>}
/>
</DemoBox>
</Section>
</div>
</div>
</>
);
}