Skip to main content

Buttons & Icons

This page answers one question: How do I get an icon from the Invoice Ninja UI repo into the docs page I am editing?

At a glance​

  • Input: TSX icons from external/invoiceninja-ui/src/components/icons
  • Tool: npm run icons:sync
  • Output: SVG files in static/assets/images/icons/
  • Usage in Markdown/MDX docs: <img src="/assets/images/icons/<IconName>.svg" ... />
  • Usage in React pages (src/pages/*.tsx): import Icon from "@site/static/assets/images/icons/<IconName>.svg"

If you only need the fast path, go to: How to use it to reach a concrete result.

Which usage mode?​

  • Use <img ...> when editing docs content files in docs/ (Markdown/MDX).
  • Use SVG import as React component when editing page components in src/pages/.

Icon paths​

  • Source icons from external/invoiceninja-ui/src/components/icons.
  • Store publishable SVGs in static/assets/images/icons/.
  • Run npm run icons:sync to normalize TSX icons into SVGs.

Only keep icons that are actually used in docs to avoid asset bloat.

Icon sync workflow​

Use this flow when the icon set in the Invoice Ninja UI repository changed.

  1. Ensure the UI repo is available at external/invoiceninja-ui.
  2. Run the sync script:
npm run icons:sync
  1. Review generated changes in static/assets/images/icons/.
  2. Validate determinism in CI or before commit:
npm run icons:check

icons:check reruns extraction and fails if Git diff changes, which helps catch out-of-date icon output.

How to use it to reach a concrete result​

Goal: show a specific UI icon on a specific docs page.

  1. Identify the icon component name in the Invoice Ninja UI repo: external/invoiceninja-ui/src/components/icons
    Example: ArrowRight.tsx -> target file name will be ArrowRight.svg.
  2. Generate/update docs icons:
npm run icons:sync
  1. Confirm the expected output file exists: static/assets/images/icons/ArrowRight.svg
  2. Use it in your docs page:
<img src="/assets/images/icons/ArrowRight.svg" alt="" aria-hidden="true" />

Or, if you are inside a React page component (src/pages/*.tsx):

import ArrowRightIcon from "@site/static/assets/images/icons/ArrowRight.svg";

<span aria-hidden="true">
<ArrowRightIcon />
</span>
  1. Reference that image in your CTA/button snippet and run the site locally (npm start) to verify it renders.

Expected result:

  • The icon is available under /assets/images/icons/<Name>.svg.
  • The icon renders either via <img ...> (docs content) or via SVG component import (React page).

Quick command map by goal​

  • Update generated icon set from default Invoice Ninja source: npm run icons:sync
  • Verify generated icon output is up to date (CI/pre-commit): npm run icons:check
  • Use a different icon source directory: node scripts/extract-icons.js --src /absolute/path/to/icons

Custom source directory​

If your icons are not under the default Invoice Ninja checkout path, use one of these overrides:

node scripts/extract-icons.js --src /absolute/path/to/icons
ICON_SRC=/absolute/path/to/icons node scripts/extract-icons.js

What the script does​

  • Reads TSX icon components.
  • Strips JSX-only syntax and normalizes SVG attributes.
  • Forces a deterministic root SVG shape (width/height, viewBox, colors).
  • Writes output to static/assets/images/icons/.
  • Removes stale generated SVGs that no longer exist in source.

Troubleshooting​

  • ICON_SRC not found ... The configured source path does not exist. Ensure external/invoiceninja-ui is present or pass --src.
  • Expected icon SVG not generated Check script output for skipping ... notices (for example styled wrappers or unsupported JSX patterns).
  • Icon file exists but does not render Verify exact filename/case in the image path and restart local dev server.
  • I need brand logos (Discord/YouTube/Slack) from UI stack The Invoice Ninja UI icon set contains generic product icons, not full brand-logo packs. Use the closest UI icon (for example Users, MediaPlay, Message) for visual consistency.

Minimal CTA buttons​

<a href="/docs/self-host/self-host-installation" class="card-btn card-btn-primary">
Primary CTA
</a>

<a href="/docs/user-guide" class="card-btn card-btn-outline">
Secondary CTA
</a>

Buttons with icon​

<a class="card-btn card-btn-outline" href="https://www.youtube.com/watch?v=xo6a3KtLC2g" target="_blank" rel="noopener noreferrer">
<img src="/assets/images/icons/MediaPlay.svg" alt="" aria-hidden="true" />
Watch demo
</a>

Primary buttons invert icon color automatically.

Card with CTA stack​

<div class="card-panel">
<p><strong>Secure & fast maintenance</strong></p>
<h3>INmanage CLI installer</h3>
<p>Provisioning, upgrades, backups, and alerts in one flow.</p>
<div class="card-cta">
<a class="card-btn card-btn-primary" href="https://github.com/DrDBanner/inmanage" target="_blank" rel="noopener noreferrer">
Open CLI
<img src="/assets/images/icons/ArrowRight.svg" alt="" aria-hidden="true" />
</a>
</div>
</div>

Best practices​

  • Use card-btn for consistency.
  • For off-site links always include target="_blank" rel="noopener noreferrer".
  • Keep CTA labels action-oriented and short.