Skip to content

Plataforma técnica · Sevastopol

Biblioteca de Componentes UI

Sevastopol UI Components Atomic Design

La Biblioteca de Componentes UI provee un conjunto de componentes SolidJS reutilizables organizados según los principios de Atomic Design. Es la base sobre la que se construyen todas las islands del frontend Sevastopol, asegurando consistencia visual, mantenibilidad y type-safety.

La jerarquía está dividida en cuatro capas:

  • Átomos: primitivas de formulario, acción, búsqueda y navegación (Input, Button, SearchBox, etc.).
  • Moléculas: composiciones cortas con propósito específico (PageHeader, StatCard, Breadcrumb).
  • Organismos: componentes interactivos complejos (Modal, DataTable).
  • Plantillas: layouts a nivel de página (IslandBase).

Todos los componentes soportan modo oscuro vía CSS custom properties y consumen utilidades de estilo centralizadas en sevastopol/src/lib/ui.ts.


flowchart LR
  subgraph TPL["Plantillas"]
    ISB["IslandBase.tsx<br/>Layout estándar"]
  end
  subgraph ORG["Organismos"]
    DT["DataTable.tsx<br/>items · headers · sumKeys"]
    MD["Modal.tsx<br/>open · onClose · children"]
  end
  subgraph MOL["Moléculas"]
    PH["PageHeader.tsx<br/>title · description · actions"]
    SG["StatsGrid.tsx<br/>children (StatCards)"]
    SC["StatCard.tsx<br/>label · value · sub"]
    FB["FilterBar.tsx<br/>children (filtros)"]
    BC["Breadcrumb.tsx<br/>text"]
  end
  subgraph ATM["Átomos"]
    FI["Fields.tsx<br/>Input · Select · Button · Checkbox · TextArea"]
    SB["SearchBox.tsx<br/>value · onChange · delay"]
    PG["Pagination.tsx<br/>total · limit · offset"]
    TP["TenantPicker.tsx<br/>tenants · value · onChange"]
    TA["TableAction.tsx<br/>variant · icon · onClick"]
  end
  ISB --> BC
  ISB --> PH
  ISB --> SG
  ISB --> FB
  SG -->|slot| SC
  SG -->|slot| TP
  FB -->|slot| SB
  FB -->|slot| FI
  PH -->|slot| FI
  DT --> SB
  DT --> TA
  DT --> PG
  MD -->|slot| FI

Esta arquitectura habilita máxima reutilización. DataTable es consumido por PayrollViewIsland, EmployeesViewIsland, ContractsViewIsland, TenantsViewIsland y PlanContableViewIsland, cada uno configurado con definiciones de columnas distintas desde sevastopol/src/config/headers.ts.


Los átomos son los bloques de construcción fundamentales. Son primitivas que no pueden descomponerse más. Todos soportan modo oscuro y accesibilidad de teclado.

Por claridad de uso, los agrupamos en tres categorías funcionales: campos de formulario, acciones y búsqueda/navegación.

Todos viven en sevastopol/src/components/atoms/Fields.tsx y se exportan desde @/components/atoms.

Envuelve un <input> HTML nativo con estilos estandarizados y gestión de etiqueta.

PropTipoRequeridoDescripción
labelstringTexto de etiqueta sobre el input
namestringNombre del campo de formulario
...restJSX.InputHTMLAttributesNoAtributos nativos (type, placeholder, value, etc.)
<Input
label="RUT"
name="rut"
required
placeholder="12345678-9"
value={editing()?.rut ?? ""}
/>

Menú desplegable con normalización de tipos. Convierte explícitamente tanto el value actual como los IDs de cada opción a string, previniendo desajustes value={0} vs value="0".

PropTipoRequeridoDescripción
labelstringNoTexto de etiqueta sobre el select
namestringNombre del campo
optionsOption[]Array de objetos {id, nombre}
valuestring | number | nullNoValor seleccionado (normalizado a string)
placeholderstringNoPlaceholder (default: "—")
density"normal" | "compact"NoVariante de densidad visual
type Option = {
id: string;
nombre: string;
[key: string]: any;
};

