Records table
A React table of the DNS records a domain needs, each with its plan or observed status, a copy button per value, and the reason a record is blocked.
records-table lists the records your product needs at a domain, one row each, with the type, the
name, a copy control for the value, and where the record stands.
import { Domain } from "@domainkit/react";
import { ProviderRow } from "@/components/domainkit/provider-row";
import { RecordsTable } from "@/components/domainkit/records-table";
import {
PreviewRoot,
previewDomain,
previewMarks,
previewRequirements,
} from "../../lib/preview-flow.tsx";
function Table() {
const flow = Domain.useFlow({ domain: previewDomain, requirements: previewRequirements });
return <RecordsTable flow={flow} header={<ProviderRow flow={flow} marks={previewMarks} />} />;
}
export default function RecordsTableExample() {
return (
<PreviewRoot>
<Table />
</PreviewRoot>
);
}
Installation
npx shadcn@latest add https://domain-kit.dev/r/records-table.jsonpnpm dlx shadcn@latest add https://domain-kit.dev/r/records-table.jsonyarn dlx shadcn@latest add https://domain-kit.dev/r/records-table.jsonbunx shadcn@latest add https://domain-kit.dev/r/records-table.jsonnubx shadcn@latest add https://domain-kit.dev/r/records-table.jsonaube dlx shadcn@latest add https://domain-kit.dev/r/records-table.jsonWhat a row says
A plan still awaiting its apply gets a column of its own saying what it will do: add the record,
leave it, or nothing while it is blocked. The status column beside it is always what the observers
read back. Records.standingOf hands the row both facts, so the table renders each column from the
one that is about it.
A blocked record gets a second row under it naming what is in the way and what to do about it, both from the message catalog.
Here an A record already sits on the tracking host, so its CNAME is a conflict. The plan approves the records that can be added and leaves the blocked one for the customer to fix at their provider.
import { Domain } from "@domainkit/react";
import { PlanAction } from "@/components/domainkit/plan-action";
import { ProviderRow } from "@/components/domainkit/provider-row";
import { RecordsTable } from "@/components/domainkit/records-table";
import {
PreviewRoot,
previewConflictSeed,
previewDomain,
previewMarks,
previewRequirements,
} from "../../lib/preview-flow.tsx";
// Hydrate on load: the preview renders nothing until its grant lands, so the island has no
// server-rendered element for the default visible trigger to observe.
export const client = "load";
function Table() {
const flow = Domain.useFlow({ domain: previewDomain, requirements: previewRequirements });
return (
<div className="space-y-3">
<RecordsTable flow={flow} header={<ProviderRow flow={flow} marks={previewMarks} />} />
<PlanAction flow={flow} />
</div>
);
}
/** A zone whose A record on the tracking host blocks the CNAME, so the plan carries a conflict. */
export default function RecordsTableConflictExample() {
return (
<PreviewRoot connected seed={previewConflictSeed}>
<Table />
</PreviewRoot>
);
}
API
| Prop | Type | Required | Description |
|---|---|---|---|
flow |
Domain.Flow |
yes | The flow whose requirements the table renders. |
header |
ReactNode |
no | The line above the table, where the row goes. |
Boundary
The table renders what the plan and the observation already decided. Observing DNS, and deciding what readiness means for your product, both stay outside it.