Core
Ikony
Kde se název ikony přeloží, jak přidat vlastní sadu a co se stane, když si dvě sady nárokují stejný název.
Na této stránce
- Ikony
- Použití v Blade
- Použití v PHP
- Dostupné ikony
- Wire-friendly aliasy
- Přístupnost
- Přidávání vlastních ikon
- 1. Ze složky SVG souborů (nejjednodušší)
- 2. Inline, podle názvu
- 3. Znovupoužitelná sada ikon (pokročilé)
- Použití více sad ikon
- Prefixy, které si balíčky už zabraly
- Výměna výchozí (neprefixované) sady
- Vykreslení opakované ikony jen jednou
- Odchytávání překlepů
- Regenerace přibalených Heroicons
- Související
Každá ikona ve frameworku je název, ne markup: 'outline:user' projde
sloupcem, akcí i notifikací beze změny a na SVG se převede jednou, při
vykreslení. Právě tahle nepřímost dovoluje aplikaci vyměnit celou sadu, aniž by
sáhla na jedinou komponentu.
Ikony
Kompletní kolekce Heroicons solid (324 ikon,
20x20 viewBox) je přibalena inline — bez externích závislostí, bez extra balíčku.
Je to výchozí sada, adresovaná holými názvy (pencil, user). Můžete
zaregistrovat libovolný počet dalších sad (Lucide, Feather, vlastní brand ikony)
vedle ní — viz Použití více sad ikon.
Každá ikona nese svůj vlastní viewBox a fill/stroke stylování, takže 20×20 fill-based
Heroicons a 24×24 stroke-based sady se vykreslí správně vedle sebe.
Použití v Blade
<x-wire::icon name="check" class="w-5 h-5" /><x-wire::icon name="trash" class="w-4 h-4 text-red-500" /> {{-- Prefixovaná ikona z jiné registrované sady --}}<x-wire::icon name="lucide:home" class="w-5 h-5" /> {{-- Vystavit asistivní technologii (jinak je ikona aria-hidden) --}}<x-wire::icon name="trash" label="Delete" />
Použití v PHP
use NyonCode\WireCore\Foundation\Icons\IconManager; $manager = app(IconManager::class); $manager->render('check'); // plný <svg> řetězec$manager->render('trash', 'w-5 h-5', 'text-red-500', label: 'Delete');$manager->has('lucide:home'); // bool$manager->resolve('check'); // ?ResolvedIcon (body + viewBox + attrs)$manager->allNames(); // každý dostupný název (prefixovaný pro ne-výchozí sady)
render() je kanonický vstupní bod — aplikuje vlastní viewBox a stylování každé
ikony. getPath() vrací jen vnitřní markup a je zachován jen pro volající,
kteří obalují svůj vlastní <svg> (správné jen pro 0 0 20 20 fill ikony).
Dostupné ikony
Každá výchozí ikona používá svůj kanonický Heroicons název — název souboru z heroicons.com (solid varianta). Procházejte celou sadu tam; pár příkladů:
academic-cap, arrow-down-tray, bars-3, chevron-up, cog-6-tooth,
document-text, envelope, funnel, magnifying-glass, pencil, qr-code,
trash, user, wrench-screwdriver, x-mark.
Pro IDE autocompletion můžete na ikony odkazovat přes enum Icon místo
surových řetězců:
use NyonCode\WireCore\Foundation\Icons\Icon; Action::make('edit')->icon(Icon::pencilSquare);
Wire-friendly aliasy
Malá sada krátkých aliasů mapuje na kanonické ikony pro pohodlí:
| Alias | Resolvuje na | Alias | Resolvuje na |
|---|---|---|---|
pen, edit |
pencil |
delete |
trash |
view |
eye |
add |
plus |
download, export |
arrow-down-tray |
upload, import |
arrow-up-tray |
duplicate, copy |
document-duplicate |
x, close |
x-mark |
settings |
cog |
mail, email |
envelope |
exclamation, warning |
exclamation-triangle |
information, info |
information-circle |
question |
question-mark-circle |
archive |
archive-box |
refresh |
arrow-path |
shield |
shield-check |
lock |
lock-closed |
filter |
funnel |
more, dots-vertical |
ellipsis-vertical |
dots-horizontal |
ellipsis-horizontal |
external-link |
arrow-top-right-on-square |
Přístupnost
Ikony se ve výchozím stavu vykreslují jako dekorativní (aria-hidden="true"). Předejte label, když
ikona nese význam sama o sobě — pak je vystavena jako obrázek s tím
popiskem (role="img" + aria-label):
<x-wire::icon name="check-circle" label="Verified" />
Přidávání vlastních ikon
Nemusíte se spokojit s přibalenou sadou. Vyberte přístup, který vám sedí. Vlastní
ikony (složky a inline) jsou holo-pojmenované a mají prioritu před výchozí
sadou, takže se vlastní ikona použije všude, kde je název přijímán
(->icon('logo'), <x-wire::icon name="logo" />, …).
Když vložíte kompletní <svg>…</svg>, jeho viewBox a stylovací atributy
(fill, stroke, stroke-width, …) jsou zachovány — takže můžete vhodit ikony
z jakéhokoli zdroje a formátu. Holý <path> fragment spadne na Heroicons
solid formát (0 0 20 20, fill="currentColor").
1. Ze složky SVG souborů (nejjednodušší)
Vhoďte .svg soubory do adresáře a zaregistrujte cestu — název souboru se stane
názvem ikony (logo.svg → logo). Žádná třída, žádný boilerplate.
Přes config (config/wire-core.php), skvělé pro ikony pro celou aplikaci. Řetězcový klíč přidá
pomlčkou spojený prefix názvu a předchází kolizím názvů souborů mezi složkami:
'icons' => [ 'paths' => [ resource_path('icons'), // resources/icons/logo.svg => "logo" 'brand' => resource_path('icons/brand'), // icons/brand/mark.svg => "brand-mark" ],],
Nebo za běhu:
use NyonCode\WireCore\Foundation\Icons\IconManager; app(IconManager::class)->registerIconsFromDirectory( resource_path('icons/brand'), prefix: 'brand', // brand/logo.svg => "brand-logo");
prefixsložky produkuje plochý název (brand-logo) — není to totéž jakoprefix:namenamespace sady popsaný níže.
2. Inline, podle názvu
Zaregistrujte jednotlivé ikony — vložte plný <svg>…</svg> (wrapper je odstraněn,
jeho viewBox/stylování zachováno) nebo jen vnitřní <path>:
app(IconManager::class)->registerIcons([ 'logo' => '<svg viewBox="0 0 20 20"><path d="M10 2 …"/></svg>', 'spark' => '<path d="M10 1 12 8 …"/>',]);
Znovupoužijte stejný název jako přibalená ikona pro její přepis. Vložte volání do
boot() service provideru, aby byly ikony dostupné všude:
public function boot(): void{ app(IconManager::class)->registerIconsFromDirectory(resource_path('icons'));}
3. Znovupoužitelná sada ikon (pokročilé)
Pro kompletní, vyměnitelný styl implementujte IconSet. Implementujte i volitelnou
schopnost ProvidesIconMetadata, pokud jsou vaše ikony stroke-based nebo používají
ne-20x20 viewBox (Lucide, Feather, Heroicons outline) — to nechá každou ikonu
nést svůj vlastní ResolvedIcon (body + viewBox + atributy):
use NyonCode\WireCore\Foundation\Icons\{IconSet, ProvidesIconMetadata, ResolvedIcon}; final class LucideIconSet implements IconSet, ProvidesIconMetadata{ private string $dir = '/abs/path/to/node_modules/lucide-static/icons'; public function getIcon(string $name): ?ResolvedIcon { $file = "{$this->dir}/{$name}.svg"; // fromSvg() zachová Lucide viewBox="0 0 24 24" + fill=none stroke=currentColor. return is_file($file) ? ResolvedIcon::fromSvg(file_get_contents($file)) : null; } public function getPath(string $name): ?string { return $this->getIcon($name)?->body; } public function has(string $name): bool { return is_file("{$this->dir}/{$name}.svg"); } public function names(): array { /* basenames of *.svg */ return []; }}
Sady, které implementují jen IconSet, stále fungují — jejich getPath() výstup se obalí
do výchozího 0 0 20 20 fill formátu.
Použití více sad ikon
Resolvování je deterministické a namespaced:
- Výchozí sada je neprefixovaná —
pencil,user,lucidealiasy, vlastní ikony — a je vždy Heroicons, dokud ji nevyměníte (níže). - Každá další sada vyžaduje unikátní prefix a adresuje se jako
prefix:name.
Zaregistrujte další sady v configu pod jejich prefix klíčem:
// config/wire-core.php'icons' => [ 'default_set' => 'default', 'sets' => [ 'default' => DefaultIconSet::class, // → "pencil" (Heroicons, 20×20 fill) 'lucide' => LucideIconSet::class, // → "lucide:home" (24×24 stroke) 'custom' => App\Wire\Icons\MyIconSet::class, ],],
<x-wire::icon name="pencil" /> {{-- Heroicons --}}<x-wire::icon name="lucide:home" /> {{-- Lucide --}}
To zaručuje, že sady nikdy nekolidují: holý název je vždy výchozí sada,
prefixovaný název je vždy přesně ta sada. Kvůli tomu registrace ne-výchozí
sady bez prefixu vyhodí InvalidArgumentException:
app(IconManager::class)->registerIconSet(new LucideIconSet, 'lucide'); // okapp(IconManager::class)->registerIconSet(new LucideIconSet); // vyhodí
Oddělovač je dvojtečka (
:). Názvy ikon samy používají pomlčky (arrow-down-tray), takže není žádná nejednoznačnost. Použijtedefault:namek adresování základní sady explicitně.
Prefixy, které si balíčky už zabraly
Tři sady jsou zaregistrované za vás — těmi balíčky, které je kreslí. Každá dodává glyfy, na které Heroicons nemá odpověď, ve formátu, jaký ten jeden povrch potřebuje:
| Prefix | Registruje | Glyfy | Formát |
|---|---|---|---|
wire |
wire-core | wire:star, wire:star-outline — značky hodnocení |
24×24 fill |
forms |
wire-forms | lišta rich editoru, dvacet položek: forms:bold, forms:italic, forms:link, … |
24×24 fill |
table |
wire-table | table:checkbox-check, table:checkbox-indeterminate — značky uvnitř vlastního zaškrtávátka tabulky |
16×16 stroke |
Formát je důvod, proč glyf patří do sady a ne na hromadu: sada deklaruje jeden viewBox a jednu sadu atributů stroke/fill pro všechno v sobě. Značky zaškrtávátka tabulky jsou kreslené v 16×16 tahem, protože se vykreslují do 16px orámovaného okénka a nikam jinam — ve společné sadě s 24×24 vyplněnými ikonami by se jedno z obou vykreslovalo ve špatné váze. Těla se načítají až při prvním použití, takže stránka, která z dané sady nekreslí nic, její soubor vůbec neotevře.
Ta tři jména jsou zabraná a vzít si je zpět má své pořadí. Registrace sady
pod prefix, který už jednu má, tu původní tiše nahradí — a balíčky registrují své
sady při bootu, tedy až po tom, co manažer přečetl icons.sets z konfigurace
(čte ji, když se poprvé vytváří). Deklarace 'table' => MyIconSet::class
v konfiguraci proto neudělá nic: registrace balíčku proběhne později a vyhraje.
Registrujte místo toho z boot() vlastního service provideru, který se spouští
po těch balíčkových:
public function boot(): void{ app(IconManager::class)->registerIconSet(new MyTableIconSet, 'table'); }
Pro výměnu jediného glyfu místo celé sady nechte svou sadu odpovídat na to jedno jméno a zbytek delegujte na sadu balíčku — sada je objekt, takže je to obyčejná kompozice.
Výměna výchozí (neprefixované) sady
Aby se jiná sada stala neprefixovaným základem — např. dodat Lucide jako váš primární
styl — nasměrujte default_set na její klíč:
'icons' => [ 'default_set' => 'lucide', // holé názvy teď resolvují vůči Lucide 'sets' => [ 'lucide' => LucideIconSet::class, 'default' => DefaultIconSet::class, // vynechána: základem je teď Lucide ],],
Dodaný záznam 'default' může v seznamu zůstat; dokud je základem jiná sada,
přeskočí se, protože default: vždy adresuje základní sadu. default_set
s klíčem, který v sets není, vyhodí při startu IconSetRegistrationException,
místo aby potichu ponechal Heroicons.
Za běhu: app(IconManager::class)->setDefaultIconSet(new LucideIconSet).
Vykreslení opakované ikony jen jednou
Tabulka kreslí v každém řádku stejných pár ikon — každé tlačítko akce, booleovský sloupec, značku výběru — a každá z nich nese celá data svých cest. Zapněte sprite a opakovaná ikona putuje jen jednou:
// config/wire-core.php'icons' => [ 'sprite' => env('WIRE_ICONS_SPRITE', true), ],
Uvnitř Livewire renderu je každá ikona stejné <svg> jako vždy — stejné třídy,
viewBox, fill/stroke, aria-* i předané Alpine atributy — jen místo těla drží
<use href="#wi-…"/>. Tělo odchází jako <symbol> jednou za každý kus markupu,
který Livewire posílá celý:
| kus | nese symboly, na které odkazuje |
|---|---|
| render komponenty | ano |
| render ostrova (island) | ano |
partial, kterým odpovídá zápis (rowPartials(), partialy polí formuláře) |
ano |
| cokoli mimo Livewire render — PDF, e-mail, obyčejné Blade v layoutu | vůbec se nespritují; inline jako dřív |
Ať prohlížeč přimorfuje kterýkoli z nich, jeho ikony se vyřeší samy, ještě než
proběhne jakýkoli skript. Symboly jedou uvnitř prvního spritovaného <svg>
daného kusu, ne ve skrytém elementu vedle něj: nový poslední potomek by posunul
každé :last-child, last: i space-y-* z Tailwindu 4 ve vašem markupu.
Malý skript wire-core-icons.js (pod 1 kB) kopíruje každý symbol, který uvidí,
do jednoho spritu na konci <body>; na ten <use> sáhne, když ikona, která
symbol nesla, byla odmorfována — třeba když se kolem ní přerenderoval ostrov.
Livewiru ho předá jako asset první komponenta, která nakreslí spritovanou ikonu,
takže do layoutu není co přidávat.
Naměřeno na tabulce s 50 řádky, čtyřmi sloupci ikon, třemi řádkovými akcemi a skupinou o třech položkách (605 ikon, 17 různých): 851 965 → 705 288 bajtů surově (−17 %), 22 315 → 17 297 bajtů gzip (−22 %), čas renderu beze změny.
Za co to vyměňujete. <use> kreslí svůj symbol ve stínovém stromu a
selektory do něj nepronikají. Dědičné vlastnosti se k cestám stále dostanou —
color, fill, stroke, opacity, stroke-dashoffset — což je vše, na čem
stojí vlastní markup stacku. Váš vlastní stylopis, který sahá dovnitř ikony
(.toolbar svg path { stroke-width: 1 }), přestane zabírat, a proto je přepínač
ve výchozím stavu vypnutý. Než ho zapnete, projděte své CSS na selektory tvaru
svg path.
Některá těla se nespritují nikdy, ať přepínač říká cokoli: tělo s id nebo odkazy
url(#…) (gradienty, masky, ořezové cesty), protože každá kopie symbolu by
nesla totéž id. Inline zůstávají i ikony ve specifikaci líného menu akcí — ten
JSON se stává markupem teprve při otevření menu.
Vykreslit spritovanou ikonu sami nevyžaduje nic nového: icon(), <x-wire::icon>
i IconManager::render() rozhodují při každém volání. Kód, který si <svg>
staví sám, se zeptá IconManager::body($icon) na to, co do něj patří.
Odchytávání překlepů
Nastavte icons.warn_missing (nebo WIRE_ICONS_WARN_MISSING=true) pro logování varování,
kdykoli se vykreslí neznámý název ikony — stále vykreslí fallback
placeholder, ale log pomáhá odhalit překlepy ve vývoji.
Regenerace přibalených Heroicons
Přibalené cesty žijí v generovaném PHP data souboru
packages/core/resources/icons/heroicons-solid.php, produkovaném z oficiálního
npm balíčku heroicons (20/solid SVG, klíčované názvem souboru). Regenerujte ten
soubor místo ruční editace cest ikon.
Související
- Barvy — stejný tvar resolveru pro druhou polovinu povrchu
- Enumy — enum, který si pojmenuje vlastní ikonu
- Motivy a přizpůsobení — výměna sady, kterou aplikace používá
- Foundation — concerny, kterými se k tomuhle dostanete