@impactsmartsuite/impact-icons
v0.1.8-beta.10
Published
Inline SVG React icon components for Impact Smart Suite
Keywords
Readme
@impactsmartsuite/impact-icons
Inline SVG React icon components for Impact Smart Suite. Each icon is a forwardRef component that accepts standard SVG props. Generated monochrome icons use currentColor for fill/stroke so colors are controlled via CSS color.
Accessibility
Icons render with aria-hidden="true" by default, making them invisible to screen readers. This is correct for decorative icons (next to visible text labels, inside buttons with text, etc.).
For meaningful icons that convey information without accompanying text, override the defaults:
// Decorative (default) — hidden from screen readers
<Close />
// equivalent to: <Close aria-hidden="true" />
// Meaningful — visible to screen readers
<Close role="img" aria-label="Close dialog" aria-hidden={undefined} />Quick start
import { Icon, DeleteBlack, Close } from '@impactsmartsuite/impact-icons';
// Once per app (SCSS):
import '@impactsmartsuite/impact-icons/styles/icon.scss';
<Icon icon={Close} variant="dark" size={20} />
<Icon icon={DeleteBlack} variant="light" disabled size={24} />
<Icon icon={Close} size={{ width: 24, height: 16 }} />
// Or set color directly on the SVG component
<DeleteBlack style={{ color: 'red', width: 20, height: 20 }} />Icon wrapper
The Icon component sets an explicit color via SCSS (variant="light" | "dark") so currentColor paths do not inherit from arbitrary parents. Override tokens in your theme:
:root {
--impact-icon-light: #1f2b4d;
--impact-icon-dark: #f4f4f5;
}Multi-color icons (NotificationRead, NotificationBookmark, BookMarkedFill) keep hardcoded fills and are not fully themeable via Icon.
Run npm run audit:icons to verify generated icons remain currentColor-compatible.
How icons get here
1. Copy SVGs from the impact-ui repo (primary, recommended)
Ensure you have the correct branch checked out:
git -C ../impact-ui switch develop/impact-v3/testThen copy SVGs:
node scripts/fetch-svgs.mjs --local-dir ../impact-ui/frontend/src/assetsThis copies .svg files into svgs/, skipping:
- Subdirectories like
clientLogos/ - Raster-in-SVG files (embedded
data:image/pngordata:image/jpeg)
2. CDN mode (optional, requires auth)
The DAM listing API requires authentication. Pass the token via environment variable (not CLI arguments, to avoid leaking secrets in shell history):
IMPACT_KIT_AUTH_TOKEN=<token> npm run fetch:svgs -- --cdnCDN base URL defaults to https://impact-kit.devs.iaproducts.ai. Override with --base-url.
Icon file URLs follow this pattern:
https://impact-kit.devs.iaproducts.ai/api/v1/files/uploads/impact-ui/prod/icons/<name>.svgFor most workflows, use --local-dir instead.
Building
npm install
# Generate React components from svgs/ (Phase-1 allowlist — recommended)
npm run generate
# Or generate ALL icons (skip allowlist)
# WARNING: --all may incorrectly convert intentional multi-color SVGs.
# Those icons will have arbitrary fill/stroke values rewritten to currentColor,
# losing their intended colors. Use the Phase-1 allowlist for production.
node scripts/build-icons.mjs --all
# Preview what would be generated
node scripts/build-icons.mjs --dry-run
# Build distributable (ESM + CJS + TypeScript declarations)
npm run build
# Full pipeline: generate + build
npm run build:iconsOutput
Generated components live in src/ (git-tracked). The dist/ folder (gitignored) is produced by tsup:
| File | Format |
|------|--------|
| dist/index.mjs | ESM |
| dist/index.js | CJS |
| dist/index.d.mts | ESM type declarations |
| dist/index.d.ts | CJS type declarations |
currentColor behavior
The SVGR pipeline rewrites a known set of monochrome fill/stroke hex values to currentColor:
#000, #000000, #333, #333333, black, #60697D, #60697d, #758490, #798293, #7a8294, #4259ee
This means CSS color controls the icon color for generated Phase-1 monochrome icons. Arbitrary SVGs supplied via --all may contain fill/stroke values outside this set, which will not be rewritten — those icons will retain their original hardcoded colors.
What stays on CDN
Not all assets in the DAM are converted to React components. These stay as <img> or background-image references:
- Client logos (
clientLogos/subfolder) - Landing page illustrations and empty-state graphics
- Multi-color brand marks
- Raster-in-SVG files (SVGs containing embedded PNG/JPEG data)
- All
.png/.webpassets
// Client logos use the clientLogos/ path, not icons/
<img src="https://impact-kit.devs.iaproducts.ai/api/v1/files/uploads/impact-ui/prod/clientLogos/Starboard.svg" />Adding new icons
- Place the
.svgfile insvgs/ - If using Phase-1 mode (recommended), add the filename stem to
PHASE1_ALLOWLISTinscripts/build-icons.mjs - Run
npm run build:icons - Commit the new
src/<ComponentName>.tsxand updatedsrc/index.ts
Component API
Every icon component is typed as:
React.ForwardRefExoticComponent<
Omit<React.SVGProps<SVGSVGElement>, 'ref'> &
React.RefAttributes<SVGSVGElement>
>Supported props include className, style, width, height, aria-label, aria-hidden, role, onClick, and all standard SVG attributes.
Filename to component name
Filenames are converted to PascalCase: delete-black.svg becomes DeleteBlack. Known typos are corrected via the NAME_OVERRIDES map in scripts/build-icons.mjs (e.g. keyboardShortuctIcon.svg becomes KeyboardShortcutIcon).
Publishing
This package is scoped to @impactsmartsuite and published as public on npm:
# Authenticate with the npm registry (if not already)
npm login --registry=https://registry.npmjs.org --scope=@impactsmartsuite
# Build and publish
npm run build:icons
npm publish --access publicEnsure your .npmrc is configured for the @impactsmartsuite scope if using a private registry:
@impactsmartsuite:registry=https://your-private-registry.example.com/
//your-private-registry.example.com/:_authToken=${NPM_TOKEN}Testing expectations
When adding tests (e.g. via Vitest + React Testing Library), verify:
- Generated component renders without errors
viewBoxattribute is retained on the root<svg>- Hardcoded
width/heightattributes are removed (sizing via CSS/props) - Expected fill/stroke values (
#60697D,#758490,#4259ee, etc.) becomecurrentColor aria-hidden="true"is present by default- Raster-in-SVG files are skipped during generation
- Barrel
index.tsexports match the generated component files - Consumer can override
aria-hidden, addrole="img"andaria-label
