Usage

Basic usage

TSX
import { IconShoppingCart } from '@devigner-ui/icons';

function Example() {
  return (
    <div>
      {/* Defaults: outline, sized by CSS */}
      <IconShoppingCart className="size-6" />

      {/* The four styles */}
      <IconShoppingCart className="size-6" />                         {/* outline */}
      <IconShoppingCart variant="TwoTone" className="size-6" />       {/* twotone */}
      <IconShoppingCart variant="Bold" className="size-6" />          {/* bold */}
      <IconShoppingCart variant="Bulk" className="size-6" />          {/* bulk */}

      {/* Size and colour come from the class */}
      <IconShoppingCart className="size-8" />
      <IconShoppingCart className="size-6 text-indigo-500" />

      {/* Stroke width, in the 24px drawing's own units */}
      <IconShoppingCart strokeWidth={1} className="size-6" />
      <IconShoppingCart strokeWidth={3} className="size-6" />
    </div>
  );
}

There are three props of its own (className, variant, strokeWidth) on top of everything an <svg> takes. There is no size and no color: size and colour are CSS, and strokes are currentColor, so text-* colours them.

The styles

A style is one variant string:

Style variant Fill Stroke
outline (the default) ✅ Full linework
twotone "TwoTone" ✅ Secondary at half tone
bold "Bold" ❌ One filled form
bulk "Bulk" ❌ Secondary mass at half tone

Defaults are variant = "Outline" and strokeWidth = "1.5", so a bare <IconShoppingCart /> is outline at 1.5. strokeWidth only reaches linework, which Bold and Bulk do not have.

All 8,584 icons are free and MIT. See the licensing guide.

To have the CLI write the right prop for you:

Terminal
npx @devigner-ui/icons copy ShoppingCart --style=bold

Accessibility

An icon renders aria-hidden="true" and focusable="false" by default, so an icon beside its own text label is not announced twice. Label it when it carries meaning and the icon becomes role="img" instead:

TSX
<IconShoppingCart className="size-6" />                                  {/* decorative */}
<IconShoppingCart aria-label="Shopping cart" className="size-6" />       {/* role="img" */}

Everything an <svg> accepts reaches the element, aria-* included, so there is nothing to wrap. Inside a button that already has a label, leave the icon decorative.

Per-icon style metadata

TSX
import metadata from '@devigner-ui/icons/metadata.json';

const cart = metadata.icons.find(i => i.name === 'ShoppingCart');
cart.freeStyles;  // ['outline', 'twotone', 'bold', 'bulk']
cart.proStyles;   // []

metadata.json is JSON, so it is a default import; there is no named metadata export.

proStyles is empty for every icon. There is nothing to unlock.

With Next.js App Router

TSX
// app/layout.tsx
import { IconShoppingCart } from '@devigner-ui/icons';

export default function Layout({ children }) {
  return (
    <header>
      <IconShoppingCart className="size-7" />
    </header>
  );
}

The bundle carries a "use client" banner, so the icons are client components and can be rendered from a server component without marking your own file.

With Vite

TSX
import { IconShoppingCart } from '@devigner-ui/icons';

Works as-is.

Rendering by name

There is no IconMap export: one of the icons is called Map, so IconMap is that component. For a small, known set, write the map out; it is the version that tree shakes:

TSX
import { IconShoppingCart, IconArrowRight, IconUser } from '@devigner-ui/icons';
import type { IconComponentType } from '@devigner-ui/icons';

const ICONS = {
  ShoppingCart: IconShoppingCart,
  ArrowRight: IconArrowRight,
  User: IconUser,
} satisfies Record<string, IconComponentType>;

function DynamicIcon({ name }: { name: keyof typeof ICONS }) {
  const Component = ICONS[name];
  return <Component variant="TwoTone" className="size-6" />;
}

If you genuinely need all 8,584 icons reachable by string, use the namespace and accept that nothing tree shakes:

TSX
import * as Icons from '@devigner-ui/icons';
import type { IconComponentType } from '@devigner-ui/icons';

const Component = Icons[`Icon${name}`] as IconComponentType;

Props type

TSX
import type { IconProps } from '@devigner-ui/icons';

interface IconProps extends SVGProps<SVGSVGElement> {
  className?: string;
  variant?: 'Outline' | 'TwoTone' | 'Bold' | 'Bulk';
  strokeWidth?: string | number;
}

IconName, IconStyle, IconVariant and IconComponentType are exported too; see the TypeScript API.

Documentation

Browse all 8,584 icons