Icon tidak tampil
->icon('shield') menghasilkan ruang kosong tanpa error dan tanpa apa pun di log. Icon registry adalah allowlist pada waktu build: nama yang bukan key di resources/js/panel/icons/registry.ts akan di-resolve menjadi tidak ada. Gunakan halaman ini ketika icon hilang dari button, navigation item, widget, atau notification.
Mulai dari sini
php artisan panel:icons
npm run build2
INFO Registered 24 icons.Command memindai directory app/ milik aplikasi dan source framework untuk semua pola deklarasi nama icon, memeriksa setiap nama terhadap icon yang benar-benar disediakan Lucide, lalu menulis ulang registry. Setelah itu lakukan rebuild: registry adalah TypeScript module, sehingga entry baru belum masuk bundle sampai Vite memprosesnya.
Mengapa nama yang tidak dikenal menghasilkan icon kosong
Nama icon datang dari server sebagai string biasa. Seluruh proses resolve melewati satu map dan tidak ada lookup lain.
Jika nama arbitrer dari server dapat langsung di-resolve menjadi component, metadata panel dapat menjangkau isi bundle secara dinamis. Dynamic import yang key-nya berasal dari runtime juga tidak dapat dianalisis secara statis. Lucide menyediakan 1768 icon; panel biasanya hanya memakai beberapa puluh, dan hanya icon yang benar-benar digunakan yang perlu masuk bundle.
Generated registry mengubah siapa yang memelihara daftar tersebut, bukan jaminan yang diberikan oleh daftar itu.
Command
php artisan panel:icons # rewrite the registry from the source
php artisan panel:icons --check # fail instead of writing, for CI2
| Opsi | Efek |
|---|---|
| (tanpa opsi) | Menulis resources/js/panel/icons/registry.ts dan melaporkan jumlah icon yang terdaftar |
--check | Membandingkan file yang seharusnya ditulis dengan file di disk, tidak menulis apa pun, dan gagal jika keduanya berbeda |
Exit code:
| Kondisi | Exit |
|---|---|
| File ditulis dan semua nama merupakan icon Lucide yang valid | 0 |
| File ditulis tetapi satu atau lebih nama bukan icon Lucide | 1, setelah Not a Lucide icon: shildd |
--check, file current dan semua nama valid | 0 |
--check, file out of date | 1, setelah The icon registry is out of date. Run php artisan panel:icons. |
--check, file current tetapi terdapat nama yang tidak dikenal | 1 |
Nama yang tidak dimiliki Lucide membuat command gagal dengan menyebut namanya. Itu adalah satu-satunya warning eksplisit; icon yang tidak terdaftar di registry hanya akan tidak tampil tanpa error.
Tambahkan --check ke CI bersama static check lainnya:
php artisan panel:icons --check
composer run analyse
npm run typecheck2
3
Source yang dibaca command
Ada dua root, dan keduanya dipindai untuk file .php:
| Root | Alasan |
|---|---|
app_path() | panel, resource, page, widget, dan action milik aplikasi |
src/ milik framework | banyak icon panel berasal dari action bawaan framework — delete, edit, export |
Root kedua tidak opsional. Setelah framework terpasang sebagai package di vendor, scan yang hanya membaca app/ akan menulis ulang registry tanpa icon bawaan, sehingga seluruh built-in action kehilangan icon tanpa error.
Ada lima literal pattern, ditambah body dari method yang secara literal bernama icon():
->icon('shield') // the fluent setter
protected static ?string $navigationIcon = 'users';
->emptyState(heading: 'None yet', icon: 'users') // any named argument called icon
['icon' => 'download'] // a serialized array entry
PandaPanel\Forms\Prime\Icon::make('mail') // the prime component2
3
4
5
// scanned because the method is named icon()
public function icon(): string
{
return match ($this) {
self::Paid => 'check',
self::Overdue => 'triangle-alert',
};
}2
3
4
5
6
7
8
Body method icon() dipindai sebagai kasus khusus karena enum yang menjawab "icon mana yang digunakan case ini" biasanya menyimpan nama icon di match arms, dan pola literal umum tidak dapat menemukannya. Scan dibatasi pada nama method tersebut agar match yang mengembalikan string biasa di tempat lain tidak salah dianggap daftar icon.
Nama yang bukan literal tidak terlihat oleh scanner. Constant, variable, atau nama hasil concatenation tidak akan didaftarkan:
->icon(self::ICON) // not seen
->icon('user-'.$suffix) // not seen
->icon('user-check') // seen2
3
Nama harus mengikuti pola [a-z0-9-]+, sesuai penamaan kebab-case Lucide.
Memeriksa nama terhadap Lucide
Command membaca node_modules/@lucide/vue/dist/esm/icons dan memperlakukan setiap filename .mjs sebagai nama icon yang tersedia.
WARN @lucide/vue is not installed; nothing to check names against.Jika Lucide belum terinstal di disk, tidak ada sumber yang dapat dipakai untuk memvalidasi nama. Menganggap semua nama salah justru akan mengosongkan registry dan membuat setiap icon pada panel menghilang hanya karena seseorang menjalankan command sebelum npm install. Dalam kondisi ini nama tetap digunakan untuk menulis registry; hanya tahap validasinya yang dilewati.
Registry module
import { isPanelIconName, resolveIcon } from '@/panel/icons/registry';
import type { PanelIconName } from '@/panel/icons/registry';
isPanelIconName('shield'); // true — narrows string to PanelIconName
resolveIcon('shield'); // the Lucide component
resolveIcon('shildd'); // null, plus one dev-only console warning
resolveIcon(null); // null, silently2
3
4
5
6
7
| Export | Signature | Catatan |
|---|---|---|
PanelIconName | type PanelIconName = keyof typeof ICONS | semua nama yang terdaftar sebagai union type |
isPanelIconName | isPanelIconName(name: string): name is PanelIconName | type guard |
resolveIcon | resolveIcon(name: string | null | undefined): Component | null | null jika nama tidak dikenal atau tidak diberikan |
resolveIcon() mengembalikan null baik untuk nama yang tidak dikenal maupun untuk kondisi tidak ada nama. Caller cukup tidak merender icon daripada menampilkan icon rusak, dan production console tetap bersih. Pada development, warning muncul satu kali per nama:
[panel] The icon [shildd] is not in the icon registry, so nothing is drawn for it.
Run `php artisan panel:icons` to rebuild the registry from the icons your panels declare.2
Warning tersebut membedakan dua kasus yang sebelumnya tampak sama: typo pada nama icon dan lupa menjalankan generator ulang. Warning hanya muncul di development; pada production icon tetap tidak tampil karena ini adalah build problem, bukan runtime problem.
Registry yang dikirim saat ini berisi nama-nama berikut:
check circle-alert copy download eye
info layout-grid link mail palette
pencil plus receipt rotate-ccw search
settings shield trash trash-2 triangle-alert
unlink upload user users2
3
4
5
Daftar itu adalah generated output, bukan daftar icon yang didukung secara permanen. Gunakan nama Lucide apa pun yang Anda perlukan lalu jalankan panel:icons.
Lokasi file registry
use PandaPanel\Support\FrontendPaths;
FrontendPaths::panel(); // resource_path('js/panel')
FrontendPaths::panel('icons/registry.ts'); // resource_path('js/panel/icons/registry.ts')
FrontendPaths::pages(); // resource_path('js/pages/Panels')2
3
4
5
| Method | Signature | Config key | Default |
|---|---|---|---|
panel | static panel(string $path = ''): string | panda-panel.frontend.panel_path | js/panel |
pages | static pages(string $path = ''): string | panda-panel.frontend.pages_path | js/pages/Panels |
// config/panda-panel.php
'frontend' => [
'panel_path' => 'js/panel',
'pages_path' => 'js/pages/Panels',
],2
3
4
5
Project yang mengatur resources/js dengan struktur berbeda dapat mengubah config key tersebut. panel:icons, vendor:publish, dan panel:assets semuanya akan mengikuti path yang sama karena membaca class yang sama.
Memverifikasi registry dalam test
Test suite framework berjalan melalui setiap panel, navigation item, row action, dan bulk action pada setiap resource, lalu memastikan setiap nama icon yang diminta merupakan key di registry. Pola test tersebut layak digunakan juga di aplikasi:
use PandaPanel\Core\PanelManager;
use PandaPanel\Support\NavigationBuilder;
$source = file_get_contents(resource_path('js/panel/icons/registry.ts'));
$body = str($source)->between('const ICONS = {', '} satisfies')->toString();
preg_match_all("/^\s*'?([a-z0-9-]+)'?:/m", $body, $matches);
expect($matches[1])->toContain('shield');2
3
4
5
6
7
8
9
Navigation bukan satu-satunya lokasi nama icon dapat tersembunyi. Row action dan bulk action pada table juga membawa nama icon, dan nama yang tidak terdaftar akan gagal dengan cara diam yang sama.
Catatan
- Registry adalah generated file. Jangan edit manual. File tersebut menyatakan hal ini di bagian atas, dan run
panel:iconsberikutnya akan menimpa perubahan manual. - Menambahkan icon membutuhkan dua langkah: jalankan command generator dan
npm run build. Salah satu saja tidak cukup. - Command ini tidak didaftarkan sebagai hook
optimize.panel:cachedanpanel:clearterdaftar;panel:iconsadalah source-generation step dan seharusnya berada di build pipeline sebelum asset dikompilasi. - Nama salah eja dan nama baru yang ditambahkan setelah generator terakhir terlihat sama di screen — keduanya tidak menggambar apa pun. Warning dev console adalah pembeda, dan hanya muncul di development.
--checkgagal pada clean checkout biasanya berarti icon ditambahkan di PHP tetapi registry belum diregenerasi. Jalankan command lalu commit hasilnya.- Icon dalam metadata tetap berupa string sampai ke frontend. Server tidak memvalidasi apakah nama itu ada di bundle, karena pertanyaan tersebut hanya dapat dijawab oleh build.
icon()milik panel,$navigationIconmilik resource,$navigationIcondan$activeNavigationIconmilik cluster,icon()milik action, sertaicon()milik notification semuanya menggunakan registry yang sama. Tidak ada lookup kedua.