Skip to content
Destyler UI Destyler UI Destyler UI

Edit

Displays an input field used for editing a single line of text, rendering as static text on load. It transforms into a text input field when the edit interaction is triggered.

Type something...
Type something...

Features

Install

Install the component from your command line.

Terminal window
      
        
npm install @destyler/edit @destyler/vue
Terminal window
      
        
npm install @destyler/edit @destyler/react
Terminal window
      
        
npm install @destyler/edit @destyler/svelte
Terminal window
      
        
npm install @destyler/edit @destyler/solid

Anatomy

Import all parts and piece them together.

<script setup lang="ts">
import * as edit from "@destyler/edit";
import { normalizeProps, useMachine } from "@destyler/vue";
import { computed, useId } from "vue";
const [state, send] = useMachine(edit.machine({
id: useId(),
placeholder: 'Type something...',
}));
const api = computed(() => edit.connect(state.value, send, normalizeProps));
</script>
<template>
<div v-bind="api.getRootProps()">
<div v-bind="api.getAreaProps()">
<input v-bind="api.getInputProps()" />
<span v-bind="api.getPreviewProps()" />
</div>
<button v-bind="api.getSubmitTriggerProps()" ></button>
<button v-bind="api.getCancelTriggerProps()" ></button>
<button v-bind="api.getEditTriggerProps()" ></button>
</div>
</div>
</template>
import * as edit from '@destyler/edit'
import { normalizeProps, useMachine } from '@destyler/react'
import { useId } from 'react'
export default function Edit() {
const [state, send] = useMachine(edit.machine({
id: useId(),
placeholder: 'Type something...',
}))
const api = edit.connect(state, send, normalizeProps)
return (
<>
<div {...api.getRootProps()} >
<div {...api.getAreaProps()} >
<input {...api.getInputProps()} />
<span {...api.getPreviewProps()} />
</div>
<button {...api.getSubmitTriggerProps()} ></button>
<button {...api.getCancelTriggerProps()}></button>
<button {...api.getEditTriggerProps()}></button>
</div>
</>
)
}
<script lang="ts">
import * as edit from "@destyler/edit";
import { normalizeProps, useMachine } from "@destyler/svelte";
const [state, send] = useMachine(edit.machine({
id: crypto.randomUUID(),
placeholder: 'Type something...',
}))
const api = $derived(edit.connect(state, send, normalizeProps));
</script>
<div {...api.getRootProps()} >
<div {...api.getAreaProps()}>
<input {...api.getInputProps()}/>
<span {...api.getPreviewProps()}></span>
</div>
<button {...api.getSubmitTriggerProps()}></button>
<button {...api.getCancelTriggerProps()}></button>
<button {...api.getEditTriggerProps()}></button>
</div>
import * as edit from '@destyler/edit'
import { normalizeProps, useMachine } from '@destyler/solid'
import { createMemo, createUniqueId } from 'solid-js'
export default function Edit() {
const [state, send] = useMachine(edit.machine({
id: createUniqueId(),
placeholder: 'Type something...',
}))
const api = createMemo(() => edit.connect(state, send, normalizeProps))
return (
<>
<div {...api().getRootProps()}>
<div {...api().getAreaProps()} >
<input {...api().getInputProps()} />
<span {...api().getPreviewProps()}/>
</div>
<button {...api().getSubmitTriggerProps()}></button>
<button {...api().getCancelTriggerProps()}></button>
<button {...api().getEditTriggerProps()}></button>
</div>
</>
)
}

Setting the initial value

To set the initial value of the editable, pass the value property to the machine’s context.

const [state, send] = useMachine(
edit.machine({
value: "Hello World",
}),
)

Listening for value changes

The editable machine supports two ways of listening for value changes:

  • onValueChange: called when value changes.

  • onValueCommit: called when the value is committed.

const [state, send] = useMachine(
edit.machine({
onValueChange(details) {
console.log("Value changed", details.value)
},
onValueCommit(details) {
console.log("Value submitted", details.value)
},
}),
)

Auto-resizing the editable

To auto-grow the editable as the content changes, pass the autoResize: true property to the machine’s context.

const [state, send] = useMachine(
edit.machine({
autoResize: true,
}),
)

Setting a maxWidth

It is a common pattern to set a maximum of the editable as it auto-grows. To achieve this, set the maxWidth property of the machine’s context to the desired value.

const [state, send] = useMachine(
edit.machine({
autoResize: true,
maxWidth: "320px",
}),
)

When the editable reaches the specified max-width, it’ll clip the preview text with an ellipsis.

Editing with double click

he editable supports two modes of activating the “edit” state:

  • when the preview part is focused (with pointer or keyboard).

  • when the preview part is double-clicked.

To change the mode to “double-click”, set the activationMode: 'dblclick' property in the machine’s context.

