Sistema de componentes
Sistema de componentes
Por qué los componentes cambian todo
Un diseño sin componentes es una fotografía: estático, difícil de mantener, imposible de escalar. Un diseño con componentes bien organizados es un sistema vivo: cambias el componente maestro y todas las instancias se actualizan automáticamente.
OpenPencil implementa un sistema de componentes que va un paso más allá del modelo tradicional de Figma. Los componentes en OpenPencil se conectan directamente con las variables de diseño, soportan múltiples temas de forma nativa, y tienen una correspondencia directa con los componentes del framework frontend que uses.
graph TD
A[Componente Maestro] --> B[Instancia 1]
A --> C[Instancia 2]
A --> D[Instancia N]
B --> B1[Override: texto diferente]
C --> C1[Override: variante dark]
D --> D1[Override: estado disabled]
E[Variables de diseño] --> A
E --> B
E --> C
E --> D
Crear un componente maestro
Método 1: Desde la interfaz
- Diseña el elemento que quieres convertir en componente (un frame con su contenido)
- Selecciónalo
- Click derecho → “Crear componente” (o
Cmd+Alt+K) - El frame se convierte en un componente: aparece con un ícono de diamante en el panel de capas
Una vez creado, el componente original es el maestro. Cualquier copia que hagas es una instancia.
Método 2: Con la IA
[En el chat, con un frame seleccionado]
"Convierte este botón en un componente con 4 variantes:
- primary: fondo azul, texto blanco
- secondary: fondo blanco, borde azul, texto azul
- ghost: sin fondo, sin borde, texto azul
- destructive: fondo rojo, texto blanco"
Método 3: Via CLI
# Crear un componente desde un nodo existente
op component create --file diseño.op --node "btn-principal" --name "Button/Primary"
# Crear componente con variantes
op component create \
--file diseño.op \
--node "btn-base" \
--name "Button" \
--variants "primary,secondary,ghost,destructive"
Anatomía de un componente
Un componente bien estructurado en OpenPencil tiene:
Button/Primary (Componente maestro)
├── frame "btn-container" (auto-layout horizontal, padding 12/20, gap 8)
│ ├── icon "btn-icon" (opcional, 16x16)
│ └── text "btn-label" ("Botón")
Buenas prácticas de nomenclatura
Usa la barra / para crear jerarquías en el panel de componentes:
Button/Primary
Button/Secondary
Button/Ghost
Button/Destructive
Button/Loading
Card/Default
Card/Highlighted
Card/Compact
Input/Default
Input/Focus
Input/Error
Input/Disabled
Badge/Success
Badge/Error
Badge/Warning
Badge/Info
Badge/Neutral
Esta nomenclatura crea una estructura de árbol en el panel de Assets (activos), facilitando la búsqueda y organización.
Instancias y overrides
Crear instancias
Para usar un componente en el diseño:
- Abre el panel de Assets (
Cmd+Alt+Oo click en el ícono de Assets) - Busca el componente que quieres usar
- Arrastra al canvas para crear una instancia
O bien: copia el componente maestro (Cmd+C) y pégalo (Cmd+V). OpenPencil detecta automáticamente que es un componente y crea una instancia.
Tipos de overrides
Los overrides son propiedades que se pueden cambiar en una instancia sin romper el vínculo con el maestro:
Override de texto: Cambia el contenido del texto en la instancia.
Maestro: text "Enviar"
Instancia 1: text "Cancelar" → Override de texto
Instancia 2: text "Confirmar" → Override de texto
Override de imagen: Reemplaza imágenes o iconos en la instancia.
Override de visibilidad: Oculta/muestra layers específicos de la instancia.
Override de variante: Cambia entre variantes del componente.
Override de propiedad de componente: Si el componente tiene props definidos, puedes cambiarlos en la instancia.
Definir props del componente
Al igual que los componentes React tienen props, los componentes de OpenPencil pueden tener props definidos:
- Selecciona el componente maestro
- En el panel derecho, sección “Component properties”
- Haz click en
+para agregar una prop
Tipos de props disponibles:
- Text: Una cadena de texto (para labels)
- Boolean: Para mostrar/ocultar elementos
- Instance swap: Para permitir cambiar un ícono o imagen
- Variant: Para seleccionar entre variantes predefinidas
Componente: Button
Props:
- label: Text (default: "Botón")
- icon: Instance swap (default: ninguno)
- showIcon: Boolean (default: false)
- variant: Variant (opciones: primary, secondary, ghost, destructive)
- size: Variant (opciones: sm, md, lg)
- isLoading: Boolean (default: false)
Cuando alguien usa una instancia de Button, puede configurar todos estos props desde el panel de propiedades sin entrar en el componente.
Variables de diseño
Las variables (también llamadas “tokens de diseño” o “design tokens”) son el sistema nervioso de un design system. Almacenan valores reutilizables que se pueden cambiar en un solo lugar y actualizar automáticamente en todo el diseño.
Tipos de variables
| Tipo | Ejemplos |
|---|---|
| Color | #2563EB, rgba(37, 99, 235, 0.5) |
| Number | 8, 16, 24, 1.5 |
| String | "Inter", "400" |
| Boolean | true, false |
Crear variables
- Abre el panel de Variables (
Cmd+Alt+V) - Click en
+para crear una nueva colección - Nómbrala (ej: “Brand Colors”)
- Agrega variables con
+
Estructura recomendada para un sistema de tokens:
Colección: Primitives (valores base, no usar directamente en componentes)
blue-50: #EFF6FF
blue-100: #DBEAFE
blue-500: #3B82F6
blue-600: #2563EB
blue-900: #1E3A8A
slate-50: #F8FAFC
slate-100: #F1F5F9
slate-900: #0F172A
green-500: #22C55E
red-500: #EF4444
Colección: Semantic (significado, referencian a Primitives)
color/background: → blue-50
color/text/primary: → slate-900
color/text/secondary: → slate-500
color/border: → slate-200
color/action/primary: → blue-600
color/action/primary-hover:→ blue-700
color/status/success: → green-500
color/status/error: → red-500
Colección: Component (específico por componente, referencian a Semantic)
button/bg: → color/action/primary
button/text: → #FFFFFF
button/border-radius: → 8
input/border: → color/border
input/bg: → color/background
Vincular variables a propiedades
Para vincular una variable a la propiedad de un nodo:
- Selecciona el nodo
- En el panel de propiedades, haz click en el campo de valor
- Aparece el ícono de “variable” (una caja pequeña) a la derecha del campo
- Click en ese ícono para abrir el selector de variables
- Selecciona la variable correspondiente
Frame "btn-container"
fills[0].color → button/bg
cornerRadius → button/border-radius
Text "btn-label"
fills[0].color → button/text
fontSize → typography/size/base
fontFamily → typography/family/sans
Ahora si cambias el valor de button/bg, todos los botones del diseño se actualizan instantáneamente.
Sintaxis $variable en el chat de IA
Al hablar con el agente de IA, puedes referenciar variables con la notación $nombre-variable:
"Diseña un card para artículo de blog.
Usa $color/background para el fondo.
El título debe usar $typography/size/xl y $color/text/primary.
El extracto debe usar $typography/size/base y $color/text/secondary.
El borde debe ser $color/border."
El agente reconoce las variables y las vincula correctamente al crear los nodos.
Temas Light/Dark
OpenPencil soporta múltiples temas nativamente. Un tema es simplemente un conjunto de modos para las variables de diseño.
Crear modos de tema
En el panel de Variables, cada colección puede tener múltiples modos:
- En la colección “Semantic”, haz click en el ícono de modos
- El modo inicial es “Light” (o “Default”)
- Haz click en
+para agregar el modo “Dark” - Para cada variable en la colección, puedes definir un valor diferente por modo
color/background:
Light mode → #FFFFFF
Dark mode → #0F172A
color/text/primary:
Light mode → #0F172A
Dark mode → #F8FAFC
color/border:
Light mode → #E2E8F0
Dark mode → #1E293B
color/action/primary:
Light mode → #2563EB
Dark mode → #3B82F6 (ligeramente más claro en dark)
Previsualizar temas
Con un frame seleccionado, en el panel de propiedades en la sección “Variables”:
- Puedes cambiar el modo de tema del frame para previsualizar cómo se ve en cada modo
- Los children del frame heredan el modo del padre a menos que tengan su propio override
Frame "App" → modo: Light
Frame "Sidebar" → hereda Light
Frame "Content" → hereda Light
Frame "DarkCard" → modo: Dark (override local)
Esto permite previsualizar componentes dark mode dentro de una pantalla light mode.
Exportar con soporte de temas
Al exportar a React + Tailwind, el motor genera el CSS de ambos modos:
op export react \
--file diseño.op \
--component "Card" \
--out ./src/components \
--themes "light,dark"
El código generado usa el atributo data-theme para alternar:
// Card.tsx — con soporte de temas
export function Card({ children }: { children: React.ReactNode }) {
return (
<div className="bg-background text-text-primary border border-border rounded-xl p-6">
{children}
</div>
)
}
/* tokens.css — con temas */
:root, [data-theme="light"] {
--background: #FFFFFF;
--text-primary: #0F172A;
--border: #E2E8F0;
}
[data-theme="dark"] {
--background: #0F172A;
--text-primary: #F8FAFC;
--border: #1E293B;
}
Variantes de componentes
Las variantes son la forma de gestionar múltiples estados y versiones de un componente dentro de un único componente maestro.
Crear variantes
- Selecciona el componente maestro
- En el panel de propiedades, haz click en
+junto a “Variants” - Define las dimensiones de variación (ej: “variant” con valores “primary, secondary, ghost”)
- Para cada combinación de valores, diseña la apariencia
graph TD
A[Button Component] --> B[variant=primary<br/>size=sm]
A --> C[variant=primary<br/>size=md]
A --> D[variant=primary<br/>size=lg]
A --> E[variant=secondary<br/>size=sm]
A --> F[variant=secondary<br/>size=md]
A --> G[variant=secondary<br/>size=lg]
A --> H[variant=ghost<br/>size=sm]
A --> I[variant=ghost<br/>size=md]
A --> J[variant=ghost<br/>size=lg]
Con 2 dimensiones (variant × size), tienes 9 variantes en un solo componente.
Seleccionar variante en una instancia
Cuando usas una instancia del componente Button, en el panel de propiedades ves los controles de variante:
Variante: [primary ▼] Tamaño: [md ▼]
Cambiar la variante actualiza la apariencia de la instancia sin romper el vínculo con el maestro.
Auto-generar variantes con IA
[Con el componente Button seleccionado]
"Agrega una variante 'loading' para cada tamaño.
La variante loading debe mostrar un spinner (Heroicons: arrow-path)
en lugar del texto, animado con rotate.
El botón debe estar deshabilitado durante loading."
Organizar una librería de diseño
Una librería de diseño profesional en OpenPencil tiene una estructura clara de páginas:
mi-design-system.op
├── Página: 🎨 Foundations
│ ├── Colors (palette completa)
│ ├── Typography (escala tipográfica)
│ ├── Spacing (escala de espaciado)
│ ├── Shadows (niveles de elevación)
│ └── Icons (iconografía)
│
├── Página: 🧩 Atoms (componentes básicos)
│ ├── Button (todas las variantes)
│ ├── Input
│ ├── Badge
│ ├── Avatar
│ ├── Checkbox / Radio / Toggle
│ └── Tag / Chip
│
├── Página: 🔧 Molecules (componentes compuestos)
│ ├── SearchBar
│ ├── FormField (label + input + error)
│ ├── Card
│ ├── Notification / Toast
│ └── Dropdown
│
├── Página: 🏗️ Organisms (secciones)
│ ├── Navbar
│ ├── Sidebar
│ ├── DataTable
│ ├── Modal
│ └── Form / Checkout
│
└── Página: 📋 Templates
├── Dashboard layout
├── Form page
└── Marketing page
Publicar como librería compartida
Para que el equipo acceda a los componentes desde otros documentos:
# Publicar la librería
op library publish mi-design-system.op \
--name "Mi Design System" \
--version "1.2.0"
# En otros documentos, agregar la librería
op library add "Mi Design System" --to mi-proyecto.op
# Actualizar cuando hay cambios
op library update "Mi Design System" --in mi-proyecto.op
Desde la UI: Panel de Assets → Libraries → Manage Libraries → Add.
Versioning de la librería
Las librerías de OpenPencil soportan versioning semántico. Cuando publicas una nueva versión con cambios breaking (cambios en el API de los componentes), el sistema notifica a todos los documentos que usan la librería.
# Ver todos los documentos que usan una librería
op library dependents "Mi Design System"
# Ver qué versión usa cada documento
op library audit mi-proyecto.op
Documentación de componentes
OpenPencil permite agregar anotaciones de documentación directamente en el archivo de diseño:
Notas de componente
- Selecciona el componente maestro
- Panel derecho → sección “Documentation”
- Agrega descripción, props y ejemplos de uso
## Button Component
Un botón interactivo con soporte para múltiples variantes y estados.
### Props
- `variant`: primary | secondary | ghost | destructive
- `size`: sm | md | lg
- `isLoading`: boolean
- `disabled`: boolean
### Uso correcto
- Usa `primary` para la acción principal de cada pantalla
- Usa `secondary` para acciones alternativas
- Usa `ghost` para acciones de menor importancia
- Máximo 2 botones primarios visibles al mismo tiempo
### Accesibilidad
- Contraste mínimo 4.5:1 en todos los estados
- Focus visible siempre activo (no remover outline)
- Loading state comunica el estado con aria-label
Exportar documentación
# Generar sitio de documentación del design system
op docs generate mi-design-system.op --out ./docs --format html
# Generar en formato Storybook
op docs generate mi-design-system.op --out ./storybook --format storybook
Sincronizar componentes con el código
El flujo ideal de trabajo con componentes:
flowchart TD
A[Diseñador crea/actualiza componente en OpenPencil] --> B[Exportar con op export]
B --> C[Código en src/components/generated/]
C --> D[Desarrollador extiende con lógica]
D --> E[Componente en producción]
F[Cambio en el diseño] --> G[Re-exportar el componente]
G --> H{¿Cambio breaking?}
H -->|No| I[Actualización automática del código generado]
H -->|Sí| J[Desarrollador adapta la lógica]
I --> E
J --> E
Resumen
En este capítulo has aprendido:
- Crear componentes maestros e instancias
- Definir y usar overrides
- Configurar props tipados para los componentes
- Crear y usar variables de diseño con jerarquía primitivas → semántica → componente
- Implementar temas Light/Dark con modos de variables
- Gestionar variantes de componentes con múltiples dimensiones
- Organizar una librería de diseño profesional
- Publicar y versionar librerías compartidas
- Documentar componentes y exportar la documentación
En el último capítulo aplicaremos todo lo aprendido en un proyecto real de principio a fin.