Skip to content
fandhe-frontendcore v0.4.3
GitHub

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 上不正)は意図的に出力しません。

キーボード操作

キー対象効果
EnterInput(edit 中)確定して edit を抜ける(dispatch "submit"。submit_mode が enter/both のときのみ確定する想定)
EscapeInput(edit 中)取り消して edit を抜ける(dispatch "cancel")
TabPreview(activation_mode="focus")tabindex="0"(!disabled && !readonly のときのみ)によりキーボードで到達できる
Space / EnterEditTrigger / 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 状態の最小例です。

CSS
[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 自体はスタイルを持ちません。

Ada Lovelace
Locked value
Read-only value

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-trigger

API Reference

Arguments

NameTypeDefaultDescription
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 ×4false ×4root/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 / childrenVec<(&str, &str)> / Vec<Node>—各パーツ共通の追加属性・子ノード(代表 1 行に集約)。

Data Attributes

PartAttributeObserved Values
areadata-disabled(値なし)
areadata-placeholder-shown(値なし)
areadata-stateedit, preview
cancel-triggerdata-disabled(値なし)
cancel-triggerdata-stateedit, preview
controldata-stateedit, preview
edit-triggerdata-disabled(値なし)
edit-triggerdata-stateedit, preview
inputdata-disabled(値なし)
inputdata-invalid(値なし)
inputdata-readonly(値なし)
inputdata-required(値なし)
inputdata-stateedit, preview
labeldata-disabled(値なし)
labeldata-invalid(値なし)
labeldata-required(値なし)
labeldata-stateedit, preview
previewdata-disabled(値なし)
previewdata-invalid(値なし)
previewdata-placeholder-shown(値なし)
previewdata-readonly(値なし)
previewdata-stateedit, preview
rootdata-activation-modefocus
rootdata-disabled(値なし)
rootdata-readonly(値なし)
rootdata-stateedit, preview
rootdata-submit-modeboth
submit-triggerdata-disabled(値なし)
submit-triggerdata-stateedit, 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 自体はスタイルを持ちません。

Ada Lovelace
CSS
[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

KeyDescription
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

AttributeDescription
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 は文言を持たない)。