const [state, send] = useMachine(
editable.machine({
activationMode: "dblclick",
}),
)

Styling guide

Earlier, we mentioned that each hover card part has a data-part attribute added to them to select and style them in the DOM.

Focused state

When the editable is in the focused mode, we set a data-focus attribute on the “area” part.

[data-part="area"][data-focus] {
/* CSS for the editable's focus state */
}

Empty state

When the editable’s value is empty, we set a data-empty attribute on the “area” part.

[data-part="area"][data-empty] {
/* CSS for the editable's focus state */
}

Disabled state

When the editable is disabled, we set a data-disabled attribute on the “area” part.

[data-part="area"][data-disabled] {
/* CSS for the editable's focus state */
}

Methods and Properties

Machine Context

The edit machine exposes the following context properties:

ids
Partial<{ root: string; area: string; label: string; preview: string; input: string; control: string; submitTrigger: string; cancelTrigger: string; editTrigger: string; }>
The ids of the elements in the editable. Useful for composition.
invalid
boolean
Whether the input's value is invalid.
name
string
The name attribute of the editable component. Used for form submission.
form
string
The associate form of the underlying input.
autoResize
boolean
Whether the editable should auto-resize to fit the content.
activationMode
ActivationMode
The activation mode for the preview element. - "focus" - Enter edit mode when the preview is focused - "dblclick" - Enter edit mode when the preview is double-clicked - "click" - Enter edit mode when the preview is clicked
submitMode
SubmitMode
The action that triggers submit in the edit mode: - "enter" - Trigger submit when the enter key is pressed - "blur" - Trigger submit when the editable is blurred - "none" - No action will trigger submit. You need to use the submit button - "both" - Pressing `Enter` and blurring the input will trigger submit
edit
boolean
Whether the editable is in edit mode.
edit.controlled
boolean
Whether the editable is controlled.
selectOnFocus
boolean
Whether to select the text in the input when it is focused.
value
string
The value of the editable in both edit and preview mode.
maxLength
number
The maximum number of characters allowed in the editable.
disabled
boolean
Whether the editable is disabled.
readOnly
boolean
Whether the editable is readonly.
required
boolean
Whether the editable is required.
onValueChange
(details: ValueChangeDetails) => void
The callback that is called when the editable's value is changed.
onValueRevert
(details: ValueChangeDetails) => void
The callback that is called when the esc key is pressed or the cancel button is clicked.
onValueCommit
(details: ValueChangeDetails) => void
The callback that is called when the editable's value is submitted.
onEditChange
(details: EditChangeDetails) => void
The callback that is called when the edit mode is changed.
placeholder
string | { edit: string; preview: string; }
The placeholder value to show when the `value` is empty.
translations
IntlTranslations
Specifies the localized strings that identifies the accessibility elements and their states.
finalFocusEl
() => HTMLElement
The element that should receive focus when the editable is closed. By default, it will focus on the trigger element.
dir
"ltr" | "rtl"
The document's text/writing direction.
id
string
The unique identifier of the machine.
getRootNode
() => Node | ShadowRoot | Document
A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.
onPointerDownOutside
(event: PointerDownOutsideEvent) => void
Function called when the pointer is pressed down outside the component.
onFocusOutside
(event: FocusOutsideEvent) => void
Function called when the focus is moved outside the component.
onInteractOutside
(event: InteractOutsideEvent) => void
Function called when an interaction happens outside the component.

Machine API

The edit api exposes the following methods:

editing
boolean
Whether the editable is in edit mode
empty
boolean
Whether the editable value is empty
value
string
The current value of the editable
valueText
string
The current value of the editable, or the placeholder if the value is empty
setValue
(value: string) => void
Function to set the value of the editable
clearValue
() => void
Function to clear the value of the editable
edit
() => void
Function to enter edit mode
cancel
() => void
Function to exit edit mode, and discard any changes
submit
() => void
Function to exit edit mode, and submit any changes

Data Attributes

Area

name
desc
data-scope
editable
data-part
area
data-focus
Present when focused
data-disabled
Present when disabled
data-placeholder-shown
Present when placeholder is shown

Label

name
desc
data-scope
editable
data-part
label
data-focus
Present when focused
data-invalid
Present when invalid

Input

name
desc
data-scope
editable
data-part
input
data-disabled
Present when disabled
data-readonly
Present when read-only
data-invalid
Present when invalid

Preview

name
desc
data-scope
editable
data-part
preview
data-placeholder-shown
Present when placeholder is shown
data-readonly
Present when read-only
data-disabled
Present when disabled
data-invalid
Present when invalid

Accessibility

Keyboard Interaction

name
desc
Enter
Saves the edited content and exits edit mode.
Escape
Discards the changes and exits edit mode.