Skip to content
Component installs need the registry setup
VegaStack Design

Field Type Link Step

The "Links to" step of FieldTypePicker — grouped kinds of record, each explained in one line, and a table choice for Rows.

Status
stable
Since
0.25.90
Accessibility pattern
searchable listbox per view; Backspace goes up a view

Last updated

Install

Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Field Type Link Step before installation. Retain the digest printed by this command.

pnpm exec vegastack-design verify field-type-link-step

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/field-type-link-step

Run the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.

The same command installs the registry items it composes: @vegastack/command, @vegastack/field-type-picker.

Usage

import { FieldTypePicker } from "@/components/ui/field-type-picker";
import { FieldTypeLinkStep } from "@/components/ui/field-type-link-step";

<FieldTypePicker
  types={[
    ...types,
    { id: "link", label: "Link to", icon: <Link2 />, next: true },
  ]}
  onSelect={(type) => addField({ type })}
  renderStep={(type, controls) => (
    <FieldTypeLinkStep
      controls={controls}
      kinds={recordKinds}
      tables={tables}
      onSelect={({ kind, table }) => addField({ type: type.id, kind, table })}
    />
  )}
/>;

A link field points at another kind of record, and a flat list of a dozen kinds says nothing about what a link does. This step — rendered from FieldTypePicker's renderStep for the link type — lists the kinds in their groups, each with one line on what a link to it does. A kind marked table (Rows) asks which table in a third view and retitles the picker's step header ("Which table's rows?"); the choice comes back as { kind, table? }.

Scope

  • Owns: the kinds and tables views, their search, the header title in the table view, and going up a view.
  • Does not own: which kinds exist or what they're called (the host's kinds), the tables (the host's tables), or the field it creates.
  • Compose with: FieldTypePicker, which draws the back header and owns the type list.

Examples

Choose Link to, then a kind — or Rows, then a table.

In place

The same picker without a popover. The header's back button returns to the types; Backspace in an empty search goes up one view (tables → kinds → types).

Nothing chosen yet

API Reference

PropTypeDefaultDescription
controls*FieldTypePickerStepControls—The controls renderStep hands over: the third view retitles the step header with them.
kinds*readonly FieldLinkKind[]—The kinds of record, in order within their groups.
onSelect*(choice: FieldLinkChoice) => void—Called with the final choice.
classNamestring—Classes on the command root.
currentLabelstring"current"Read after the current choice's name.
emptyLabelstring"No kind of record matches."
groupOrderreadonly string[]—Group order; groups not listed follow in first-seen order.
placeholderstring"Search kinds of record"
refReact.Ref<HTMLDivElement>—Ref forwarded to the command root (data-slot="field-type-link-step").
tableEmptyLabelstring"No table matches."
tablePlaceholderstring"Search tables"
tablesreadonly FieldLinkTable[][]The tables a kind marked table can point at.
tablesLoadingbooleanfalseThe tables are still arriving: the table view says so.
tablesLoadingLabelstring"Loading tables…"
tableTitle((kind: FieldLinkKind) => React.ReactNode)(kind) => `Which table's ${kind.label.toLowerCase()}?`The step header's label in the table view.
valuePartial<FieldLinkChoice>—The current choice, checked.

Data attributes and CSS variables on FieldTypeLinkStep

AttributeValues
data-checked""
data-slot"field-type-link-step" | "field-type-link-step-kind" | "field-type-link-step-table"
data-view"kinds" | "tables"

FieldLinkKind

PropTypeDefaultDescription
id*string—Stable id ("page", "table_row").
label*string—Its name, plural ("Pages", "Rows").
descriptionstring—One line on what a link to it does ("Each cell links to pages in the Library").
disabledReasonstring—Why it can't be chosen here — shown, and the pick is refused.
groupstring—The group heading it sits under ("Library", "Sales"); ungrouped kinds come first.
iconReact.ReactNode—Its icon.
keywordsreadonly string[]—Extra words a search matches.
tablebooleanfalseThe kind lives in a table (rows): choosing it asks which table.

FieldLinkTable

PropTypeDefaultDescription
id*string—The table's id.
label*string—Its name.
descriptionstring—A muted line ("Sales · 117 rows").
iconReact.ReactNode—Its icon.

FieldLinkChoice

PropTypeDefaultDescription
kind*string—The kind's id.
tablestring—The table's id, for a kind marked table.

Accessibility

  • Each view is a searchable listbox named by its search field ("Search kinds of record", "Search tables"); the explanation is part of each option's text.
  • A kind that can't be chosen is disabled and says why.
  • The current choice reads "current" after its name.
  • Focus lands in the search on every view change.
KeyAction
ArrowUp / ArrowDownMoves through the kinds or tables
EnterChooses, or opens the table choice for Rows
Backspace (empty search)Goes up one view: tables → kinds → types
EscapeCloses the popover the picker sits in
ContractStates tested
Behaviourdefault, searching, empty, disabled-kind, current, tables, tables-loading
Accessibilitylabeled, keyboard, browser-accessibility-test
Visualdefault, highlighted, disabled, current

Do / Don't

Do
Group the kinds and give each one line on what a link to it does; ask for the table right after Rows.
Don't
List every record kind in one flat Select, or ask for the table in a separate field afterwards.

On this page