Skip to main content
BEEQ ships an <bq-icon> web component that loads SVG files on demand. By default, icons are sourced from Phosphor Icons, but you can point the component at any CDN or local folder containing SVG files.

How the icon system works

The bq-icon component:
  1. Reads the name prop and appends .svg to construct a filename (e.g. bell-ringing.svg).
  2. Resolves the full URL by prepending the base path set via setBasePath.
  3. Fetches the SVG over HTTP and inlines it into the component’s Shadow DOM.
Because icons are fetched at runtime, the SVG assets must be accessible from the browser — either hosted on a CDN or copied into your project’s output directory.

Setting the base path

Call setBasePath once at application startup, before any bq-icon components render:
import { setBasePath } from '@beeq/core';

// Local icons copied to your output directory
setBasePath('/assets/svg/');

Copying icons from node_modules

The SVG assets live in node_modules/@beeq/core/dist/beeq/svg. Copy them to your output directory using your bundler:
vite.config.ts
import { defineConfig } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';

export default defineConfig({
  plugins: [
    viteStaticCopy({
      targets: [
        {
          src: './node_modules/@beeq/core/dist/beeq/svg/*',
          dest: 'assets/svg',
        },
      ],
    }),
  ],
});
Then set the path:
main.ts
import { setBasePath } from '@beeq/core';

setBasePath('assets/svg');

Using bq-icon

Once the base path is set, use <bq-icon> anywhere in your templates:
<!-- Basic usage -->
<bq-icon name="bell-ringing"></bq-icon>

<!-- Custom size (in pixels) -->
<bq-icon name="bell-ringing" size="32"></bq-icon>

<!-- Custom color using a palette token -->
<bq-icon name="bell-ringing" color="text--brand" size="24"></bq-icon>

<!-- Accessible label -->
<bq-icon name="warning" label="Warning" size="24"></bq-icon>

<!-- Custom source (bypasses name + base path) -->
<bq-icon src="/my-icons/custom-icon.svg" size="24"></bq-icon>

Props reference

PropTypeDefaultDescription
namestringIcon filename (without .svg) to load from the base path
sizestring | number24Width and height of the SVG in pixels
colorstringStroke color; accepts palette token values (e.g. text--brand)
labelstring"{name} icon"Accessible label for screen readers
srcstringDirect URL to an SVG file; overrides name

CSS custom properties

PropertyDefaultDescription
--bq-icon--colorcurrentColorSVG stroke color
--bq-icon--size24pxSVG width and height

Using external icon libraries

You can use any SVG icon library by pointing setBasePath at its CDN endpoint. The name prop must match the filenames provided by that library.

Heroicons example

import { setBasePath } from '@beeq/core';

// Heroicons 2.x — 24px outline style
setBasePath('https://cdn.jsdelivr.net/npm/[email protected]/24/outline');
<!-- Loads https://cdn.jsdelivr.net/npm/[email protected]/24/outline/bell.svg -->
<bq-icon name="bell" size="24"></bq-icon>

<!-- Loads https://cdn.jsdelivr.net/npm/[email protected]/24/outline/academic-cap.svg -->
<bq-icon name="academic-cap" size="24"></bq-icon>
When using an external library, icon names must exactly match the SVG filenames provided by that library. Phosphor Icons names (the BEEQ default) will not work with Heroicons, and vice versa.

RTL support

The icon component respects the --bq-icon--direction CSS custom property, which is automatically flipped when dir="rtl" is set on a parent element:
/* Set automatically by BEEQ's global styles */
:root              { --bq-icon--direction: 1;  }  /* LTR */
[dir='rtl']        { --bq-icon--direction: -1; }  /* RTL — icons are mirrored */

Events

The bq-icon component emits a single event:
EventDescription
svgLoadedEmitted after the SVG content has been successfully fetched and rendered
const icon = document.querySelector('bq-icon');
icon.addEventListener('svgLoaded', (event) => {
  console.log('SVG content loaded:', event.detail);
});

Build docs developers (and LLMs) love