Getting started

Praticon icons are drawn on a 24 × 24 grid with a 2 px round stroke and inherit your text colour. Use them as typed React, Vue or Svelte components, as Web Components, or as plain SVG, a sprite or an icon font anywhere else.

Install

Install the package for your framework:

npm i @praticon-glyphs/react
npm i @praticon-glyphs/vue
npm i @praticon-glyphs/svelte

For any other framework, or plain HTML, the Web Components package works everywhere:

npm i @praticon-glyphs/elements

For server templates and static sites, the core package ships the SVG files, an SVG sprite, an icon font, the icon data and a toSvg() helper:

npm i @praticon-glyphs/core

They all work with pnpm and Yarn too. The framework packages need React 18, Vue 3.3 or Svelte 5 or later.

Use in React

Import icons by name. Each one renders an inline SVG that is 24 px, uses the current text colour and has a 2 px stroke.

import { ArrowLeft, Terminal } from "@praticon-glyphs/react";

export function Toolbar() {
  return (
    <>
      <button aria-label="Back">
        <ArrowLeft />
      </button>
      <Terminal size={32} strokeWidth={1.5} color="#5b21b6" />
    </>
  );
}

Use in Vue

The Vue package has the same icons and props. Bind numbers with :, and write strokeWidth as stroke-width in templates if you prefer:

<script setup>
import { ArrowLeft, Terminal } from "@praticon-glyphs/vue";
</script>

<template>
  <button aria-label="Back">
    <ArrowLeft />
  </button>
  <Terminal :size="32" :stroke-width="1.5" color="#5b21b6" />
</template>

Other attributes and the default slot pass through to the <svg>. Wrap your own icons with createIcon(), exactly as in React.

Use in Svelte

The Svelte package needs Svelte 5. Each icon is its own component file, so only the icons you import are bundled:

<script>
  import { ArrowLeft, Terminal } from "@praticon-glyphs/svelte";
</script>

<button aria-label="Back">
  <ArrowLeft />
</button>
<Terminal size={32} strokeWidth={1.5} color="#5b21b6" />

Children such as a <title> render inside the <svg>. To draw your own icons with the same props, use the Icon component:

<script>
  import { Icon } from "@praticon-glyphs/svelte";
</script>

<Icon name="rocket" node={[["path", { d: "M12 15l-3-3a12 12 0 0 1 9-9" }]]} />

Web Components

Every icon is also a custom element named praticon-<name>, which works in Angular, Solid, Lit, server-rendered pages or plain HTML. Importing the package registers all of them:

<script type="module">
  import "@praticon-glyphs/elements";
</script>

<button aria-label="Back">
  <praticon-arrow-left></praticon-arrow-left>
</button>
<praticon-terminal size="32" stroke-width="1.5" color="#5b21b6"></praticon-terminal>

Without a build step, load it from a CDN:

<script type="module" src="https://cdn.jsdelivr.net/npm/@praticon-glyphs/elements/+esm"></script>

To bundle only the icons you use, import each one from its own module instead. Importing it registers its tag:

import "@praticon-glyphs/elements/icons/arrow-left";

The attributes are size, color and stroke-width, with the same defaults as the props below, and the elements have matching size, color and strokeWidth properties. The SVG is drawn in a shadow root; style it from outside with ::part(svg). Wrap your own icons with defineIcon(name, node).

Props

PropTypeDefaultDescription
sizenumber | string24Width and height, in px or any CSS length.
colorstring"currentColor"Stroke colour.
strokeWidthnumber | string2Stroke width in grid units, so it scales with the icon.
any SVG propPassed to the <svg>, including className (class in Vue and Svelte), style, event handlers and, in React, ref.

Importing

Named imports are tree-shaken, so your bundle only contains the icons you use. Every icon also has an …Icon alias for when a name clashes with one of your own components:

import { Copy, CopyIcon } from "@praticon-glyphs/react"; // the same component

Each icon can also be imported from its own module:

import ArrowLeft from "@praticon-glyphs/react/icons/arrow-left";

Accessibility

Icons are decorative by default and get aria-hidden="true", which is right when they sit next to text that already says what they mean. When an icon stands alone, give it a label and it becomes role="img" with that accessible name:

<Terminal aria-label="Open terminal" />

// or with a visible-to-assistive-tech title
<Terminal aria-labelledby="terminal-title">
  <title id="terminal-title">Open terminal</title>
</Terminal>

Styling

Icons use currentColor, so they follow the colour of the text around them. Every icon has the classes praticon and praticon-<name>, and your own className is added after them:

.praticon {
  vertical-align: -0.125em;
}

.nav-link:hover .praticon {
  color: #5b21b6;
}

Without a framework

toSvg() returns SVG markup as a string, for plain HTML, server templates or any framework. It takes the same options as the component props, plus extra attributes:

import { toSvg } from "@praticon-glyphs/core";

document.querySelector("#back").innerHTML = toSvg("arrow-left", {
  size: 20,
  strokeWidth: 1.5,
  attrs: { class: "icon", "aria-label": "Back" },
});

Like the components, the output is decorative unless you pass an aria-label or aria-labelledby. Unknown icon names and invalid attribute names throw an error.

The optimised SVG files are in the package at @praticon-glyphs/core/svg/<name>.svg, and any npm CDN can serve them. Note that an SVG loaded with <img> cannot inherit your text colour:

<img src="https://cdn.jsdelivr.net/npm/@praticon-glyphs/core/svg/arrow-left.svg" alt="Back" width="24" height="24" />

The package also exports icons (the shapes of every icon), metadata (names, tags, aliases and categories) and categories.

SVG sprite

@praticon-glyphs/core/sprite.svg holds every icon as a <symbol> named after the icon. Serve the file from your own site, then point a <use> at an icon. The browser downloads the sprite once and caches it:

<svg width="24" height="24" stroke-width="2" aria-hidden="true">
  <use href="/sprite.svg#arrow-left" />
</svg>

Set the size and stroke width on the outer <svg>; the icon follows the text colour. Browsers only load sprites from the same origin as the page, so copy the file into your public folder rather than linking to a CDN.

Icon font

For places that only take text or CSS, such as CMS templates or older stacks, the icon font draws every icon as a character. Load its stylesheet, then use the praticon class with the icon's class:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@praticon-glyphs/core/font/praticon.css" />

<i class="praticon praticon-arrow-left" aria-hidden="true"></i>

Icons are sized with font-size and coloured with color, and sit on the text baseline. A font cannot change its stroke width, so it is always the standard one: 2 px at 24 px, scaling with the size. Each icon keeps its character between releases; font/codepoints.json lists them.

TypeScript

Every package ships its own types. IconName is a union of every icon name, so typos are caught at compile time:

import { toSvg, type IconName } from "@praticon-glyphs/core";
import type { IconProps } from "@praticon-glyphs/react";

const name: IconName = "file-code";
toSvg("file-cdoe"); // Type error: not an icon name

Your own icons

createIcon() wraps your own 24 × 24 stroke icons in the same API, with the same props, accessibility defaults and classes:

import { createIcon } from "@praticon-glyphs/react";

export const Rocket = createIcon("rocket", [
  ["path", { d: "M12 15l-3-3a12 12 0 0 1 9-9 12 12 0 0 1-9 9" }],
  ["path", { d: "M9 12H4l3-5h5" }],
]);