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