Editable
クリック(または表示切替)でテキストを「表示専用」から「編集可能」へ切り替える inline 編集部品です。preview/edit の 2 モードを anatomy 全体で切り替え、確定・キャンセルの 2 操作をトリガーとして提供します。
fandhe-frontend-headless-ui の editable mod が提供する構造・アクセシビリティ(WAI-ARIA・キーボード操作)・表示状態(data-*)のみを持つ unstyled 部品です。Themes 版が備える見た目は持たず、anatomy・data-* のみを提供します。CSS は利用者が当てます。
EditableInputFlags(disabled/readonly/required/invalid)を Root/Label/Area/Preview/Input へ共通で渡します。反映先はパートごとに異なり、Root は data-disabled/data-readonly のみ、Label は data-disabled/data-invalid/data-required、Area は data-disabled、Preview は data-disabled/data-readonly/data-invalid・aria-disabled="true"(disabled 時のみ)・aria-invalid="true"(invalid 時のみ)・tabindex="0"(!disabled && !readonly のときのみ)、Input はネイティブ disabled/readonly/required・data-disabled/data-readonly/data-required/data-invalid・aria-invalid="true"(invalid 時のみ)を出力します。data-focus(実行時のフォーカス状態)・data-autoresize(レイアウト計測)・aria-readonly(role なし span への付与が ARIA in HTML 上不正)は意図的に出力しません。
キーボード操作
| キー | 対象 | 効果 |
|---|---|---|
| Enter | Input(edit 中) | 確定して edit を抜ける(dispatch "submit"。submit_mode が enter/both のときのみ確定する想定) |
| Escape | Input(edit 中) | 取り消して edit を抜ける(dispatch "cancel") |
| Tab | Preview(activation_mode="focus") | tabindex="0"(!disabled && !readonly のときのみ)によりキーボードで到達できる |
| Space / Enter | EditTrigger / SubmitTrigger / CancelTrigger | ネイティブ <button type="button"> の標準操作 |
ポインタ・キーボード操作の実際の DOM 配線(fandhe-frontend-wasm-full)は本イシューのスコープ外です。本部品は SSR 静的マークアップと dispatch 契約のみを提供します。
スタイル済みの表示例は Editable を参照してください。
関連 API: fandhe-frontend-headless-ui API
自前 CSS の最小例
Themes 版を使わず本部品を直接使う場合、[data-scope="editable"][data-part="..."] セレクタでスタイルを当てます。以下は preview のテキストらしさ・フォーカスリング・placeholder 表現、input の invalid 状態、root の disabled 状態の最小例です。
[data-scope="editable"][data-part="preview"] {
cursor: text;
border-bottom: 1px dashed transparent;
}
[data-scope="editable"][data-part="preview"]:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
[data-scope="editable"][data-part="preview"][data-placeholder-shown] {
color: #9ca3af;
font-style: italic;
}
[data-scope="editable"][data-part="input"][data-invalid] {
border-color: #dc2626;
}
[data-scope="editable"][data-part="root"][data-disabled] {
opacity: 0.5;
}Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Features
- root/label/area/input/preview/control/edit_trigger/submit_trigger/cancel_trigger の anatomy を持ち、EditMode(Preview/Edit)で表示専用と編集可能を切り替える(editable.rs:163-180)。
- input(<input type="text">)は preview モード時に hidden、preview(<span>)は edit モード時に hidden を出力する(全パーツを DOM に掲載し hidden で切り替える方針、editable.rs:349-463)。
- edit_trigger/submit_trigger/cancel_trigger はいずれも <button type="button"> で、表示は現在モードに応じて hidden 切り替えされる(editable.rs:445-513)。
- activationMode/submitMode の実際の DOM 配線(focus/dblclick 起動・Enter/Escape/blur)は wasm-full 側の後続責務であり、本モジュールは data-activation-mode/data-submit-mode という SSR 静的ヒントのみを提供する(editable.rs module doc「スコープ外」節)。
- イシュー #1606 で ark-ui との参照突合を行い、EditableInputFlags(disabled/readonly/required/invalid)を root/label/area/preview/input へ共通で渡す設計へ揃え、label へ data-invalid/data-required、area へ data-disabled、preview へ data-disabled/data-readonly/data-invalid・aria-disabled/aria-invalid(該当時のみ)・tabindex="0"(!disabled && !readonly のときのみ)を追加した。activationMode に Click/None、submitMode に None を追加した。
- data-focus(area/label)・data-autoresize(input/preview)・aria-readonly(preview)は意図的に出力しない(data-focus は SSR 静的マークアップで表現できない実行時フォーカス状態、data-autoresize はレイアウト計測関心のため headless 層の対象外、aria-readonly は role なし span への付与が ARIA in HTML 上不正なため)。
Anatomy
root
label
area
preview
input
control
edit-trigger
submit-trigger
cancel-triggerAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root(mode, flags, activation_mode, submit_mode) | EditMode, EditableInputFlags, EditableActivationMode, EditableSubmitMode | — | 現在モードと、起動・確定方式の SSR 静的ヒント。flags のうち disabled/readonly のみ root へ反映する(editable.rs:248-269)。 |
label(mode, flags, input_id) | EditMode, EditableInputFlags, Option<&str> | — | input との for/id 関連付け。flags の disabled/invalid/required を data-disabled/data-invalid/data-required へ反映する(editable.rs:273-296)。 |
area(mode, flags, placeholder_shown) | EditMode, EditableInputFlags, bool | — | input/preview のラッパー。flags の disabled を data-disabled へ反映する(editable.rs:298-315)。 |
preview(mode, flags, placeholder_shown) | EditMode, EditableInputFlags, bool | — | flags の disabled/readonly/invalid を data-* へ、disabled/invalid を aria-disabled/aria-invalid(該当時のみ)へ反映し、!disabled && !readonly のとき tabindex="0" を付与する(editable.rs:405-441)。 |
input(mode, name, value, props, flags) | EditMode, &str, &str, EditableInputProps, EditableInputFlags | — | <input type="text"> の name/value と id/placeholder/maxlength・disabled/readonly/required・invalid(invalid 時のみ aria-invalid="true" を追加、editable.rs:349-403)。 |
EditableInputFlags { disabled, readonly, required, invalid } | bool ×4 | false ×4 | root/label/area/preview/input へ共通で渡すフラグ束。反映先パーツはパートごとに異なる(上記各行参照、editable.rs:317-346)。 |
edit_trigger(mode, disabled) / submit_trigger(mode, disabled) / cancel_trigger(mode, disabled) | EditMode, bool | — | 各トリガー(<button type="button">)の表示モード切り替えと無効化(editable.rs:445-513、同型の 3 関数のため 1 行に集約)。 |
attrs / children | Vec<(&str, &str)> / Vec<Node> | — | 各パーツ共通の追加属性・子ノード(代表 1 行に集約)。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
area | data-disabled | (値なし) |
area | data-placeholder-shown | (値なし) |
area | data-state | edit, preview |
cancel-trigger | data-disabled | (値なし) |
cancel-trigger | data-state | edit, preview |
control | data-state | edit, preview |
edit-trigger | data-disabled | (値なし) |
edit-trigger | data-state | edit, preview |
input | data-disabled | (値なし) |
input | data-invalid | (値なし) |
input | data-readonly | (値なし) |
input | data-required | (値なし) |
input | data-state | edit, preview |
label | data-disabled | (値なし) |
label | data-invalid | (値なし) |
label | data-required | (値なし) |
label | data-state | edit, preview |
preview | data-disabled | (値なし) |
preview | data-invalid | (値なし) |
preview | data-placeholder-shown | (値なし) |
preview | data-readonly | (値なし) |
preview | data-state | edit, preview |
root | data-activation-mode | focus |
root | data-disabled | (値なし) |
root | data-readonly | (値なし) |
root | data-state | edit, preview |
root | data-submit-mode | both |
submit-trigger | data-disabled | (値なし) |
submit-trigger | data-state | edit, preview |
Examples
Edit mode
maxlength 付きの edit モード(submit/cancel トリガー表示)の例です。
edit モード(maxlength="20" 付き)の Editable の組み立て例です。
自前 CSS の最小例
data-* 属性セレクタで見た目を組み立てる最小例です。
利用者が data-scope / data-part / data-state / data-invalid / data-disabled / data-placeholder-shown 属性セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません。
[data-scope="editable"][data-part="preview"] {
cursor: text;
border-bottom: 1px dashed transparent;
}
[data-scope="editable"][data-part="preview"]:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
[data-scope="editable"][data-part="preview"][data-placeholder-shown] {
color: #9ca3af;
font-style: italic;
}
[data-scope="editable"][data-part="input"][data-invalid] {
border-color: #dc2626;
}
[data-scope="editable"][data-part="root"][data-disabled] {
opacity: 0.5;
}
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Enter(edit 中の input) | dispatch("submit") に対応する。submit_mode が Enter/Both のときのみ確定して preview へ戻る想定(DOM 配線は wasm-full 側の後続責務、editable.rs module doc「キーボード操作」節参照)。 |
| Escape(edit 中の input) | dispatch("cancel") に対応する。activation_mode/submit_mode に関わらず常に取消可能(editable.rs module doc「キーボード操作」節参照)。 |
| Tab(preview、activation_mode="focus") | preview が tabindex="0"(!disabled && !readonly のときのみ付与)を持つため、キーボードで到達できる(editable.rs:405-441)。 |
| Space / Enter(各 trigger) | edit_trigger/submit_trigger/cancel_trigger は <button type="button"> のためネイティブの Space/Enter による活性化が働く(editable.rs:445-513)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-invalid="true"(input・preview) | flags.invalid が true のときのみ付与する(false 時は属性自体を省略、editable.rs:349-403, 405-441)。 |
| aria-disabled="true"(preview) | flags.disabled が true のときのみ付与する(input は代わりにネイティブ disabled 属性を使う、editable.rs:405-441)。 |
| for / id(label ↔ input) | label(mode, flags, input_id) の input_id と input(..., props) の props.id を同じ文字列にして関連付ける。 |
| tabindex="0"(preview) | !disabled && !readonly のときのみ付与する(Zag isInteractive と同義、editable.rs:405-441)。 |
| hidden(input・preview・edit_trigger・submit_trigger・cancel_trigger) | 現在モードに応じて排他表示する存在属性(preview モードで input が hidden、edit モードで preview が hidden、等)。 |
| aria-label 等の翻訳文言 | 利用者が attrs 経由で渡す方針(headless-ui は文言を持たない)。 |