Icons

Every icon in the library, what to import, and how they take their colour and size.

PanelUI ships a small icon set — enough to draw its own components without pulling in a dependency, and enough for most of an app. Every one is a React component exported from the package, so there is nothing to install and no sprite sheet to load.

import { SearchIcon, ClockIcon } from 'panelui-native';

<SearchIcon />
<ClockIcon size={20} />

The set

Search by name or by what it is — "arrow", "chevron", "shield". Click any icon to copy its tag.

62 of 62

The names shown are without the Icon suffix that every export carries. The bell is BellIcon, not Bell.

Size

size sets both dimensions — they are always square.

<BellIcon size={24} />

Each icon has a default suited to where it is normally drawn, so most call sites can leave it off. Most default to 16. CheckIcon and MinusIcon default to 14, being the glyphs inside a checkbox. Eleven that are usually drawn larger — the brand marks, the sun and moon toggles, the filled status icons, MenuIcon, ArrowUpRightIcon and StarIcon — default to 18 or 20.

Colour

An icon takes its colour in this order:

  1. An explicit color prop.
  2. The colour provided by an enclosing surface.
  3. Its own fallback.

The fallback is a mid grey for most of the set, and differs for the few that are normally drawn somewhere specific — CheckIcon falls back to white, because it sits on a filled checkbox.

The middle step is the one that matters, and it is why an icon dropped into a Button looks right without being told anything:

// The icon comes out in the primary foreground, not grey —
// Button provides the colour that reads against its own fill.
<Button startContent={<SendIcon size={16} />}>Send</Button>

Any component painting its own background does this. To do it yourself, wrap a subtree in the provider:

import { IconColorProvider } from 'panelui-native';
import { useCSSVariable } from 'uniwind';

const tint = useCSSVariable('--color-destructive');

<IconColorProvider color={tint}>
  <TrashIcon />
  <XIcon />
</IconColorProvider>

Pass a token rather than a hex, so the icon follows the theme — see Colors for useCSSVariable.

Brand marks keep their own colours

GoogleIcon and FacebookIcon carry their palettes and ignore both the color prop and the surrounding context, because a recoloured brand mark is the wrong mark. AppleIcon is the exception among the three: it is monochrome by design and Apple's guidelines require it to match the button's text, so it does follow the colour context.

Filled and outlined

A few icons have an on state, taking filled — a like that has been given, a bookmark that has been saved, a vote that has been cast.

<HeartIcon filled={liked} />
<BookmarkIcon filled={saved} />

HeartIcon, BookmarkIcon, StarIcon, ArrowUpIcon, ArrowDownIcon and MessageCircleIcon take it. The outline stays put and only the inside changes, so the row does not shift when the state does.

BadgeCheckIcon is filled either way and takes a checkColor for the tick inside it, which defaults to white.

Direction

ChevronLeftIcon and ChevronRightIcon mirror themselves inside a Direction dir="rtl" subtree. Yoga moves a chevron to the other end of its row, but it cannot turn the glyph around — so without this an RTL list row ends up with a right-pointing chevron on its left edge, pointing back at the text.

Only glyphs whose meaning is a direction do this. A pencil or a magnifier means the same thing either way round, and flipping it would just be a wrong drawing.

Using another icon set

Nothing in PanelUI requires its own icons. Every prop that takes an icon takes any React element, so a lucide-react-native or @expo/vector-icons component drops straight in:

import { Rocket } from 'lucide-react-native';

<Button startContent={<Rocket size={16} />}>Launch</Button>

The one thing you give up is the colour context: a third-party icon does not know about IconColorProvider, so on a coloured surface it needs the colour passing explicitly.

<Button startContent={<Rocket size={16} color="white" />}>Launch</Button>

Next

On this page