Checkbox estilizado con etiqueta opcional y mensaje personalizado.

PropTipoRequeridoDescripción
labelstringNoTexto de etiqueta sobre el checkbox
namestringNombre del campo
messagestringNoTexto junto al checkbox (default: "Activar")
...restJSX.InputHTMLAttributesNoAtributos nativos

Entrada multi-línea con estilos consistentes.

PropTipoRequeridoDescripción
labelstringTexto de etiqueta sobre el textarea
namestringNombre del campo
...restJSX.TextareaHTMLAttributesNoAtributos nativos

Componentes para disparar acciones del usuario.

Botón con tres variantes visuales y soporte opcional para icono. Vive en sevastopol/src/components/atoms/Fields.tsx.

PropTipoRequeridoDescripción
labelstringTexto del botón
iconstring | JSX.ElementNoEmoji o componente SVG
variant"primary" | "secondary" | "danger"NoEstilo visual (default: "primary")
...restJSX.ButtonHTMLAttributesNoAtributos nativos
VarianteEstilo
primaryFondo negro (oscuro: blanco), alto contraste
secondaryFondo blanco con borde, sutil
dangerFondo rose-600, para acciones destructivas

Botón basado en icono optimizado para filas de DataTable. Estados hover sutiles con coloración por variante. Vive en sevastopol/src/components/atoms/TableAction.tsx.

PropTipoRequeridoDescripción
onClick() => voidManejador de click
iconanyNoComponente de icono o emoji
labelstringNoTexto de tooltip/aria-label
variantstringNoVariante de estilo visual
classstringNoClases CSS adicionales
disabledbooleanNoEstado deshabilitado

Exporta también un objeto Icons con SVG pre-construidos:

  • Icons.Edit — lápiz
  • Icons.Delete — papelera
  • Icons.Eye — vista/preview
  • Icons.Database
  • Icons.Download
<TableAction
label="Editar"
variant="edit"
icon={ActionIcons.Edit}
onClick={() => startEdit(row)}
/>

Input de búsqueda con debounce (createEffect + setTimeout) para reducir peticiones API durante la escritura. Vive en sevastopol/src/components/atoms/SearchBox.tsx.

PropTipoRequeridoDescripción
placeholderstringNoTexto placeholder
valuestringValor actual
delaynumberNoDebounce en ms (default: 300)
onChange(v: string) => voidHandler de cambio (llamado después del debounce)
classstringNoClases CSS adicionales
<SearchBox
placeholder="Buscar por nombre, rut o email..."
value={q()}
onChange={setQ}
/>

Controles simples para navegar datos paginados. Calcula automáticamente los estados deshabilitados según offset y total. Vive en sevastopol/src/components/atoms/Pagination.tsx.

PropTipoRequeridoDescripción
totalnumberNúmero total de registros
limitnumberRegistros por página
offsetnumberOffset actual
onPrev() => voidHandler de página anterior
onNext() => voidHandler de página siguiente

Select para elegir organización tenant, típicamente embebido dentro del StatsGrid de IslandBase. Vive en sevastopol/src/components/atoms/TenantPicker.tsx. Usa la utilidad selectCls de lib/ui.ts para estilos consistentes.

PropTipoRequeridoDescripción
tenantsTenant[]Tenants disponibles
valuestringID del tenant seleccionado
onChange(id: string) => voidHandler de selección
type Tenant = {
id: string;
rut: string;
business_name: string;
// ... campos adicionales
};

Composiciones cortas construidas a partir de átomos. Viven en sevastopol/src/components/molecules/ y se importan desde @/components/molecules. Se usan mayoritariamente dentro de IslandBase.

Encabezado de página: título, descripción opcional y slot de botones de acción. Archivo: molecules/PageHeader.tsx.

PropTipoRequeridoDescripción
titlestringTítulo de la página
descriptionstringNoTexto descriptivo bajo el título
actionsJSX.ElementNoSlot para botones (típicamente <Button>)

