How to Customize the Icon Registry with Custom SVG Icons in Astryx

You can customize Astryx’s icon registry by calling registerIcons() with a mapping of semantic names to React SVG nodes, which overrides the defaults defined in defaultIcons.tsx and works in both React Server Components and client-side code.

Astryx (facebook/astryx) provides a global icon registry that maps semantic names like close, menu, and search to React nodes. By default, this registry is populated with lightweight inline SVGs located in packages/core/src/Icon/defaultIcons.tsx. To replace these defaults or add new icon names, you register custom icons through the registerIcons helper exported from packages/core/src/Icon/globalIconRegistry.tsx.

Understanding the Global Icon Registry

The registry lives at module-level in globalIconRegistry.tsx and contains no use client directive, making it safe to use in React Server Components (RSC) as well as client components. It stores a plain JavaScript object that maps IconName keys to ReactNode values.

When you call registerIcons(customIcons), the function merges your definitions into the global registry. Later calls overwrite earlier entries for the same name, allowing you to layer multiple icon packs or theme-specific overrides.

Creating Custom Icon Definitions

Define a plain object that conforms to the IconRegistry type (or Partial<IconRegistry> for selective overrides). Each key must be a member of the IconName union type, and each value should be an inline <svg> element.

// src/custom-icons.tsx
import type { IconRegistry } from '@astryxdesign/core/Icon/globalIconRegistry';

export const customIcons: Partial<IconRegistry> = {
  // Override an existing semantic name
  menu: (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      width="1em"
      height="1em"
      aria-hidden
    >
      <path d="M4 6h16M4 12h16M4 18h16" />
    </svg>
  ),

  // Add a brand-specific icon
  logo: (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 48 48"
      fill="currentColor"
      width="1em"
      height="1em"
      aria-hidden
    >
      <path d="M24 4L4 44h40L24 4z" />
    </svg>
  ),
};

Registering Icons at Application Startup

Call registerIcons() once in your root layout or a top-level provider component that runs before other Astryx components render. This ensures the custom icons are available throughout the component tree.

// src/app/root-layout.tsx
import { registerIcons } from '@astryxdesign/core/Icon';
import { customIcons } from '@/custom-icons';

// Register once before any components render
registerIcons(customIcons);

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return <>{children}</>;
}

Because the registry is a plain object, you can safely call registerIcons multiple times to merge different icon packs. The last registration wins for any duplicate keys.

Using Custom Icons in Components

Once registered, all components using the <Icon> component or the getIcon helper will resolve your custom SVGs automatically. Unregistered names fall back to the built-in defaults from defaultIcons.tsx.

import { Icon } from '@astryxdesign/core/Icon';

export function Header() {
  return (
    <header>
      {/* Renders the custom "menu" SVG defined above */}
      <Icon name="menu" size="large" />
    </header>
  );
}

To retrieve an icon programmatically as a React node:

import { getIcon } from '@astryxdesign/core/Icon';

const customLogo = getIcon('logo'); // Returns the ReactNode from customIcons

Advanced: Extending IconName Types

If you add brand-specific icons (like logo in the example above) that are not part of the default IconName union, you can extend the type in your own type definition for TypeScript autocomplete, or cast the key as any if strict typing is not required.

Summary

  • Register once using registerIcons() from packages/core/src/Icon/globalIconRegistry.tsx before rendering dependent components.
  • Provide inline SVGs as React nodes mapped to semantic IconName keys in a Partial<IconRegistry> object.
  • Override selectively by including only the keys you want to replace; unregistered names fall back to defaultIcons.tsx.
  • Merge multiple packs by calling registerIcons repeatedly—later calls overwrite earlier entries.
  • Access anywhere via the <Icon> component or getIcon() helper, with full support for React Server Components.

Frequently Asked Questions

Can I use the custom icon registry in React Server Components?

Yes. The registry in globalIconRegistry.tsx lives at module-level and contains no use client directive, so it works in both React Server Components and client-side code without hydration issues.

How do I reset the icon registry to its default state?

Import resetIcons from packages/core/src/Icon/globalIconRegistry.tsx and call it to restore the original mappings from defaultIcons.tsx. This is useful for testing or when switching themes dynamically.

What happens if I register an icon name that already exists?

Later calls to registerIcons overwrite earlier entries for the same key. Because the registry is a plain JavaScript object, you can layer multiple icon packs by calling registerIcons multiple times, with the last registration taking precedence.

Do I need to import my custom icons in every component?

No. Once you call registerIcons in your root layout or provider, the mappings are available globally. Any component using <Icon name="..." /> or getIcon() will automatically resolve the custom SVGs without additional imports.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →