Ir al contenido
English

Navegar

Escribe para buscar. Pulsa Escape para cerrar.

    Proyecto

    Contribuir

    iVOLT es una base de código pequeña con reglas estrictas. La mayoría de esas reglas existen porque un sistema de diseño se rompe despacio: una clase sin prefijo, un !important, un componente documentado con marcado que ninguna prueba llega a renderizar. Las pruebas de contrato que vienen más abajo codifican esas reglas para que una pull request falle pronto en lugar de ir derivando.

    Licencia: MIT. Idioma: código, identificadores y documentación pública en inglés. Todo cambio de la superficie pública: un registro de decisión en docs/DECISIONS.md.

    Puesta en marcha

    git clone https://github.com/iNTERVOLUTIONS-Labs/iVOLT
    cd iVOLT
    npm ci                 # instala desde el único lockfile, nunca `npm install` en CI
    npm run build          # genera packages/ivolt/dist
    npm run dev:docs   # compila el paquete antes si falta dist/       # servidor de desarrollo de Astro para apps/docs

    El repositorio es un workspace de npm con un solo lockfile en la raíz. dist/ se genera y no se versiona, así que compila antes de lanzar la suite de navegador, el informe de tamaños o la prueba de humo del empaquetado.

    Comandos

    ComandoQué hace
    npm run buildCompila el paquete: primero se generan tokens y utilidades, después se escriben el CSS y el JS en packages/ivolt/dist.
    npm testVitest: pruebas unitarias de los componentes JS y pruebas de contrato sobre las fuentes CSS y los fragmentos documentados.
    npm run test:browserPlaywright. Solo Chromium por defecto; IVOLT_ALL_BROWSERS=1 npm run test:browser ejecuta Chromium, Firefox y WebKit. Cubre comportamiento, axe, desbordamiento de 320 a 1920 px, RTL, temas, páginas de documentación y recetas.
    npm run sizesInforma del tamaño de cada artefacto compilado. Un cambio que mueva esas cifras de forma apreciable debería explicar por qué.
    npm run pack-smokeEmpaqueta con npm pack, instala el tarball en un proyecto desechable y comprueba que los exports se resuelven y que los componentes sin usar se eliminan por tree-shaking.
    npm run check-examplesCarga las páginas de ejemplo y las recetas y verifica que siguen funcionando con la compilación actual.
    npm run build:docsCompila el sitio estático de documentación.
    npm run verifyTodo lo anterior en orden. Es la puerta antes de cerrar una fase.

    Playwright necesita que instales sus navegadores una vez (npx playwright install); las comprobaciones de axe pasan por @axe-core/playwright.

    Estructura del repositorio

    iVOLT/
    ├─ package.json              # workspaces + scripts de raíz
    ├─ package-lock.json         # el único lockfile
    ├─ docs/                     # contratos, sistema de diseño, listón de calidad, ADR, hoja de ruta
    ├─ packages/ivolt/
    │  ├─ tokens/tokens.json     # única fuente de verdad de los tokens
    │  ├─ fixtures/<familia>/*.html  # una fuente para documentación, pruebas y plantillas
    │  ├─ src/css/               # reset, tokens (generado), base, layout/, components/,
    │  │                         # utilities (generado), core.css, ivolt.css, ivolt.flat.css
    │  ├─ src/js/                # core/ (registro, opciones, eventos, foco, teclas),
    │  │                         # components/, theme.js, index.js, auto.js, iife.js
    │  ├─ scripts/               # build-tokens, build-utilities, build-css, build-js, sizes
    │  └─ dist/                  # generado, no versionado
    ├─ apps/docs/                # sitio estático de Astro
    ├─ examples/                 # plain-html, vite, recipes/
    ├─ tests/                    # unit, browser, contracts, integration
    └─ scripts/                  # pack-smoke, check-examples, sync-examples

    Hay dos archivos generados que nunca deben editarse a mano: src/css/tokens.css (desde tokens/tokens.json) y src/css/utilities.css (desde la configuración de utilidades). Cambia la fuente y vuelve a compilar. Lo mismo vale para custom-media.css, reset.layer.css y core/breakpoints.js.

    Reglas para un cambio

    CSS

    • Prefíjalo todo. Clases iv-, utilidades iv-u-, propiedades personalizadas --iv-, atributos de datos data-iv-.
    • Nada de !important. La única excepción es .iv-u-sr-only, y está documentada como tal.
    • Especificidad igual o menor que (0,2,0) en los selectores de componente, para que una utilidad — emitida con el selector duplicado a exactamente (0,2,0) y cargada la última — gane siempre. Las alternativas documentadas con :target para diálogo y panel lateral son la única excepción admitida.
    • Selectores de elemento solo dentro de .iv-root. Nada del paquete puede dar estilo a un elemento suelto de forma global.
    • Los módulos no declaran @layer ni importan nada. Las entradas asignan las capas en el momento de importar, y cada módulo se importa exactamente una vez por entrada.
    • Puntos de ruptura con nombres de @custom-media, nunca var() dentro de una media query, porque no funciona.
    • Los colores vienen de tokens semánticos. Un hexadecimal suelto en un archivo de componente es un error; no seguirá a los temas.

    Las fixtures son la fuente única

    Una fixture en packages/ivolt/fixtures/<familia>/<caso>.html es a la vez la vista previa de la página de documentación, el fragmento copiable y el marcado que renderizan las pruebas. No escribas marcado de ejemplo en línea dentro de una página de componente, ni marcado de prueba dentro de un archivo de spec. Si el fragmento documentado y el marcado probado pueden divergir, acabarán divergiendo.

    Cuándo está terminada una familia

    Contar variantes no ensancha el alcance. Una familia de componentes está terminada solo cuando tiene las cinco cosas:

    1. Estados: normal, hover, foco, activo, deshabilitado, y los de carga o error que necesite.
    2. Comportamiento de teclado, documentado tecla a tecla.
    3. Una alternativa para cuando JavaScript no se ejecuta.
    4. Documentación con fixtures.
    5. Pruebas: unitarias del comportamiento, de navegador del renderizado y axe en ambos temas.

    JavaScript

    • Sin acceso en el nivel superior a document, window, navigator ni matchMedia; las importaciones en SSR no deben lanzar.
    • Sin eval, sin new Function, sin innerHTML con datos externos, sin atributos on*. El paquete tiene que funcionar bajo script-src 'self'.
    • Sin dependencias, sin peticiones de red, sin telemetría.
    • init() es idempotente; destroy() devuelve el DOM a los atributos que encontró, y eso se prueba.
    • Los eventos llevan el prefijo iv: y forman parte del contrato: añadir o renombrar uno es un cambio de contrato.

    Los cambios de contrato necesitan un ADR

    Todo lo que cambie una superficie pública — un nombre de clase, un nombre de token, una opción, un evento, un export, el orden de capas — necesita una entrada en docs/DECISIONS.md con la decisión, las alternativas consideradas y la evidencia. El ADR forma parte de la pull request, no es un seguimiento posterior.

    Las pruebas de contrato

    Se ejecutan con npm test y fallan de forma ruidosa si se rompe alguna regla de arriba:

    ComprobaciónFalla cuando
    Los módulos no declaran capa ni importan nadaUn módulo fuente añade @layer o un @import
    Nada de !important fuera de las utilidades sr-onlyCualquier otra declaración lo usa
    Prefijos en clases y propiedades personalizadasAparece un nombre sin prefijo en las fuentes
    Selectores de elemento acotados a .iv-rootUn selector de elemento suelto se escapa del ámbito en base.css
    Techo de especificidad (0,2,0)Un selector de componente lo supera fuera de las excepciones documentadas
    Puntos de ruptura vía @custom-mediaUna media query lee una propiedad personalizada
    Las utilidades coinciden exactamente con la matriz declaradaEl archivo generado gana o pierde una clase respecto al contrato
    Las entradas importan cada módulo una vez y declaran el orden de capasUn import duplicado se come en silencio una asignación de capa
    Los fragmentos coinciden con la distribuciónEl marcado documentado deja de coincidir con lo que el paquete distribuye de verdad

    Si una prueba de contrato bloquea un cambio que crees correcto, la solución es un ADR que mueva el contrato, no una excepción en la prueba.

    Pull requests

    • Ejecuta npm run verify antes de abrir una, y di en la descripción qué comprobaciones pasaste y cuáles no pudiste pasar.
    • Mantén el cambio centrado en una familia o en un asunto; las refactorizaciones mezcladas son difíciles de revisar contra un contrato.
    • Informa de los errores de accesibilidad y de navegador con el nombre de la fixture, el motor y los pasos: la fixture hace que sea reproducible con un solo comando.
    • Desde la 1.0 la superficie pública sigue SemVer. Un cambio correcto que rompa compatibilidad espera a una versión mayor y se registra antes; un cambio cómodo pero sin registrar no entra nunca.

    Licencia

    MIT, Copyright (c) 2026 iNTERVOLUTIONS. Mira LICENSE en la raíz del repositorio. Las contribuciones se aceptan bajo la misma licencia.