Skip to main content
Firstlight

Firstlight / Docs

Recipes for the screens a forms app needs, setup for your coding agent, Laravel on native screens, and accessibility.

View source
Use custom icons

Use Custom Icons

SF Symbols and Material Icons cover most actions, but not your brand mark, a domain object or an icon from your design system. NativePHP Mobile builds SVG files in resources/icons into native icons: a template image in the iOS asset catalogue and a VectorDrawable on Android. You refer to each one as custom:<name>.

Firstlight draws custom icons wherever it accepts an authored icon: Button, Icon Button, List Item (leading and trailing icons, swipe actions and context menus), Pill Group options, Status Label and Text Field. They take the control's colour, like system icons.

Install icons

Install icons from any Iconify set with set:name:

php artisan firstlight:icon lucide:git-commit-vertical heroicons:rocket-launch-solid tabler:plant-2

Each icon is written to resources/icons/<name>.svg, so these become custom:git-commit-vertical, custom:rocket-launch-solid and custom:plant-2. Useful sets include lucide, heroicons, tabler, ph (Phosphor), material-symbols, mdi, and Font Awesome Free as fa7-solid, fa7-regular and fa7-brands.

You can also install an SVG file or URL:

php artisan firstlight:icon ~/Downloads/logo.svg --as=brand
php artisan firstlight:icon https://example.com/icons/route.svg
Option Effect
--as=<name> Installs a single icon under this name.
--force Replaces icons that are already installed.

The command checks each SVG with NativePHP's own converter before writing it, so an icon the native build would reject is never installed. The error names the element and attribute to fix, such as a transform or a gradient. An icon that already exists is skipped without being downloaded. If any icon fails, the others are still installed and the command exits with status 1.

Names must be lowercase kebab-case. When the source name isn't, such as Rocket Launch.svg, pass --as.

The first line of each file records where it came from, such as <!-- lucide:git-commit-vertical from Iconify. Set and licence: https://icon-sets.iconify.design/lucide/ -->. Check the licence of every set you use, and credit it the way the licence asks.

Install Font Awesome Pro icons

Create an API token with your Font Awesome account at fontawesome.com/account/general and put it in .env as FA_API_TOKEN, the variable the Font Awesome CLI uses. Never commit the token.

FA_API_TOKEN=your-api-token

Then name the style and icon, or the family, style and icon:

php artisan firstlight:icon fontawesome:light/rocket-launch fontawesome:duotone/solid/kiwi-bird fontawesome:sharp/regular/house

The family defaults to classic. Icons come from the latest Font Awesome 7 release. Font Awesome's API only returns the styles your plan includes. Duotone icons keep their two layers as one colour at two opacities.

The Font Awesome Pro licence lets you embed Pro icons in your app, but not give others permission to reuse them. Keep Pro SVGs out of public or openly licensed repositories.

Use an icon

Pass custom:<name> to any icon attribute:

<firstlight:icon-button icon="custom:rocket-launch-solid" a11y-label="Launch" @press="launch" />

<firstlight:list-item
    headline="Greenhouse"
    leading-icon="custom:plant-2"
    trailing-icon="chevron-right"
    trailing-icon-ios="chevron.right"
    trailing-icon-android="chevron_right"
    @press="openGreenhouse"
/>

<firstlight:text-field label="Branch" native:model="branch" leading-icon="custom:git-commit-vertical" />

Platform overrides accept custom icons too, so you can use your icon on one platform and a system icon on the other:

<firstlight:list-item headline="Pets" leading-icon="pets" leading-icon-ios="custom:paw-print-fill" @press="openPets" />

In PHP, Native\Mobile\Icon\Icon::custom('plant-2') returns 'custom:plant-2'.

Build the app

Icons are compiled into the native project, so adding or changing an SVG needs a native build. Run php artisan native:run to see it; hot reload does not pick up icon changes.

A build without the icon, such as Jump or a build made before you installed it, draws the system icon with the same name instead. custom:bell shows the system bell, so naming an icon after the system icon it replaces gives a sensible fallback.

Check that the icon renders

Open the screen on iOS and Android in light and dark appearance. The icon should take the control's colour and sit at the same size as the system icons beside it. The showcase app has a Custom Icons screen with every supported control.

Custom icons are decorative, like system icons: VoiceOver and TalkBack read the control's label, not the icon. Give icon-only controls an a11y-label.

Served from firstlightui/nativephp on GitHub.