Skip to content
DomainKit
Esc
navigateopen⌘Jpreview
On this page

Composed flow

Replace one slot of the domain flow with your own component, place the slots in your own layout, and keep every other part of the lifecycle intact.

Every part of Domain.Flow is a slot with a default. Replacing one changes that part and nothing else, and the flow adds no layout container around a slot’s output.

/** One slot replaced, the rest of the flow untouched. */
export function DomainSetupWithMyTable() {
  return (
    <Domain.Flow
      domain={domain}
      requirements={requirements}
      slots={{
        records: ({ readiness, records }) => (
          <Records.Table caption="Add these records" readiness={readiness} records={records} />
        ),
      }}
    />
  );
}

Usage

/** Own one piece of the flow and keep the rest. Every slot has a default. */
export function DomainSettings() {
  return (
    <DomainKit.Root transport={transport}>
      <Domain.Flow
        domain="app.example.com"
        requirements={requirements}
        slots={{
          records: ({ records, readiness }) =>
            records.map((record) => (
              <Records.Card
                className="my-card"
                key={Records.identity(record)}
                readiness={readiness}
                record={record}
              />
            )),
        }}
        onApplied={(receipt) => track("dns.applied", { receiptId: receipt.id })}
      />
    </DomainKit.Root>
  );
}

Slots

Slot Receives Default
connection { controller, domain } Connect.Card once connected, Connect.Dialog until then
records { records, readiness, controller, domain } Records.Table
verification { controller, domain } Verify.Status
actions { connection, provisioning, cleanup, domain } Review changes, Approve, Decline, Remove records

Your own layout

/**
 * `Domain.Flow` wraps no slot in a container of its own, so the slot output is a direct child of
 * the flow root and your grid places it.
 */
export function DomainSettingsInAGrid() {
  return (
    <DomainKit.Root transport={transport}>
      <Domain.Flow
        className="settings-grid"
        domain="app.example.com"
        requirements={requirements}
        slots={{
          connection: ({ controller }) => <Connect.Card controller={controller} />,
          verification: ({ controller }) => <Verify.Status controller={controller} />,
        }}
      />
    </DomainKit.Root>
  );
}

Your own actions

/** The actions slot receives all three controllers, so a host can drive its own buttons. */
export function DomainSettingsWithMyButtons() {
  return (
    <DomainKit.Root transport={transport}>
      <Domain.Flow
        domain="app.example.com"
        requirements={requirements}
        slots={{
          actions: ({ cleanup, provisioning }) => (
            <div className="my-actions">
              <button onClick={provisioning.plan} type="button">
                Review DNS changes
              </button>
              <button onClick={cleanup.plan} type="button">
                Remove records
              </button>
            </div>
          ),
        }}
      />
    </DomainKit.Root>
  );
}

Read composition for parts, render, and state-aware className.

Was this page helpful?