Icons in Preact
Preact führt die React-Komponenten von glyphfox über preact/compat ohne Codeänderungen aus. Wenn Ihre App compat nicht lädt, funktioniert die Web Component glyph-fox in reinem Preact.
Installation
Installieren Sie glyphfox neben Preact. preact/compat ist Teil des Pakets preact, eine zweite Abhängigkeit ist also nicht nötig.
npm install glyphfox
Es gibt zwei Wege, Icons zu rendern, und beide nutzen dieselbe Rendering-Engine und dieselben Props:
- Die Komponenten aus
glyphfox/react, von Preact über compat ausgeführt. Am besten geeignet, wenn Ihre App React bereits per Alias umleitet oder andere React-Pakete nutzt. - Die Web Component
<glyph-fox>, die ganz ohne compat auskommt. Am besten geeignet, wenn Sie Preact schlank halten und nur Icons brauchen.
So laufen die Komponenten unter Preact
Der React-Einstiegspunkt importiert genau sechs Dinge aus react: createElement, forwardRef, useState, useEffect, useMemo und useRef. compat implementiert sie alle. Sobald der Bundler react zu preact/compat auflöst, rendern die Komponenten daher mit dem eigenen Renderer von Preact, im selben Baum und mit denselben Hooks wie der Rest Ihrer App.
Die SVG-Attribute werden mit React-Namen wie strokeWidth und strokeLinecap erzeugt, und compat wandelt sie am Element wieder in stroke-width und stroke-linecap um. Die Animationen der lebendigen Zustände sind ein <style>-Element innerhalb des SVG, gesetzt über dangerouslySetInnerHTML, das Preact ebenfalls unterstützt.
Vite
Das offizielle Preact-Preset für Vite leitet react, react-dom und die JSX-Runtime bereits per Alias auf compat um. Mehr ist nicht nötig:
import { defineConfig } from 'vite'; import preact from '@preact/preset-vite'; export default defineConfig({ plugins: [preact()], });
webpack und esbuild
Fügen Sie bei webpack die Aliase zu resolve.alias hinzu. glyphfox braucht nur react, aber wenn Sie den ganzen Satz per Alias umleiten, bleiben alle anderen React-Pakete in Ihrer App auf derselben Preact-Instanz:
module.exports = {
resolve: {
alias: {
react: 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react-dom': 'preact/compat',
'react/jsx-runtime': 'preact/jsx-runtime',
},
},
};esbuild bietet dieselbe Option. Aktivieren Sie gleichzeitig Code-Splitting, sonst bettet esbuild jedes Icon-Modul ein, das der On-Demand-Loader erreichen kann (warum, erklärt der Leitfaden zum Tree-Shaking):
import * as esbuild from 'esbuild'; await esbuild.build({ entryPoints: ['src/main.jsx'], bundle: true, splitting: true, format: 'esm', outdir: 'dist', jsx: 'automatic', jsxImportSource: 'preact', alias: { react: 'preact/compat', 'react-dom': 'preact/compat' }, });
TypeScript
Die Deklarationen von glyphfox/react sind gegen die React-Typen geschrieben (ForwardRefExoticComponent, SVGProps). Bilden Sie react in paths auf compat ab, damit sie zu den Typen von Preact aufgelöst werden. Meldet der Typprüfer weiterhin Probleme in den Deklarationsdateien von Abhängigkeiten, lassen Sie skipLibCheck aktiviert, wie es die meisten Preact-Templates tun:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact",
"skipLibCheck": true,
"paths": {
"react": ["./node_modules/preact/compat/"],
"react-dom": ["./node_modules/preact/compat/"]
}
}
}Die Komponenten verwenden
Importieren Sie Icons nach Namen und kombinieren Sie sie wie gewohnt mit Preact-Hooks. Alles aus dem React-Leitfaden gilt auch hier: Icon mit der Namenssyntax, Fusion, MorphIcon, useMorph, Modifier und Refs.
import { useState } from 'preact/hooks'; import { HeartIcon, MorphIcon, Fusion } from 'glyphfox/react'; export function Card() { const [liked, setLiked] = useState(false); return ( <article className="card"> <button type="button" onClick={() => setLiked(!liked)} aria-pressed={liked}> <HeartIcon animate="pop" trigger="state" active={liked} variant={liked ? 'solid' : 'outline'} /> Like </button> <MorphIcon name={liked ? 'check' : 'plus'} duration={250} /> <Fusion icons={['user', 'shield']} layout="badge" /> </article> ); }
Refs laufen über das forwardRef von compat, daher zeigt ref an einem Icon auf das gerenderte <svg>-Element, bereit für getBoundingClientRect() oder die Web Animations API. Event-Handler wie onClick und Attribute wie data-* gehen direkt an das Element, genau wie in React.
Übergeben Sie bei Signals den Wert statt des Signals. Preact entpackt Signals, die an DOM-Attribute gebunden sind, aber eine Icon-Komponente erhält das Signal-Objekt selbst und liest ihre Props als einfache Werte. Sie würde also weder den richtigen Wert lesen noch aktualisiert werden, wenn sich das Signal ändert:
import { signal } from '@preact/signals'; import { CloudIcon } from 'glyphfox/react'; const syncing = signal(false); export function Status() { return <CloudIcon modifier={syncing.value ? 'sync' : undefined} />; }
Ohne compat: die Web Component
Das Custom Element <glyph-fox> rendert dieselben Icons mit denselben Props als Attribute in kebab-case. Importieren Sie glyphfox/web einmal, um es mit allen Icons zu definieren, oder definieren Sie es selbst und registrieren Sie nur die Icons, die Sie verwenden:
import { defineGlyphFox } from 'glyphfox/web/element'; import { registerIcons } from 'glyphfox/core'; import { iconHome, iconSearch, iconMenu, iconX } from 'glyphfox'; registerIcons([iconHome, iconSearch, iconMenu, iconX]); defineGlyphFox();
import { useState } from 'preact/hooks'; import './icons.js'; export function Header() { const [open, setOpen] = useState(false); return ( <header> <glyph-fox name="home" size="20"></glyph-fox> <glyph-fox name="search" weight="1.5" title="Search"></glyph-fox> <button type="button" onClick={() => setOpen(!open)} aria-expanded={open} aria-label="Menu"> <glyph-fox name={open ? 'x' : 'menu'} morph></glyph-fox> </button> </header> ); }
Preact setzt unbekannte Props an Custom Elements als Attribute, und genau auf diese reagiert das Element. Dynamische Werte wie name={open ? 'x' : 'menu'} funktionieren daher, und das Attribut morph animiert jede Änderung. Fügen Sie in TypeScript glyph-fox in einer Deklarationsdatei zu den JSX.IntrinsicElements von Preact hinzu, so wie es die Preact-Dokumentation für jedes Custom Element beschreibt.
Attribute, die Größensteuerung im Shadow DOM und das serverseitige Rendering des Elements behandelt der Leitfaden zu Web Components.
Welcher Weg ist schlanker?
Beide Wege liefern dieselbe Engine (Rendering, Achsen, Modifier, Fusion und Morph), daher kosten die Icons in beiden Fällen etwa gleich viel. Der eigentliche Unterschied ist compat: Lädt Ihre App es bereits für andere Pakete, bringen die Komponenten nichts Neues hinzu; lädt sie es nicht, umgeht die Web Component es. Importieren Sie in beiden Fällen nur die Icons, die Sie verwenden, wie oben gezeigt.
Props
Die Komponenten akzeptieren diese Props. Bei <glyph-fox> sind dieselben Props Attribute in kebab-case (secondary-color, flip-x, morph-to), dazu kommen name, layout, gap und morph.
| Prop | Typ | Standard | Beschreibung |
|---|---|---|---|
size | number, string | 24 | Breite und Höhe; Zahlen sind Pixel. |
color | string | currentColor | Hauptfarbe. |
secondaryColor | string | color | Farbe der Duotone-Ebene und der Solid-Füllung. |
secondaryOpacity | number | 0.3 / 1 | Deckkraft der Duotone-Ebene oder der Solid-Füllung. |
weight | number | 2 | Strichstärke von 1 bis 3 im 24er-Raster, unter 24 px optisch ausgeglichen. |
absoluteWeight | boolean | false | Hält den Strich bei jeder Größe auf weight Pixeln. |
corners | round, sharp | round | Abgerundete oder spitze Verbindungen und Enden. |
variant | outline, duotone, solid | outline | Stilachse; solid entsteht aus den geschlossenen Formen. |
rotate | number | 0 | Drehung in Grad. |
flipX | boolean | false | Horizontal spiegeln. |
flipY | boolean | false | Vertikal spiegeln. |
mirrorRtl | boolean | false | In Layouts von rechts nach links spiegeln. |
animate | draw, pop, wiggle, spin, pulse, bounce, shake | keiner | Voreinstellung für den lebendigen Zustand. |
trigger | mount, hover, click, state | mount | Wann die Animation oder der Morph abläuft. |
active | boolean | false | Der Zustand für den Auslöser state. |
duration | number (ms) | je nach Voreinstellung | Dauer der Animation oder des Morphs. |
delay | number (ms) | 0 | Verzögerung der Animation oder des Morphs. |
loop | boolean, number | false | Endlos oder eine bestimmte Anzahl von Malen wiederholen (spin und pulse laufen standardmäßig in Schleife). |
modifier | plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dot | keiner | Badge mit automatischer Aussparung. |
modifierCorner | top-left, top-right, bottom-left, bottom-right | bottom-right | Ecke des Badges. |
morphTo | name, data | keiner | Ziel des Morphs; der Auslöser bestimmt, wann es erscheint. |
title | string | keiner | Zugänglicher Name: title, role img und aria-label. |
decorative | boolean | true ohne title | Verbirgt das Icon vor assistiven Technologien. |
Stolperfallen
- Ein fehlender Alias
- Ohne den Alias löst der Bundler
reactzum echten React-Paket auf (oder findet es gar nicht). Die Icons rufen dann Hooks aus einem anderen Renderer auf, was sich in Fehlern wegen ungültiger Hook-Aufrufe („Invalid hook call“) oder in Icons äußert, die sich nie aktualisieren. Prüfen Sie, obreactzupreact/compataufgelöst wird. classstattclassName- Die Komponenten führen
classNamemit ihren eigenen Klassenglyphfox glyphfox-NAMEzusammen. Eineclass-Prop wird nicht zusammengeführt und kann von diesen Klassen ersetzt werden. Verwenden Sie an Icon-Komponenten daherclassName. - Zwei Kopien von Preact
- compat muss zum selben
preactaufgelöst werden wie Ihre App. Eine doppelte Kopie innode_moduleslegt Hooks genauso lahm wie ein fehlender Alias; deduplizieren Sie sie mit Ihrem Paketmanager. - Signals als Props
- Übergeben Sie
signal.valuean Icon-Komponenten. Das Signal-Objekt selbst wird für Komponenten nicht entpackt. - Leere Elemente vor der Definition
<glyph-fox>zeichnet erst, nachdemdefineGlyphFox()im Browser gelaufen ist. Geben Sie dem Element bei vorgerendertem HTML per CSS eine Größe, damit sich das Layout nicht verschiebt, während das Skript lädt.
Häufige Fragen
Brauche ich preact/compat, um glyphfox zu nutzen?
Nur für die Komponenten aus glyphfox/react. Das Element <glyph-fox> und toSvg aus glyphfox funktionieren auch ohne compat in reinem Preact.
Rendern die Komponenten mit preact-render-to-string?
Ja. Über compat rendern sie auf dem Server wie jede React-Komponente, und das SVG steht im HTML. Bei Icons, die per Name mit Icon gerendert werden, müssen die Daten zuerst registriert werden, wie im Leitfaden zum serverseitigen Rendering beschrieben.