インライン編集
stimeo--editable
その場編集。クリック / F2 で編集、Enter で保存、Escape で取消。
stimeo--editable コントローラは、表示要素をその場で編集できるインラインエディタにする。表示要素を活性化(button の Enter/Space、または F2)すると編集モードに入り、入力へフォーカスして既存値を全選択する。Enter(複数行の textarea は Ctrl+Enter または macOS の ⌘+Enter)で保存し、Escape で取消す。どちらも表示要素へフォーカスを戻す。 submitOnBlur(既定)が真ならフォーカス喪失でも保存し、移動先のフォーカスを尊重する。保存時は表示テキストを更新し、値が実際に変化したときだけ stimeo--editable:change を { value, previous } 付きで発火する。取消時は stimeo--editable:cancel を発火する。見た目は data-mode をフックに利用側 CSS が担う。
キーボード操作
| キー | 動作 |
|---|---|
| Enter / Space / F2 | 表示要素から編集モードへ入る。 |
| Enter | 保存(単一行)。textarea では改行を挿入。 |
| Ctrl+Enter / ⌘+Enter | 複数行 textarea の編集を保存。 |
| Esc | 変更を破棄して表示モードへ戻す。 |
<%# Markup for the editable (inline editing) demo.
Click / Enter / F2 on the display element (a button) enters edit mode, focusing the
input and selecting all. The library handles mode switching (data-mode), focus /
select-all, and the commit event; the look lives in demo.css.
Two variants are shown:
1. Single-line <input>: Enter saves, Escape cancels.
2. Multiline <textarea>: Enter inserts a newline, Ctrl+Enter saves, Escape cancels.
submitOnBlur=true also saves on blur for both. %>
<div class="editable-demo">
<%# 1. Single-line inline edit. %>
<div class="editable" data-controller="stimeo--editable"
data-stimeo--editable-submit-on-blur-value="true">
<span class="editable__hint"><%= t("components.editable.demo.hint") %></span>
<button
type="button"
class="editable__display"
aria-label="<%= t("components.editable.demo.aria_label") %>"
data-stimeo--editable-target="display"
data-action="click->stimeo--editable#edit keydown->stimeo--editable#onDisplayKeydown">
<%= t("components.editable.demo.value") %>
</button>
<input
type="text"
class="editable__input"
hidden
aria-label="<%= t("components.editable.demo.aria_label") %>"
data-stimeo--editable-target="input"
data-action="keydown->stimeo--editable#onKeydown blur->stimeo--editable#onBlur" />
</div>
<%# 2. Multiline inline edit. The controller detects the <textarea> and treats Enter as a
newline, so saving is Ctrl+Enter (or blur). The display uses white-space: pre-line so
saved line breaks render. %>
<div class="editable" data-controller="stimeo--editable"
data-stimeo--editable-submit-on-blur-value="true">
<span class="editable__hint"><%= t("components.editable.demo.multiline.hint") %></span>
<button
type="button"
class="editable__display editable__display--multiline"
aria-label="<%= t("components.editable.demo.multiline.aria_label") %>"
data-stimeo--editable-target="display"
data-action="click->stimeo--editable#edit
keydown->stimeo--editable#onDisplayKeydown"><%= t(
"components.editable.demo.multiline.value"
) %></button>
<textarea
class="editable__input editable__input--multiline"
hidden
rows="3"
aria-label="<%= t("components.editable.demo.multiline.aria_label") %>"
data-stimeo--editable-target="input"
data-action="keydown->stimeo--editable#onKeydown blur->stimeo--editable#onBlur"></textarea>
</div>
</div>
/*
* Presentation-only styles for the editable demo.
* The library switches modes via data-mode and each element's hidden attribute.
* Here we give the display element an "editable-looking" appearance and style the
* input while editing.
*/
.editable-demo {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.editable {
display: inline-flex;
flex-direction: column;
gap: 0.35rem;
min-width: 16rem;
}
.editable__hint {
font-size: 0.8125rem;
color: var(--color-text-muted);
}
.editable__display {
text-align: left;
padding: 0.4rem 0.6rem;
border: 1px dashed transparent;
border-radius: 0.375rem;
background: transparent;
color: var(--fg, var(--color-text));
font: inherit;
font-weight: 600;
cursor: text;
}
.editable__display:hover {
border-color: var(--border-strong);
background: var(--surface-subtle);
}
/* Multiline display: render saved line breaks (textContent keeps the newlines). */
.editable__display--multiline {
white-space: pre-line;
}
.editable__input {
padding: 0.4rem 0.6rem;
border: 1px solid var(--accent, var(--color-primary));
border-radius: 0.375rem;
font: inherit;
color: var(--fg, var(--color-text));
}
.editable__input--multiline {
resize: vertical;
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。 共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--editable"
ターゲット
| 名前 | 説明 | 属性 |
|---|---|---|
display
必須
|
表示モードで見せる要素(通常はボタン)。起動すると編集モードに入る。 | data-stimeo--editable-target="display" |
input
必須
|
編集モードで表示し、編集中の値を保持する input または textarea。 | data-stimeo--editable-target="input" |
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
submitOnBlur
|
true(既定)のとき編集中のフォーカス喪失で保存し、false のとき編集を維持する。 | data-stimeo--editable-submit-on-blur-value |
アクション
| 名前 | 説明 | アクション |
|---|---|---|
edit
|
編集モードに入る。表示テキストを input に設定し、フォーカスして全選択する。 | stimeo--editable#edit |
onBlur
|
編集中の blur で、submitOnBlur が有効なら保存する。無効なら何もしない。 | stimeo--editable#onBlur |
onDisplayKeydown
|
表示要素での F2 を編集モードへの追加の起点として処理する。 | stimeo--editable#onDisplayKeydown |
onKeydown
|
編集中、Enter(複数行では Ctrl/Cmd+Enter)で確定し、Escape で取り消す。 | stimeo--editable#onKeydown |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
cancel
|
Escape で編集を取り消したときに発火し、変更を破棄する。 | stimeo--editable:cancel |
change
|
保存成功時、値が変化した場合のみ発火。detail に { value, previous } を載せる。 |
stimeo--editable:change |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
data-mode |
コントローラ要素 | "display" / "editing"。 |
hidden |
表示 / 入力 | 現在のモードで非アクティブな方に付与。 |