テキスト・コード・リッチコンテンツを編集するためのUIパターン。ツールバー・スラッシュコマンド・コマンドパレット・インラインツールチップ・Markdownショートカット・コードブロックを組み合わせた複合UIで、Notion・Confluence・Linear・VS Code・Zennなど幅広いプロダクトで使われる。プレーンテキストから本格的なWYSIWYGリッチエディターまで、複雑さの幅が非常に大きいパターン。
この記事を読むと、ツールバー vs スラッシュコマンドの使い分け・インライン選択ツールチップ・コードブロックのシンタックスハイライト・エディタートップレベルのキーボードショートカット・Markdownの自動変換・フォーカスモードの設計が自分でできるようになります。
1. UI例(Preview / Live)
2. 定義(Definition)
テキストコンテンツを作成・編集するためのUIパターン群。入力手段の複雑さによって3段階に分類される:
| レベル | 説明 | 例 |
|---|---|---|
| プレーンテキスト | <textarea> のみ | コメント欄・短い入力 |
| Markdownエディター | 記法で装飾、プレビュー可 | Zenn・GitHub Issues |
| WYSIWYGエディター | 見たまま編集(ツールバー付き) | Notion・Word Online |
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- 長文コンテンツの作成:ブログ記事・ドキュメント・仕様書
- コラボレーション文書:Confluenceページ・Google Docsのような共同編集
- コード入力が必要な場面:技術ドキュメント・READMEの編集
- ノートアプリ・ナレッジベース:Notion・Obsidianのようなパーソナルドキュメント
3.2 When NOT to use
- 短い入力(1〜2行):
<input type="text">または<textarea rows="2">で十分 - 定型フォーム:フォームフィールドで構造化できるデータ(名前・住所など)
4. 設計判断の核(Decision Principles)
Editor Patternsの核は「複数の入力手段の並存」——ツールバー(マウス派)・Markdownショートカット(キーボード派)・スラッシュコマンド(Notion派)の3つを同時に提供することで、ユーザーのスキルレベルや好みに合わせた入力体験を実現する。1つの手段しか提供しないと、その手段に慣れていないユーザーを排除してしまう。
判断の優先順位:① 複数入力手段の提供 → ② フォーカスモード(ステータスバー・ショートカットヒント)→ ③ 自動保存の状態表示 → ④ キーボードショートカット
- ツールバーはアイコン +
title属性でホバー時にラベルを表示する:アイコンだけでは機能が分からないことが多い(特に見慣れないユーザー)。title属性または Tooltip で「太字 (Cmd+B)」のようにショートカット込みで表示することで、使いながら覚えてもらえる /コマンド(スラッシュコマンド)は行頭の/入力で起動するコマンドパレット:Notion・Linearで普及したパターン。/+ キーワードで見出し・リスト・コードブロックなどのブロックタイプを挿入できる。キーボード派のパワーユーザーに特に好まれる- 自動保存の状態を常にステータスバーに表示する:「保存中…」「✓ 保存済み」「⚠ 保存に失敗しました(再試行)」の3状態をエディター下部のステータスバーに表示する。ユーザーが保存ボタンを押す必要なく、常に保存状態が分かる
- Tabキーのデフォルト動作を変更したらスクリーンリーダーユーザーに通知する:コードエディターでTabキーをインデントに使う場合、Tabで次のフォーカス可能要素に移動できなくなる。
Escapeキーを押すとTabがデフォルト動作(フォーカス移動)に戻る旨を案内する
5. 状態設計(States)
| 状態 | エディター | ステータスバー |
|---|---|---|
| フォーカスなし | 通常表示 | ショートカットヒント |
| フォーカス中 | フォーカスリング | 「編集中」表示 |
| 入力中(未保存) | — | 「未保存」または「保存中…」 |
| 自動保存完了 | — | 「✓ 保存済み」 |
| 保存失敗 | — | 「⚠ 保存に失敗しました(再試行)」 |
| 文字制限超過 | 入力制限 or 赤ボーダー | 文字数カウンター(赤) |
6. バリエーション設計(Variants)
| バリアント | 特徴 | 使用例 |
|---|---|---|
| Markdownエディター | テキスト記法・プレビュー分割 | Zenn・GitHub・Qiita |
| WYSIWYGエディター | ツールバー・見たまま編集 | Notion・Confluence |
| コードエディター | シンタックスハイライト・言語選択 | VS Code・CodePen |
| インラインエディター | クリックでその場編集 | Notion の各ブロック |
| ミニマルエディター | ツールバーなし・フォーカスモード | 執筆アプリ・日記 |
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- ツールバーのアイコンに
titleがなく機能が分からない:「B」「I」ボタンが何の操作をするか分からず、マウスを合わせても説明が出ない - 自動保存の状態が分からない:ユーザーが「保存されたか?」と不安になり、意図的に保存操作を繰り返す
- Tabキーがインデントになりキーボードでフォーカスが抜けられない:テキストエリアでTabを押すとインデントが入り、エディターから外にTabで移動できなくなる
7.1 Bad(典型3つ)
- ツールバーボタンに
aria-labelもtitleもなく、アイコンの意味がアクセシビリティ的に無名 - コンテンツの変更を
localStorageに保存しているが、「保存済み」インジケーターがなく保存されているか分からない onKeyDownで全Tabをインデントに横取りし、スクリーンリーダーユーザーがエディターから出られなくなる
7.2 Good(対になる3つ)
- 各ツールバーボタンに
aria-label="太字 (Cmd+B)"とtitle="太字 (Cmd+B)"を設定する useEffectで内容が変わるたびにdebounce付きの保存処理を走らせ、ステータスバーに「保存中…」→「✓ 保存済み」を表示するEscapeキーでTabの動作をデフォルト(フォーカス移動)に戻し、「Tab = インデント / Escape で離脱」をUI上にヒント表示する
7.3 How to fix(手順)
- 全ツールバーボタンに
aria-label+title(ショートカット込み)を追加する useDebouncedCallbackで自動保存を実装し、ステータスバーに保存状態を表示する- Tabキーの動作を切り替え可能にし、Escape での離脱案内をツールチップやステータスバーで示す
- 分割プレビューモードの追加で、MarkdownとHTMLの両方を確認できるようにする
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Screen Reader / Keyboard
<!-- ツールバー -->
<div role="toolbar" aria-label="テキスト書式設定">
<button aria-label="太字 (Cmd+B)" aria-pressed="false">B</button>
<button aria-label="イタリック (Cmd+I)" aria-pressed="false">I</button>
<button aria-label="見出し1">H1</button>
</div>
<!-- エディター本体 -->
<textarea
aria-label="記事の本文"
aria-describedby="editor-hint"
/>
<p id="editor-hint">
Tab でインデント。Escape を押すとタブキーでフォーカスを移動できます。
</p>
<!-- ステータスバー -->
<div role="status" aria-live="polite">
✓ 保存済み
</div>
10. 実装メモ(Implementation Notes)
- リッチテキストエディターのライブラリ選定:
Tiptap(ProseMirsor ベース):拡張性が高くコラボレーション機能(Yjs)も対応。Notion風のエディターを作るなら第一候補Slate.js:完全カスタマイズ可能だが低レベルAPIのため設計コストが高いQuill:シンプルなWYSIWYGが必要な場合に適した老舗ライブラリCodeMirror 6/Monaco Editor:コードエディターに特化
- 自動保存の実装:
useDebouncedCallback(saveContent, 1000)で入力後1秒の無操作で自動保存。beforeunloadイベントで未保存のまま閉じるのを防ぐ警告を出す - スラッシュコマンドの実装:
onInputで現在行が/で始まるか検出し、/以降のテキストでコマンドリストをフィルタリングするポップオーバーを表示する。Tiptap では@tiptap/suggestion拡張として実装できる - コラボレーション(共同編集):Tiptap + Yjs +
y-websocketで複数ユーザーのリアルタイム共同編集(CRDT)を実装できる。各ユーザーのカーソル位置も共有可能
11. 関連リンク
- 関連するUIデザイン原則: フィードバック (Feedback), システム状態の可視性 (Visibility of System Status)
- 用語集(定義): アクセシビリティ
- 関連するUIコンポーネント(横): Command Palette(コマンドパレット), Floating Panel(フローティングパネル), Scroll Area(スクロールエリア), Tooltip(ツールチップ), AI Chat UI(AIチャットUI)
12. まとめ
Editor Patternsの設計で最重要なのは「複数の入力手段の並存」と「自動保存状態の常時表示」です。ツールバー・Markdownショートカット・スラッシュコマンドの3つを同時に提供することで、マウス派・キーボード派・パワーユーザーのすべてをカバーできます。Tabキーをインデントに使う場合のアクセシビリティ対策(Escape による離脱手段の案内)は特に見落としやすいポイントです。プロダクションレベルの実装では Tiptap を起点にすることを強く推奨します。