Saltar al contenido

Icon

Iconos de Iconify y SVG propios, tipados e incrustados en el HTML al compilar.

Uso

Buscar en el proyecto

meeko
<p><UIIcon name="lucide:search" /> Buscar en el proyecto</p>
<UIButton variant="outline">
  <UIIcon name="lucide:trash-2" label="Eliminar" />
</UIButton>

UIIcon escribe un <svg> en línea. Cada nombre literal se resuelve durante el build con el paquete de la colección instalado en el proyecto: no hay peticiones en tiempo de ejecución ni CDN, y el bundle sólo lleva los iconos que usas.

Instalación y colecciones

Necesitas @meekojs/meeko >=1.8 <2, con el registro de módulos por su nombre. Instala el módulo y cada colección de Iconify que quieras usar como @iconify-json/<colección>. El módulo se registra por su nombre y sus opciones van en la clave icon, tipada en meeko.config.ts.

ts
// pnpm add @meekojs/icon && pnpm add -D @iconify-json/lucide
// meeko.config.ts
export default defineMeekoConfig({
  modules: ['@meekojs/icon'],
  icon: {
    collections: ['lucide'], // @iconify-json/lucide del proyecto
    local: 'app/icons', // SVG propios: 'local:<nombre>'
    size: '1em',
    include: ['lucide:sun', 'lucide:moon'], // para bind:name
  },
})

Los nombres disponibles forman una unión de TypeScript que Meeko genera en .meeko/types: el editor completa name="lucide:…", y un nombre que no existe es un error de meeko check con la sugerencia más parecida. Si icon.collections nombra una colección que no está instalada, meeko check, meeko dev y meeko build fallan con el comando para instalarla.

Nombres dinámicos

Con bind:name, los literales de la expresión se resuelven al compilar igual que un nombre fijo. Un valor que no aparece en el código, como el que llega de datos, sólo funciona si está en icon.include (o con 'colección:*', que incluye la colección entera). Si no, se pinta un <svg> vacío y meeko dev avisa en la consola.

meeko
<!-- Literales de la expresión: se resuelven al compilar -->
<UIIcon
  bind:name="open.value ? 'lucide:x' : 'lucide:menu'"
  bind:label="open.value ? 'Cerrar menú' : 'Abrir menú'" />

<!-- Un valor que llega de datos: el icono debe estar en icon.include -->
<UIIcon bind:name="mode.value" />

Cómo se resuelve

  • Nombres literales. Durante el build, un plugin de Vite resuelve cada name="…" de <UIIcon> con @iconify/utils y lo incrusta en el componente que lo usa, antes de que Meeko lo compile. El bundle de cada página sólo lleva sus iconos; el SSR y el navegador ven el mismo SVG, así que la hidratación y la navegación no parpadean.
  • Nombre inexistente. Es un error de tipos (TS2820, con la sugerencia más parecida) en meeko check, meeko build y el editor; el build también lo rechaza con el archivo y la posición.

Tipos

El módulo genera la unión de los nombres disponibles en .meeko/types/modules/%40meekojs%2Ficon/, una declaración por colección más la de los SVG locales. name de <UIIcon> y icon.include de meeko.config.ts usan esa unión. Con Lucide (2.302 nombres), Tabler y Material Design Icons a la vez (22.802), la comprobación de TypeScript 7 sube unos 35 ms.

ts
import type { IconName } from '@meekojs/icon'

const close: IconName = 'lucide:x'

SVG propios

Cada archivo de app/icons (o de la carpeta de icon.local) es local:<nombre>, en kebab-case. Al compilar se sanea con una lista de elementos y atributos permitidos: se quitan <foreignObject>, <image>, enlaces, animaciones, class y <script>, <style>, manejadores on*, style y toda referencia fuera del icono (href y url(…) sólo a #id). Los id internos se prefijan por icono para que dos iconos no choquen, y un icono de un solo color pasa a currentColor.

meeko
<!-- app/icons/paw.svg -->
<UIIcon name="local:paw" label="Meeko" size="1.5em" />

Accesibilidad, tamaño y color

Sin label, el icono es decorativo: aria-hidden="true" y focusable="false". Con label, el <svg> lleva role="img" y aria-label; úsalo cuando el icono sea el único contenido de un botón o un enlace.

Mide 1em de alto por defecto, así que sigue al texto que lo rodea, y toma el color con currentColor. Ancho, alto, viewBox y relleno son atributos, nunca estilos en línea: funciona con una Content Security Policy estricta. La hoja del módulo sólo alinea el icono con la línea base (.meeko-icon).

API

Propiedades
Nombre Tipo / valor inicial Descripción
name IconName Icono: colección:icono o local:nombre. Un literal se resuelve al compilar.
label string Texto accesible. Sin él, el icono es decorativo.
size string icon.size (1em) Alto, una longitud CSS. El ancho sigue la proporción del icono.
class string Clases del svg, que siempre lleva meeko-icon.

Opciones del módulo

Propiedades
Nombre Tipo / valor inicial Descripción
collections string[] [] Colecciones de Iconify (lucide, mdi…); cada una, el paquete @iconify-json/<colección> del proyecto. El editor completa las instaladas.
include IconInclude[] [] Iconos para nombres dinámicos, o colección:* para una entera.
local string | false app/icons si existe Carpeta de SVG propios.
size string 1em Alto por defecto de los iconos.

¿Te sirvió esta página?

Añadir un comentario

Se envía al elegir «Sí» o «No». Solo se guardan la página, tu respuesta y el comentario: ni cookies ni datos tuyos.

0 de 2000 caracteres