contenteditable属性を指定した要素の外でクリックしてもフォーカスされる問題を解消する
デザインエンジニアのりょーたです。
FigmaでFigTodoというタスク管理用のプラグインを開発しています。
今回は、以前から発生していた、contenteditable
属性を指定した要素でないところをクリックしても、contenteditable
属性を指定した要素でfocus
イベントが発生する不具合を解消したため、その方法をご紹介します。
入力範囲外をクリックしても編集モードになる
結論
contenteditable
属性を、focus
イベントが発生した場合にのみ有効にするように変更します。
const [isEditing, setIsEditing] = useState(false);
<div
- contentEditable
+ contentEditable={isEditing}
onBlur={() => setIsEditing(false)}
onFocus={() => setIsEditing(true)}
tabIndex={0}
>
{text}
</div>
色々試してみたところ、contentEditable
属性が有効な場合に親要素のfocus
イベントが一番近い要素に継承されているのかな、と思います。(正確な答えではないため、リソースを見つけられた方はコメントいただけますと幸いです)
contenteditable属性を指定していない要素をクリックしてもフォーカスが継承されない
おまけ
contenteditable
属性は便利ですが、アクセシビリティの観点からは、適切なWAI-ARIA属性を追加した方が良いです!
以下は、先ほどのコードを改善した例です。
<div
contentEditable={isEditing}
onBlur={() => setIsEditing(false)}
onFocus={() => setIsEditing(true)}
tabIndex={0}
+ role={isEditing ? 'textbox' : undefined}
+ aria-multiline={isEditing ? true : undefined}
>
{text}
</div>
textbox
ロールは、自由形式テキストの入力ができる要素を識別するために使用されます。
このケースでは、isEditing
がtrue
のときにtextbox
を設定し、false
のときにundefined
を設定して属性を削除します。
aria-multiline="true"
が設定されている場合、支援技術はテキストボックスが複数行入力に対応していることをユーザーに知らせます。
このケースでは、isEditing
がtrue
のときにtrue
を設定しfalse
のときにundefined
を設定して属性を削除します。
これにより、contenteditable
属性が動的に切り替わる際に、適切なWAI-ARIA属性も一緒に設定され、アクセシビリティが向上します。
参照
以上です😊
Discussion