Saltar al contenido

Guía de diseño ​

Un plugin del panel no tiene diseño propio: usa el del panel. La interfaz de un plugin debe ser indistinguible de la del núcleo, y eso se consigue de una sola manera: todo sale de los tokens y del kit de componentes.

Regla del sistema (admin/src/styles/tokens.css): ningún componente ni página usa colores, radios, sombras o tamaños sueltos; todo sale de los tokens. Así todas las pantallas se ven igual.

  • Tokens de diseño: colores, tipografía, espaciado, radios y sombras, en claro y oscuro, leídos de tokens.css.
  • Catálogo de componentes: los componentes de admin/src/components/ui con sus props, eventos, slots y un ejemplo de uso.
  • Iconos: los iconos disponibles.

Principios ​

  1. Usa el kit antes de escribir HTML. Cada pantalla empieza por AppPage; las listas son UiTable o UiList; los formularios, UiField con su control. Si el kit no tiene lo que necesitas, compón con él antes de crear un componente nuevo.
  2. Nada de valores sueltos. En el CSS de tu plugin usa var(--s-4), var(--r-md), var(--surface), var(--fs-md). Un #fff, un 12px o un border-radius: 8px literal son un defecto.
  3. El color solo tiene significado. El acento (--accent) es la marca; verde, ámbar, rojo y azul son estados (success, warning, danger, info). No se colorea por decoración.
  4. Claro y oscuro desde el principio. Los tokens cambian solos con el tema (prefers-color-scheme o data-theme). Si usas solo variables, tu pantalla funciona en los dos. Comprueba siempre en oscuro.
  5. Móvil. UiTable se convierte en tarjetas por debajo de 720 px. Define qué columna es el título (mobile: "title") y cuáles se ocultan (mobile: "hide").
  6. Accesibilidad. El foco visible (:focus-visible) lo pone la base. Los textos muted y faint cumplen 4,5:1 sobre las superficies indicadas en Tokens. Los botones de solo icono llevan label; los controles sin texto visible llevan aria-label.
  7. Estados completos. Cada lista tiene su estado de carga (loading o UiSkeleton), vacío (UiEmpty con el primer paso) y error (UiLoadError con reintento).

Estructura típica de una página ​

vue
<AppPage :title="t('Notas')" :description="t('Notas internas del local.')">
  <template #actions><UiButton variant="primary" icon="plus">{{ t("Nueva nota") }}</UiButton></template>
  <UiToolbar><UiSearch v-model="q" /></UiToolbar>
  <UiCard flush>
    <UiTable … />
  </UiCard>
</AppPage>
  • Una acción principal por pantalla (variant="primary").
  • Editar sin perder la lista: UiDrawer para fichas largas, UiModal para formularios cortos y confirmaciones.
  • Confirmar lo destructivo con useFeedback().confirm({ tone: "danger" }); avisar del resultado con useFeedback().toast().

Tono de los textos ​

Las pantallas internas hablan serio y técnico:

  • Frases cortas, en infinitivo para acciones (Guardar, Crear nota) y en indicativo para estados (Sin notas).
  • Sin chistes, modismos, exclamaciones ni emojis.
  • Di qué ocurre y qué hacer: «No se pudo guardar. Inténtalo de nuevo.», no «¡Ups!».
  • Los errores de la API llegan traducidos por su code; muestra el mensaje con useFeedback().error(err).
  • Un estado vacío explica qué es la pantalla y ofrece el primer paso.
  • Los botones nombran la acción, no «Aceptar»: Borrar nota, Guardar cambios.
  • Cifras, fechas y dinero con @/lib/format (money, number, percent, date, dateTime): respetan el idioma.

Iconos ​

Un único estilo: trazo de 1,75 sobre rejilla de 24x24 (UiIcon). El icono acompaña al texto, no lo sustituye; si va solo, el botón lleva label. El nombre de icono de plugin.json y de la entrada de menú es uno de este catálogo. No incluyas SVG propios en la interfaz salvo ilustraciones que el kit no cubra.

Idiomas (i18n) ​

  • El español es la clave. t("Nueva nota") es el texto en español y también la clave del diccionario. El español no lleva fichero.
  • Cada plugin trae admin/i18n/{en,ca,fr}.json: un objeto plano { "Texto en español": "Translation" }. El runtime carga solo el idioma activo.
  • Parámetros: t("Hay {n} notas", { n: 3 }). El nombre va entre llaves; si falta, la llave se queda tal cual.
  • Si una clave no tiene traducción, se muestra el español: ninguna pantalla se rompe, pero no dejes claves sin traducir.
  • Un texto que ya existe en el panel con la misma clave no se pisa desde un plugin: gana el del panel. Usa un texto distinto si necesitas otro matiz.
  • En la API, los textos van con trKey("texto en español"); en notificaciones, trFor(locale, texto, params).
  • Un tutorial (tour.ts) lleva sus textos en el mismo diccionario del plugin.
  • Idiomas del panel: es, ca, fr, en.

Qué evitar ​

  • Importar CSS global o una librería de componentes ajena: el panel ya trae el kit.
  • Fijar fuentes: la tipografía viene de --font, --font-display y --mono.
  • Estilos con !important o que afecten fuera de tu componente: usa <style scoped>.
  • Mostrar la pantalla de un módulo apagado: declara feature y meta.permission en la ruta.

Contrato con el host: apiVersion 2. Sitio estático: no recoge datos ni usa servicios de terceros.