Contenedor responsive para mostrar tarjetas de métricas en cuadrícula. Es un wrapper puro de slot. Archivo: molecules/StatsGrid.tsx.

PropTipoRequeridoDescripción
childrenJSX.ElementComponentes StatCard y opcionalmente TenantPicker embebido

Tarjeta de visualización de métrica única. Archivo: molecules/StatCard.tsx.

PropTipoRequeridoDescripción
labelstringEtiqueta (texto pequeño superior)
valuestring | numberValor central destacado
substringSubtítulo (texto pequeño inferior)
highlightbooleanNoAplica ring rose para destacar
colorstringNoClase de color custom para label y valor

Contenedor para SearchBox + controles de filtro personalizados. Wrapper puro de slot. Archivo: molecules/FilterBar.tsx.

PropTipoRequeridoDescripción
childrenJSX.ElementTípicamente SearchBox + uno o más Select de filtro

Ruta de navegación jerárquica. Muestra MÓDULO · TÍTULO en mayúsculas. Archivo: molecules/Breadcrumb.tsx.

PropTipoRequeridoDescripción
textstringTexto formateado, ej: "REM · LIQUIDACIONES"

Componentes complejos que combinan átomos y moléculas, con estado propio.

Overlay de diálogo para formularios y confirmaciones. Backdrop con click-para-cerrar. Archivo: sevastopol/src/components/atoms/Modal.tsx (vive bajo atoms/ en código por convención del proyecto, pero conceptualmente es organismo).

PropTipoRequeridoDescripción
openbooleanControla visibilidad
titlestringNoTítulo del modal
onClose() => voidHandler de cierre (también disparado por backdrop click)
childrenJSX.ElementContenido
widthClassstringNoAncho custom (default: "w-[min(100vw-2rem,1400px)]")
titleClassstringNoEstilos custom para el título
<div
class="absolute inset-0 bg-black/60 dark:bg-black/80 backdrop-blur-sm"
onClick={props.onClose}
/>

El componente más complejo y ampliamente usado. Tabla con filtrado, ordenamiento, paginación, formato automático y renderizado personalizable. Archivo: sevastopol/src/components/atoms/DataTable.tsx.

flowchart LR
  subgraph UTIL["Funciones utilitarias"]
    CS["changeSort(key)<br/>alterna sortDesc"]
    FN["formatNumber(v)<br/>locale de-DE"]
    FD["formatDate(iso)<br/>slice(0,10)"]
    INU["isNumeric(v)<br/>type check"]
  end
  DT["DataTable<br/>(items, headers, sumKeys)"]
  subgraph SIG["Señales SolidJS"]
    SK["sortKey"]
    SD["sortDesc"]
    PGN["page"]
    FLT["filter"]
  end
  subgraph DER["Estado derivado<br/>(createMemo)"]
    FILT["filteredItems()<br/>filtra por año/mes"]
    SORT["sortedItems()<br/>ordena por columna"]
    PAG["paginated()<br/>PAGE_SIZE = 10"]
  end
  TABLE["render con encabezados + filas"]
  DT --> SK --> SORT
  DT --> SD --> SORT
  DT --> PGN --> PAG
  DT --> FLT --> FILT
  CS --> SK
  CS --> SD
  FILT --> SORT --> PAG --> TABLE
  FN --> TABLE
  FD --> TABLE
  INU --> TABLE
