Components, icons and config

Your own React components under components/ (any React works; defineComponent adds typed, defaulted props and a catalog entry), icons from any Iconify set or your icons/*.svg, and the app's public config values.

@appbricx/ui10 membersSDK referenceCustom screens guide

On this page
  1. Components
  2. defineComponent
  3. lazyComponent
  4. p.string
  5. p.uuid
  6. p.number
  7. p.bool
  8. p.json
  9. Icons
  10. <Icon>
  11. Config and clock
  12. useConfig
  13. useClock
  14. Types

Pages render on the server and hydrate in the browser, so a render must give the same output in both: take now from useClock, format dates with an explicit time zone, and render browser-only libraries with client: true or lazyComponent.

Components

defineComponentfunction

A component with typed, defaulted props and an entry in the console's component catalog. client: true renders skeleton on the server and in the first paint, then the component: use it for browser-only libraries (maps, canvases, editors). A plain React component works too.

defineComponent<S extends Record<string, AnyProp>>(def: { name: string; props?: S; client?: boolean; skeleton?: ReactNode; render: (props: { [K in keyof S]: Val<S[K]> }) => ReactNode; }): ComponentType<Props<S>> & { info: ComponentInfo }

Parameters

NameTypeDescription
defrequired{ name: string; props?: S; client?: boolean; skeleton?: ReactNode; render: (props: { [K in keyof S]: Val<S[K]> }) => ReactNode; }name, props (built with p), client, skeleton and render(props).
Returns
The component, with info (name, props, client).
Errors
Does not throw.
Permissions
None.
Example
import { defineComponent, p } from "@appbricx/ui";

export const StatCard = defineComponent({
  name: "StatCard",
  props: { label: p.string(), value: p.number(), cols: p.number().default(3) },
  render: ({ label, value }) => (
    <div className="rounded-lg border p-4"><p>{label}</p><p className="text-2xl">{value}</p></div>
  ),
});

Source: internal/kernel/appsdk/ui/component.tsx:66

lazyComponentfunction

A component whose code is its own chunk, loaded after the first paint, with skeleton until then. Use it for a library that touches window as soon as it is imported, or to keep a heavy chart out of the route's budget (100 KB gzip per route).

lazyComponent<P extends object>(load: () => Promise<{ default: ComponentType<P> }>, opts: { skeleton?: ReactNode } = {}): ComponentType<P>

Parameters

NameTypeDescription
loadrequired() => Promise<{ default: ComponentType<P> }>
optsoptional{ skeleton?: ReactNode }
Returns
ComponentType<P>
Errors
Does not throw.
Permissions
None.
Example
import { lazyComponent } from "@appbricx/ui";

const BookingsChart = lazyComponent(() => import("../components/BookingsChart"), {
  skeleton: <div className="h-64 animate-pulse rounded bg-stone-100" />,
});

Source: internal/kernel/appsdk/ui/component.tsx:94

p.stringfunction

A text prop. .default(v) makes it optional with a value; .optional() makes it optional.

p.string(): Prop<string, false>
Returns
Prop<string, false>
Errors
Does not throw.
Permissions
None.
Example
props: { title: p.string(), subtitle: p.string().optional() }

Source: internal/kernel/appsdk/ui/component.tsx:34

p.uuidfunction

An id prop (a row's id).

p.uuid(): Prop<string, false>
Returns
Prop<string, false>
Errors
Does not throw.
Permissions
None.
Example
props: { booking: p.uuid() }

Source: internal/kernel/appsdk/ui/component.tsx:35

p.numberfunction

A number prop.

p.number(): Prop<number, false>
Returns
Prop<number, false>
Errors
Does not throw.
Permissions
None.
Example
props: { cols: p.number().default(3) }

Source: internal/kernel/appsdk/ui/component.tsx:36

p.boolfunction

A true/false prop.

p.bool(): Prop<boolean, false>
Returns
Prop<boolean, false>
Errors
Does not throw.
Permissions
None.
Example
props: { compact: p.bool().default(false) }

Source: internal/kernel/appsdk/ui/component.tsx:37

p.jsonfunction

Any JSON value, typed by you.

p.json<T>(): Prop<T, false>
Returns
Prop<T, false>
Errors
Does not throw.
Permissions
None.
Example
props: { series: p.json<Array<{ day: string; n: number }>>() }

Source: internal/kernel/appsdk/ui/component.tsx:38

Icons

<Icon>component

An icon from any Iconify set (lucide:calendar-check, ph:confetti-duotone) or your own icons/<name>.svg (app:<name>). Names must be literals: the build collects them into one SVG sprite, so there is no JavaScript per icon and currentColor themes it. size (default 1em) and title (an icon that means something on its own).

Icon<N extends string>({ name, size = "1em", title, className, ...rest }: IconProps<N>): Element

Parameters

NameTypeDescription
{ name, size = "1em", title, className, ...rest }requiredIconProps<N>
Returns
Element
Errors
  • An app: name that isn't in icons/ is a type error; an unknown Iconify name fails the build.
Permissions
None.
Example
import { Icon } from "@appbricx/ui";

<Icon name="lucide:calendar-check" />
<Icon name="app:mark" size={24} title="Teamday" />

Source: internal/kernel/appsdk/ui/icon.tsx:27

Config and clock

useConfigfunction

The app's public config values: the config entries app.config.ts marks public: true, set per environment and the same in the server render. Typed from app.config.ts.

useConfig(): PublicConfig
Returns
PublicConfig
Errors
Does not throw.
Permissions
Only public values reach the browser.
Example
const { SUPPORT_PHONE } = useConfig();
{SUPPORT_PHONE ? <footer>Help: {SUPPORT_PHONE}</footer> : null}

Source: internal/kernel/appsdk/ui/app.tsx:474

useClockfunction

The app's time zone and locale, as the server render used them, so dates format the same on the server and in the browser (a mismatch is a hydration error and a verify failure).

useClock(): Clock
Returns
Clock
Errors
Does not throw.
Permissions
None.
Example
const { tz, locale } = useClock();
const when = new Intl.DateTimeFormat(locale ?? "en-GB", { timeZone: tz ?? "UTC", dateStyle: "medium" }).format(new Date(row.starts_at));

Source: internal/kernel/appsdk/ui/app.tsx:469

Types

interface IconProps<N extends string = string> extends Omit<React.SVGProps<SVGSVGElement>, "name"> {
  name: N & IconName<N>;
  /** Width and height (default 1em: the text's size). */
  size?: number | string;
  /** A label for an icon that means something on its own (else it is decorative). */
  title?: string;
}

Source: internal/kernel/appsdk/ui/icon.tsx:19

interface Clock {
  tz?: string;
  locale?: string;
}

Source: internal/kernel/appsdk/ui/app.tsx:88