| ← Back to UI Components | ← Back to Table of Contents |
9.2 Bootstrap Icons
KMP templates primarily render Bootstrap Icons with bi CSS classes:
<i class="bi bi-calendar-event" aria-hidden="true"></i>
The authenticated application stylesheet, app/assets/css/app.css, currently
imports Bootstrap Icons 1.11.3 from the versioned unpkg font stylesheet and then
imports app/assets/css/bootstrap-icon-sizes.css. The public-event layout also
loads that versioned stylesheet directly. The Vite build owns app.css; see
Asset management.
KMP also bundles Font Awesome through @fortawesome/fontawesome-free. Do not
mix bi-* and fa-* classes on one icon or assume that a name exists in both
sets.
Template patterns
Use an icon plus visible text for actions whenever space permits:
<button type="button" class="btn btn-primary">
<i class="bi bi-download me-2" aria-hidden="true"></i>
<?= __('Export CSV') ?>
</button>
An icon-only control needs an accessible name and a useful visible tooltip only as a supplement:
<button
type="button"
class="btn btn-sm btn-outline-secondary"
aria-label="<?= h(__('Edit member')) ?>"
title="<?= h(__('Edit member')) ?>">
<i class="bi bi-pencil" aria-hidden="true"></i>
</button>
Status must include text, not only color or an icon:
<span class="text-success">
<i class="bi bi-check-circle-fill me-1" aria-hidden="true"></i>
<?= __('Active') ?>
</span>
When an icon itself conveys an image or status without adjacent text, give its
container an accessible name. Decorative icons must use aria-hidden="true".
Size and color
Icons inherit font-size and currentColor. Bootstrap utilities such as
fs-4, text-success, and me-2 are usually sufficient. KMP’s additional
size classes are defined in bootstrap-icon-sizes.css:
- relative sizes:
bi-2xs,bi-xs,bi-sm,bi-lg,bi-xl,bi-2xl; - multiples:
bi-1xthroughbi-10x.
Prefer relative sizing that follows surrounding text. Large decorative icons must not displace labels, reduce touch targets, or obscure visible focus.
Dynamic icons
Treat an icon class derived from data as an allowlisted presentation value. Never concatenate untrusted input into a class or emit raw HTML.
<?php
$icons = [
'active' => 'bi-check-circle-fill',
'pending' => 'bi-clock',
'inactive' => 'bi-x-circle',
];
$icon = $icons[$status] ?? 'bi-question-circle';
?>
<i class="bi <?= h($icon) ?>" aria-hidden="true"></i>
<span><?= h($statusLabel) ?></span>
Icon helpers
AppView conditionally loads Templating.Icon and
Templating.IconSnippet when the optional templating classes are installed,
and config/app.php declares a Bootstrap icon set. Existing Queue-plugin
templates use this helper surface. The general KMP templates use bi class
markup; follow the nearby template instead of converting styles opportunistically.
The helper’s configured metadata path and the CSS-font delivery path are separate concerns. A Vite build does not generate Bootstrap Icon metadata.
Finding an icon
Use the official Bootstrap Icons gallery and verify the selected icon exists in the pinned 1.11.3 set before committing it. Then search the codebase for an established KMP usage:
rg 'bi-calendar-event' app/templates app/plugins
Troubleshooting
If a bi icon does not display:
- Confirm the page loads
appCSS or the public-event Bootstrap Icons stylesheet. - Confirm the class includes both
biand the exactbi-{name}. - Inspect the stylesheet request and font requests in the browser network panel.
- Run
npm run devfromapp/after changing stylesheet imports. - Check Content Security Policy and network availability when the remote font stylesheet is involved.
If a Font Awesome icon does not display, check its fa-* classes and the
Vite-copied files under webroot/fonts; that is a different integration.