Foundations
Icons
Icons as classes, in the text's size and color, from Tabler Icons; the components' icon slots and icon-only controls.
An icon is an empty element with the icon class and the icon’s own class, icon-{name}: a square of the text’s size in the text’s color. The Icons page lists every icon to copy.
Load the icons
The icons come in two stylesheets outside Full, loaded after it: icons/icons.min.css holds the outline icons and icons/icons-filled.min.css the filled ones, whose classes end in -filled. They serve the icon classes you write: components draw their own fixed icons, such as chevrons, close buttons and checks, without them (Slots lists those).
<link rel="stylesheet" href="pelatform-ui.min.css">
<link rel="stylesheet" href="icons/icons.min.css">With a bundler, import @pelatform/ui/icons/css and @pelatform/ui/icons-filled/css; in WordPress, enqueue plf_ui_enqueue('icons') (WordPress). Each stylesheet holds its whole set, 249 KB and 110 KB with gzip, so a page with a few icons can paste their SVG from the Icons page instead.
<div class="flex items-center gap-4">
<span class="icon icon-home"></span>
<span class="icon icon-search"></span>
<span class="icon icon-bell"></span>
<span class="icon icon-settings"></span>
<span class="icon icon-user"></span>
</div><div class="plf:flex plf:items-center plf:gap-4">
<span class="plf:icon plf:icon-home"></span>
<span class="plf:icon plf:icon-search"></span>
<span class="plf:icon plf:icon-bell"></span>
<span class="plf:icon plf:icon-settings"></span>
<span class="plf:icon plf:icon-user"></span>
</div>import { Icon } from '@pelatform/react';
export function Example() {
return (
<div className="flex items-center gap-4">
<Icon name="home" />
<Icon name="search" />
<Icon name="bell" />
<Icon name="settings" />
<Icon name="user" />
</div>
);
}import { Icon } from '@pelatform/react/prefixed';
export function Example() {
return (
<div className="plf:flex plf:items-center plf:gap-4">
<Icon name="home" />
<Icon name="search" />
<Icon name="bell" />
<Icon name="settings" />
<Icon name="user" />
</div>
);
}Sizes
An icon is 1em, its text’s size. size-{n} sets its width and height on the spacing scale:
| Class | Size |
|---|---|
size-4 |
1rem, 16px |
size-5 |
1.25rem, 20px |
size-6 |
1.5rem, 24px |
size-8 |
2rem, 32px |
<div class="flex items-center gap-4">
<span class="icon icon-heart size-4"></span>
<span class="icon icon-heart size-5"></span>
<span class="icon icon-heart size-6"></span>
<span class="icon icon-heart size-8"></span>
</div><div class="plf:flex plf:items-center plf:gap-4">
<span class="plf:icon plf:icon-heart plf:size-4"></span>
<span class="plf:icon plf:icon-heart plf:size-5"></span>
<span class="plf:icon plf:icon-heart plf:size-6"></span>
<span class="plf:icon plf:icon-heart plf:size-8"></span>
</div>import { Icon } from '@pelatform/react';
export function Example() {
return (
<div className="flex items-center gap-4">
<Icon name="heart" className="size-4" />
<Icon name="heart" className="size-5" />
<Icon name="heart" className="size-6" />
<Icon name="heart" className="size-8" />
</div>
);
}import { Icon } from '@pelatform/react/prefixed';
export function Example() {
return (
<div className="plf:flex plf:items-center plf:gap-4">
<Icon name="heart" className="plf:size-4" />
<Icon name="heart" className="plf:size-5" />
<Icon name="heart" className="plf:size-6" />
<Icon name="heart" className="plf:size-8" />
</div>
);
}<div class="flex items-center gap-4">
<span class="icon icon-circle-check text-success"></span>
<span class="icon icon-alert-triangle text-warning"></span>
<span class="icon icon-circle-x text-error"></span>
<span class="icon icon-info-circle text-info"></span>
</div><div class="plf:flex plf:items-center plf:gap-4">
<span class="plf:icon plf:icon-circle-check plf:text-success"></span>
<span class="plf:icon plf:icon-alert-triangle plf:text-warning"></span>
<span class="plf:icon plf:icon-circle-x plf:text-error"></span>
<span class="plf:icon plf:icon-info-circle plf:text-info"></span>
</div>import { Icon } from '@pelatform/react';
export function Example() {
return (
<div className="flex items-center gap-4">
<Icon name="circle-check" className="text-success" />
<Icon name="alert-triangle" className="text-warning" />
<Icon name="circle-x" className="text-error" />
<Icon name="info-circle" className="text-info" />
</div>
);
}import { Icon } from '@pelatform/react/prefixed';
export function Example() {
return (
<div className="plf:flex plf:items-center plf:gap-4">
<Icon name="circle-check" className="plf:text-success" />
<Icon name="alert-triangle" className="plf:text-warning" />
<Icon name="circle-x" className="plf:text-error" />
<Icon name="info-circle" className="plf:text-info" />
</div>
);
}<div class="flex items-center gap-4">
<span class="icon icon-heart-filled text-error"></span>
<span class="icon icon-star-filled text-warning"></span>
<span class="icon icon-bookmark-filled"></span>
<span class="icon icon-bell-filled"></span>
</div><div class="plf:flex plf:items-center plf:gap-4">
<span class="plf:icon plf:icon-heart-filled plf:text-error"></span>
<span class="plf:icon plf:icon-star-filled plf:text-warning"></span>
<span class="plf:icon plf:icon-bookmark-filled"></span>
<span class="plf:icon plf:icon-bell-filled"></span>
</div>import { Icon } from '@pelatform/react';
export function Example() {
return (
<div className="flex items-center gap-4">
<Icon name="heart-filled" className="text-error" />
<Icon name="star-filled" className="text-warning" />
<Icon name="bookmark-filled" />
<Icon name="bell-filled" />
</div>
);
}import { Icon } from '@pelatform/react/prefixed';
export function Example() {
return (
<div className="plf:flex plf:items-center plf:gap-4">
<Icon name="heart-filled" className="plf:text-error" />
<Icon name="star-filled" className="plf:text-warning" />
<Icon name="bookmark-filled" />
<Icon name="bell-filled" />
</div>
);
}Slots
An icon in a component’s icon slot, such as a button or a menu item, takes the slot’s size and color with no other class. An <svg> of yours there takes the slot’s class.
<div class="flex flex-wrap items-center gap-2">
<button class="btn btn-primary">
<span class="icon icon-device-floppy"></span>
Save
</button>
<button class="btn btn-outline btn-square" aria-label="Settings">
<span class="icon icon-settings"></span>
</button>
</div><div class="plf:flex plf:flex-wrap plf:items-center plf:gap-2">
<button class="plf:btn plf:btn-primary">
<span class="plf:icon plf:icon-device-floppy"></span>
Save
</button>
<button class="plf:btn plf:btn-outline plf:btn-square" aria-label="Settings">
<span class="plf:icon plf:icon-settings"></span>
</button>
</div>import { Button, Icon } from '@pelatform/react';
export function Example() {
return (
<div className="flex flex-wrap items-center gap-2">
<Button color="primary">
<Icon name="device-floppy" />
Save
</Button>
<Button variant="outline" shape="square" aria-label="Settings">
<Icon name="settings" />
</Button>
</div>
);
}import { Button, Icon } from '@pelatform/react/prefixed';
export function Example() {
return (
<div className="plf:flex plf:flex-wrap plf:items-center plf:gap-2">
<Button color="primary">
<Icon name="device-floppy" />
Save
</Button>
<Button variant="outline" shape="square" aria-label="Settings">
<Icon name="settings" />
</Button>
</div>
);
}| Rule | Why |
|---|---|
Give an icon-only control an aria-label or sr-only text |
The control, not the icon, needs the accessible name |
| Leave the icon element empty | Assistive technology passes over an empty element, so it needs no aria-hidden |
| Make the control, never the icon, the click target | Native buttons keep keyboard, focus and disabled behavior |
| Choose the glyph for right-to-left pages yourself | Directional icons are not mirrored automatically |
Components draw their fixed icons themselves, with no icon stylesheet: a colored Alert’s or Toast’s icon, the icon an Alert Dialog’s or Result Dialog’s color puts in its empty icon box, the x of an empty Toast, Modal or Sheet close button, Mockup’s lock and sizes, the chevrons of Pagination, Accordion, Collapsible, Breadcrumb, Carousel, DataTable’s pager, a Navigation Menu trigger and a collapsible Sidebar group, Sortable’s and Resizable’s grips, Code Block’s copy, Theme Switch’s icons, the password toggle’s eye, Command’s search, a date picker’s calendar, and the icons their scripts add, such as Select’s chevron and check. An icon you write in a slot takes the drawn one’s place. The loader of a Spinner, <span class="loading"></span>, or a loading Button, <span class="btn-icon btn-icon-loading"></span>, stops turning under reduced motion; you set aria-busy, disabled and the loading label.
The table names where each component finds its icon, the class an SVG takes there, and the size variable to override with its default; --plf-control-icon-size is 16px at the default 14px control font and scales with it.
| Component | Icon in | SVG class | Size |
|---|---|---|---|
| Accordion | accordion-trigger |
accordion-icon |
--plf-accordion-icon-size, control icon size |
| Alert | alert-body |
alert-icon |
--plf-alert-icon-size, 1.25em |
| Alert Dialog | alert-dialog-icon |
alert-dialog-svg |
--plf-alert-dialog-icon-size, 1.25em |
| Attachment | attachment-media, File Upload’s file-upload-remove |
attachment-icon |
--plf-attachment-icon-size, 1.25rem |
| Badge | badge |
badge-icon |
--plf-badge-icon-size, 1em |
| Breadcrumb | A link | None | --plf-breadcrumb-icon-size, control icon size |
| Button | btn, or its btn-label |
btn-icon |
--plf-button-icon-size, 14/16/18px for small/default/large |
| Carousel | A carousel-control |
carousel-icon |
Control icon size |
| Code Block | code-block-copy |
code-block-copy-icon |
Control icon size |
| Collapsible | collapse-trigger |
collapse-icon |
--plf-collapsible-icon-size, control icon size |
| Combobox | <template data-plf-combobox-icon>, cloned into combobox-icon |
None | --plf-combobox-icon-size, 14/16/18px for small/default/large |
| Command | command-item, command-search |
command-icon |
16px |
| Context Menu | menu-item |
menu-icon |
Control icon size |
| Dropdown Menu | menu-item |
menu-icon |
Control icon size |
| Empty | empty-media |
empty-icon |
--plf-empty-icon-size, 24px |
| File Upload | file-upload-picker-label |
file-upload-picker-icon |
2rem |
| Hover Card | hover-card-meta, hover-card-media |
hover-card-icon |
--plf-hover-card-icon-size, control icon size |
| Input Group | input-group, input-group-addon, input-group-action |
input-group-icon |
--plf-input-group-icon-size, 14/16/18px for small/default/large |
| Item | item-media, item-actions |
item-icon |
--plf-item-icon-size, control icon size |
| Navigation Menu | navigation-menu-entry |
navigation-menu-icon |
--plf-navigation-menu-icon-size, control icon size |
| Pagination | A control, such as pagination-link |
pagination-icon |
--plf-pagination-icon-size, control icon size |
| Resizable | resizable-grip |
resizable-icon |
--plf-resizable-icon-size, control icon size |
| Result Dialog | result-dialog-icon |
result-dialog-svg |
1.5rem |
| Sheet | sheet-close |
sheet-icon |
Control icon size |
| Sidebar | sidebar-link, sidebar-identity-icon |
sidebar-icon |
Control icon size |
| Sortable | sortable-handle |
sortable-icon |
Control icon size |
| Timeline | timeline-marker |
timeline-icon |
--plf-timeline-icon-size, 16px (14px small) |
| Toast | alert; toast-close |
alert-icon; toast-close-icon |
Control icon size |
| Toggle | The toggle | btn-icon |
--plf-button-icon-size, as on Button |
| Tree View | tree-view-link |
tree-view-icon |
Control icon size |
React
Icon from @pelatform/react renders an icon’s classes on an empty span, as a Server Component; it needs the icon stylesheets, as the classes do.
| Prop | Values | Default |
|---|---|---|
name |
The icon’s name after icon-: arrow-right, or heart-filled for a filled icon (IconName) |
Required |
It also takes a span’s props, className, style and ref included.
Inline SVG
Where the icon stylesheets are not loaded, such as in an email, an icon’s SVG from the Icons page goes in the markup, with the slot’s class and aria-hidden="true"; any SVG in currentColor with a viewBox works in a slot.
<button class="btn btn-primary">
<svg class="btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h10l4 4v10a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2"/><path d="M10 14a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"/><path d="M14 4l0 4l-6 0l0 -4"/></svg>
Save
</button><button class="plf:btn plf:btn-primary">
<svg class="plf:btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h10l4 4v10a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2"/><path d="M10 14a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"/><path d="M14 4l0 4l-6 0l0 -4"/></svg>
Save
</button>Tabler Icons
The icons, and the components’ own, such as Select’s chevron and check, are Tabler Icons by Paweł Kuna, release 3.50.0, under the MIT License, with their geometry as drawn: the stylesheets that hold them keep the license in their first lines, and the package ships tabler-notices.txt. Brand icons are their owners’ trademarks. No icon runtime or CDN is required.
Keep the license notice when you redistribute the icons or the files that contain them.