Skip to content

CodeField component

CodeField is a text field for code and settings: custom CSS, a JSON config, an embed snippet. It has highlighting, line numbers, Tab and Shift+Tab to indent, Enter that keeps the indent, and, for JSON, a live note of where the text stops being valid. It is a real textarea underneath, so typing, undo and mobile keyboards behave as usual, and it has no dependencies. It is not a full code editor: there is no completion, folding or multiple cursors.

Forms16 propsAccessibility notes

Playground

Change a prop on the right and the preview updates. Switch to Code to copy what you see.

Highlighting and size

Set language to css, json, javascript, typescript, html, markdown, yaml, python, sql, bash and more. The field grows with its text between minRows and maxRows (4 and 20) and then scrolls. tabSize is the number of spaces per indent.

<CodeField label="Custom CSS" language="css" value={css} onChange={setCss} />
<CodeField label="Embed code" language="html" value={snippet} isReadOnly tabSize={4} showLineNumbers={false} />

JSON in a form

With language json the field shows Not valid JSON (line 3, column 7) while typing. Add the json validation rule so a Form refuses to submit invalid JSON.

<Form onSubmit={save}>
  <CodeField
    label="Config"
    name="config"
    language="json"
    minRows={6}
    validation={{ rules: { required: true, json: true } }}
  />
</Form>

Props

The full public API for CodeField. Every prop is stable and intentionally typed.

Data

value / defaultValue

string

default: ""

The text. value makes it controlled.

onChange

(value: string) => void

default: —

Every change.

name

string

default: —

In a Form: the key the text is stored under. Outside one: the textarea's name.

validation

FieldValidation

default: —

Rules when inside a Form. { json: true } checks the text is valid JSON.

Appearance

language

string

default: plaintext

Highlighting: css, json, javascript, typescript, html, markdown, yaml, python, sql, bash and the other languages the TextEditor code block knows.

showLineNumbers

boolean

default: true

The line-number gutter.

minRows / maxRows

number

default: 4 / 20

The field grows with its text between these heights, in lines, then scrolls.

size

"sm" | "md"

default: md

Font size and padding.

classNames

Partial<Record<slot, string>>

default: —

Class per part: base, label, control, gutter, input, description, error.

Content

label / description

ReactNode

default: —

A visible label (it names the field) and help text.

error

ReactNode | boolean

default: form's error for name

An error message, or true for the invalid look.

labels

Partial<CodeFieldLabels>

default: English

tabHint and invalidJson(line, column). Also set app-wide with LocaleProvider.

Behavior & states

tabSize

number

default: 2

Spaces per indent.

checkJson

boolean

default: true

With language="json", shows where the text stops being valid while typing.

isReadOnly

boolean

default: false

Read-only keeps the text selectable but not editable.

isDisabled

boolean

default: false

Dims the field and ignores input.

Accessibility

  • A real textarea named by its label. The coloured copy and the line numbers are hidden from screen readers, so the text is read once.
  • Tab indents instead of leaving the field. A hidden hint linked with aria-describedby says to press Escape, then Tab, to move to the next field. Shift+Tab outdents.
  • Indenting and auto-indent go through the browser's own typing, so Ctrl or Cmd+Z undoes them.
  • Token colours keep 4.5:1 contrast in light and dark themes; keywords are also bold and comments italic, so colour is not the only cue.

Best practices

  • Tell people about the Escape, then Tab, way out if the field is not the last one in a long form.
  • Use the json rule for settings that are stored as JSON, so a typo is caught before it is saved.
  • For long files or editing with completion, use a dedicated code editor instead.