@cemresearchproject/icons
v0.11.2
Published
CEM Research Project icon set — 134 single-color SVG icons with React + Blade components, accessibility, and CSS state hooks.
Readme
@cemresearchproject/icons
CEM Research Project icon set — 134 single-color SVG icons with React + Blade components, accessibility built in, and CSS state hooks.
Install
npm install @cemresearchproject/iconsreact >= 17 is a peer dependency (React layer only — raw SVG and
sprite are framework-agnostic).
Use — React
Named import. Tree-shakes with any modern bundler:
import { Foundation, DriftTax, Pentagon } from '@cemresearchproject/icons';
<Foundation /> // 56×56, decorative (aria-hidden)
<DriftTax size={24} aria-label="Drift tax indicator" /> // semantic
<Pentagon title="CEM scoring" /> // semantic + tooltipDirect import — bypasses the barrel, best build performance:
import Foundation from '@cemresearchproject/icons/Foundation';Never import * as Icons — it pulls all 73 into the bundle.
Accessibility
Icons are decorative by default — they emit aria-hidden="true" and
no role. To make an icon semantic, pass either aria-label or title:
| Pattern | Behavior |
|---|---|
| <Icon /> | aria-hidden="true", focusable="false" |
| <Icon aria-label="..." /> | role="img" + aria-label, no aria-hidden |
| <Icon title="..." /> | role="img" + inline <title> element |
Color
Color is not a prop — icons use currentColor, so they inherit CSS
color:
.light-register { color: #6051F0; } /* iris-500 */
.dark-register { color: #8478FF; } /* iris-400 */Use — Laravel / Blade
The React components do not run in Blade. Register the packaged Blade component once per app:
use Illuminate\Support\Facades\Blade;
public function boot(): void
{
Blade::anonymousComponentPath(
base_path('node_modules/@cemresearchproject/icons/blade'), 'cem'
);
}<x-cem::cem-icon name="foundation" />
<x-cem::cem-icon name="drift-tax" :size="24" aria-label="Drift tax indicator" />
<x-cem::cem-icon name="pentagon" title="CEM scoring" />Same accessibility contract as React. Full guide: BLADE.md.
Use — runtime / dynamic names
import { iconRegistry } from '@cemresearchproject/icons';
const { default: Icon } = await iconRegistry['drift-tax']();Use — no React, no Blade
import sprite from '@cemresearchproject/icons/sprite.svg';
// <svg><use href={`${sprite}#cem-foundation`} /></svg>
import foundationUrl from '@cemresearchproject/icons/svg/foundation.svg';CSS state hooks (optional)
import '@cemresearchproject/icons/css/cem-icons.css';<Foundation className="cem-icon cem-icon--updating" />
<Foundation data-state="stale" />States: --stale (faded), --muted (heavier dim), --flagged
(out-of-range warm color), --updating (subtle pulse, respects
prefers-reduced-motion).
Adding icons
See CONTRIBUTING.md. The short version: drop an SVG in svg/, run
npm run audit, run npm run generate, add a changeset. The audit
script (scripts/audit.mjs) enforces every rule in ICONS-SPEC.md and
fails the build on any violation.
Documentation
ICONS-SPEC.md— the spec. Locked invariants for every icon.CONTRIBUTING.md— contributor workflow.BLADE.md— Laravel consumption guide.ONTOLOGY-ALIASES.md— formula codes → icon aliases (F-BCR, F-KYR, F-DEI).CHANGELOG.md— release history.
Component name reference
PascalCase, derived from the kebab-case filename. Numeric-leading names
move the digit to the end (80-premise → Premise80, n-1 → N1,
s-01-commit-velocity → S01CommitVelocity). Sprite ids and registry
keys stay kebab-case (cem-foundation, drift-tax).
License
MIT.
