` para elementos interactivos
+ - `aria-label` o `aria-labelledby` en todo componente interactivo
+ - `aria-invalid` + `aria-describedby` en inputs con error
+ - `role="status"` para loading states
+ - Focus management en modales/popovers
+7. **Discriminated unions** cuando las props cambian segun variante:
+
+```tsx
+type Props = { size?: 'sm' | 'md' | 'lg'; children: React.ReactNode } & (
+ | { variant: 'link'; href: string; onClick?: never }
+ | { variant: 'button'; onClick: () => void; href?: never }
+)
+```
+
+### Patron de archivo .tsx
+
+```tsx
+import * as React from 'react'
+import { cva, type VariantProps } from 'class-variance-authority'
+import { cn } from '../core/cn'
+
+const componentVariants = cva(
+ 'base-classes-here', // clases base
+ {
+ variants: {
+ variant: {
+ default: 'classes...',
+ secondary: 'classes...',
+ },
+ size: {
+ sm: 'classes...',
+ md: 'classes...',
+ lg: 'classes...',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'md',
+ },
+ }
+)
+
+interface ComponentProps
+ extends React.ComponentPropsWithoutRef<'div'>,
+ VariantProps
{
+ // props adicionales con JSDoc
+ /** Descripcion de la prop */
+ customProp?: string
+}
+
+const Component = React.forwardRef(
+ ({ className, variant, size, customProp, ...props }, ref) => {
+ return (
+
+ )
+ }
+)
+Component.displayName = 'Component'
+
+export { Component, componentVariants }
+export type { ComponentProps }
+```
+
+### Patron de archivo .md
+
+**IMPORTANTE:** El campo `lang` debe ser `ts` (no `typescript`). El indexer solo reconoce `ts`. Los IDs siguen el formato `{name}_ts_{domain}`.
+
+```yaml
+---
+name: component_name
+kind: component
+lang: ts
+domain: ui
+version: "1.0.0"
+purity: impure
+signature: "ComponentName(props: ComponentProps): JSX.Element"
+description: "Descripcion concisa de que hace el componente"
+tags: [component, ui, ...]
+uses_functions: [cn_ts_core]
+uses_types: []
+returns: []
+returns_optional: false
+error_type: ""
+imports: ["@base-ui/react", "class-variance-authority"]
+tested: false
+tests: []
+test_file_path: ""
+file_path: "frontend/functions/ui/component_name.tsx"
+props:
+ - name: variant
+ type: "'default' | 'secondary'"
+ required: false
+ description: "Estilo visual"
+ - name: className
+ type: "string"
+ required: false
+ description: "Clases CSS adicionales"
+emits: []
+has_state: false
+framework: react
+variant: [default, secondary]
+---
+
+## Ejemplo
+
+...codigo de ejemplo...
+
+## Notas
+
+...notas relevantes...
+```
+
+### Despues de crear
+
+```bash
+./fn index && ./fn show {id}
+```
+
+---
+
+## CREAR FEATURE
+
+Para features dentro de una app existente. Co-location obligatoria.
+
+### Estructura
+
+```
+src/features/{feature_name}/
+ components/
+ FeatureMain.tsx # Componente principal
+ FeatureDetail.tsx # Sub-componentes
+ hooks/
+ useFeatureData.ts # Hooks del feature
+ types.ts # Tipos locales
+ index.ts # Barrel export
+```
+
+### Barrel export (index.ts)
+
+```ts
+// Solo exportar la API publica del feature
+export { FeatureMain } from './components/FeatureMain'
+export { useFeatureData } from './hooks/useFeatureData'
+export type { FeatureItem, FeatureConfig } from './types'
+```
+
+### Patrones de estado obligatorios
+
+**Server state** (datos de API/backend):
+```tsx
+// Con @tanstack/react-query
+const queryKeys = {
+ all: ['feature'] as const,
+ list: (filters: Filters) => [...queryKeys.all, 'list', filters] as const,
+ detail: (id: string) => [...queryKeys.all, 'detail', id] as const,
+}
+
+function useFeatureList(filters: Filters) {
+ return useQuery({
+ queryKey: queryKeys.list(filters),
+ queryFn: () => fetchFeatureList(filters),
+ })
+}
+```
+
+**Client state** (UI state compartido):
+```tsx
+// Con Zustand
+import { create } from 'zustand'
+
+interface FeatureStore {
+ selectedId: string | null
+ setSelected: (id: string | null) => void
+}
+
+const useFeatureStore = create((set) => ({
+ selectedId: null,
+ setSelected: (id) => set({ selectedId: id }),
+}))
+```
+
+**Wails** (apps de escritorio):
+```tsx
+// Usar hooks del registry
+import { useWailsQuery, useWailsMutation } from '@fn_library'
+
+function useFeatureData() {
+ return useWailsQuery('GetFeatureData', [], { staleTime: 60_000 })
+}
+```
+
+### Code splitting por ruta
+
+```tsx
+import { lazy, Suspense } from 'react'
+import { Skeleton } from '@fn_library'
+
+const FeaturePage = lazy(() => import('./features/feature/components/FeaturePage'))
+
+function AppRoutes() {
+ return (
+
+ }>
+
+
+ } />
+
+ )
+}
+```
+
+---
+
+## CHECKLIST DE VALIDACION (ejecutar siempre al final)
+
+Antes de dar por terminado cualquier trabajo frontend, verificar:
+
+### Colores y estilos
+- [ ] CERO colores hardcodeados (no hex, no rgb, no oklch inline en componentes)
+- [ ] Solo clases Tailwind mapeadas a CSS variables: `bg-primary`, `text-foreground`, `border-border`, etc.
+- [ ] `cn()` usado para merge de clases en todo componente
+- [ ] CVA usado para variantes (no condicionales manuales con ternarios)
+
+### Componentes del registry
+- [ ] Verificado que no se esta recreando algo que ya existe en `@fn_library` (`frontend/functions/ui/`)
+- [ ] Componentes de `@fn_library` usados donde aplica: Alert, Badge, Button, Card, Dialog, Input, Label, Select, SimpleSelect, Skeleton, Sparkline, Tabs, Tooltip, FormField, PageHeader, ProgressBar, KPICard, ThemeProvider, DashboardLayout, DataTable, charts (AreaChart, BarChart, LineChart, PieChart, ChartContainer), hooks Wails (useWailsQuery, useWailsMutation, useWailsStream, useWailsEvent)
+
+### TypeScript
+- [ ] Props interfaces con `React.ComponentPropsWithoutRef` para HTML spreading
+- [ ] Discriminated unions donde las props varian segun tipo/variante
+- [ ] `as const` para arrays literales y config objects
+- [ ] No `any` — usar `unknown` + type guards si es necesario
+
+### Accesibilidad
+- [ ] Elementos semanticos (button, a, dialog — no div onClick)
+- [ ] `aria-label` en botones de solo icono
+- [ ] `aria-invalid` + `aria-describedby` en inputs con validacion
+- [ ] Focus trap en modales y popovers
+- [ ] `prefers-reduced-motion` respetado (ya en app.css base)
+
+### Performance
+- [ ] Lazy loading en rutas (`React.lazy` + `Suspense`)
+- [ ] `manualChunks` en vite.config para vendor splitting
+- [ ] Sin barrel exports profundos que maten tree-shaking
+- [ ] Listas largas virtualizadas si >100 items
+
+### Estructura
+- [ ] Features co-located: componente + hook + tipos + barrel en el mismo directorio
+- [ ] Un `index.ts` por feature con API publica explicita
+- [ ] Componentes reutilizables de la app en `src/components/`
+- [ ] Tipos compartidos en `src/types/`
+
+---
+
+## ANTI-PATRONES (nunca hacer)
+
+1. **``** → usar `