# Shared Components Specification
**Version:** 1.0.0
**Fecha:** 2025-12-05
---
## UI Components
### Button
```tsx
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
loading?: boolean;
leftIcon?: ReactNode;
rightIcon?: ReactNode;
fullWidth?: boolean;
type?: 'button' | 'submit' | 'reset';
onClick?: () => void;
children: ReactNode;
}
// Uso
```
### Card
```tsx
interface CardProps {
className?: string;
padding?: 'none' | 'sm' | 'md' | 'lg';
shadow?: 'none' | 'sm' | 'md' | 'lg';
border?: boolean;
hoverable?: boolean;
onClick?: () => void;
children: ReactNode;
}
// Variantes
```
### Badge
```tsx
interface BadgeProps {
variant?: 'default' | 'success' | 'warning' | 'danger' | 'info';
size?: 'sm' | 'md';
dot?: boolean;
removable?: boolean;
onRemove?: () => void;
children: ReactNode;
}
// Uso
Activo
Pendiente
```
### Modal
```tsx
interface ModalProps {
isOpen: boolean;
onClose: () => void;
title?: string;
description?: string;
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
closeOnOverlayClick?: boolean;
closeOnEscape?: boolean;
showCloseButton?: boolean;
children: ReactNode;
footer?: ReactNode;
}
// Uso
```
### Tabs
```tsx
interface TabsProps {
defaultValue?: string;
value?: string;
onChange?: (value: string) => void;
children: ReactNode;
}
interface TabProps {
value: string;
label: string;
icon?: ReactNode;
disabled?: boolean;
badge?: number | string;
}
// Uso
```
### Dropdown
```tsx
interface DropdownProps {
trigger: ReactNode;
items: DropdownItem[];
align?: 'start' | 'end';
side?: 'top' | 'bottom';
}
interface DropdownItem {
label: string;
value: string;
icon?: ReactNode;
disabled?: boolean;
danger?: boolean;
onClick?: () => void;
}
// Uso
}
items={[
{ label: 'Editar', value: 'edit', icon: },
{ label: 'Duplicar', value: 'duplicate', icon: },
{ label: 'Eliminar', value: 'delete', icon: , danger: true },
]}
/>
```
### Progress
```tsx
interface ProgressProps {
value: number;
max?: number;
variant?: 'default' | 'success' | 'warning' | 'danger';
size?: 'sm' | 'md' | 'lg';
showLabel?: boolean;
labelFormat?: (value: number, max: number) => string;
animated?: boolean;
}
// Uso
```
### Avatar
```tsx
interface AvatarProps {
src?: string;
name?: string;
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
shape?: 'circle' | 'square';
status?: 'online' | 'offline' | 'busy' | 'away';
fallback?: ReactNode;
}
// Uso
```
### Tooltip
```tsx
interface TooltipProps {
content: ReactNode;
position?: 'top' | 'bottom' | 'left' | 'right';
delay?: number;
disabled?: boolean;
children: ReactNode;
}
// Uso
```
### Alert
```tsx
interface AlertProps {
type: 'info' | 'success' | 'warning' | 'error';
title?: string;
message: string;
dismissible?: boolean;
onDismiss?: () => void;
action?: {
label: string;
onClick: () => void;
};
}
// Uso
{} }}
/>
```
---
## Form Components
### Input
```tsx
interface InputProps extends InputHTMLAttributes {
label?: string;
helper?: string;
error?: string;
leftAddon?: ReactNode;
rightAddon?: ReactNode;
leftIcon?: ReactNode;
rightIcon?: ReactNode;
}
// Uso
```
### Select
```tsx
interface SelectProps {
label?: string;
placeholder?: string;
options: SelectOption[];
value?: string | string[];
onChange?: (value: string | string[]) => void;
multiple?: boolean;
searchable?: boolean;
clearable?: boolean;
disabled?: boolean;
error?: string;
loading?: boolean;
}
interface SelectOption {
value: string;
label: string;
disabled?: boolean;
group?: string;
}
// Uso
```
### DatePicker
```tsx
interface DatePickerProps {
label?: string;
value?: Date | null;
onChange?: (date: Date | null) => void;
format?: string;
placeholder?: string;
minDate?: Date;
maxDate?: Date;
disabled?: boolean;
error?: string;
}
interface DateRangePickerProps {
label?: string;
value?: { start: Date | null; end: Date | null };
onChange?: (range: { start: Date | null; end: Date | null }) => void;
// ... same as DatePicker
}
// Uso
```
### FileUpload
```tsx
interface FileUploadProps {
label?: string;
accept?: string;
maxSize?: number; // bytes
maxFiles?: number;
multiple?: boolean;
onUpload?: (files: File[]) => void;
onRemove?: (file: File) => void;
value?: File[];
error?: string;
helper?: string;
preview?: boolean;
dragAndDrop?: boolean;
}
// Uso
```
### CurrencyInput
```tsx
interface CurrencyInputProps {
label?: string;
value?: number;
onChange?: (value: number) => void;
currency?: string; // MXN, USD
locale?: string;
precision?: number;
min?: number;
max?: number;
error?: string;
}
// Uso
```
### Form (React Hook Form Integration)
```tsx
interface FormProps {
onSubmit: (data: T) => void | Promise;
defaultValues?: DefaultValues;
schema?: ZodSchema;
children: ReactNode;
}
// Uso
Guardar
```
---
## Table Components
### DataTable
```tsx
interface DataTableProps {
columns: ColumnDef[];
data: T[];
loading?: boolean;
emptyMessage?: string;
sortable?: boolean;
selectable?: boolean;
selectedRows?: string[];
onSelectRows?: (ids: string[]) => void;
onRowClick?: (row: T) => void;
rowActions?: (row: T) => DropdownItem[];
pagination?: PaginationProps;
stickyHeader?: boolean;
}
interface ColumnDef {
id: string;
header: string | ReactNode;
accessor: keyof T | ((row: T) => any);
cell?: (value: any, row: T) => ReactNode;
sortable?: boolean;
width?: number | string;
align?: 'left' | 'center' | 'right';
}
// Uso
const columns: ColumnDef[] = [
{ id: 'code', header: 'Codigo', accessor: 'code', sortable: true },
{ id: 'name', header: 'Nombre', accessor: 'name', sortable: true },
{
id: 'status',
header: 'Estado',
accessor: 'status',
cell: (value) => {value}
},
{
id: 'progress',
header: 'Avance',
accessor: 'progressPercentage',
cell: (value) =>
}
];
[
{ label: 'Editar', onClick: () => handleEdit(row) },
{ label: 'Eliminar', onClick: () => handleDelete(row), danger: true }
]}
/>
```
### TableFilters
```tsx
interface TableFiltersProps {
filters: FilterConfig[];
values: Record;
onChange: (values: Record) => void;
onClear?: () => void;
}
interface FilterConfig {
key: string;
label: string;
type: 'text' | 'select' | 'date' | 'dateRange' | 'number';
options?: SelectOption[]; // for select
placeholder?: string;
}
// Uso
```
---
## Chart Components
### LineChart
```tsx
interface LineChartProps {
data: ChartData[];
xKey: string;
yKey: string | string[];
height?: number;
showGrid?: boolean;
showLegend?: boolean;
showTooltip?: boolean;
colors?: string[];
curve?: 'linear' | 'monotone' | 'step';
}
// Uso
```
### BarChart
```tsx
interface BarChartProps {
data: ChartData[];
xKey: string;
yKey: string | string[];
height?: number;
orientation?: 'vertical' | 'horizontal';
stacked?: boolean;
showGrid?: boolean;
showLegend?: boolean;
colors?: string[];
}
// Uso
```
### PieChart
```tsx
interface PieChartProps {
data: PieData[];
nameKey: string;
valueKey: string;
height?: number;
donut?: boolean;
showLabels?: boolean;
showLegend?: boolean;
colors?: string[];
}
// Uso
```
### GaugeChart
```tsx
interface GaugeChartProps {
value: number;
max?: number;
min?: number;
thresholds?: { value: number; color: string }[];
label?: string;
showValue?: boolean;
size?: 'sm' | 'md' | 'lg';
}
// Uso
```
---
## Layout Components
### PageHeader
```tsx
interface PageHeaderProps {
title: string;
subtitle?: string;
breadcrumbs?: BreadcrumbItem[];
actions?: ReactNode;
tabs?: TabItem[];
activeTab?: string;
onTabChange?: (tab: string) => void;
}
// Uso
+ Nuevo Proyecto}
/>
```
### Sidebar
```tsx
interface SidebarProps {
items: SidebarItem[];
collapsed?: boolean;
onCollapse?: (collapsed: boolean) => void;
logo?: ReactNode;
footer?: ReactNode;
}
interface SidebarItem {
label: string;
href?: string;
icon?: ReactNode;
badge?: number | string;
children?: SidebarItem[];
active?: boolean;
}
```
### EmptyState
```tsx
interface EmptyStateProps {
icon?: ReactNode;
title: string;
description?: string;
action?: ReactNode;
}
// Uso
}
title="Sin documentos"
description="No hay documentos en esta carpeta"
action={}
/>
```
### LoadingSpinner
```tsx
interface LoadingSpinnerProps {
size?: 'sm' | 'md' | 'lg';
fullScreen?: boolean;
message?: string;
}
// Uso
```
---
## Utility Components
### ConfirmDialog
```tsx
interface ConfirmDialogProps {
isOpen: boolean;
onClose: () => void;
onConfirm: () => void | Promise;
title: string;
message: string;
confirmLabel?: string;
cancelLabel?: string;
variant?: 'danger' | 'warning' | 'info';
loading?: boolean;
}
// Uso
setIsDeleteDialogOpen(false)}
onConfirm={handleDelete}
title="Eliminar proyecto"
message="Esta accion no se puede deshacer. Se eliminaran todos los datos asociados."
variant="danger"
confirmLabel="Eliminar"
/>
```
### Toast
```tsx
// Hook
const { toast } = useToast();
toast({
title: 'Proyecto creado',
description: 'El proyecto se ha creado exitosamente',
type: 'success',
duration: 5000
});
toast.success('Guardado exitosamente');
toast.error('Error al guardar');
toast.warning('Atencion requerida');
toast.info('Informacion importante');
```
### Skeleton
```tsx
interface SkeletonProps {
width?: number | string;
height?: number | string;
variant?: 'text' | 'rectangular' | 'circular';
animation?: 'pulse' | 'wave' | 'none';
}
// Uso
```
---
*Ultima actualizacion: 2025-12-05*