| name | sodeker-design |
| description | Estándar visual de Sódeker Suite para construir UIs Vue.js + Bootstrap 5 consistentes entre desarrolladores. Define paleta, tipografía Saira, espaciado 4px, radios 4px, sombras casi invisibles y patrones de componentes (botones, cards, badges, stat-cards, inputs, tablas). **Antes de generar código escanea el proyecto actual** (`src/components/**/*.vue`, tokens, composables) para que lo nuevo encaje con lo que el equipo ya tiene construido (Base*, App*, DataTable, etc.) y reutilice componentes existentes en vez de duplicarlos. Aplícala SIEMPRE que un desarrollador pida construir, maquetar, estilar o refactorizar cualquier UI, componente, vista, pantalla, dashboard, modal, formulario, tabla o pieza visual de un producto Sódeker — incluso si no menciona "Sódeker" o "estilo visual" explícitamente. También aplícala si revisas código UI existente y debes opinar sobre colores, espaciados o jerarquía. La meta es que 7 desarrolladores produzcan piezas que parezcan parte de la misma aplicación. |
| metadata | {"type":"visual-identity"} |
Sódeker Visual Identity
Estándar visual compartido para los equipos de Sódeker Suite. La idea es simple: cada desarrollador conserva su creatividad para resolver el problema (estructura, interacción, contenido), pero el lenguaje visual — colores, tipos, espacios, radios, sombras, componentes base — sale siempre del mismo cajón. Así 7 desarrolladores construyen 7 piezas que se sienten parte de un mismo producto.
En una frase
Dashboard enterprise compacto y honesto — blanco sobre azul-blanco #f3f3f9, energía cyan-a-teal, tipografía Saira condensada a 14px, radios de 4px, sombras casi invisibles y motion puramente funcional.
Cuándo aplicar este estándar
Aplica esta skill en cualquiera de estos escenarios:
- "Hazme un componente / vista / pantalla / dashboard / modal / formulario / tabla …"
- "Maquéta / estila / rediseña …"
- "Revisa este componente y dime si está bien"
- Cualquier código
.vue, .html o .scss para un producto Sódeker
- Cuando elijas colores, tipografía, espaciados, iconos o componentes Bootstrap
Si la petición es claramente NO-UI (lógica de negocio, queries, infraestructura), no fuerces el estándar.
Flujo de trabajo
Cuando recibas una petición de UI, sigue estos pasos en orden:
1. Reconoce el proyecto y sus componentes existentes
Antes de generar nada, escanea el proyecto en el que estás trabajando para entender qué piezas ya existen. La meta es que tu output se sienta como una continuación natural del código del equipo, no como algo importado de afuera. El estándar de esta skill es el techo; lo que el proyecto ya implementó es el suelo.
a) Confirma el stack y convenciones del proyecto. Lee:
package.json — versión de Vue (2 vs 3), si usan TypeScript, Pinia/Vuex, sass, bootstrap (versión), iconos (boxicons, etc.).
vite.config.* / vue.config.* — alias (@/components), plugins.
tsconfig.json si existe.
b) Descubre componentes existentes. Usa Glob con estos patrones típicos (en orden de probabilidad):
src/components/**/*.vue
src/components/base/**/*.vue
src/components/ui/**/*.vue
src/components/shared/**/*.vue
src/components/common/**/*.vue
src/views/**/*.vue
src/layouts/**/*.vue
components/**/*.vue (Nuxt o estructura plana)
c) Identifica los componentes base y reutilizables. Prioriza leer:
- Cualquier archivo que empiece por
Base*, App*, The* (convención Vue para singletons/base).
- Carpetas
ui/, base/, shared/, common/, forms/, tables/.
- Componentes con nombre que coincida con lo que vas a construir (si te piden una tabla, lee primero
DataTable.vue, BaseTable.vue, etc.).
Lee de 2 a 4 de los más relevantes — no escanees todo el repo. El objetivo es captar el dialecto, no inventariar.
d) Detecta tokens y estilos globales del proyecto. Busca:
src/assets/styles/**/*.{css,scss}
src/styles/**/*.{css,scss}
src/assets/scss/**/*.scss
**/sodeker-tokens.css
**/_variables.scss
**/tailwind.config.{js,ts}
Si el proyecto ya tiene un sodeker-tokens.css, _variables.scss con $primary: #25a0e2 o equivalente: úsalo. No dupliques tokens en tu componente. Importa o usa las clases utility que ya estén montadas.
Si no existen, ofrécele al dev el archivo assets/sodeker-tokens.css de esta skill como punto de partida, pero no lo crees sin consultar.
e) Absorbe el dialecto del equipo. De los componentes que leíste, fíjate y replica:
| Aspecto | Qué observar |
|---|
| API de Vue | <script setup> vs Options API vs Composition API clásica |
| TypeScript | <script setup lang="ts"> con defineProps<{...}>() vs JS plano |
| Naming de componentes | PascalCase (estándar) vs kebab-case en el filesystem |
| Props | Objeto detallado con type, required, default, validator vs corto |
| Slots | <slot name="header"> con fallbacks vs slots únicos |
| Scoping de estilos | <style scoped> vs CSS Modules vs estilos globales |
| SCSS vs CSS plano | Si usan <style lang="scss">, hazlo igual |
| Importes | Alias @/components/... vs rutas relativas |
| i18n | $t('clave') vs strings directos |
| Eventos | defineEmits con array vs objeto tipado |
| Composables | Si hay useTable, useFilter, useApi, úsalos en vez de recrear |
f) Punto de decisión: ¿modificar existente o crear nuevo? Este es el momento más importante del workflow. Si encuentras un componente que podría cubrir lo solicitado (total o parcialmente), detente y pregunta antes de codear. No asumas, no infieras, no decidas tú solo: la elección entre "modificar lo existente" o "crear uno nuevo" es del desarrollador, no tuya.
Cuándo aplicar esta pausa obligatoria:
| Hallazgo en el proyecto | Acción |
|---|
Existe un componente con el mismo propósito (DataTable.vue y piden tabla) | Pregunta antes de tocar nada |
| Existe un componente similar que cubre el 70%+ del caso | Pregunta antes de tocar nada |
Existe un componente base que el nuevo debería usar (BaseButton.vue) | Úsalo sin preguntar (es composición, no modificación) |
| No existe nada parecido | Crea uno nuevo siguiendo el estándar |
Cómo formular la pregunta. Sé concreto: nombra el archivo, resume qué hace, lista las opciones con sus consecuencias.
💬 "Encontré src/components/tables/DataTable.vue (152 líneas) que ya implementa una tabla con paginación, ordenamiento y filtro por columna. Tres opciones:
- Modificarlo para agregar las columnas y el filtro de estado que pides — afecta a otros lugares que ya lo usan (X vistas según mi escaneo).
- Crear
InvoicesTable.vue nuevo que envuelva o extienda DataTable.vue (no rompe nada existente).
- Crear un componente totalmente independiente (descartado salvo razón fuerte: duplicaría lógica).
¿Cuál prefieres?"
Plantilla genérica:
Ya existe `<ruta/Componente.vue>` que <qué hace en 1 línea>.
Opciones:
1. Modificarlo (afecta a <N> lugares que lo usan).
2. Componer/extender en un componente nuevo `<Sugerencia.vue>`.
3. Crear uno paralelo (solo si <justificación>).
¿Cuál prefieres?
Reglas para la pregunta:
- Cuenta los usos: antes de preguntar, busca con
Grep cuántos archivos importan el componente existente. Eso le da contexto al dev sobre el blast radius de la opción 1.
- Recomienda implícitamente: ordena las opciones de menos invasiva a más invasiva. La opción 2 (componer/extender) suele ser la más sana — el dev verá tu sesgo.
- No empieces a codear "mientras tanto": espera respuesta. Mostrar código adelantado sesga la decisión y a veces el dev ya no se atreve a pedir otra cosa.
- Excepciones legítimas para no preguntar: si el dev fue explícito en su petición original ("crea un nuevo componente X", "modifica el DataTable"), respeta lo que pidió y procede.
Otros puntos de decisión que también requieren pregunta:
- Encontraste dos componentes similares (
DataTable.vue y AdvancedTable.vue). Pregunta cuál es el canónico y si conviene consolidar.
- El componente existente está en inglés pero el resto del proyecto en español (o viceversa). Pregunta la convención antes de propagar.
- El componente existente usa Options API pero el resto del proyecto migró a
<script setup>. Pregunta si modernizar al pasar o respetar el estilo legacy.
- La variante que necesitas se podría implementar como prop nueva (
<DataTable :selectable="true" />) o como componente derivado (SelectableDataTable.vue). Pregunta el patrón que sigue el equipo.
Lo que NO debe hacer el agente:
- ❌ Crear
DataTableV2.vue o NewDataTable.vue sin avisar — eso fragmenta el codebase.
- ❌ Modificar
DataTable.vue "porque parecía lo correcto" cuando el dev solo pidió "una tabla" — puede romper otras vistas.
- ❌ Asumir que duplicar es más seguro — duplicar es deuda técnica disfrazada de prudencia.
- ❌ Ocultar el hallazgo en una nota al final del código — la pregunta va antes de escribir nada.
Cómo seguir después de la respuesta:
- Si el dev elige modificar el existente → muestra el diff propuesto antes de aplicarlo, especialmente si hay >5 usos del componente.
- Si elige crear uno nuevo que extiende → impórtalo correctamente con el alias del proyecto (
@/components/tables/DataTable.vue o lo que use).
- Si elige paralelo → documenta brevemente la justificación en un comentario del componente nuevo, para que un futuro lector entienda por qué no se compuso.
g) Resuelve conflictos entre proyecto y estándar. Si lo que ves en el proyecto contradice el estándar Sódeker (por ejemplo: cards con border-radius: 12px o tipografía Inter en vez de Saira), tienes tres opciones, en este orden:
- Si la divergencia es local y reciente (un par de componentes nuevos que se desviaron): respeta el estándar de la skill y avisa al dev: "Vi que
XyzCard.vue usa radio 12px; el estándar Sódeker es 4px. Sigo el estándar en lo nuevo; ¿quieres que abra una nota para corregir el existente?".
- Si la divergencia está extendida (la mayoría de componentes hacen lo mismo): el equipo ya tomó una decisión consciente. Síguela y comenta el desvío del estándar en el resumen final para que el dev decida.
- Si hay duda, pregunta antes de codear.
h) Si el proyecto está vacío o no es un repo Sódeker reconocible. No fuerces el escaneo. Aplica el estándar de la skill tal cual y avisa: "No encontré componentes previos en este proyecto, así que parto del estándar Sódeker base."
2. Entiende el contexto del componente
Antes de codear, asegúrate de saber:
- ¿Es público (login, landing) o interno (dashboard, panel admin)? El gradiente firma
linear-gradient(-45deg, #25a0e2 50%, #00bd9d) solo se usa en auth/onboarding; el interior es plano.
- ¿Es denso (tabla de datos, lista) o expresivo (KPI, hero)? La densidad sube el peso de tipografías y aprieta paddings.
- ¿Hay un tema oscuro asociado? Si sí, usa
data-bs-theme="dark" y comprueba contraste.
Si falta información crítica, pregunta antes de generar.
3. Elige los tokens correctos
La paleta y la escala están en references/design-tokens.md. Memoriza esta tabla mínima — cubre el 80% de los casos:
| Rol | Token / Hex | Cuándo usarlo |
|---|
| Primary | #25a0e2 | Links, foco, estados activos, botón principal por defecto |
| Success / CTA | #00bd9d | Acción principal en dashboards, ingresos, barras "good" |
| Indigo marca | #405189 | Iconos primarios, rellenos oscuros, acentos fuertes |
| Fondo página | #f3f3f9 | Nunca #fff puro; el blanco se usa para tarjetas |
| Tarjeta | #ffffff | La separación es por contraste con el fondo, no por borde |
| Texto base | #212529 | Cuerpo. Nunca negro puro |
| Texto heading | #495057 | H1-H6, peso 600 |
| Texto secundario | #878a99 | Sub-labels, hints |
| Texto muted | #adb5bd | Placeholders, deshabilitado |
| Borde | #e9ebec | Bordes 1px sólidos |
| Sidebar oscuro | #0a2b3d | Sidebar y topbar dark |
Semánticos: info #32ccff · warning #ffbc0a · danger #f06548 · secondary #878a99.
Si necesitas usar un color fuera de la paleta, detente y consulta: probablemente hay un semántico o un subtle/border/text del mismo rol que ya cubre el caso.
4. Aplica las reglas duras
Estas son las que más se rompen entre desarrolladores y donde el agente debe ser firme:
- Tipografía:
Saira, 300–700. Base 14px (0.875rem). Headings peso 600, color #495057, line-height 1.2. Mono solo para código (SFMono, Menlo, Consolas).
- Casing: Title Case en títulos y labels · sentence case en cuerpo y formularios · ALL CAPS solo en labels de categoría (ej.
ANALYTICS).
- Densidad base: 14px, paddings compactos. Sidebar 250px (compacto 180, icon 70). Header 70px. Card padding
1.25rem (20px).
- Espaciado: unidad base 4px. Escala 4 / 8 / 16 / 24 / 48. No inventes 6, 10, 14, 18.
- Radios:
4px para inputs/botones/cards · 8px modales · 50rem pills · 50% avatares. Nada de 12px, 16px, ni rounded-3 por capricho.
- Bordes y sombras: borde 1px sólido
#e9ebec. Cards sin borde visible en light; la separación es por contraste con el fondo. Sombra de card 0 1px 2px rgba(56,65,74,.15) — casi invisible. Cero shadow-lg, cero shadow-xl, cero gradientes agresivos.
- Focus ring:
0 0 0 0.25rem rgba(37,160,226,.25). Nunca uses outline: none sin reemplazarlo.
- Motion: funcional,
0.15–0.2s ease-in-out. Sin spring, sin bounce, sin escalado en hover. Hover de fila rgba(body-color, .04).
- Iconos: Boxicons (
bx-) como primario, stroke preferido sobre filled. Acento por defecto #405189. En stat cards van dentro de un círculo rgba(primary, .15). Cero SVG ad-hoc dibujados a mano, cero emoji.
- Idioma: español neutro LatAm. Tono directo, business, sin relleno. Sin signos de admiración salvo en CTAs.
- Numérica:
k para miles, M para millones, moneda formato $559.25k.
- Imágenes: reales (lifestyle/profesional), nunca generadas. Patrón decorativo: franjas diagonales (salmón, navy, sage, beige).
5. Elige patrones de componente, no reinventes
Para componentes recurrentes (botones, cards, badges, stat-cards, inputs, tablas, alerts, modales), consulta references/components.md y reutiliza el patrón. La skill bundlea snippets .vue listos en assets/component-snippets/ que puedes copiar o adaptar:
BaseButton.vue — solid / outline / soft / ghost / pill, sm/lg, loading, block
BaseCard.vue — slots header/body/footer, sombra correcta
BaseBadge.vue — default / soft / outline / pill, todos los semánticos
StatCard.vue — KPI con icono en círculo, valor grande, sub-label, trend
Si el dev no tiene los tokens importados, incluye assets/sodeker-tokens.css como referencia para añadirlos al proyecto.
6. Entrega el código
Genera el componente Vue listo, con tokens aplicados directamente (clases Bootstrap correctas, CSS scoped si hace falta). No expliques en exceso — un comentario corto solo cuando el "porqué" no sea obvio (un workaround, un constraint del negocio). El nombre de los identificadores ya cuenta el "qué".
Si el componente se sale de los patrones estándar (caso legítimo, no capricho), explica brevemente qué regla doblaste y por qué.
Sí / No rápidos
| ✅ Sí | ❌ No |
|---|
background: #f3f3f9 en body | background: #fff en body |
border-radius: 4px en card | border-radius: 12px o rounded-3 |
box-shadow: 0 1px 2px rgba(56,65,74,.15) | box-shadow: 0 10px 30px ... en cards |
font-family: Saira; font-size: .875rem | font-family: Inter o tamaño base 16px |
color: #495057 en headings | color: #000 en headings |
Botón CTA en #00bd9d (teal) | Botón CTA en #25a0e2 para dashboards |
transition: .15s ease-in-out | transition: .4s cubic-bezier(.34,1.56,...) |
Icono Boxicon en círculo rgba(primary,.15) | Icono SVG inline custom con gradiente |
Hover de fila rgba(33,37,41,.04) | Hover de fila con background: #eef |
Referencias adicionales
references/design-tokens.md — paleta completa (subtle/border/text por color), tipografía detallada, espaciado, sombras, dark mode.
references/components.md — patrones de cada componente con código Vue/Bootstrap.
references/do-and-dont.md — comparativas de código antes/después con explicación.
assets/sodeker-tokens.css — variables CSS listas para :root.
assets/sodeker-overrides.scss — overrides de Bootstrap 5 (variables $primary, $success, etc.).
assets/component-snippets/ — componentes .vue base.
Filosofía
El estándar no existe para limitar al diseñador. Existe para que el usuario sienta que está usando una aplicación, no siete. La creatividad debe ir en la solución del problema: qué información mostrar, en qué orden, cómo facilitar la tarea. El lenguaje visual es vocabulario compartido — usa el vocabulario, escribe la frase tuya.