PropTipoRequeridoDescripción
itemsany[]Array de objetos a mostrar
headersHeaderConfig[]Configuración de columnas
sumKeysstring[]NoClaves a sumar en fila de pie
chartsbooleanNoHabilitar visualización de gráficos (default: true)
variant"default" | "island"NoVariante visual
manualPaginationbooleanNoDeshabilitar paginación interna
actions{ onEdit?, onDelete? }NoHandlers de acción de fila
type HeaderConfig = {
key: string; // clave de propiedad en items
label: string; // texto de encabezado
sortable?: boolean; // default true
align?: "left" | "center" | "right";
render?: (value: any, row: any) => any; // renderizador custom
};
  1. Filtrado automático: auto-detecta columnas año, mes, year, month y genera dropdowns de filtro.

    const filterFields = headers.filter((h) =>
    ["año", "mes", "year", "month"].includes(h.key)
    );
  2. Ordenamiento multi-columna: click en encabezado alterna dirección. Estado preservado vía señales.

    const [sortKey, setSortKey] = createSignal(headers[0]?.key ?? "");
    const [sortDesc, setSortDesc] = createSignal(true);
  3. Formato de números: locale alemán (de-DE) para separadores de miles.

    function formatNumber(value: any): string {
    const num = typeof value === "string" ? parseFloat(value) : Number(value);
    if (isNaN(num)) return "0";
    return num.toLocaleString("de-DE", {
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
    });
    }
  4. Formato de fechas: detecta columnas fecha y aplica YYYY-MM-DD.

  5. Pie de resumen: cuando se provee sumKeys, renderiza una <tfoot> con totales/promedios.

    {sumKeys.length > 0 && (
    <tfoot class="sticky bottom-0 bg-emerald-50 dark:bg-emerald-900/20">
    <tr class="font-bold">
    {/* sumas/promedios para claves especificadas */}
    </tr>
    </tfoot>
    )}
  6. Acciones de fila: columna dedicada con editar/eliminar opcional.

  7. Paginación integrada: tamaño configurable (default: 10).

VarianteDescripciónCaso de uso
defaultTabla estándar con contenedor externoTablas independientes
islandflex-1 con min-height para layouts de página completaTablas embebidas en IslandBase

Plantilla estandarizada que provee la estructura de layout consistente para todas las vistas de negocio. Archivo: sevastopol/src/components/templates/IslandBase.tsx.

Opera en dos modos: Simple (contenedor básico) y Estándar (layout completo con tenant, stats y filtros). El cambio de modo se activa automáticamente al recibir la prop module.

flowchart TB
  ISB["IslandBase"]
  subgraph TOP["Barra superior"]
    CLOSE["Botón cerrar<br/>(handleClose)"]
    TITLE["Título simple<br/>(opcional)"]
  end
  subgraph LAY["Elementos de layout<br/>(activos con prop module)"]
    BC["Breadcrumb<br/>(MÓDULO · TÍTULO)"]
    PH["PageHeader<br/>(title · description · actions)"]
    SG["StatsGrid<br/>(métricas + TenantPicker)"]
    FB["FilterBar<br/>(SearchBox + filtros)"]
  end
  CONTENT["Área de contenido<br/>children (vista específica)"]
  ISB --> TOP
  ISB --> LAY
  ISB --> CONTENT
  BC --> PH --> SG --> FB --> CONTENT
  ISB -.->|"sin prop module"| CONTENT

Las props se organizan por funcionalidad.

Contenedor básico:

PropTipoRequeridoDescripción
titlestringNoTítulo de página (usado en ambos modos)
subtitlestringNoSubtítulo (sólo modo simple)
childrenJSX.ElementContenido específico de la vista
onClose() => voidNoHandler custom (default: dispatch sidebar:navigate)
isLoadingbooleanNoActiva overlay de carga
hideCloseButtonbooleanNoOculta el botón de cerrar

Layout estándar (activado por module):

PropTipoRequeridoDescripción
modulestringNoNombre de módulo (ej: "REMUNERACIONES") — activa modo estándar
descriptionstringNoTexto descriptivo bajo el título
onNew() => voidNoHandler para botón “Nuevo”
newLabelstringNoEtiqueta del botón (default: "+ Nuevo")
actionsJSX.ElementNoSlot de botones de acción custom

Gestión de tenant:

PropTipoRequeridoDescripción
tenantsTenant[]NoLista de tenants disponibles
selectedTenantIdstringNoID del tenant seleccionado
onTenantChange(id: string) => voidNoHandler de selección

Stats y filtros:

