/**
* Component Contracts: Base UI Components
*
* TypeScript interfaces for shadcn/ui base components.
* These contracts define the props for reusable UI components.
*
* Note: These are design-time contracts for planning. Actual implementations
* will be generated by shadcn/ui CLI and may have additional props.
*/
import { ReactNode } from 'react'
// ============================================================================
// Button Component
// ============================================================================
export interface ButtonProps {
/**
* Visual style variant
* @default 'default'
*/
variant?: 'default' | 'primary' | 'secondary' | 'ghost' | 'link' | 'destructive'
/**
* Size variant
* @default 'md'
*/
size?: 'sm' | 'md' | 'lg'
/**
* Disabled state - prevents interaction
* @default false
*/
disabled?: boolean
/**
* Loading state - shows spinner, disables interaction
* @default false
*/
loading?: boolean
/**
* Click handler
*/
onClick?: () => void
/**
* Button type attribute
* @default 'button'
*/
type?: 'button' | 'submit' | 'reset'
/**
* Button content
*/
children: ReactNode
/**
* Additional CSS classes
*/
className?: string
}
// ============================================================================
// Card Component
// ============================================================================
export interface CardProps {
children: ReactNode
className?: string
/**
* Padding size
* @default 'md'
*/
padding?: 'sm' | 'md' | 'lg'
}
export interface CardHeaderProps {
children: ReactNode
className?: string
}
export interface CardTitleProps {
children: ReactNode
className?: string
}
export interface CardDescriptionProps {
children: ReactNode
className?: string
}
export interface CardContentProps {
children: ReactNode
className?: string
}
export interface CardFooterProps {
children: ReactNode
className?: string
}
// ============================================================================
// Input Component
// ============================================================================
export interface InputProps {
/**
* Input type
* @default 'text'
*/
type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url'
/**
* Placeholder text
*/
placeholder?: string
/**
* Current value
*/
value?: string
/**
* Change handler
*/
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
/**
* Disabled state
* @default false
*/
disabled?: boolean
/**
* Error state - shows red border
* @default false
*/
error?: boolean
/**
* Error message to display below input
*/
errorMessage?: string
/**
* Label text
*/
label?: string
/**
* Required field indicator
* @default false
*/
required?: boolean
/**
* Additional CSS classes
*/
className?: string
}
// ============================================================================
// Table Component
// ============================================================================
export interface TableColumn<T> {
/**
* Data key to display in this column
*/
key: keyof T
/**
* Column header text
*/
header: string
/**
* Custom render function for cell content
*/
render?: (value: T[keyof T], row: T) => ReactNode
/**
* Whether this column is sortable
* @default false
*/
sortable?: boolean
/**
* Column width (CSS value)
*/
width?: string
}
export interface TableProps<T> {
/**
* Array of data rows
*/
data: T[]
/**
* Column definitions
*/
columns: TableColumn<T>[]
/**
* Loading state - shows skeleton rows
* @default false
*/
loading?: boolean
/**
* Message to display when data is empty
* @default 'No data available'
*/
emptyMessage?: string
/**
* Row click handler
*/
onRowClick?: (row: T) => void
/**
* Current sort column key
*/
sortBy?: keyof T
/**
* Current sort direction
*/
sortDirection?: 'asc' | 'desc'
/**
* Sort change handler
*/
onSort?: (key: keyof T, direction: 'asc' | 'desc') => void
}
// ============================================================================
// Dialog (Modal) Component
// ============================================================================
export interface DialogProps {
/**
* Whether the dialog is open
*/
open: boolean
/**
* Open state change handler
*/
onOpenChange: (open: boolean) => void
/**
* Dialog content
*/
children: ReactNode
}
export interface DialogContentProps {
children: ReactNode
className?: string
}
export interface DialogHeaderProps {
children: ReactNode
className?: string
}
export interface DialogTitleProps {
children: ReactNode
className?: string
}
export interface DialogDescriptionProps {
children: ReactNode
className?: string
}
export interface DialogFooterProps {
children: ReactNode
className?: string
}
// ============================================================================
// Skeleton Component
// ============================================================================
export interface SkeletonProps {
/**
* Additional CSS classes
*/
className?: string
/**
* Width (CSS value)
*/
width?: string
/**
* Height (CSS value)
*/
height?: string
/**
* Skeleton variant
* @default 'rectangular'
*/
variant?: 'text' | 'circular' | 'rectangular'
}
// ============================================================================
// Alert Component
// ============================================================================
export interface AlertProps {
/**
* Alert visual variant
* @default 'default'
*/
variant?: 'default' | 'info' | 'warning' | 'error' | 'success'
/**
* Alert title
*/
title?: string
/**
* Alert description
*/
description?: string
/**
* Whether the alert can be dismissed
* @default false
*/
dismissible?: boolean
/**
* Dismiss handler
*/
onDismiss?: () => void
/**
* Alert content (alternative to title/description)
*/
children?: ReactNode
/**
* Additional CSS classes
*/
className?: string
}
// ============================================================================
// Badge Component
// ============================================================================
export interface BadgeProps {
/**
* Badge visual variant
* @default 'default'
*/
variant?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error'
/**
* Badge content
*/
children: ReactNode
/**
* Additional CSS classes
*/
className?: string
}
// ============================================================================
// Select Component
// ============================================================================
export interface SelectOption {
value: string
label: string
}
export interface SelectProps {
/**
* Available options
*/
options: SelectOption[]
/**
* Current selected value
*/
value?: string
/**
* Change handler
*/
onChange?: (value: string) => void
/**
* Placeholder text
*/
placeholder?: string
/**
* Disabled state
* @default false
*/
disabled?: boolean
/**
* Error state
* @default false
*/
error?: boolean
/**
* Label text
*/
label?: string
/**
* Required field indicator
* @default false
*/
required?: boolean
/**
* Additional CSS classes
*/
className?: string
}
// ============================================================================
// Tooltip Component
// ============================================================================
export interface TooltipProps {
/**
* Tooltip content
*/
content: string | ReactNode
/**
* Element to show tooltip on hover
*/
children: ReactNode
/**
* Tooltip position
* @default 'top'
*/
side?: 'top' | 'right' | 'bottom' | 'left'
/**
* Delay before showing tooltip (milliseconds)
* @default 200
*/
delay?: number
}
// ============================================================================
// Form Component (Composition)
// ============================================================================
export interface FormProps {
/**
* Form submit handler
*/
onSubmit: (data: any) => void | Promise<void>
/**
* Form content (Input, Select, Button components)
*/
children: ReactNode
/**
* Additional CSS classes
*/
className?: string
}
export interface FormFieldProps {
/**
* Field name (for form state)
*/
name: string
/**
* Field label
*/
label: string
/**
* Whether field is required
* @default false
*/
required?: boolean
/**
* Field content (Input, Select, etc.)
*/
children: ReactNode
/**
* Error message
*/
error?: string
/**
* Helper text
*/
helperText?: string
}
// ============================================================================
// Usage Examples
// ============================================================================
/**
* Example: Button usage
*
* ```tsx
* <Button variant="primary" size="lg" onClick={handleSubmit}>
* Submit
* </Button>
*
* <Button variant="destructive" disabled>
* Delete
* </Button>
* ```
*/
/**
* Example: Card usage
*
* ```tsx
* <Card>
* <CardHeader>
* <CardTitle>API Usage</CardTitle>
* <CardDescription>Current month's metrics</CardDescription>
* </CardHeader>
* <CardContent>
* <p>1,234 requests</p>
* </CardContent>
* <CardFooter>
* <Button variant="link">View Details</Button>
* </CardFooter>
* </Card>
* ```
*/
/**
* Example: Table usage
*
* ```tsx
* <Table
* data={apiKeys}
* columns={[
* { key: 'name', header: 'Name', sortable: true },
* { key: 'createdAt', header: 'Created', render: (val) => formatDate(val) },
* ]}
* sortBy="createdAt"
* sortDirection="desc"
* onRowClick={(row) => console.log(row)}
* />
* ```
*/
/**
* Example: Dialog usage
*
* ```tsx
* <Dialog open={isOpen} onOpenChange={setIsOpen}>
* <DialogContent>
* <DialogHeader>
* <DialogTitle>Confirm Deletion</DialogTitle>
* <DialogDescription>
* Are you sure you want to delete this API key?
* </DialogDescription>
* </DialogHeader>
* <DialogFooter>
* <Button variant="secondary" onClick={() => setIsOpen(false)}>
* Cancel
* </Button>
* <Button variant="destructive" onClick={handleDelete}>
* Delete
* </Button>
* </DialogFooter>
* </DialogContent>
* </Dialog>
* ```
*/