@substrate-system/editable-field
v0.0.1
Published
Input with edit button
Maintainers
Readme
Editable Field
editable-field is a tiny Web Component that wraps a disabled <input>
together with a pencil/save/cancel button set. The pencil button enables
editing, and the save/cancel controls are revealed once the field is in
edit mode. It keeps the host attributes (name, value, disabled) in
sync with the internal input and emits lifecycle events that bubble up to
any listener, including handlers that watch for namespaced event names.
See a live demo and
check the example/ folder for a hands-on playbook.
Install
Install via npm, yarn, or pnpm and the package will register the
<editable-field> custom element globally.
npm i -S @substrate-system/editable-fieldQuick start
Import the element and its styles into your bundle entry. The JS import
touches customElements.define so the tag is ready to use; the CSS import
brings the default gap, outline, and button styles.
import '@substrate-system/editable-field'
import '@substrate-system/editable-field/css'Now use <editable-field> in your markup.
API
Attributes
name(string, default'') Mirrors the attribute to the inner<input>'snameandidviahandleChange_name, so the field can participate in form submission.value(string, default'') Syncs to the inputvalue. Updating the host attribute when the field is idle updates what appears when the next edit session starts.disabled(any truthy value, defaulttrue) Keeps the input disabled and addsaria-disabled="true". Remove the attribute (or set it to'false') to re-enable typing. Example: `<editable-field name="email" value="[email protected]" disabled`
Events
edit- Origin: host element via
this.emit('edit')/this.dispatch('edit') - Bubbles: yes
- Notes: Fires when the pencil button enables editing.
The event is also available as
editable-field:editthroughfield.on('edit', handler).
- Origin: host element via
save- Origin: internal
<input> - Bubbles: yes
- Notes: Fired when the save button is clicked. Because the event
originates from the
<input>,event.target.valuegives the new value. A namespacededitable-field:saveis emitted viafield.on('save', …)as shown inexample/index.ts.
- Origin: internal
cancel- Origin: host element (
this.emit('cancel'),this.dispatch('cancel')) - Bubbles: yes
- Notes: Triggered by the cancel button. The component resets the cached
_originalValuebefore the event bubbles.
- Origin: host element (
The example/index.ts file also shows how to log the events, inspect their
type, and listen for the wildcard field.addEventListener('*', handler)
that surfaces every emitted event.
Usage
See `./example/index.ts.
JavaScript
import { type EditableField } from '@substrate-system/editable-field'
const field = document.querySelector<EditableField>('editable-field')
field?.addEventListener('save', ev => {
const input = ev.target
console.log('saved value:', input.value)
})
field?.on('save', ev => {
console.log('namespaced event:', ev.type)
})HTML
The component consumes the same attributes as the native <input>:
<form>
<label for="email">Email</label>
<editable-field
id="email"
name="email"
value="[email protected]"
></editable-field>
</form>When placed inside a form, the name attribute flows through to the inner
input so form serialization (via FormData) works without extra wiring.
CSS
The package ships with default styles:
import '@substrate-system/editable-field/css'
// or for the minified output:
import '@substrate-system/editable-field/min/css'Include these imports once in your CSS/JS entry point before you render the elements so the buttons and outlines behave as shipped.
CSS variables
--editable-field-gap(0.5rem): Gap between the input and the button trio.--pencil-button-color(currentcolor): Stroke color for the pencil icon.--pencil-button-size(1.5rem): Width/height of the pencil icon.--save-button-color(currentcolor): Stroke color for the save checkmark.--save-button-size(1.5rem): Width/height of the save icon.--x-button-color(currentcolor): Stroke color for the cancel "x".--x-button-size(1.5rem): Width/height of the cancel icon.
Override any of these variables on the host to restyle the buttons or the spacing without touching the component internals.
editable-field {
--editable-field-gap: 1rem;
--save-button-color: #0b99ff;
--x-button-color: #e66;
}Pre-built files
If you prefer a drop-in script, copy the bundled JS/CSS from dist/ into
your public folder.
cp ./node_modules/@substrate-system/editable-field/dist/index.min.js ./public/editable-field.min.js
cp ./node_modules/@substrate-system/editable-field/dist/style.min.css ./public/editable-field.css<head>
<link rel="stylesheet" href="./editable-field.css">
</head>
<body>
<script type="module" src="./editable-field.min.js"></script>
</body>Notes
- The component keeps
aria-disabled="true"on the host until the pencil button is clicked;input.focus()runs as soon as editing starts. - Save/cancel buttons are hidden by default and shown via the
.editingclass when editing is active. The pencil button is hidden while in edit mode. - The cancel flow restores the cached
_originalValuebefore it emitscancel. - To inspect live logging, set
localStorage.DEBUGtoeditable-fieldand runexample/index.tsduring development.