PropTipoRequeridoDescripción
statsJSX.ElementNoSlot de tarjetas de estadísticas
searchPlaceholderstringNoPlaceholder del SearchBox
searchValuestringNoValor de búsqueda actual
onSearchChange(val: string) => voidNoHandler de cambio de búsqueda
filtersJSX.ElementNoSlot de filtros custom
<Show when={props.module} fallback={props.children}>
{/* renderizado del layout estándar */}
</Show>

En orden vertical:

  1. BreadcrumbMÓDULO · TÍTULO en mayúsculas.
  2. PageHeader — título, descripción y botones de acción.
  3. StatsGrid — métricas + TenantPicker integrado.
  4. FilterBarSearchBox + filtros custom.
  5. Área de contenidochildren con manejo de scroll.

Cuando se pasan tenants y onTenantChange, el componente renderiza el picker dentro del StatsGrid:

<Show when={props.tenants && props.onTenantChange}>
<div class="bg-white dark:bg-zinc-800 rounded-xl shadow p-4">
<div class="text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">
Organización
</div>
<TenantPicker
tenants={props.tenants!}
value={props.selectedTenantId || ""}
onChange={props.onTenantChange!}
/>
</div>
</Show>
<Show when={props.isLoading}>
<div class="absolute inset-0 z-50 flex items-center justify-center
bg-white/50 dark:bg-zinc-900/50 backdrop-blur-sm">
<div class="w-8 h-8 border-4 border-indigo-500 border-t-transparent
rounded-full animate-spin" />
</div>
</Show>

Las definiciones de columnas para DataTable viven centralizadas en sevastopol/src/config/headers.ts y se reutilizan a través de las islands. Este patrón asegura consistencia y habilita lógica de renderizado compleja sin repetirla en cada vista.

flowchart LR
  CFG["headers.ts"]
  subgraph FOOT["Footer sum keys"]
    FSP["FOOTER_SUM_KEYS_PROVEEDORES"]
    FSC["FOOTER_SUM_KEYS_CLIENTES"]
  end
  subgraph HEAD["Definiciones"]
    HPROV["HEADERS_PROVEEDORES"]
    HCLI["HEADERS_CLIENTES"]
    HPAY["HEADERS_PAYROLL"]
    HEMP["HEADERS_EMPLEADOS"]
    HCON["HEADERS_CONTRATOS"]
    HVAC["HEADERS_VACATIONS"]
  end
  subgraph FMT["Utils de formato"]
    CLP["fmtCLP()"]
    DATE["fmtDate()"]
    INT["fmtInt()"]
  end
  CFG --> FSP
  CFG --> FSC
  CFG --> HPROV
  CFG --> HCLI
  CFG --> HPAY
  CFG --> HEMP
  CFG --> HCON
  CFG --> HVAC
  HPAY --> CLP
  HVAC --> DATE
  HPAY --> INT
export const HEADERS_PROVEEDORES = [
{ key: "rut_proveedor", label: "RUT" },
{ key: "razon_social", label: "Razón Social" },
{ key: "año", label: "Año" },
{ key: "mes", label: "Mes" },
{ key: "total_documentos", label: "# Docs" },
// ... más columnas
];

Los renderizadores habilitan formato complejo y JSX inline:

export const HEADERS_PAYROLL = [
{ key: "periodo", label: "Periodo" },
{ key: "empleado_nombre", label: "Empleado" },
{ key: "total_haberes", label: "Haberes", render: (v) => fmtCLP(num(v)) },
{ key: "total_descuentos", label: "Descuentos", render: (v) => fmtCLP(num(v)) },
// ...
];

Pueden acceder al valor de celda y al objeto de fila completo:

export const HEADERS_CONTRATOS = [
{ key: "id", label: "Trabajador" },
{ key: "numero_contrato", label: "N°", render: (v) => v ?? "—" },
{ key: "tipo_contrato", label: "Tipo" },
{ key: "fecha_inicio", label: "Inicio", render: (v) => fmtDate(v) },
{
key: "semaforo",
label: "Estado",
render: (v, row: Contrato) => v ?? row.estado ?? "—",
},
];

Para cada conjunto de encabezados, las claves de suma definen qué columnas agregar en el pie:

