Skip to content
Twilight React Playground
ثيم رائدaren

defineComponent

functionBeginnerserverbrowserlive demo

Registers a component under a name when its file loads, and returns the same component so it can also be imported and rendered directly.

import { defineComponent } from '@salla.sa/twilight-theme-engine';

In plain words

Instead of writing a component and remembering to register it somewhere else, wrap it: export const Promo = defineComponent({ name: 'my-theme:promo', component: PromoImpl }).

The component is in the registry as soon as the file is imported, and Promo is still an ordinary component you can render.

Signature

function defineComponent<P = Record<string, unknown>>(config: {
  name: string;
  component: ComponentType<P>;
  override?: boolean;   // true: registry.override, otherwise registry.register
}): ComponentType<P>

Try it live

defineComponent registers a component and returns it, so the same component works by import and by name.Try this: change the title: both copies update, because they are the same function.
Storefront canvas · en · LTR
Rendered directly:
Free delivery on orders over 200 SAR
Rendered by name through the registry:
Free delivery on orders over 200 SAR
registry.has('playground:promo-strip') → true
Controls
What a theme writes
// app/components/PromoStrip.tsx
import { defineComponent } from '@salla.sa/twilight-theme-engine';

export const PromoStrip = defineComponent({
  name: 'my-theme:promo-strip',
  component: function PromoStrip({ title, tone }: { title: string; tone: 'light' | 'dark' }) {
    return <div className={`promo promo--${tone}`}>{title}</div>;
  },
});

// Elsewhere, either way renders it:
// <PromoStrip title="Free delivery on orders over 200 SAR" tone="light" />
// <Component name="my-theme:promo-strip" title="Free delivery on orders over 200 SAR" tone="light" />

Example

app/components/PromoStrip.tsx
import { defineComponent } from '@salla.sa/twilight-theme-engine';

export const PromoStrip = defineComponent({
  name: 'my-theme:promo-strip',
  component: function PromoStrip({ title }: { title: string }) {
    return <div className="promo-strip">{title}</div>;
  },
});

How it behaves

  • It returns config.component itself, not a wrapper, so props, displayName and identity are unchanged.

  • The config type (DefineComponentConfig) is not exported; TypeScript infers P from component.

Gotchas

  • Registration is a side effect of importing the file. A file nothing imports never registers, and one imported only by a page registers only once that page loads. Import such files from app/router.tsx.

  • override: true on a name nothing registered records no original, exactly like registry.override; for product:card that is not enough (see registry).

Related

Source and docs