@alphinex/icons
v1.2.0
Published
Icon abstraction layer decoupling components from any specific icon set.
Readme
@alphinex/icons
An icon abstraction layer that decouples every call site — @alphinex/ui components and consuming
apps alike — from any specific icon library. Icons are looked up by name from a registry rather than
imported directly, so swapping icon libraries or adding a domain-specific icon set (e.g. medical
icons for a Hospital SaaS tenant) never requires touching component code. See ADR-0001 for why this
stays a thin abstraction rather than a full design-system icon component with variants.
Icon
The one component that renders icons. Look one up by registered name, or pass a component directly
via icon as an escape hatch for a one-off icon that isn't registered. size accepts the named scale
("sm" | "md" | "lg", default "md") or a raw number/string; tone maps to a semantic color token
and is ignored if color is explicitly supplied. Icons are decorative (hidden from assistive tech) by
default — pass label to give one an accessible name instead:
import { Icon } from "@alphinex/icons";
<Icon name="check" tone="success" />
<Icon name="alert-triangle" tone="danger" size="lg" label="Warning" />
<Icon name="search" size={20} color="#6366f1" />If name doesn't resolve to a registered icon (and no icon override is given), Icon warns to the
console and renders nothing — a useful signal that registerIconSet() wasn't called, or the name is
misspelled.
Registering icons: registerIconSet, getIcon, hasIcon
The registry starts pre-loaded with defaultIconSet — the platform's built-in icons (chevrons,
check, alert/info glyphs, basic rich-text-editor icons like bold/italic/list, etc.), sourced from
lucide-react. Registration is additive: call registerIconSet with your own
Record<string, SvgIconComponent> to add icons alongside the built-in set, not replace it. By default
it warns and skips a name that's already registered — pass { overwrite: true } to replace it
intentionally:
import { registerIconSet } from "@alphinex/icons";
import { Stethoscope, Syringe } from "lucide-react";
registerIconSet({
stethoscope: Stethoscope,
syringe: Syringe,
});
// Later, anywhere in the app:
<Icon name="stethoscope" label="Consultation" />;Call registerIconSet once, early — e.g. in your app's entry point, before any <Icon> renders.
Any component matching the SvgIconComponent shape (ComponentType<SvgIconProps> — same shape as a
lucide-react icon: size, color, and standard SVG props) can be registered, not just lucide icons:
import { registerIconSet, hasIcon, getIcon } from "@alphinex/icons";
import { MyCustomLogoIcon } from "./MyCustomLogoIcon";
registerIconSet({ "brand-logo": MyCustomLogoIcon }, { overwrite: true });
hasIcon("brand-logo"); // true
getIcon("brand-logo"); // MyCustomLogoIcon — mostly useful for testing/introspectiondefaultIconSet itself is also exported, in case you need to reference or enumerate the built-in
names directly rather than going through the registry.
Tokens: ICON_SIZES, ICON_TONE_VARS
ICON_SIZES maps the named IconSize scale (sm/md/lg) to rem values — icons are sized on their
own primitive scale, independent of the type scale. ICON_TONE_VARS maps each IconTone
(neutral/muted/accent/danger/success/warning) to the matching CSS custom property set by
@alphinex/theme's ThemeProvider at runtime, so tone="danger" always tracks the current theme
without a hardcoded color:
import { ICON_SIZES, ICON_TONE_VARS } from "@alphinex/icons";
ICON_SIZES.lg; // "1.5rem"
ICON_TONE_VARS.accent; // "var(--aui-color-accent-default)"These are what Icon resolves size/tone against internally — pull them directly only if you're
sizing/coloring something that renders outside of <Icon> but needs to match it exactly.
See documentation/ARCHITECTURE.md for the full package contract, dependency rules, and roadmap placement.