export const FOOTER_SUM_KEYS_PROVEEDORES = [
"total_documentos",
"total_neto",
"total_iva_recuperable",
"total_iva_no_recuperable",
"total_compras",
"total_exento",
"total_activo_fijo",
"total_iva_activo_fijo",
"total_facturas",
"total_notas_credito",
"total_notas_debito",
"promedio_monto_documentos",
];
import { HEADERS_PAYROLL } from "@/config/headers";
<DataTable
items={filteredPayrolls()}
headers={HEADERS_PAYROLL}
sumKeys={["total_haberes", "total_descuentos", "total_liquido"]}
actions={{
onEdit: (row) => handleEdit(row),
onDelete: (row) => handleDelete(row),
}}
/>

Los tipos UI centrales viven en sevastopol/src/types/ui.ts y aseguran type-safety a través de todos los componentes.

export type Option = {
id: string;
nombre: string;
[key: string]: any;
};
export type HeaderConfig = {
key: string;
label: string;
sortable?: boolean;
align?: "left" | "center" | "right";
render?: (value: any, row: any) => any;
};
export type StatusType =
| "ACTIVO"
| "INACTIVO"
| "PENDIENTE"
| "APROBADO"
| "RECHAZADO";
export type Semaforo = "VENCIDO" | "POR_VENCER" | "VIGENTE" | null;
export type ToastKind = "ok" | "error" | "info" | "warning";
export type PaginationMeta = {
page: number;
pageSize: number;
totalPages: number;
totalRecords: number;
};
export type StatCardProps = {
label: string;
value: string | number;
sub: string;
highlight?: boolean;
color?: string;
};

Modal de crear/editar usado a través de la aplicación:

<Modal
open={showFormModal()}
onClose={() => setShowFormModal(false)}
title={editing() ? "Editar" : "Nuevo"}
>
<form onSubmit={handleSave}>
<div class="grid grid-cols-2 gap-x-4 gap-y-3">
<Input label="RUT" name="rut" required value={editing()?.rut ?? ""} />
<Input label="Nombre" name="nombre" required value={editing()?.nombre ?? ""} />
<Select
label="Tipo"
name="tipo"
options={tipoOptions}
value={editing()?.tipo ?? ""}
/>
<Checkbox label="Activo" name="activo" checked={editing()?.activo ?? true} />
</div>
<div class="flex gap-3 mt-6 justify-end">
<Button label="Cancelar" variant="secondary" onClick={handleCancel} />
<Button label="Guardar" variant="primary" type="submit" />
</div>
</form>
</Modal>

Vista de lista con filtrado, stats y acciones:

<IslandBase
module="REMUNERACIONES"
title="Liquidaciones"
description="Gestión de liquidaciones de sueldo"
onNew={handleNew}
searchValue={q()}
onSearchChange={setQ}
stats={<><StatCard label="Total" value={total} sub="Liquidaciones" /></>}
tenants={tenants()}
selectedTenantId={selectedTenantId()}
onTenantChange={handleTenantChange}
>
<DataTable
items={filteredItems()}
headers={HEADERS_PAYROLL}
sumKeys={["total_haberes", "total_descuentos", "total_liquido"]}
actions={{
onEdit: handleEdit,
onDelete: handleDelete,
}}
/>
</IslandBase>

Patrón 3: Renderizadores custom con TableAction

Section titled “Patrón 3: Renderizadores custom con TableAction”
const tableHeaders: HeaderConfig[] = [
{ key: "rut", label: "RUT" },
{ key: "nombre", label: "Nombre" },
{
key: "actions",
label: "",
render: (_, row) => (
<div class="flex items-center justify-end gap-1">
<TableAction label="Editar" variant="edit" icon={ActionIcons.Edit} onClick={() => handleEdit(row)} />
<TableAction label="Borrar" variant="delete" icon={ActionIcons.Delete} onClick={() => handleDelete(row)} />
</div>
),
},
];

Todos los átomos se exportan centralmente desde sevastopol/src/components/atoms/index.ts:

