@vunojs/ui
| Install | |
|---|---|
npm install @vunojs/ui |
|
| Latest Version: | 0.0.25 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 23, 2026 |
| Links: | npm |
@vunojs/ui
Librería de UI de Vuno: más de 90 componentes Vue con prefijo (VButton, VCard, VSelect…), un design system de Panda CSS y unos pocos composables públicos. Cada componente pinta con su receta de Panda; la librería no depende de Tailwind. Es la librería de diegootayza portada a Vuno con la misma estructura, los mismos nombres y la misma lógica.
Instalación y registro
En una aplicación de este workspace, añade el paquete y mantén @vunojs/core, Vue y TypeScript en versiones compatibles:
pnpm --filter my-app add -D '@vunojs/ui@workspace:*'
Registra el módulo una sola vez en vuno.config.ts. Aporta el CSS, los componentes globales y los autoimports públicos; no necesitas importar cada componente en todas las páginas:
import { defineConfig } from '@vunojs/core/config'
import { vunoUi } from '@vunojs/ui'
export default defineConfig({ modules: [vunoUi()] })
<script setup lang="ts">
const state = reactive({ name: '' })
const toast = useToast()
</script>
<template>
<VForm
:state="state"
@submit="toast.success('Guardado')"
>
<VFormField
label="Nombre"
name="name"
>
<VInput v-model="state.name" />
</VFormField>
<VButton
label="Guardar"
type="submit"
/>
</VForm>
</template>
Opciones
vunoUi({ prefix, icons, theme }):
| Opción | Por defecto | Qué hace |
|---|---|---|
prefix |
'V' |
Prefijo con que se registran los componentes globales. Solo cambia el nombre global: el barrel @vunojs/ui/components y la librería por dentro siempre usan V. |
icons |
[] |
Nombres Iconify completos que entran siempre en el bundle cuando se componen en tiempo de ejecución. Los nombres sin prefijo siguen siendo de Lucide. Ver «Iconos». |
theme |
ver abajo | Defaults visuales globales, tipados y parciales. Las props explícitas y luego ui conservan la prioridad final. |
El módulo aporta además:
- su design system de Panda CSS, con
kit.setPandaDesignSystem('@vunojs/ui'): los tokens, recetas y estilos ya extraídos conpanda libentran en la configuración de Panda que Vuno genera para la aplicación; - el CSS de la librería (
main.css: las variables depalette.cssytokens.css, los estilos de documento debase.cssy las clasesintent-*deutility.css; elresetlo pone elpreflightde la aplicación) y el alias#uisobre el runtime; - la directiva
v-toc, registrada conkit.addAppPlugin(): corre en el servidor y en el navegador antes deapp/vuno.app.ts; - el plugin de iconos.
No aporta modo de color: los temas cuelgan de las clases .light y .dark, que son las que el framework pone en <html> por defecto.
Componentes
Se registran globalmente con el prefijo: components/Button/index.vue es VButton. Las partes internas —la carpeta components/ de cada componente y components/_shared/— no se registran; las importan los componentes que las pintan.
Para importarlos explícitamente, por ejemplo para leer las props de un componente o usarlo en h(), está el barrel @vunojs/ui/components:
import { VButton } from '@vunojs/ui/components'
const button = h(VButton, { label: 'Guardar', size: 'sm' })
Sale del mismo listado con que se registran, así que no pueden divergir. Sus tipos son los que emite vue-tsc para cada .vue.
Subrutas
| Import | Qué trae |
|---|---|
@vunojs/ui |
vunoUi y los tipos VunoUiOptions y ThemeOptions |
@vunojs/ui/components |
Todos los componentes públicos, por su nombre con V |
@vunojs/ui/components/<Nombre>/utils |
Los valores de una prop: components/Canvas/utils (CANVAS_PATTERNS) y components/Text/utils (TEXT_TAGS) |
@vunojs/ui/types |
Los tipos públicos (SelectProps, NavigationEntry, Color, Size…) |
@vunojs/ui/theme/components/<Nombre> |
La receta de un componente (theme/components/Button) |
@vunojs/ui/theme/variants/<x> |
Las variantes compartidas del tema (theme/variants/color…) |
@vunojs/ui/utils/<x> |
utils/labels (DEFAULT_LABELS), utils/highlight (CODE_LANGUAGES…) y utils/model |
@vunojs/ui/composables/<x> |
Los composables públicos, también para importarlos a mano |
@vunojs/ui/content |
vunoUiContent, el renderer de @vunojs/content con la tipografía y los componentes de la UI |
@vunojs/content es un peerDependency opcional: solo lo necesita quien usa @vunojs/ui/content, y una aplicación que no renderiza Markdown no tiene que instalarlo.
El paquete exporta solo lo que usa una aplicación. Las subrutas de valores salen de src/public, donde cada archivo nombra exactamente lo que publica; el resto del runtime —composables internos, utilidades de los componentes, components/_shared/*, el registro de componentes— no forma parte del contrato público y el mapa de exports bloquea su importación.
Composables
Solo se autoimportan los públicos: useClipboard, useConfirm, useFormDraft, useKeydown, useListbox, useShortcuts, useToast y useToc. El resto son internos de la librería.
useToast() y useConfirm() necesitan un host montado una vez. VApp monta ambos y el enlace de salto global sin añadir un wrapper de layout:
<template>
<VApp>
<RouterView />
</VApp>
</template>
Cada layout monta exactamente un VMain, que aporta el destino y permite que el teclado salte directamente al contenido:
<template>
<VMain>
<RouterView />
</VMain>
</template>
Las opciones de los hosts se pasan con toaster y confirm-dialog. skip-link acepta una etiqueta propia o false para desactivarlo. Para colas adicionales, monta otro <VToaster group="…" /> o <VConfirmDialog group="…" /> junto al contenido. El estado vive en useState, por petición en el servidor.
Temas
Las recetas de Panda de los componentes viven en theme/components/<Nombre>.ts (subruta pública @vunojs/ui/theme/components/*), con los fragmentos compartidos en theme/variants/ (@vunojs/ui/theme/variants/*). La prop ui añade clases por slot como escape final; en la aplicación, esas clases salen de css() de #vuno/styled-system/css, que van en la capa utilities, por encima de cualquier receta.
Todos los componentes parten de una intención neutral. El consumidor puede cambiar los defaults con autocompletado; el objeto es deep-partial:
vunoUi({
theme: {
color: 'neutral',
size: 'md',
rounded: 'md',
padding: 'md',
variant: {
action: 'solid',
field: 'outlined',
surface: 'outlined',
status: 'soft',
},
},
})
La precedencia es: defaults de la librería → vunoUi({ theme }) → contexto heredado (VGroup) → prop explícito → clases de ui. Los controles usan alturas de 32, 40, 48 y 56 px para sm, md, lg y xl; las superficies usan padding de 12, 16 y 24 px para sm, md y lg.
Los overlays comparten un contrato: el slot por defecto contiene un único trigger sin wrapper, Modal y Slideover colocan el contenido en #body, y Popover en #content. El trigger recibe ARIA, data-state y active cuando es un componente Vue; los slots de contenido reciben { open, show, close, toggle }.
Los colores salen de los tokens intent-* de assets/css/tokens.css, que cumplen WCAG 2.2 en claro y en oscuro; las recetas de Panda leen esas variables CSS directamente (theme/variants/vars.ts) en vez de tokens de Panda, para que vean la intención del componente y un .dark anidado.
Iconos
<VIcon name="lucide:arrow-right" />, y la prop icon de los componentes, aceptan cualquier colección oficial de Iconify instalada en la aplicación. Por ejemplo:
pnpm --filter @vunojs/playground add -D @iconify-json/vscode-icons
<VIcon name="vscode-icons:file-type-vue" />
No hace falta registrar la colección. El módulo lee las dependencias @iconify-json/* del consumidor, detecta los nombres colección:icono escritos en la librería y en app/, y sirve solo esos iconos en virtual:vuno-ui-icons. Lucide viene incluido por defecto. Todo se resuelve sin red y el servidor y el navegador pintan el mismo SVG.
Un nombre que el código compone en tiempo de ejecución —`${collection}:${name}`— no se puede leer. Escríbelo como literal o declara el nombre completo en vunoUi({ icons: ['vscode-icons:file-type-vue'] }); icons: ['arrow-right'] se conserva como abreviatura de lucide:arrow-right. Un icono que no está disponible deja su caja vacía, del mismo tamaño. En desarrollo, el navegador indica una vez por nombre si falta instalar la colección o declarar el icono; el build avisa si un nombre explícito no existe.
TypeScript es un peer obligatorio
typescript@^6.0.3 es peerDependency y no es opcional: los componentes se publican como .vue con defineProps<Props>() sobre tipos importados, y @vue/compiler-sfc necesita TypeScript para resolverlos al construir la aplicación.
La 7.x no sirve y por eso el rango la excluye: ya no expone ts.sys, así que la compilación falla con No fs option provided to compileScript in non-Node environment, un mensaje que no menciona TypeScript.
Consulta el README del repositorio y las páginas de componentes de apps/vuno (/modules/ui/components/<componente>).
Desarrollo en este monorepo
El pnpm dev de la raíz inicia el watcher de UI y la aplicación apps/vuno. Al editar un .vue o .ts del paquete, el watcher reconstruye el runtime y sus declaraciones para que el checker de la aplicación lea el contrato actualizado de @vunojs/ui/components; un cambio solo de CSS omite la emisión de tipos. Los componentes públicos del barrel siempre conservan el prefijo V, aunque cambies vunoUi({ prefix }) para el registro global.
Si acabas de cambiar los scripts del watcher, reinicia pnpm dev para que el proceso cargue su versión nueva. Si el editor o el overlay todavía menciona @vunojs/ui/components, ejecuta pnpm --filter @vunojs/ui build y después pnpm typecheck desde la raíz; el gate reconstruye dependencias y permite distinguir tipos realmente inválidos de un dist desactualizado. No edites dist a mano: el siguiente build lo reemplaza.
Related Packages
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.0.25 | ^3.5.44 | MIT | |
| 0.0.24 | ^3.5.44 | MIT | |
| 0.0.23 | ^3.5.44 | MIT | |
| 0.0.22 | ^3.5.44 | MIT | |
| 0.0.21 | ^3.5.44 | MIT | |
| 0.0.20 | ^3.5.44 | MIT | |
| 0.0.19 | ^3.5.43 | MIT | |
| 0.0.18 | ^3.5.43 | MIT | |
| 0.0.17 | ^3.5.43 | MIT | |
| 0.0.16 | ^3.5.43 | MIT | |
| 0.0.15 | ^3.5.43 | MIT | |
| 0.0.14 | ^3.5.43 | MIT | |
| 0.0.13 | ^3.5.43 | MIT | |
| 0.0.12 | ^3.5.43 | MIT | |
| 0.0.11 | ^3.5.43 | MIT | |
| 0.0.10 | ^3.5.43 | MIT | |
| 0.0.9 | ^3.5.43 | MIT | |
| 0.0.8 | ^3.5.43 | MIT | |
| 0.0.7 | ^3.5.43 | MIT | |
| 0.0.6 | ^3.5.43 | MIT | |
| 0.0.5 | ^3.5.43 | MIT | |
| 0.0.4 | ^3.5.43 | MIT |
Pre-releases (1)
| Version | Released | License |
|---|---|---|
| 0.0.0-stage |