Skip to main content

Icon Registry

@plaud/design ships no icon implementations. It only defines an icon contract (IconRegistry). Every icon used inside the components is injected by the consumer at the app entry — design provides no fallback. If the registry is missing or a key is absent, the affected component throws at render time.

Why this design:

  • Icon implementations are decoupled from the component library, so consumers can plug in any icon source (hand-drawn SVGs, lucide-react, etc.)
  • Configure once, globally — swap the whole icon set in a single place
  • TypeScript + runtime double validation surfaces missing icons at compile / dev time

Quick start

Inject a registry covering every key at the app root, using DesignProvider (or the lightweight IconRegistryProvider):

import { DesignProvider } from '@plaud/design'
import type { IconRegistry } from '@plaud/design'

const icons = {
search: MySearchIcon,
calendar: MyCalendarIcon,
// …cover every key of IconRegistry
} satisfies IconRegistry

export const App = () => (
<DesignProvider icons={icons}>
<YourApp />
</DesignProvider>
)

satisfies IconRegistry validates at compile time: a missing key — or an icon component whose props don't match (e.g. sort must accept sortDirection) — fails the build.

Two providers

ProviderCapabilityWhen to use
DesignProviderTheme + overlay host + icon injection (icons required)Application entry, all-in-one
IconRegistryProviderIcon injection only (icons required), no theme managementWhen theme is owned elsewhere (e.g. this docs site's Docusaurus)

The contract (IconKey)

Every key of IconRegistry is available via the runtime constant ICON_KEYS:

import { ICON_KEYS } from '@plaud/design'

console.log(ICON_KEYS) // ['infoCircle', 'checkmarkCircle', ...]

Most icons are typed ComponentType<IconProps> (IconProps mirrors native <svg> props). sort is the exception: it additionally receives sortDirection, so it is typed ComponentType<SortIconProps>.

Plug in your own icon library

Any source works as long as it satisfies the contract — for example using lucide-react:

import { Search, Calendar, ChevronDown } from 'lucide-react'
import type { IconRegistry } from '@plaud/design'

const icons = {
search: Search,
calendar: Calendar,
chevronDown: ChevronDown,
// …the remaining keys
} satisfies IconRegistry

Reference implementation

This docs site uses a default set sourced from the Figma Design System (packages/design-site/src/icons/plaud-icon-registry.tsx), injected via IconRegistryProvider in src/theme/Root.tsx so that every component example below renders its icons:

src/theme/Root.tsx
import { IconRegistryProvider } from '@plaud/design'

import { plaudIconRegistry } from '../icons/plaud-icon-registry'

const Root = ({ children }) => (
<IconRegistryProvider icons={plaudIconRegistry}>{children}</IconRegistryProvider>
)

Consumers can copy plaudIconRegistry as a starting point and replace individual icons as needed.

Validation behavior

  • Compile time: icons is required on DesignProvider / IconRegistryProvider, and satisfies IconRegistry guarantees full coverage
  • Dev time: on mount the provider lists any missing keys via console.error
  • Runtime: rendering a component that needs an unprovided icon throws, naming the missing key