export { TenantPicker, type Tenant } from "./TenantPicker";
export { ToastProvider, useToast } from "./ToastProvider";
export { Input, Select, TextArea, Checkbox, Button } from "./Fields";
export { Modal } from "./Modal";
export { SearchBox } from "./SearchBox";
export { Pagination } from "./Pagination";
export { TableAction, Icons as ActionIcons } from "./TableAction";
export { DataTable } from "./DataTable";

Esto habilita importaciones limpias en las islands:

import {
Input,
Select,
Button,
Modal,
DataTable,
TableAction,
ActionIcons,
} from "@/components/atoms";

Constantes centralizadas en sevastopol/src/lib/ui.ts:

export const inputCls =
"w-full bg-white dark:bg-zinc-800 text-black dark:text-white ...";
export const selectCls =
"w-full bg-white dark:bg-zinc-800 ... bg-[url('data:image/svg+xml;...')]";
export const chipCls =
"px-2 py-0.5 rounded text-[11px]";

Aseguran estilos consistentes en todos los componentes de formulario con soporte integrado de modo oscuro. selectCls incluye una flecha dropdown SVG embebida vía data URL.

Configuración Tailwind: el modo oscuro se activa por estrategia de clase:

darkMode: ["class", '[data-theme="dark"]'];

Lista canónica de todos los componentes presentes en sevastopol/src/components/. Los marcados como pendiente aún no tienen sección dedicada en esta página.

Átomos (sevastopol/src/components/atoms/)

Section titled “Átomos (sevastopol/src/components/atoms/)”
ComponenteArchivoProps claveDocumentado
InputFields.tsxlabel, name, ...rest
SelectFields.tsxoptions, value, onChange
ButtonFields.tsxlabel, variant, icon
CheckboxFields.tsxname, checked, message
TextAreaFields.tsxlabel, name
SearchBoxSearchBox.tsxvalue, onChange, delay
PaginationPagination.tsxtotal, limit, offset
TenantPickerTenantPicker.tsxtenants, value, onChange
TableActionTableAction.tsxvariant, icon, onClick
ToastProviderToastProvider.tsx(provider + useToast hook)pendiente
ChartContainerChartContainer.tsx(wrapper para charts)pendiente
ExportButtonsExportButtons.tsx(exportación CSV/Excel/PDF)pendiente
LoadingSpinnerLoadingSpinner.tsx(spinner standalone)pendiente
MarkdownEditorMarkdownEditor.tsx(editor markdown)pendiente
MarkdownViewMarkdownView.tsx(visor markdown)pendiente
PlotlyChartPlotlyChart.tsx(gráfico Plotly)pendiente

Moléculas (sevastopol/src/components/molecules/)

Section titled “Moléculas (sevastopol/src/components/molecules/)”
ComponenteArchivoProps claveDocumentado
PageHeaderPageHeader.tsxtitle, description, actions
StatsGridStatsGrid.tsxchildren
StatCardStatCard.tsxlabel, value, sub, highlight
FilterBarFilterBar.tsxchildren
BreadcrumbBreadcrumb.tsxtext
BoolBadgeBoolBadge.tsx(badge booleano)pendiente
StatusBadgeStatusBadge.tsx(badge de StatusType)pendiente
TypeBadgeTypeBadge.tsx(badge por tipo)pendiente
RegimeBadgeRegimeBadge.tsx(badge de régimen tributario)pendiente
PeriodicidadBadgePeriodicidadBadge.tsx(badge de periodicidad)pendiente
ParameterFormModalParameterFormModal.tsx(modal de formulario parametrizado)pendiente
ComponenteArchivoProps claveDocumentado
Modalatoms/Modal.tsxopen, onClose, children
DataTableatoms/DataTable.tsxitems, headers, sumKeys, actions

Plantillas (sevastopol/src/components/templates/)

Section titled “Plantillas (sevastopol/src/components/templates/)”
ComponenteArchivoProps claveDocumentado
IslandBaseIslandBase.tsxmodule, title, stats, children
WorkspaceThemeWorkspaceTheme.tsx(wrapper de tema para workspaces)pendiente