Icons are the one dependency a project takes for granted and then ships whole. In @enigmax/icons every glyph is its own module, so the bundler keeps the handful you import and drops the rest.
Every icon is a 24x24 viewBox painted with currentColor, so it inherits the surrounding text colour and needs no theming of its own.
An icon is always asked for by the weight it is drawn in. Bold duotone is what ships today; Weights is why there is no default one.
Browse
Type to search, or narrow by category. Click any icon to copy its component name.
Installation
A plain package, so it installs like one. There is no enigma add item and no scaffolding step: the icons carry no styles and no recipe, so there is nothing to write into your project.
One package holds every weight, so there is nothing to choose at install time. React 18 or newer is the only requirement; @tabler/icons-react is an optional peer, needed only if you import one of the brand marks below.
Weights
There is no default weight. Every weight is its own subpath and an icon comes from the one it is drawn in:
import { IconMapPin } from "@enigmax/icons/bold-duotone";
A default would make one weight the one you get by not choosing, and with many weights that winner is arbitrary - every other weight then has to argue with it, and the first one to ship keeps an advantage it never earned. The root carries only what the weights share: the Icon and IconProps types, and the brand marks, which are real logos and have no weight to pick.
A weight is a build dimension, not a prop. <IconMapPin weight="outline" /> reads friendlier and is the one design this package cannot have: the component would need every body reachable at runtime, so importing one icon would pull all of its weights into your bundle and the rest of this page would stop being true. Each weight is generated into its own directory instead, so two weights of one icon are two imports and a project that uses one never downloads the other.
That makes a new weight an addition and never a rename: @enigmax/icons/<weight> is where it appears, with the same names and the same categories under it, and nothing you have already written changes. A weight that is declared but incomplete fails the package’s own suite rather than shipping - half a weight renders some icons and vanishes the rest, which reads as a broken page rather than a missing line in a JSON file.
Usage
Import by name from a weight. The name is the one shown under each icon in the browser above, prefixed with Icon:
import { IconSearch, IconSun } from "@enigmax/icons/bold-duotone";
<IconSearch />
<IconSun size={18} className="text-muted" />
size sets both width and height and defaults to 24. Everything else is forwarded to the <svg>, so className, style, onClick and the ARIA attributes behave as they would on any element. A ref reaches the SVG itself.
stroke is accepted and ignored. These icons are filled rather than stroked, so there is no line to widen - and forwarding a number into the SVG stroke attribute, which takes a colour, paints the icon with an invalid value until it disappears. Keeping it in the signature means a stroked weight can be imported in place of a filled one without touching the call sites that pass it.
Only what you render
The package declares no side effects and ships one module per icon, so an icon you never import is unreachable code that never reaches your output. Nothing is resolved at runtime and nothing is fetched at install time - the drawings are plain strings written into the modules at build.
The weight’s barrel is enough to get that. The deeper subpaths exist for when you want to be explicit, or want a whole group at once:
import { IconSun } from "@enigmax/icons/bold-duotone"; // one icon
import { IconSun } from "@enigmax/icons/bold-duotone/icons/IconSun"; // the same icon, named directly
import * as weather from "@enigmax/icons/bold-duotone/categories/weather"; // a category
Categories are the same in every weight, because a category is what an icon IS rather than how it is drawn.
Brand marks
A logo is a trademark, not a glyph to redraw: this set has none, and hand-drawing one produces something that is recognisably wrong and legally someone else’s. The brand names are re-exported from @tabler/icons-react instead, and they come from the root rather than from a weight - a logo has only one form:
import { IconBrandGithub } from "@enigmax/icons";
That is the only reason the package has an optional peer dependency. Import no brand and it is never needed.
The external link arrow
Use the diagonal arrow pointing up and to the right for an external link, not the box with an arrow leaving it. The box reads as clutter at the size a link marker is actually drawn, and beside a filled glyph it looks like a different icon family:
import { IconExternalLink } from "@enigmax/icons/bold-duotone";
IconExternalLink is already mapped to the diagonal arrow in every weight, so importing it by that name gives the right glyph. The package’s own test suite asserts it, so the convention cannot drift back.