Editable
Reveal an editing control from an explicit presentation trigger.
Default
Click the text (or focus it and press Enter) to edit it in place. Enter or clicking away saves; Escape cancels. The control keeps the same size in both states.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-editable/ui-editable.html"
>
<ui-editable
value="Editable text"
label="Project title"
> </ui-editable><script setup>
import { UiEditable } from "@threadlabs/looma";
</script>
<template>
<UiEditable
value="Editable text"
label="Project title"
> </UiEditable>
</template>import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
value="Editable text"
label="Project title"
> </UiEditable>;
}/** @jsxImportSource preact */
import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
value="Editable text"
label="Project title"
> </UiEditable>;
}<script>
import { UiEditable } from "@threadlabs/looma";
</script>
<UiEditable
value="Editable text"
label="Project title"
> </UiEditable>import { Component } from "@angular/core";
import { UiEditable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiEditable],
template: `
<div
ui-editable
[value]="'Editable text'"
[label]="'Project title'"
> </div>
`,
})
export default class Example {}hint="Rename"
Hint adds visible text beside the value to signal that it can be edited. Nothing is shown unless you ask for it.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-editable/ui-editable.html"
>
<ui-editable
value="Quarterly roadmap"
label="Document title"
hint="Rename"
> </ui-editable><script setup>
import { UiEditable } from "@threadlabs/looma";
</script>
<template>
<UiEditable
value="Quarterly roadmap"
label="Document title"
hint="Rename"
> </UiEditable>
</template>import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
value="Quarterly roadmap"
label="Document title"
hint="Rename"
> </UiEditable>;
}/** @jsxImportSource preact */
import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
value="Quarterly roadmap"
label="Document title"
hint="Rename"
> </UiEditable>;
}<script>
import { UiEditable } from "@threadlabs/looma";
</script>
<UiEditable
value="Quarterly roadmap"
label="Document title"
hint="Rename"
> </UiEditable>import { Component } from "@angular/core";
import { UiEditable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiEditable],
template: `
<div
ui-editable
[value]="'Quarterly roadmap'"
[label]="'Document title'"
[hint]="'Rename'"
> </div>
`,
})
export default class Example {}actions
Actions shows explicit Save and Cancel buttons while editing, for cases where an implicit save on Enter or blur is not enough.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-editable/ui-editable.html"
>
<ui-editable
value="Quarterly roadmap"
label="Document title"
actions
> </ui-editable><script setup>
import { UiEditable } from "@threadlabs/looma";
</script>
<template>
<UiEditable
value="Quarterly roadmap"
label="Document title"
:actions="true"
> </UiEditable>
</template>import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
value="Quarterly roadmap"
label="Document title"
actions
> </UiEditable>;
}/** @jsxImportSource preact */
import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
value="Quarterly roadmap"
label="Document title"
actions
> </UiEditable>;
}<script>
import { UiEditable } from "@threadlabs/looma";
</script>
<UiEditable
value="Quarterly roadmap"
label="Document title"
actions
> </UiEditable>import { Component } from "@angular/core";
import { UiEditable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiEditable],
template: `
<div
ui-editable
[value]="'Quarterly roadmap'"
[label]="'Document title'"
[actions]="true"
> </div>
`,
})
export default class Example {}edit and disabled
Edit starts in edit mode; disabled prevents entering it.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-editable/ui-editable.html"
>
<ui-stack
gap="s"
align="start"
>
<ui-editable
value="Editing now"
label="Title"
edit
> </ui-editable>
<ui-editable
value="Locked title"
label="Locked title"
disabled
> </ui-editable>
</ui-stack><script setup>
import { UiEditable, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
gap="s"
align="start"
>
<UiEditable
value="Editing now"
label="Title"
:edit="true"
> </UiEditable>
<UiEditable
value="Locked title"
label="Locked title"
:disabled="true"
> </UiEditable>
</UiStack>
</template>import { UiEditable, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
align="start"
>
<UiEditable
value="Editing now"
label="Title"
edit
> </UiEditable>
<UiEditable
value="Locked title"
label="Locked title"
disabled
> </UiEditable>
</UiStack>;
}/** @jsxImportSource preact */
import { UiEditable, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
align="start"
>
<UiEditable
value="Editing now"
label="Title"
edit
> </UiEditable>
<UiEditable
value="Locked title"
label="Locked title"
disabled
> </UiEditable>
</UiStack>;
}<script>
import { UiEditable, UiStack } from "@threadlabs/looma";
</script>
<UiStack
gap="s"
align="start"
>
<UiEditable
value="Editing now"
label="Title"
edit
> </UiEditable>
<UiEditable
value="Locked title"
label="Locked title"
disabled
> </UiEditable>
</UiStack>import { Component } from "@angular/core";
import { UiEditable, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiEditable],
template: `
<div
ui-stack
[gap]="'s'"
[align]="'start'"
>
<div
ui-editable
[value]="'Editing now'"
[label]="'Title'"
[edit]="true"
> </div>
<div
ui-editable
[value]="'Locked title'"
[label]="'Locked title'"
[disabled]="true"
> </div>
</div>
`,
})
export default class Example {}Required short text
Native required and maximum-length constraints keep an invalid draft open. Action labels and the empty placeholder can match the field.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-editable/ui-editable.html"
>
<ui-editable
label="Short name"
value="Untitled"
actions
required
max-length="24"
placeholder="Enter a short name"
save-label="Apply"
cancel-label="Discard"
></ui-editable><script setup>
import { UiEditable } from "@threadlabs/looma";
</script>
<template>
<UiEditable
label="Short name"
value="Untitled"
:actions="true"
:required="true"
:max-length="24"
placeholder="Enter a short name"
save-label="Apply"
cancel-label="Discard"
/>
</template>import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
label="Short name"
value="Untitled"
actions
required
maxLength={24}
placeholder="Enter a short name"
saveLabel="Apply"
cancelLabel="Discard"
/>;
}/** @jsxImportSource preact */
import { UiEditable } from "@threadlabs/looma";
export default function Example() {
return <UiEditable
label="Short name"
value="Untitled"
actions
required
maxLength={24}
placeholder="Enter a short name"
saveLabel="Apply"
cancelLabel="Discard"
/>;
}<script>
import { UiEditable } from "@threadlabs/looma";
</script>
<UiEditable
label="Short name"
value="Untitled"
actions
required
maxLength={24}
placeholder="Enter a short name"
saveLabel="Apply"
cancelLabel="Discard"
/>import { Component } from "@angular/core";
import { UiEditable } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiEditable],
template: `
<div
ui-editable
[label]="'Short name'"
[value]="'Untitled'"
[actions]="true"
[required]="true"
[maxLength]="24"
[placeholder]="'Enter a short name'"
[saveLabel]="'Apply'"
[cancelLabel]="'Discard'"
></div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: div
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
actions | Show explicit Save and Cancel buttons while editing. Without them, Enter or leaving the field saves and Escape cancels. | actions | boolean | false | — |
cancel-label | Visible text for the Cancel action. | cancelLabel | string | Cancel | — |
disabled | Prevents entering or changing edit mode. | disabled | boolean | false | — |
edit | Whether edit mode is active initially or when set externally. | edit | boolean | false | — |
hint | Optional text shown beside the value to signal it is editable (for example "Edit"). | hint | string | | — |
label | Accessible name for the editor. | label | string | Edit value | — |
max-length | Maximum draft length; 0 leaves the length unrestricted. | maxLength | number | 0 | — |
placeholder | Hint shown in the text input while the draft is empty. | placeholder | string | | — |
required | Prevent an empty draft from being saved. | required | boolean | false | — |
save-label | Visible text for the Save action. | saveLabel | string | Save | — |
value | The displayed value, and the text the editor starts from. It is not a form field: nothing is submitted with a form, so a form that needs the value copies it from the change event into a field of its own. | value | string | | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
actions | boolean | false | — |
cancelLabel | string | Cancel | — |
disabled | boolean | false | — |
edit | boolean | false | — |
hint | string | | — |
label | string | Edit value | — |
maxLength | number | 0 | — |
placeholder | string | | — |
required | boolean | false | — |
saveLabel | string | Save | — |
value | string | | — |
Events
| Name | Detail | Description |
|---|---|---|
change | object
| Emitted when a toggleable control changes checked state. |
edit-change | object
| Emitted with the declared detail payload. |
input | object
| Emitted with the declared detail payload. |
Slots
No slots.
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
No component tokens.
Shared tokens
| Token | Fallback |
|---|---|
--ui-accent-solid | — |
--ui-border-strong | — |
--ui-border-width | — |
--ui-control-focus | var(--ui-accent-solid) |
--ui-control-focus-halo-shadow | — |
--ui-control-inset | — |
--ui-control-size-sm | — |
--ui-control-surface | var(--ui-surface-elevated) |
--ui-disabled-text | — |
--ui-focus-halo | — |
--ui-font-size-sm | — |
--ui-line-height-md | — |
--ui-motion-ease | — |
--ui-motion-fast | — |
--ui-radius-md | — |
--ui-raised | — |
--ui-raised-highlight | — |
--ui-space-1 | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-surface-elevated | — |
--ui-surface-muted | — |
--ui-text-on-accent | — |
--ui-text-primary | — |
--ui-text-secondary | — |