{
  "$meta": {
    "library": "onaris-ui",
    "stack": "React 18 + TypeScript",
    "count": 32
  },
  "components": [
    {
      "id": "button",
      "name": "Button",
      "category": "Forms",
      "export": "<Button />",
      "description": "Acciones primarias y secundarias. Seis variantes semánticas, tres tamaños, cinco estados. El variante primary es el CTA global; secondary para acciones neutras; ghost para acciones terciarias; danger para destructivas; link para navegación inline. Todos los tamaños por defecto son de 32px para maximizar densidad en backoffice.",
      "variants": [
        {
          "title": "Variantes",
          "detail": "primary · secondary · ghost · danger · soft-accent · link"
        },
        {
          "title": "Tamaños",
          "detail": "sm (28) · md (32, default) · lg (40)"
        },
        {
          "title": "Estados · Primary"
        },
        {
          "title": "Estados · Secondary"
        },
        {
          "title": "Loading y block"
        }
      ],
      "props": {
        "Button": [
          {
            "prop": "variant",
            "type": "'primary' | 'secondary' | 'ghost' | 'danger' | 'soft-accent' | 'link'",
            "default": "'primary'",
            "description": "Estilo visual y semántica."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Altura del botón. md = 32px."
          },
          {
            "prop": "loading",
            "type": "boolean",
            "default": "false",
            "description": "Muestra spinner y bloquea clicks."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el botón (opacity 0.5, no cursor)."
          },
          {
            "prop": "block",
            "type": "boolean",
            "default": "false",
            "description": "Ocupa todo el ancho disponible."
          },
          {
            "prop": "type",
            "type": "'button' | 'submit' | 'reset'",
            "default": "'button'",
            "description": "Tipo nativo HTML."
          },
          {
            "prop": "onClick",
            "type": "(e) => void",
            "default": "—",
            "description": "Handler de click."
          },
          {
            "prop": "children",
            "type": "ReactNode",
            "default": "—",
            "description": "Contenido del botón."
          }
        ]
      },
      "example": "// Uso básico\n<Button variant=\"primary\">Guardar</Button>\n<Button variant=\"secondary\" size=\"sm\">Cancelar</Button>\n<Button variant=\"danger\" loading>Eliminar</Button>\n<Button variant=\"primary\" block>Continuar</Button>"
    },
    {
      "id": "iconbutton",
      "name": "IconButton",
      "category": "Forms",
      "export": "<IconButton />",
      "description": "Botón cuadrado de icono puro. Para barras de acciones densas, toolbars y controles inline donde el texto ocuparía demasiado. Requiere aria-label obligatorio. Cuando se use junto a iconos de Onaris UI, el contenedor aplica color vía currentColor.",
      "variants": [
        {
          "title": "Variantes",
          "detail": "ghost · outline · primary · circle"
        },
        {
          "title": "Tamaños",
          "detail": "sm (28) · md (32) · lg (40)"
        }
      ],
      "props": {
        "IconButton": [
          {
            "prop": "variant",
            "type": "'ghost' | 'outline' | 'primary'",
            "default": "'ghost'",
            "description": "Estilo visual."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "28 / 32 / 40 px."
          },
          {
            "prop": "shape",
            "type": "'square' | 'circle'",
            "default": "'square'",
            "description": "Forma del contenedor."
          },
          {
            "prop": "aria-label",
            "type": "string",
            "default": "— (requerido)",
            "description": "Etiqueta accesible. Obligatoria."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el botón."
          }
        ]
      },
      "example": "<IconButton variant=\"ghost\" aria-label=\"Editar\">\n  <IconLapiz />\n</IconButton>"
    },
    {
      "id": "input",
      "name": "Input",
      "category": "Forms",
      "export": "<Input />",
      "description": "Campo de texto de una línea. Soporta todos los type HTML (text, number, password, email, search, tel, url). Acepta prefix y suffix para unidades, iconos o acciones. Siempre se usa envuelto en <Field> con label y hint opcional.",
      "variants": [
        {
          "title": "Estructura base",
          "detail": "Label + Input + Hint"
        },
        {
          "title": "Tamaños",
          "detail": "sm (28) · md (32, default) · lg (40)"
        },
        {
          "title": "Estados"
        },
        {
          "title": "Con prefix / suffix"
        },
        {
          "title": "Con botón de limpiar",
          "detail": "aparece al enfocar un campo con texto"
        },
        {
          "title": "Error"
        }
      ],
      "props": {
        "Input": [
          {
            "prop": "type",
            "type": "'text' | 'number' | 'password' | 'email' | 'search' | 'tel' | 'url'",
            "default": "'text'",
            "description": "Tipo nativo HTML."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "28 / 32 / 40 px."
          },
          {
            "prop": "prefix",
            "type": "ReactNode",
            "default": "—",
            "description": "Contenido en el borde izquierdo (unidad, icono…)."
          },
          {
            "prop": "suffix",
            "type": "ReactNode",
            "default": "—",
            "description": "Contenido en el borde derecho."
          },
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Valor controlado."
          },
          {
            "prop": "onChange",
            "type": "(e) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "placeholder",
            "type": "string",
            "default": "—",
            "description": "Texto de ayuda inline."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el input."
          },
          {
            "prop": "readOnly",
            "type": "boolean",
            "default": "false",
            "description": "Solo lectura."
          },
          {
            "prop": "invalid",
            "type": "boolean",
            "default": "false",
            "description": "Aplica estilo de error."
          },
          {
            "prop": "clearable",
            "type": "boolean",
            "default": "false",
            "description": "Muestra el botón ✕ al enfocar si hay texto. Lo borra de un clic."
          }
        ]
      },
      "example": "<Field label=\"Nombre\" hint=\"Aparecerá en la ficha\">\n  <Input placeholder=\"Camiseta algodón\" />\n</Field>\n\n<Field label=\"Precio\">\n  <Input type=\"number\" prefix=\"€\" />\n</Field>\n\n<Field label=\"Email\" error=\"Formato no válido\">\n  <Input type=\"email\" />\n</Field>"
    },
    {
      "id": "password",
      "name": "PasswordInput",
      "category": "Forms",
      "export": "<PasswordInput />",
      "description": "Campo de contraseña con botón para mostrar/ocultar el texto, usando los iconos ojo / ojo-oculto de Onaris. Por defecto oculta el contenido.",
      "variants": [
        {
          "title": "Oculta / visible"
        }
      ],
      "props": {
        "PasswordInput": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Valor controlado."
          },
          {
            "prop": "onChange",
            "type": "(e) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "defaultVisible",
            "type": "boolean",
            "default": "false",
            "description": "Empieza mostrando el texto."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Altura del campo."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el campo."
          }
        ]
      },
      "example": "<Field label=\"Contraseña\">\n  <PasswordInput value={pw} onChange={setPw} />\n</Field>"
    },
    {
      "id": "textarea",
      "name": "Textarea",
      "category": "Forms",
      "export": "<Textarea />",
      "description": "Campo de texto multilínea, redimensionable en vertical. Mismas convenciones que Input: se usa dentro de Field con label y hint.",
      "variants": [
        {
          "title": "Estados"
        }
      ],
      "props": {
        "Textarea": [
          {
            "prop": "rows",
            "type": "number",
            "default": "3",
            "description": "Alto inicial en líneas."
          },
          {
            "prop": "maxLength",
            "type": "number",
            "default": "—",
            "description": "Límite de caracteres."
          },
          {
            "prop": "resize",
            "type": "'none' | 'vertical' | 'both'",
            "default": "'vertical'",
            "description": "Comportamiento de redimensionado."
          },
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Valor controlado."
          },
          {
            "prop": "onChange",
            "type": "(e) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el campo."
          },
          {
            "prop": "invalid",
            "type": "boolean",
            "default": "false",
            "description": "Aplica estilo de error."
          }
        ]
      },
      "example": "<Field label=\"Descripción\">\n  <Textarea rows={4} placeholder=\"Describe el artículo…\" />\n</Field>"
    },
    {
      "id": "select",
      "name": "Select",
      "category": "Forms",
      "export": "<Select />",
      "description": "Desplegable de selección única. Es un combobox custom, no un <select> nativo: así el menú desplegado usa los mismos tokens que el resto del sistema en todos los navegadores. Prueba a abrir cualquiera de los ejemplos — el menú es idéntico al documentado abajo.",
      "variants": [
        {
          "title": "Tamaños",
          "detail": "S (28) · M (32, default) · L (40) — clicables"
        },
        {
          "title": "Estados"
        },
        {
          "title": "Desplegable abierto",
          "detail": "estado is-open, con la opción seleccionada marcada"
        }
      ],
      "props": {
        "Select": [
          {
            "prop": "value",
            "type": "string | number",
            "default": "—",
            "description": "Opción seleccionada."
          },
          {
            "prop": "onChange",
            "type": "(value) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "options",
            "type": "{ value, label }[]",
            "default": "—",
            "description": "Alternativa a children."
          },
          {
            "prop": "searchable",
            "type": "boolean",
            "default": "false",
            "description": "Activa combobox con filtro."
          },
          {
            "prop": "clearable",
            "type": "boolean",
            "default": "false",
            "description": "Botón para limpiar selección."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Altura del control."
          },
          {
            "prop": "placeholder",
            "type": "string",
            "default": "—",
            "description": "Texto cuando no hay selección."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el control."
          },
          {
            "prop": "invalid",
            "type": "boolean",
            "default": "false",
            "description": "Aplica estilo de error."
          }
        ]
      },
      "example": "<Field label=\"Categoría\">\n  <Select value={category} onChange={setCategory}>\n    <Select.Option value=\"camisetas\">Camisetas</Select.Option>\n    <Select.Option value=\"pantalones\">Pantalones</Select.Option>\n  </Select>\n</Field>\n\n// Con búsqueda\n<Select searchable options={cats} />"
    },
    {
      "id": "datepicker",
      "name": "DatePicker",
      "category": "Forms",
      "export": "<DatePicker />",
      "description": "Selección de fecha con icono calendario de Onaris. Al enfocar despliega un calendario; admite rango con range. El input es editable manualmente respetando el formato.",
      "variants": [
        {
          "title": "Campo"
        }
      ],
      "props": {
        "DatePicker": [
          {
            "prop": "value",
            "type": "Date | [Date, Date]",
            "default": "—",
            "description": "Fecha o rango seleccionado."
          },
          {
            "prop": "onChange",
            "type": "(value) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "range",
            "type": "boolean",
            "default": "false",
            "description": "Selección de rango."
          },
          {
            "prop": "format",
            "type": "string",
            "default": "'dd/MM/yyyy'",
            "description": "Formato de visualización."
          },
          {
            "prop": "min / max",
            "type": "Date",
            "default": "—",
            "description": "Límites seleccionables."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el campo."
          }
        ]
      },
      "example": "<DatePicker value={date} onChange={setDate} format=\"dd/MM/yyyy\" />\n<DatePicker range value={[from, to]} onChange={setRange} />"
    },
    {
      "id": "timepicker",
      "name": "TimePicker",
      "category": "Forms",
      "export": "<TimePicker />",
      "description": "Selección de hora con icono reloj de Onaris. Formato 24h por defecto, con paso configurable (minutos).",
      "variants": [
        {
          "title": "Campo"
        }
      ],
      "props": {
        "TimePicker": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Hora en formato 'HH:mm'."
          },
          {
            "prop": "onChange",
            "type": "(value) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "format",
            "type": "'24h' | '12h'",
            "default": "'24h'",
            "description": "Formato horario."
          },
          {
            "prop": "step",
            "type": "number",
            "default": "30",
            "description": "Intervalo en minutos."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el campo."
          }
        ]
      },
      "example": "<TimePicker value={time} onChange={setTime} step={15} />"
    },
    {
      "id": "colorpicker",
      "name": "ColorPicker",
      "category": "Forms",
      "export": "<ColorPicker />",
      "description": "Selección de color con muestra (swatch) a la izquierda y valor hexadecimal editable. Al abrir despliega un selector. Útil para marcar familias, etiquetas o temas de catálogo.",
      "variants": [
        {
          "title": "Campo"
        }
      ],
      "props": {
        "ColorPicker": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Color en hex (#RRGGBB)."
          },
          {
            "prop": "onChange",
            "type": "(value) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "presets",
            "type": "string[]",
            "default": "—",
            "description": "Colores predefinidos (paleta de marca)."
          },
          {
            "prop": "format",
            "type": "'hex' | 'rgb'",
            "default": "'hex'",
            "description": "Formato del valor."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el campo."
          }
        ]
      },
      "example": "<ColorPicker value={color} onChange={setColor} />"
    },
    {
      "id": "checkbox",
      "name": "Checkbox",
      "category": "Forms",
      "export": "<Checkbox />",
      "description": "Selección múltiple. Admite estado indeterminate para headers de tabla que controlan la selección de todas las filas. Label clickeable por defecto.",
      "variants": [
        {
          "title": "Variantes"
        },
        {
          "title": "Estados"
        },
        {
          "title": "Grupo vertical"
        }
      ],
      "props": {
        "Checkbox": [
          {
            "prop": "checked",
            "type": "boolean",
            "default": "false",
            "description": "Estado controlado."
          },
          {
            "prop": "defaultChecked",
            "type": "boolean",
            "default": "false",
            "description": "Estado inicial no controlado."
          },
          {
            "prop": "indeterminate",
            "type": "boolean",
            "default": "false",
            "description": "Tercer estado (ni on ni off)."
          },
          {
            "prop": "onChange",
            "type": "(checked) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el checkbox."
          },
          {
            "prop": "children",
            "type": "ReactNode",
            "default": "—",
            "description": "Etiqueta inline (clickeable)."
          }
        ]
      },
      "example": "<Checkbox checked={value} onChange={setValue}>\n  Destacar en catálogo\n</Checkbox>\n\n<Checkbox indeterminate>Todos</Checkbox>"
    },
    {
      "id": "radio",
      "name": "Radio",
      "category": "Forms",
      "export": "<Radio /> · <RadioGroup />",
      "description": "Selección única exclusiva. Siempre se usa dentro de RadioGroup, que coordina el estado y el name del grupo.",
      "variants": [
        {
          "title": "Estados"
        },
        {
          "title": "Grupo vertical"
        }
      ],
      "props": {
        "RadioGroup": [
          {
            "prop": "name",
            "type": "string",
            "default": "—",
            "description": "Nombre del grupo (para accesibilidad)."
          },
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Valor seleccionado."
          },
          {
            "prop": "onChange",
            "type": "(value) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "orientation",
            "type": "'vertical' | 'horizontal'",
            "default": "'vertical'",
            "description": "Dirección de layout."
          }
        ],
        "Radio": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Valor que representa este radio."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva este radio."
          },
          {
            "prop": "children",
            "type": "ReactNode",
            "default": "—",
            "description": "Etiqueta."
          }
        ]
      },
      "example": "<RadioGroup name=\"visibilidad\" value={value} onChange={setValue}>\n  <Radio value=\"clientes\">Solo clientes</Radio>\n  <Radio value=\"todos\">Todos</Radio>\n  <Radio value=\"admin\">Privado</Radio>\n</RadioGroup>"
    },
    {
      "id": "switch",
      "name": "Switch",
      "category": "Forms",
      "export": "<Switch />",
      "description": "Toggle de activación instantánea. Usar para ajustes que se aplican en el momento (modo oscuro, visibilidad, notificaciones). Para opciones que se confirman con submit, usar Checkbox.",
      "variants": [
        {
          "title": "Estados"
        },
        {
          "title": "Con label inline"
        }
      ],
      "props": {
        "Switch": [
          {
            "prop": "checked",
            "type": "boolean",
            "default": "false",
            "description": "Estado controlado."
          },
          {
            "prop": "defaultChecked",
            "type": "boolean",
            "default": "false",
            "description": "Estado inicial no controlado."
          },
          {
            "prop": "onChange",
            "type": "(checked) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "size",
            "type": "'md' | 'lg'",
            "default": "'md'",
            "description": "28×16 o 36×20 px."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva el switch."
          },
          {
            "prop": "children",
            "type": "ReactNode",
            "default": "—",
            "description": "Label inline (clickeable)."
          }
        ]
      },
      "example": "<Switch checked={dark} onChange={setDark}>\n  Modo oscuro\n</Switch>"
    },
    {
      "id": "badge",
      "name": "Badge",
      "category": "Feedback",
      "export": "<Badge />",
      "description": "Etiqueta corta para marcar estados, categorías o conteos. Por defecto en variante soft (fondo tintado + texto oscuro); variante solid cuando se necesita mayor contraste (sobre imágenes, tarjetas oscuras).",
      "variants": [
        {
          "title": "Variantes soft (default)"
        },
        {
          "title": "Variantes solid"
        },
        {
          "title": "Tamaños",
          "detail": "sm (16) · md (18, default) · lg (22)"
        },
        {
          "title": "Count y dot",
          "detail": "Variantes especiales"
        }
      ],
      "props": {
        "Badge": [
          {
            "prop": "variant",
            "type": "'neutral' | 'accent' | 'success' | 'warning' | 'danger' | 'info'",
            "default": "'neutral'",
            "description": "Color semántico."
          },
          {
            "prop": "solid",
            "type": "boolean",
            "default": "false",
            "description": "Fondo sólido en vez de soft."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Tamaño del badge."
          },
          {
            "prop": "count",
            "type": "boolean",
            "default": "false",
            "description": "Forma circular para números."
          },
          {
            "prop": "dot",
            "type": "boolean",
            "default": "false",
            "description": "Punto de 8px sin texto."
          },
          {
            "prop": "children",
            "type": "ReactNode",
            "default": "—",
            "description": "Contenido (ignorado si dot)."
          }
        ]
      },
      "example": "<Badge variant=\"success\">Activo</Badge>\n<Badge variant=\"danger\" solid>Crítico</Badge>\n<Badge variant=\"accent\" count>12</Badge>\n<Badge variant=\"success\" dot />"
    },
    {
      "id": "pill",
      "name": "Pill",
      "category": "Feedback",
      "export": "<Pill />",
      "description": "Indicador de estado con semáforo de color integrado (dot delante). Se usa en tablas, headers de entidad y listas para comunicar el estado de un registro a golpe de vista.",
      "variants": [
        {
          "title": "Variantes semánticas"
        },
        {
          "title": "Tamaños",
          "detail": "sm (18) · md (22, default) · lg (26)"
        },
        {
          "title": "Uso en contexto"
        }
      ],
      "props": {
        "Pill": [
          {
            "prop": "variant",
            "type": "'neutral' | 'accent' | 'success' | 'warning' | 'danger' | 'info'",
            "default": "'neutral'",
            "description": "Color semántico."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Tamaño de la pill."
          },
          {
            "prop": "children",
            "type": "ReactNode",
            "default": "—",
            "description": "Etiqueta del estado."
          }
        ]
      },
      "example": "<Pill variant=\"success\">Publicado</Pill>\n<Pill variant=\"warning\" size=\"sm\">Borrador</Pill>"
    },
    {
      "id": "alert",
      "name": "Alert",
      "category": "Feedback",
      "export": "<Alert />",
      "description": "Mensaje informativo inline, embebido en el flujo de la página. Para notificaciones no intrusivas usar Toast; para bloqueos usar Modal.",
      "variants": [
        {
          "title": "Variantes"
        }
      ],
      "props": {
        "Alert": [
          {
            "prop": "variant",
            "type": "'info' | 'success' | 'warning' | 'danger' | 'neutral'",
            "default": "'info'",
            "description": "Color semántico."
          },
          {
            "prop": "title",
            "type": "string",
            "default": "—",
            "description": "Título del alert."
          },
          {
            "prop": "icon",
            "type": "ReactNode | false",
            "default": "auto",
            "description": "Icono custom o false para ocultar."
          },
          {
            "prop": "closable",
            "type": "boolean",
            "default": "false",
            "description": "Muestra botón de cierre."
          },
          {
            "prop": "onClose",
            "type": "() => void",
            "default": "—",
            "description": "Handler de cierre."
          },
          {
            "prop": "children",
            "type": "ReactNode",
            "default": "—",
            "description": "Descripción / contenido."
          }
        ]
      },
      "example": "<Alert variant=\"warning\" title=\"Hay cambios sin guardar\" closable>\n  Si sales ahora perderás las modificaciones.\n</Alert>"
    },
    {
      "id": "toast",
      "name": "Toast",
      "category": "Feedback",
      "export": "<Toast /> · toast()",
      "description": "Notificación flotante que aparece en la esquina (por defecto bottom-right), auto-desaparece a los 5s y puede apilarse. Se dispara imperativamente con la función toast(), no se renderiza en JSX salvo para el <Toaster /> provider.",
      "variants": [
        {
          "title": "Variantes"
        }
      ],
      "props": {
        "Toast": [
          {
            "prop": "title",
            "type": "string",
            "default": "—",
            "description": "Primer argumento, título del toast."
          },
          {
            "prop": "options.description",
            "type": "string",
            "default": "—",
            "description": "Línea secundaria."
          },
          {
            "prop": "options.duration",
            "type": "number",
            "default": "5000",
            "description": "Ms antes de auto-cerrar. 0 = no cierra."
          },
          {
            "prop": "options.actions",
            "type": "{ label, onClick }[]",
            "default": "—",
            "description": "Hasta 2 acciones inline."
          },
          {
            "prop": "options.closable",
            "type": "boolean",
            "default": "true",
            "description": "Muestra botón de cierre."
          }
        ],
        "<Toaster />": [
          {
            "prop": "position",
            "type": "'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center'",
            "default": "'bottom-right'",
            "description": "Esquina de aparición."
          },
          {
            "prop": "max",
            "type": "number",
            "default": "5",
            "description": "Máximo de toasts visibles simultáneamente."
          }
        ]
      },
      "example": "// 1. Añadir el Toaster una vez en el root de la app\n<Toaster position=\"bottom-right\" />\n\n// 2. Disparar toasts imperativamente\ntoast.success(\"Artículo guardado\", { description: \"Se ha publicado.\" });\ntoast.error(\"No se pudo eliminar\");\ntoast.warning(\"Sincronización parcial\", {\n  description: \"3 de 24 no se actualizaron.\",\n  actions: [\n    { label: \"Ver detalle\", onClick: openDetail },\n    { label: \"Reintentar\", onClick: retry },\n  ]\n});\ntoast.info(\"Exportación en curso\", { duration: 0 });"
    },
    {
      "id": "progress",
      "name": "Progress",
      "category": "Feedback",
      "export": "<Progress />",
      "description": "Barra de progreso lineal. Usa value determinado (0–100) para operaciones medibles; indeterminate para procesos sin cuantificar (cargando datos, guardando).",
      "variants": [
        {
          "title": "Valores"
        },
        {
          "title": "Estados",
          "detail": "en progreso (naranja) · finalizado · error"
        },
        {
          "title": "Indeterminado"
        }
      ],
      "props": {
        "Progress": [
          {
            "prop": "value",
            "type": "number (0–100)",
            "default": "0",
            "description": "Porcentaje completado."
          },
          {
            "prop": "indeterminate",
            "type": "boolean",
            "default": "false",
            "description": "Animación sin valor concreto."
          },
          {
            "prop": "variant",
            "type": "'progress' | 'success' | 'danger'",
            "default": "'progress'",
            "description": "Estado: en progreso (naranja) · finalizado (success) · error (danger)."
          },
          {
            "prop": "label",
            "type": "string",
            "default": "—",
            "description": "Etiqueta encima de la barra."
          },
          {
            "prop": "showValue",
            "type": "boolean",
            "default": "false",
            "description": "Muestra el % al lado del label."
          }
        ]
      },
      "example": "<Progress value={62} />\n<Progress value={100} variant=\"success\" />\n<Progress indeterminate />"
    },
    {
      "id": "spinner",
      "name": "Spinner",
      "category": "Feedback",
      "export": "<Spinner />",
      "description": "Indicador circular de carga. Para cargas dentro de botones usar <Button loading />; para áreas de contenido mayores, combinar con overlay o usar Skeleton.",
      "variants": [
        {
          "title": "Tamaños",
          "detail": "sm (16) · md (24, default) · lg (32)"
        },
        {
          "title": "Colores",
          "detail": "accent (sin fondo) · white (sobre leading)"
        },
        {
          "title": "Con label"
        }
      ],
      "props": {
        "Spinner": [
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "16 / 24 / 32 px."
          },
          {
            "prop": "color",
            "type": "'accent' | 'white'",
            "default": "'accent'",
            "description": "accent sin fondo · white sobre pastilla leading."
          },
          {
            "prop": "label",
            "type": "string",
            "default": "—",
            "description": "Texto accesible (sr-only)."
          }
        ]
      },
      "example": "<Spinner />\n<Spinner size=\"sm\" />\n<Spinner color=\"white\" />  // sobre fondo leading"
    },
    {
      "id": "skeleton",
      "name": "Skeleton",
      "category": "Feedback",
      "export": "<Skeleton />",
      "description": "Placeholder animado que reproduce la silueta del contenido real mientras se carga. Preferible al spinner para listas y cards: reduce la percepción de espera y mantiene la estabilidad del layout.",
      "variants": [
        {
          "title": "Primitivas"
        },
        {
          "title": "Card de artículo",
          "detail": "Ejemplo compuesto"
        }
      ],
      "props": {
        "Skeleton": [
          {
            "prop": "variant",
            "type": "'text' | 'title' | 'circle' | 'rect'",
            "default": "'text'",
            "description": "Forma del placeholder."
          },
          {
            "prop": "width",
            "type": "string | number",
            "default": "'100%'",
            "description": "Ancho (px o %)."
          },
          {
            "prop": "height",
            "type": "string | number",
            "default": "auto",
            "description": "Alto (px o %). Ignorado si variant text/title."
          },
          {
            "prop": "lines",
            "type": "number",
            "default": "1",
            "description": "Solo variant 'text': repite líneas con ancho decreciente."
          },
          {
            "prop": "size",
            "type": "number",
            "default": "40",
            "description": "Solo variant 'circle': diámetro."
          }
        ]
      },
      "example": "<Skeleton variant=\"title\" width=\"60%\" />\n<Skeleton variant=\"text\" lines={3} />\n<Skeleton variant=\"circle\" size={40} />\n<Skeleton variant=\"rect\" width={56} height={56} />"
    },
    {
      "id": "empty",
      "name": "Empty state",
      "category": "Feedback",
      "export": "<Empty />",
      "description": "Pantalla de contenido vacío. Obligatorio incluir al menos una acción primaria que desbloquee al usuario (crear, importar, invitar). Nunca mostrar solo el mensaje.",
      "variants": [
        {
          "title": "Sin resultados de búsqueda"
        },
        {
          "title": "Colección vacía (first run)"
        },
        {
          "title": "Error de carga"
        }
      ],
      "props": {
        "Empty": [
          {
            "prop": "icon",
            "type": "ReactNode",
            "default": "—",
            "description": "Icono superior (64×64 contenedor)."
          },
          {
            "prop": "tone",
            "type": "'neutral' | 'accent' | 'danger'",
            "default": "'neutral'",
            "description": "Color del círculo del icono."
          },
          {
            "prop": "title",
            "type": "string",
            "default": "—",
            "description": "Título principal."
          },
          {
            "prop": "description",
            "type": "string",
            "default": "—",
            "description": "Descripción de la situación."
          },
          {
            "prop": "actions",
            "type": "ReactNode[]",
            "default": "—",
            "description": "Array de acciones (1–2 botones)."
          }
        ]
      },
      "example": "<Empty\n  icon={<IconSearch />}\n  title=\"No encontramos artículos\"\n  description=\"Prueba con otros términos o quita los filtros.\"\n  actions={[\n    <Button variant=\"secondary\">Quitar filtros</Button>,\n    <Button variant=\"primary\">Nuevo artículo</Button>\n  ]}\n/>"
    },
    {
      "id": "modal",
      "name": "Modal",
      "category": "Overlays",
      "export": "<Modal />",
      "description": "Diálogo centrado con overlay que bloquea la interacción de fondo. Para acciones que requieren foco total del usuario: confirmaciones, formularios cortos, decisiones críticas. Tres composiciones: estándar, confirmación (con icono semántico) y formulario.",
      "variants": [
        {
          "title": "Confirmación destructiva",
          "detail": "size sm + icono danger"
        },
        {
          "title": "Formulario",
          "detail": "size md + footer between"
        }
      ],
      "props": {
        "Modal": [
          {
            "prop": "open",
            "type": "boolean",
            "default": "false",
            "description": "Controla la visibilidad."
          },
          {
            "prop": "onClose",
            "type": "() => void",
            "default": "—",
            "description": "Se invoca al cerrar (Esc, overlay, botón)."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "380 / 480 / 720 px."
          },
          {
            "prop": "closeOnOverlay",
            "type": "boolean",
            "default": "true",
            "description": "Cerrar al clicar el fondo."
          },
          {
            "prop": "closeOnEsc",
            "type": "boolean",
            "default": "true",
            "description": "Cerrar con tecla Escape."
          },
          {
            "prop": "initialFocus",
            "type": "RefObject",
            "default": "—",
            "description": "Elemento que recibe foco al abrir."
          }
        ]
      },
      "example": "<Modal open={open} onClose={close} size=\"sm\">\n  <Modal.Header>Eliminar artículo</Modal.Header>\n  <Modal.Body icon={<IconTrash />} tone=\"danger\">\n    ¿Seguro que quieres eliminar este artículo?\n  </Modal.Body>\n  <Modal.Footer>\n    <Button variant=\"secondary\">Cancelar</Button>\n    <Button variant=\"danger\">Eliminar</Button>\n  </Modal.Footer>\n</Modal>"
    },
    {
      "id": "drawer",
      "name": "Drawer",
      "category": "Overlays",
      "export": "<Drawer />",
      "description": "Panel lateral deslizante. Ideal para edición contextual sin perder el contexto de la lista (configurar un artículo, filtros avanzados, detalle de pedido). Posiciones: right (default), left, bottom.",
      "variants": [
        {
          "title": "Panel derecho de edición"
        }
      ],
      "props": {
        "Drawer": [
          {
            "prop": "open",
            "type": "boolean",
            "default": "false",
            "description": "Controla la visibilidad."
          },
          {
            "prop": "onClose",
            "type": "() => void",
            "default": "—",
            "description": "Handler de cierre."
          },
          {
            "prop": "position",
            "type": "'right' | 'left' | 'bottom'",
            "default": "'right'",
            "description": "Borde de aparición."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "320 / 380 / 480 px (ancho)."
          },
          {
            "prop": "closeOnOverlay",
            "type": "boolean",
            "default": "true",
            "description": "Cerrar al clicar el fondo."
          }
        ]
      },
      "example": "<Drawer open={open} onClose={close} position=\"right\" size=\"md\">\n  <Drawer.Header kicker=\"Editar artículo\">\n    Camiseta algodón orgánico\n  </Drawer.Header>\n  <Drawer.Body>{/* campos */}</Drawer.Body>\n  <Drawer.Footer>\n    <Button variant=\"secondary\">Cancelar</Button>\n    <Button>Guardar</Button>\n  </Drawer.Footer>\n</Drawer>"
    },
    {
      "id": "tooltip",
      "name": "Tooltip",
      "category": "Overlays",
      "export": "<Tooltip />",
      "description": "Etiqueta contextual que aparece al hover/focus. Solo para texto breve aclaratorio (nunca interactivo — para contenido con acciones usar Popover). Aparece tras 400ms de delay.",
      "variants": [
        {
          "title": "Simple · 4 posiciones"
        },
        {
          "title": "Rich (con título)"
        }
      ],
      "props": {
        "Tooltip": [
          {
            "prop": "content",
            "type": "string | ReactNode",
            "default": "—",
            "description": "Texto o cuerpo del tooltip."
          },
          {
            "prop": "title",
            "type": "string",
            "default": "—",
            "description": "Título (activa variante rich)."
          },
          {
            "prop": "placement",
            "type": "'top' | 'bottom' | 'left' | 'right'",
            "default": "'top'",
            "description": "Posición relativa al trigger."
          },
          {
            "prop": "delay",
            "type": "number",
            "default": "400",
            "description": "Ms antes de mostrarse."
          },
          {
            "prop": "children",
            "type": "ReactElement",
            "default": "—",
            "description": "Elemento disparador."
          }
        ]
      },
      "example": "<Tooltip content=\"Duplicar artículo\">\n  <IconButton aria-label=\"Duplicar\"><IconDuplicar /></IconButton>\n</Tooltip>\n\n<Tooltip title=\"SKU sincronizado\" content=\"Hace 3 min\" placement=\"top\">\n  <Badge variant=\"success\">Sync</Badge>\n</Tooltip>"
    },
    {
      "id": "popover",
      "name": "Popover & Menu",
      "category": "Overlays",
      "export": "<Popover /> · <Menu />",
      "description": "Panel flotante anclado a un disparador, con contenido interactivo (a diferencia del Tooltip). Menu es la variante especializada en listas de acciones: items, atajos, separadores y acciones destructivas.",
      "variants": [
        {
          "title": "Popover genérico"
        },
        {
          "title": "Menu de acciones",
          "detail": "con secciones, atajos y acción destructiva"
        }
      ],
      "props": {
        "Popover / Menu": [
          {
            "prop": "trigger",
            "type": "ReactElement",
            "default": "—",
            "description": "Elemento que abre el panel."
          },
          {
            "prop": "placement",
            "type": "'bottom-start' | 'bottom-end' | 'top-start' | …",
            "default": "'bottom-start'",
            "description": "Anclaje respecto al trigger."
          },
          {
            "prop": "open",
            "type": "boolean",
            "default": "—",
            "description": "Modo controlado (opcional)."
          },
          {
            "prop": "onOpenChange",
            "type": "(open) => void",
            "default": "—",
            "description": "Cambio de estado."
          }
        ],
        "Menu.Item": [
          {
            "prop": "icon",
            "type": "ReactNode",
            "default": "—",
            "description": "Icono a la izquierda."
          },
          {
            "prop": "shortcut",
            "type": "string",
            "default": "—",
            "description": "Atajo de teclado mostrado a la derecha."
          },
          {
            "prop": "danger",
            "type": "boolean",
            "default": "false",
            "description": "Estilo destructivo (rojo)."
          },
          {
            "prop": "onSelect",
            "type": "() => void",
            "default": "—",
            "description": "Handler al elegir el item."
          }
        ]
      },
      "example": "// Popover\n<Popover trigger={<Button>Precio</Button>} placement=\"bottom-start\">\n  {/* contenido interactivo */}\n</Popover>\n\n// Menu\n<Menu trigger={<IconButton aria-label=\"Opciones\">…</IconButton>}>\n  <Menu.Label>Artículo</Menu.Label>\n  <Menu.Item icon={<IconLapiz />} shortcut=\"E\">Editar</Menu.Item>\n  <Menu.Divider />\n  <Menu.Item danger icon={<IconEliminar />}>Eliminar</Menu.Item>\n</Menu>"
    },
    {
      "id": "tabs",
      "name": "Tabs",
      "category": "Navigation",
      "export": "<Tabs />",
      "description": "Conmutación entre vistas de un mismo contexto. Tres variantes: underline (default, para navegación de página), pill (para filtros suaves) y solid (segmented, para alternar modos de vista).",
      "variants": [
        {
          "title": "Underline (default)"
        },
        {
          "title": "Pill"
        },
        {
          "title": "Solid (segmented)"
        }
      ],
      "props": {
        "Tabs": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Tab activa (controlado)."
          },
          {
            "prop": "onChange",
            "type": "(value) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "variant",
            "type": "'underline' | 'pill' | 'solid'",
            "default": "'underline'",
            "description": "Estilo visual."
          }
        ],
        "Tabs.Tab": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Identificador de la tab."
          },
          {
            "prop": "count",
            "type": "number",
            "default": "—",
            "description": "Contador opcional."
          },
          {
            "prop": "disabled",
            "type": "boolean",
            "default": "false",
            "description": "Desactiva la tab."
          }
        ]
      },
      "example": "<Tabs value={tab} onChange={setTab} variant=\"underline\">\n  <Tabs.Tab value=\"articulos\" count={128}>Artículos</Tabs.Tab>\n  <Tabs.Tab value=\"familias\" count={12}>Familias</Tabs.Tab>\n</Tabs>"
    },
    {
      "id": "accordion",
      "name": "Accordion",
      "category": "Navigation",
      "export": "<Accordion />",
      "description": "Secciones colapsables para organizar contenido extenso (configuración de artículo, FAQs, filtros agrupados). Modo single (solo una abierta) o multiple.",
      "variants": [
        {
          "title": "Modo single"
        }
      ],
      "props": {
        "Accordion": [
          {
            "prop": "type",
            "type": "'single' | 'multiple'",
            "default": "'single'",
            "description": "Cuántos paneles abiertos a la vez."
          },
          {
            "prop": "defaultValue",
            "type": "string | string[]",
            "default": "—",
            "description": "Panel(es) abierto(s) al inicio."
          },
          {
            "prop": "collapsible",
            "type": "boolean",
            "default": "true",
            "description": "Permite cerrar todos (solo single)."
          }
        ],
        "Accordion.Item": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Identificador del panel."
          },
          {
            "prop": "title",
            "type": "string",
            "default": "—",
            "description": "Texto del trigger."
          }
        ]
      },
      "example": "<Accordion type=\"single\" defaultValue=\"general\">\n  <Accordion.Item value=\"general\" title=\"Información general\">\n    {/* contenido */}\n  </Accordion.Item>\n</Accordion>"
    },
    {
      "id": "breadcrumbs",
      "name": "Breadcrumbs",
      "category": "Navigation",
      "export": "<Breadcrumbs />",
      "description": "Ruta jerárquica que indica dónde está el usuario y permite subir niveles. Esencial en la navegación profunda de catálogos (Catálogo › Familia › Subfamilia › Artículo).",
      "variants": [
        {
          "title": "Estándar"
        },
        {
          "title": "Colapsado",
          "detail": "rutas largas con menú intermedio"
        }
      ],
      "props": {
        "Breadcrumbs": [
          {
            "prop": "maxItems",
            "type": "number",
            "default": "—",
            "description": "Colapsa el centro si se supera."
          },
          {
            "prop": "separator",
            "type": "ReactNode",
            "default": "chevron",
            "description": "Separador custom."
          }
        ],
        "Breadcrumbs.Item": [
          {
            "prop": "href",
            "type": "string",
            "default": "—",
            "description": "Destino del enlace."
          },
          {
            "prop": "current",
            "type": "boolean",
            "default": "false",
            "description": "Marca el item actual (no clickable)."
          }
        ]
      },
      "example": "<Breadcrumbs>\n  <Breadcrumbs.Item href=\"/catalogos\">Catálogos</Breadcrumbs.Item>\n  <Breadcrumbs.Item href=\"/c/primavera\">Primavera 2026</Breadcrumbs.Item>\n  <Breadcrumbs.Item current>Algodón orgánico</Breadcrumbs.Item>\n</Breadcrumbs>"
    },
    {
      "id": "pagination",
      "name": "Pagination",
      "category": "Navigation",
      "export": "<Pagination />",
      "description": "Navegación entre páginas de resultados. Muestra primera/última, vecinas y elipsis para rangos largos. Acompañar con el rango de resultados visible.",
      "variants": [
        {
          "title": "Numerada con info"
        },
        {
          "title": "Tamaño sm"
        }
      ],
      "props": {
        "Pagination": [
          {
            "prop": "page",
            "type": "number",
            "default": "1",
            "description": "Página actual."
          },
          {
            "prop": "pageCount",
            "type": "number",
            "default": "—",
            "description": "Total de páginas."
          },
          {
            "prop": "onPageChange",
            "type": "(page) => void",
            "default": "—",
            "description": "Handler de cambio."
          },
          {
            "prop": "siblingCount",
            "type": "number",
            "default": "1",
            "description": "Vecinas a cada lado de la actual."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md'",
            "default": "'md'",
            "description": "28 o 32 px por botón."
          }
        ]
      },
      "example": "<Pagination\n  page={1}\n  pageCount={13}\n  onPageChange={setPage}\n  siblingCount={1}\n/>"
    },
    {
      "id": "tree",
      "name": "Tree",
      "category": "Navigation",
      "export": "<Tree />",
      "description": "Navegación jerárquica expandible. Es la columna vertebral del backoffice de catálogos: árbol de catálogos › familias › subfamilias. Nodo activo con barra accent a la izquierda.",
      "variants": [
        {
          "title": "Árbol de catálogo"
        }
      ],
      "props": {
        "Tree": [
          {
            "prop": "value",
            "type": "string",
            "default": "—",
            "description": "Id del nodo seleccionado."
          },
          {
            "prop": "onSelect",
            "type": "(id) => void",
            "default": "—",
            "description": "Handler de selección."
          },
          {
            "prop": "defaultExpanded",
            "type": "string[]",
            "default": "—",
            "description": "Nodos abiertos al inicio."
          }
        ],
        "Tree.Node": [
          {
            "prop": "id",
            "type": "string",
            "default": "—",
            "description": "Identificador único."
          },
          {
            "prop": "label",
            "type": "string",
            "default": "—",
            "description": "Texto del nodo."
          },
          {
            "prop": "icon",
            "type": "ReactNode",
            "default": "—",
            "description": "Icono a la izquierda."
          },
          {
            "prop": "count",
            "type": "number",
            "default": "—",
            "description": "Contador a la derecha."
          }
        ]
      },
      "example": "<Tree value={selectedId} onSelect={setSelected}>\n  <Tree.Node id=\"primavera\" label=\"Primavera 2026\" count={128}>\n    <Tree.Node id=\"camisetas\" label=\"Camisetas\" count={42} />\n    <Tree.Node id=\"pantalones\" label=\"Pantalones\">…</Tree.Node>\n  </Tree.Node>\n</Tree>"
    },
    {
      "id": "table",
      "name": "Table",
      "category": "Data",
      "export": "<Table />",
      "description": "Tabla de datos con cabecera ordenable, selección múltiple y acciones por fila. Las columnas numéricas se alinean a la derecha con tabular-nums para que los dígitos cuadren verticalmente. Dos densidades: normal (40px de fila) y compacta (32px).",
      "variants": [
        {
          "title": "Tabla completa",
          "detail": "toolbar + orden + selección + acciones + footer"
        },
        {
          "title": "Densidad compacta",
          "detail": "filas de 32px para listados largos"
        }
      ],
      "props": {
        "Table": [
          {
            "prop": "columns",
            "type": "Column[]",
            "default": "—",
            "description": "Definición de columnas (ver abajo)."
          },
          {
            "prop": "data",
            "type": "T[]",
            "default": "[]",
            "description": "Filas a renderizar."
          },
          {
            "prop": "density",
            "type": "'default' | 'compact'",
            "default": "'default'",
            "description": "Alto de fila: 40px ó 32px."
          },
          {
            "prop": "striped",
            "type": "boolean",
            "default": "false",
            "description": "Bandas alternas en las filas."
          },
          {
            "prop": "selectable",
            "type": "boolean",
            "default": "false",
            "description": "Añade columna de checkbox y selección múltiple."
          },
          {
            "prop": "selectedKeys",
            "type": "string[]",
            "default": "—",
            "description": "Filas seleccionadas (controlado)."
          },
          {
            "prop": "onSelectionChange",
            "type": "(keys) => void",
            "default": "—",
            "description": "Cambio de selección."
          },
          {
            "prop": "sort",
            "type": "{ key, dir }",
            "default": "—",
            "description": "Estado de ordenación."
          },
          {
            "prop": "onSortChange",
            "type": "(sort) => void",
            "default": "—",
            "description": "Click en cabecera ordenable."
          },
          {
            "prop": "onRowClick",
            "type": "(row) => void",
            "default": "—",
            "description": "Click en fila."
          },
          {
            "prop": "loading",
            "type": "boolean",
            "default": "false",
            "description": "Muestra filas Skeleton."
          },
          {
            "prop": "empty",
            "type": "ReactNode",
            "default": "—",
            "description": "Contenido cuando no hay datos (usar Empty)."
          }
        ],
        "Column": [
          {
            "prop": "key",
            "type": "string",
            "default": "—",
            "description": "Campo del dato."
          },
          {
            "prop": "label",
            "type": "string",
            "default": "—",
            "description": "Texto de cabecera."
          },
          {
            "prop": "align",
            "type": "'left' | 'right' | 'center'",
            "default": "'left'",
            "description": "Alineación. Numéricas siempre a la derecha."
          },
          {
            "prop": "numeric",
            "type": "boolean",
            "default": "false",
            "description": "Aplica fuente mono y tabular-nums."
          },
          {
            "prop": "sortable",
            "type": "boolean",
            "default": "false",
            "description": "Cabecera clicable para ordenar."
          },
          {
            "prop": "width",
            "type": "string | number",
            "default": "auto",
            "description": "Ancho fijo de la columna."
          },
          {
            "prop": "render",
            "type": "(row) => ReactNode",
            "default": "—",
            "description": "Render personalizado de la celda."
          }
        ]
      },
      "example": "<Table\n  columns={[\n    { key: 'name',  label: 'Artículo', sortable: true },\n    { key: 'sku',   label: 'SKU', mono: true },\n    { key: 'state', label: 'Estado', render: r => <Pill variant={r.tone}>{r.state}</Pill> },\n    { key: 'price', label: 'Precio', align: 'right', numeric: true },\n  ]}\n  data={items}\n  selectable\n  density=\"compact\"\n  onRowClick={openDetail}\n/>"
    },
    {
      "id": "card",
      "name": "Card",
      "category": "Data",
      "export": "<Card />",
      "description": "Contenedor de contenido agrupado. Las cards se separan por borde, nunca por sombra: la elevación se reserva para elementos que flotan sobre el contenido. Tres composiciones: básica, interactiva (clicable) y de métrica.",
      "variants": [
        {
          "title": "Básica",
          "detail": "header + body + footer"
        },
        {
          "title": "Interactiva con media",
          "detail": "card de artículo · estados default / hover / selected"
        },
        {
          "title": "Métrica",
          "detail": "para dashboards · MetricCard"
        }
      ],
      "props": {
        "Card": [
          {
            "prop": "interactive",
            "type": "boolean",
            "default": "false",
            "description": "Cursor pointer y hover de borde."
          },
          {
            "prop": "selected",
            "type": "boolean",
            "default": "false",
            "description": "Borde accent."
          },
          {
            "prop": "onClick",
            "type": "() => void",
            "default": "—",
            "description": "Handler de click (implica interactive)."
          },
          {
            "prop": "padding",
            "type": "'none' | 'sm' | 'md'",
            "default": "'md'",
            "description": "Padding del body."
          }
        ],
        "MetricCard": [
          {
            "prop": "label",
            "type": "string",
            "default": "—",
            "description": "Etiqueta superior en mayúsculas."
          },
          {
            "prop": "value",
            "type": "string | number",
            "default": "—",
            "description": "Cifra principal."
          },
          {
            "prop": "delta",
            "type": "{ value, direction }",
            "default": "—",
            "description": "direction: 'up' | 'down' | 'flat'."
          }
        ]
      },
      "example": "<Card>\n  <Card.Header title=\"Temporada Primavera 2026\" subtitle=\"Distribuciones García\" />\n  <Card.Body>248 artículos en 12 familias.</Card.Body>\n  <Card.Footer><Button size=\"sm\">Abrir</Button></Card.Footer>\n</Card>\n\n<MetricCard label=\"Artículos activos\" value=\"1.284\"\n  delta={{ value: '+12,4%', direction: 'up' }} />"
    },
    {
      "id": "avatar",
      "name": "Avatar",
      "category": "Data",
      "export": "<Avatar /> · <AvatarGroup />",
      "description": "Representación de una persona o entidad. Prioriza imagen; si no hay, cae a iniciales; si tampoco, a icono. Admite indicador de estado y agrupación con solapamiento.",
      "variants": [
        {
          "title": "Tipos",
          "detail": "imagen · iniciales · icono"
        },
        {
          "title": "Tamaños",
          "detail": "sm (24) · md (32) · lg (40)"
        },
        {
          "title": "Con estado"
        },
        {
          "title": "Grupo",
          "detail": "solapado, con contador de resto"
        }
      ],
      "props": {
        "Avatar": [
          {
            "prop": "src",
            "type": "string",
            "default": "—",
            "description": "URL de la imagen. Si falla, cae a iniciales."
          },
          {
            "prop": "name",
            "type": "string",
            "default": "—",
            "description": "Nombre completo. Genera las iniciales y el alt."
          },
          {
            "prop": "size",
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "24 / 32 / 40 px."
          },
          {
            "prop": "shape",
            "type": "'circle' | 'square'",
            "default": "'circle'",
            "description": "Forma del contenedor."
          },
          {
            "prop": "tone",
            "type": "'leading' | 'accent' | 'soft' | 'neutral'",
            "default": "'leading'",
            "description": "Color de fondo cuando no hay imagen."
          },
          {
            "prop": "status",
            "type": "'online' | 'busy' | 'away' | 'offline'",
            "default": "—",
            "description": "Punto indicador en la esquina."
          }
        ],
        "AvatarGroup": [
          {
            "prop": "max",
            "type": "number",
            "default": "4",
            "description": "Avatares visibles antes del contador."
          },
          {
            "prop": "size",
            "type": "AvatarSize",
            "default": "'sm'",
            "description": "Tamaño aplicado a todos los hijos."
          }
        ]
      },
      "example": "<Avatar src={user.photo} name=\"María García\" size=\"md\" />\n<Avatar name=\"María García\" status=\"online\" />\n\n<AvatarGroup max={3}>\n  {users.map(u => <Avatar key={u.id} name={u.name} src={u.photo} />)}\n</AvatarGroup>"
    }
  ]
}