6.5 KiB

Avanza UI - Sistema de Componentes

📦 Biblioteca de Componentes UI Propia

Avanza UI es un sistema de componentes independiente basado en CSS Modules y Variables CSS, inspirado en Tailwind CSS y Vristo, pero sin dependencias externas de frameworks CSS.

🎯 Filosofía

La biblioteca está diseñada para:

  • Independencia: Sin dependencia de Tailwind, Bootstrap u otros frameworks CSS
  • CSS Modules: Estilos encapsulados que previenen conflictos
  • Variables CSS: Sistema de diseño basado en CSS Variables para fácil personalización
  • TypeScript: Tipado completo para mejor experiencia de desarrollo

📁 Estructura del Proyecto

packages/ui-components/
├── src/
│   ├── styles/
│   │   └── globals.css          # Variables CSS y estilos globales
│   ├── components/
│   │   ├── Button.tsx            # Componente Button
│   │   ├── Button.module.css     # Estilos del Button
│   │   ├── Card.tsx
│   │   ├── Card.module.css
│   │   └── ...
│   ├── utils/
│   │   └── helpers.ts            # Utilidades (cn, debounce, etc.)
│   ├── types/
│   │   ├── index.ts              # Tipos TypeScript
│   │   └── css-modules.d.ts      # Declaraciones para CSS Modules
│   └── index.ts                  # Punto de entrada
├── package.json
├── tsconfig.json
├── rollup.config.js
└── README.md

🎨 Sistema de Diseño (Design Tokens)

Variables CSS Globales

El sistema utiliza variables CSS con el prefijo --au- (avanza-ui):

:root {
  /* Colores Primarios */
  --au-primary-600: #4f46e5;
  --au-primary-hover: #4338ca;
  
  /* Grises */
  --au-gray-50: #f8fafc;
  --au-gray-900: #0f172a;
  
  /* Espaciado */
  --au-spacing-4: 1rem;      /* 16px */
  --au-spacing-6: 1.5rem;    /* 24px */
  
  /* Bordes */
  --au-radius-md: 0.5rem;
  --au-radius-lg: 0.75rem;
  
  /* Sombras */
  --au-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

Soporte de Temas (Light/Dark)

/* Tema Light (default) */
:root,
[data-theme="light"] {
  --au-bg-primary: var(--au-gray-50);
  --au-text-primary: var(--au-gray-900);
}

/* Tema Dark */
[data-theme="dark"] {
  --au-bg-primary: var(--au-gray-950);
  --au-text-primary: var(--au-gray-50);
}

🛠️ Desarrollo

Cómo usar este sistema en tus proyectos

# En ui-components
cd packages/ui-components
npm link

# En tu proyecto (ej: studio-panel)
cd packages/studio-panel
npm link avanza-ui

Opción 2: Dependencia local en package.json

{
  "dependencies": {
    "avanza-ui": "file:../ui-components"
  }
}

Opción 3: Publicar a npm (Producción)

cd packages/ui-components
npm publish

Uso en tu proyecto

// Importar estilos globales
import 'avanza-ui/dist/index.css';

// Importar componentes
import { Button, Card, Input } from 'avanza-ui';

function App() {
  return (
    <Card>
      <Input label="Nombre" placeholder="Tu nombre" />
      <Button variant="primary">Guardar</Button>
    </Card>
  );
}

📝 Cómo crear nuevos componentes

1. Crear el archivo de estilos (CSS Module)

/* src/components/MiComponente.module.css */
.miComponente {
  background-color: var(--au-surface);
  padding: var(--au-spacing-4);
  border-radius: var(--au-radius-md);
  border: 1px solid var(--au-border-light);
}

.miComponente:hover {
  background-color: var(--au-surface-hover);
}

2. Crear el componente TypeScript

/* src/components/MiComponente.tsx */
import React from 'react';
import { cn } from '../utils/helpers';
import type { ComponentBaseProps } from '../types';
import styles from './MiComponente.module.css';

export interface MiComponenteProps extends ComponentBaseProps {
  variant?: 'default' | 'primary';
  children?: React.ReactNode;
}

export const MiComponente = React.forwardRef<HTMLDivElement, MiComponenteProps>(
  ({ variant = 'default', children, className, style, id }, ref) => {
    return (
      <div
        ref={ref}
        className={cn(styles.miComponente, styles[variant], className)}
        style={style}
        id={id}
      >
        {children}
      </div>
    );
  }
);

MiComponente.displayName = 'MiComponente';

3. Exportar en index.ts

export { MiComponente } from './components/MiComponente';
export type { MiComponenteProps } from './components/MiComponente';

4. Compilar

npm run build

🚀 Ejemplo Real: broadcast-panel

El paquete broadcast-panel ya utiliza este sistema exitosamente. Puedes revisar su código como referencia:

packages/broadcast-panel/src/
├── styles.css                 # Importa las variables globales
├── components/
│   ├── Header.tsx
│   ├── Header.module.css
│   ├── Sidebar.tsx
│   ├── Sidebar.module.css
│   └── ...

📚 Componentes Disponibles

Button

<Button variant="primary" size="md" loading={false}>
  Click me
</Button>

Card

<Card padding="md" hoverable>
  <CardHeader>Título</CardHeader>
  <CardBody>Contenido</CardBody>
  <CardFooter>Pie</CardFooter>
</Card>

Input

<Input 
  label="Email"
  type="email"
  error={hasError}
  errorMessage="Email inválido"
/>

Dropdown

<Dropdown trigger={<Button>Opciones</Button>}>
  <DropdownItem icon={<Icon />}>Opción 1</DropdownItem>
  <DropdownDivider />
  <DropdownItem danger>Eliminar</DropdownItem>
</Dropdown>

Modal

<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
  <ModalHeader title="Título" onClose={() => setIsOpen(false)} />
  <ModalBody>Contenido del modal</ModalBody>
  <ModalFooter>
    <Button onClick={() => setIsOpen(false)}>Cerrar</Button>
  </ModalFooter>
</Modal>

🔧 Scripts NPM

npm run build      # Compilar la biblioteca
npm run dev        # Modo desarrollo con watch
npm run test       # Ejecutar tests

📦 Para usar en studio-panel

  1. Vincula la biblioteca:
cd packages/ui-components
npm run build
cd ../studio-panel
npm install ../ui-components
  1. Importa en tu código:
import { Button, Card } from 'avanza-ui';
import 'avanza-ui/dist/index.css';
  1. ¡Listo! Ya puedes usar los componentes.

🎯 Próximos Pasos

  1. Terminar de implementar todos los componentes
  2. Agregar tests unitarios
  3. Crear Storybook para documentación visual
  4. Publicar en npm registry privado o público

Avanza UI - Sistema de componentes moderno y sin dependencias para AvanzaCast