The CLI also installs the npm packages and registry items it builds on, and reads the style in your components.json to pick the Base UI or Radix build.

key-value-editor-usage.tsx
import { KeyValueEditor, type KeyValueRow } from "@/components/ui/key-value-editor"

export function EnvVars({
  rows,
  onRowsChange,
}: {
  rows: KeyValueRow[]
  onRowsChange: (rows: KeyValueRow[]) => void
}) {
  return (
    <KeyValueEditor
      aria-label="Environment variables"
      value={rows}
      onValueChange={onRowsChange}
      secretValues
    />
  )
}

KeyValueEditor

Editable rows of key and value. Pasting KEY=value text into a key splits it into rows, and duplicate keys are flagged.

Prop
valueKeyValueRow[]Controlled rows of { id, key, value }.
defaultValueKeyValueRow[]Default[]Initial value when uncontrolled.
onValueChange(rows: KeyValueRow[]) => voidCalled with the new rows after any edit, paste, add or remove.
secretValuesbooleanDefaultfalseMask every value with a password input that has its own reveal button.
keyLabelstringDefault"Key"Column heading and the start of each key input's label.
valueLabelstringDefault"Value"Column heading and the start of each value input's label.
keyPlaceholderstringDefault"KEY"Placeholder for key inputs.
valuePlaceholderstringDefault"Value"Placeholder for value inputs.
addLabelstringDefault"Add row"Text of the add button.
disabledbooleanDefaultfalseDisable every input and button.

Other props go to the <div>.

Secret values

secretValues masks every value with its own reveal button, so one secret can be checked without showing the rest. Type or paste a value to see it masked, or paste KEY=value lines into a key to add several rows.

Controlled, with duplicates

value and onValueChange keep the rows in the parent. Two rows share a key here, so both are flagged.

Duplicate key

Duplicate key

Accept: application/json
Accept: text/plain
components/ui/key-value-editor.tsx
CtrlK