Skip to content

CodeEditor

<caos-code-editor>

one code artifact, with a line gutter, edited in place

May be placed on a page inside an app.

Name Attribute Description Type Default Required
value property only The code. Set it when the artifact loads, and set it again after a save succeeds — each set becomes the baseline dirty is measured against, so the editor stops reporting unsaved work. json none declared Optional
language language, also a property What the code is, e.g. json or typescript. Informational: the engine shipped with the platform does not highlight, and an engine that does reads this. Nothing breaks when it is absent. text none declared Optional
readonly readonly, markup only Present means the code can be read, selected and copied but not changed, and save is never raised. Use it for an artifact the person may see but not edit — not as a way to disable the editor while something loads, which reads to a person as “you may not have this”. There is a readOnly property behind it for a surface that toggles it in script. boolean none declared Optional
Name When it fires What it carries
change The person edits the code. Raised on every edit, not on blur, and it bubbles and is composed. { value, dirty } — the code as it now stands, and whether it differs from the last value the page set.
save The person presses Ctrl+S (Cmd+S on a Mac). Never raised while readonly is present. The browser’s own save-page dialog is suppressed when it is. { value } — the code to save. The surface performs the write; this component does not.

Nothing goes inside this piece.

Design token What it controls
--caos-font-mono The typeface of the code and of the line numbers. One ramp for both, or the gutter drifts out of step with the code down a long file.
--caos-color-surface The ground the code sits on.
--caos-color-surface-2 The ground of the line-number gutter.
--caos-color-border The outline of the editor and the rule between the gutter and the code.
--caos-color-text The ink of the code.
--caos-color-text-muted The ink of the line numbers, and of the code while read-only.
--caos-radius-sm The corner radius of the editor.
--caos-focus-ring The ring drawn when the code has keyboard focus.
Name Description Arguments
focusEditor() Puts the cursor in the code. Use it after opening an artifact, so the person can type without reaching for the mouse. takes none
Name Type What it tells you
dirty boolean Whether the code differs from the last value the page set. Compared against that baseline rather than latched on the first keystroke, so typing a character and deleting it again leaves the editor clean.
Part Which piece of it When it is there
::part(surface) the gutter and the code together Always
::part(gutter) the line numbers Always
::part(input) the editable code area Always

A developer is editing the source of one platform artifact and needs to see it as code — with line numbers, without wrapping, and with the keystroke that saves it.

  • Inspector — The properties of the selection are what is being edited — name, label, whether a field is required. Those are fields, and a person editing them through a textarea is being asked to hand-write a shape the platform could have drawn for them.
  • TextField — It is a sentence, a description, or a note. A code editor over prose disables spellcheck and autocorrect, refuses to wrap, and numbers the lines — every one of which is wrong for prose.
  • FieldRenderer — The value belongs to a record and the platform already knows its type. Let the platform draw the right control for it rather than serialising it into a code pane.

The editing surface is a plain textarea, which is why it is one: a screen reader, braille display, dictation and native find all already know what to do with it, and each is something a hand-built editor re-implements badly. The component names the surface “Code editor” and takes aria-label off the host when a screen has more than one — label them by what they hold, not by what they are. The line numbers are aria-hidden: they are a visual aid, and read aloud they would put a number before every line of code. Ctrl/Cmd+S is intercepted only inside the editor. What the surface still owes a person: somewhere visible to see that work is unsaved — dirty and change are there for that, and a keystroke is not an announcement.

The editor doing its job: an artifact loaded as code, line numbers beside it, and the page around it holding the save.

The page around it: hands the editor the artifact and performs the save, because the code is a property rather than markup and the write belongs to the surface — the editor asks, it never writes

{
"id": "example",
"section": "Editing an artifact",
"columns": 1,
"items": [
{
"id": "code_editor_1",
"type": "component",
"key": "code_editor",
"inputs": {
"language": "json"
}
}
]
}
<caos-code-editor language="json"></caos-code-editor>

An artifact somebody may read but not change: the code can be selected and copied, Ctrl+S raises nothing, and the ink says so without a disabled control claiming the page is busy.

The page around it: sets the code it is showing, for the same reason the first example does

{
"id": "example",
"section": "Read-only",
"columns": 1,
"items": [
{
"id": "code_editor_1",
"type": "component",
"key": "code_editor",
"inputs": {
"language": "json",
"readonly": true
}
}
]
}
<caos-code-editor language="json" readonly></caos-code-editor>