Denji

Usage

Usage examples and patterns for React

Learn how to use Denji icons in your React components.

Basic Usage

Import and use icons as React components:

import { Icons } from "./icons";

function App() {
  return (
    <div>
      <Icons.Check className="size-4" />
    </div>
  );
}

Styling

With Tailwind

<Icons.Check className="size-6 text-green-500" />
<Icons.X className="size-4 text-red-500" />

With CSS

<Icons.Check className="icon" />
.icon {
  width: 1rem;
  height: 1rem;
  color: currentColor;
}

Inline Styles

<Icons.Check 
  style={{ 
    width: 24, 
    height: 24, 
    color: "green" 
  }} 
/>

Accessibility

Icons inherit a11y strategy from config, but can be customized per use:

Decorative Icons

For icons that are purely decorative:

<button>
  <Icons.Check aria-hidden="true" />
  Save Changes
</button>

Semantic Icons

For icons with meaning:

<Icons.Check 
  role="img" 
  aria-label="Success" 
/>

With Text Alternative

<button aria-label="Close dialog">
  <Icons.X aria-hidden="true" />
</button>

Configure default a11y in denji.json or per icon with --a11y flag.

Common Patterns

Button Icons

function SaveButton() {
  return (
    <button className="flex items-center gap-2">
      <Icons.Check className="size-4" />
      <span>Save</span>
    </button>
  );
}

Icon-Only Button

function CloseButton() {
  return (
    <button 
      aria-label="Close"
      className="p-2 rounded hover:bg-gray-100"
    >
      <Icons.X className="size-5" aria-hidden="true" />
    </button>
  );
}

Status Icons

const status = {
  success: { icon: Icons.Check, color: "text-green-500" },
  error: { icon: Icons.X, color: "text-red-500" },
  warning: { icon: Icons.AlertTriangle, color: "text-yellow-500" },
};

export interface StatusIconProps extends IconProps {
  type: keyof typeof status;
}

export function StatusIcon({ type, className, ...props }: StatusIconProps) {
  const statusConfig = status[type];

  if (!statusConfig) {
    throw new Error(`Invalid status type: "${type}".`);
  }

  const { icon: Icon, color } = statusConfig;

  return <Icon className={cn(color, "size-5", className)} {...props} />;
}

// Usage
<StatusIcon type="warning" className="size-8" />

Loading Spinner

function LoadingSpinner() {
  return (
    <Icons.Loader 
      className="size-6 animate-spin"
      aria-label="Loading"
    />
  );
}

Dynamic Icons

Dynamic icon patterns should only be used when icon names come from external sources (CMS, database, API). For static use cases, prefer direct imports like <Icons.Check /> - this enables better tree-shaking and smaller bundles.

export interface DynamicIconProps extends IconProps {
  name: keyof typeof Icons
}

export function DynamicIcon({ name, ...props }: DynamicIconProps) {
  const Icon = Icons[name];

  if (!Icon) {
    throw new Error(`Icon with name "${name}" does not exist.`);
  }

  return <Icon {...props} />;
}

// Usage
<DynamicIcon name="Check" className="size-4" />

Animations

function AnimatedCheck() {
  return (
    <Icons.Check 
      className="size-6 animate-bounce text-green-500"
    />
  );
}

With custom animation:

@keyframes spin {
  to { transform: rotate(360deg); }
}

.spin {
  animation: spin 1s linear infinite;
}
<Icons.Loader className="size-6 spin" />

TypeScript

Icons are fully typed. Import the types you need:

import type { IconProps, Icon, IconName } from "./icons";

// All available types:
// IconProps = React.ComponentProps<"svg">
// Icon = (props: IconProps) => React.JSX.Element
// IconName = keyof typeof Icons

// Example usage
const iconName: IconName = "Check"; // ✅ Type-safe
const invalidIcon: IconName = "NonExistent"; // ❌ Type error

Folder Mode

When using folder output mode, each icon is a standalone component file. You can import directly or use the barrel export:

Barrel Import

import { Icons } from "./icons";

// Same API as file mode
<Icons.Check className="size-4" />

Direct Import

import { Check } from "./icons/Check";

<Check className="size-4" />

Direct imports enable better tree-shaking. Barrel imports keep the same API as file mode.

Tips

  1. Tree Shaking: Only imported icons are bundled
  2. Naming: Use descriptive names with --name flag
  3. Organization: Group related icons in separate files if needed
  4. Performance: Icons are lightweight SVG components
  5. Consistency: Use same icon library for cohesive design

On this page