> For the complete documentation index, see [llms.txt](https://docs.trydrupal.com/radix/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trydrupal.com/radix/understanding-radix/icons.md).

# Icons (Icon API)

### Drupal Icon API

Radix subthemes ship a [Bootstrap Icons](https://icons.getbootstrap.com) pack integrated with Drupal core's [Icon API](https://www.drupal.org/docs/develop/drupal-apis/icon-api) (stable in Drupal 11, available via the [UI Icons](https://www.drupal.org/project/ui_icons) backport on Drupal 10). This enables you to add SVG icons to templates and render arrays without requiring additional modules.

When you generate a subtheme from the Radix starterkit, the following are included automatically:

* `<subtheme>.icons.yml` : declares the `bootstrap_icons` icon pack.
* A `bootstrap-icons` : dependency in `package.json`.
* A build step that copies the SVGs into `assets/icons/bootstrap-icons`. (feel free to disable that line if you don't need icons).

#### Setup

The icon SVGs are **not committed** to the subtheme. They are pulled from the `bootstrap-icons` npm package and copied into place by the build. After generating your subtheme, run an install and a build once:

```bash
npm install && npm run watch
# or: yarn && yarn dev / pnpm
```

This populates `assets/icons/bootstrap-icons/` with the icon SVGs.

> **First-run note:** the Icon API caches the list of discovered SVG files. If you enable your subtheme *before* the SVGs have been built, icons render blank. Run a cache rebuild once after the first build:
>
> ```bash
> drush cr
> ```

#### Usage

**In a Twig template**

```twig
{{ icon('bootstrap_icons', 'house-fill', { size: 48 }) }}
{{ icon('bootstrap_icons', 'heart-fill', { size: 64, color: '#dc3545', alt: 'Favourite' }) }}
```

**In a render array**

```php
$build['icon'] = [
  '#type' => 'icon',
  '#pack_id' => 'bootstrap_icons',
  '#icon_id' => 'house-fill',
  '#settings' => [
    'size' => 48,
  ],
];
```

Browse the available icon IDs at [https://icons.getbootstrap.com](https://icons.getbootstrap.com/).

#### Settings

The `bootstrap_icons` pack exposes three settings:

| Setting | Type    | Default | Description                                                                     |
| ------- | ------- | ------- | ------------------------------------------------------------------------------- |
| `size`  | integer | `32`    | Width and height in pixels (8–256).                                             |
| `color` | string  | -       | Any CSS color. Defaults to `currentColor` (inherits text color).                |
| `alt`   | string  | -       | Accessibility label. Leave empty for a decorative icon (renders `aria-hidden`). |

#### The icon pack definition

The pack lives in `<subtheme>.icons.yml`:

```yaml
bootstrap_icons:
  enabled: true
  label: Bootstrap Icons
  description: "Official open source SVG icon library for Bootstrap."
  links:
    - https://icons.getbootstrap.com
  license:
    name: MIT
    url: https://github.com/twbs/icons/blob/main/LICENSE
    gpl-compatible: true
  extractor: svg
  config:
    sources:
      - assets/icons/bootstrap-icons/{icon_id}.svg
  settings:
    size:
      title: "Size"
      description: "Icon size in pixels."
      type: "integer"
      default: 32
      minimum: 8
      maximum: 256
    color:
      title: "Color"
      type: "string"
      format: "color"
    alt:
      title: "Alt text"
      description: "Accessibility alternative text. Leave empty for a decorative icon."
      type: "string"
  template: >-
    <svg
      xmlns="http://www.w3.org/2000/svg"
      class="bi bi-{{ icon_id }}"
      width="{{ size|default(32) }}"
      height="{{ size|default(32) }}"
      fill="{{ color|default('currentColor') }}"
      viewBox="0 0 16 16"
      {% if alt is empty %}
        aria-hidden="true"
      {% else %}
        role="img" aria-label="{{ alt }}"
      {% endif %}
    >
      {{ content }}
    </svg>
```

#### Using a different icon set

To use another SVG icon library instead of (or alongside) Bootstrap Icons:

1. Install it: `npm install <icon-package>`.
2. Add a copy step to the build. The Bootstrap Icons sync lives in `plugins.mjs` as the `bootstrapIconsPlugin`; copy that pattern for your own package, for example:

   ```javascript
   import { cpSync, existsSync } from 'node:fs';

   export const myIconsPlugin = {
     name: 'my-icons',
     setup(build) {
       build.onEnd(() => {
         const from = 'node_modules/<icon-package>/icons';
         const to = 'assets/icons/<icon-package>';
         if (existsSync(from)) {
           cpSync(from, to, { recursive: true });
         }
       });
     },
   };
   ```

   Then add `myIconsPlugin` to the `plugins` array in `build.mjs`, `build-dev.mjs` and `watch.mjs` (alongside `bootstrapIconsPlugin`).
3. Add a new pack to `<subtheme>.icons.yml` with its own `sources` glob and `template` (match the icon set's `viewBox` and class conventions).
4. Run `npm run dev` and then `drush cr`.
