index.php
オウンドメディア『yaritori.jp』の「【最新版】ナレッジ共有ツール比較11選!導入メリットや選び方を徹底解説!」にて、DocBaseを紹介していただきました。
ナレッジの属人化防止や社内情報共有の促進にお役立てください。ぜひご覧ください。
https://yaritori.jp/work-efficiency/3972/
DocBaseがアガルートキャリア(弁護士・法務・管理部門専門の転職エージェント)のコラムで紹介されました。
運営元:領域特化型の転職エージェントを運営する株式会社ファンオブライフ
こんにちは、クレイの正岡です。
好きなモンスターはメタルスライムです、よろしくお願いします。
今回は、先日正式リリースしたDocBaseのリッチテキストエディターの開発プロセスについて喋ろうと思います。
DocBase独自のリッチテキストエディターを開発しました
DocBase独自のリッチテキストエディターとは?
既存のサービスにリッチテキストエディターを盛り込もうと思ったとき、まずは既存のOSSを探しますよね。既存のコードと要件を考慮した上で相性の良いライブラリは何なのか?と検討することと思います。
そう、普通は。
我々DocBase開発チームは違います。
僕たちはリッチテキストエディターを独自に開発することにしました。
この記事を書くにあたって、その理由を開発リーダーに改めて確認しました。
僕:どうして独自開発に踏み切ったんでしたっけ?かくかくしかじかでしたっけ?
リーダー:「やってみたかった」という理由だけで、合理的な理由はない。
僕:なるほど。
しかも僕たちが目標にしているリッチテキストエディターは、他のそれとは一味違います。
マークダウンを書きながら、同時にプレビュー側でも編集できるようにする。
という状態を目標にしました。
マークダウンでドキュメントを書くアプリには、マークダウンの結果をプレビューする機能があると思います。DocBaseでは、そのプレビューをリッチテキストエディターとしても使える状態を目指したのです。

プレビュー側で編集している動画
どうしてそんなことをするのか?
人によってはマークダウンによるメモの編集が難しくなってしまう状況があることが分かっていました。例えば、マークダウンでテーブルを編集したり、マークダウンの記号が多くなったメモを編集したりする場合です。マークダウンに対する慣れの問題も関係しますね。
なので、
・マークダウンを使えない人は、リッチテキストエディターで快適に編集してもらう
・マークダウンを使える人は、リッチテキストエディターの恩恵も受けてもらう
ということによって、圧倒的に使いやすいエディターを目指したのです。
さあ出発だ!目標は申し分なし、パーティメンバーは・・
さて、意気揚々と始まったリッチテキストエディター開発ですが、膨大なバグとの戦いの幕開けでもありました。
例えば、テキスト選択、カーソル移動、文字入力、改行はエディターの基本的な機能ですよね。そんな機能は楽勝に思えます。しかし、それらの基本的な機能にこそ非常に多くのバグとの戦いがありました。
さらに、リッチテキストエディターで使える新たな機能やリッチテキストエディター以外の機能の開発も進めなければなりません。
しかも、開発メンバーはたった4名。
ドラ⚪︎エじゃないんだから。
膨大なバグを相手にどうやって少ないメンバーで戦ったのか。
その 超画期的な 超泥臭いアジャイル手法を紹介しようと思います。

さあ出発だ
改善サイクルのブン回しと怠惰の美徳
改善サイクルの仕組み化
リッチテキストエディター開発プロジェクトが本格的に始まる前夜、先ほどの開発リーダーがリッチテキストエディター開発の基盤を作り上げました。
歓喜に湧く弊社。しかし、リーダーは冷静でした。
これから始まる戦いを予期していたのか、こんなテンプレートを作ってくれました。
WYSIWYG {不具合、要望}
<!-- ※タイトルをわかりやすいものに変更してください -->
## 概要
## 再現手順
## 期待する動作
## 対応可否
<!-- 議論した結果を記載する欄なので、最初は空欄で良いです -->
「リッチテキストエディターについてバグを見つけた場合や何か機能追加の要望を思いついたら、このテンプレートを使ってDocBaseでメモを作って共有してくれ」と。
基本的な使い方はほとんど見たままですが、
{不具合、要望}
に報告内容のタイトルを入力する概要
セクションには、動作環境やざっくりとした説明を書く再現手順
セクションには、操作手順を書く期待する動作
セクションには、どう動けば嬉しいのかを書く対応可否
セクションには、認識合わせの上、対応可能であればプロジェクト管理チケットのURLを書く。対応が不可能なら理由を書く
というものです。
このテンプレートが共有されてから、以下のようなサイクルが活発に回るようになりました。
バグの修正中に別のバグを発見するパターンも多かったです。
このサイクルによって共有されたメモの数は、テンプレートが共有された2023年1月31日から2024年5月28日までの間で約500件。
そして、昨年2023年のDocBaseのリリース回数は34回。
毎月およそ2.8回リリースできていたようです。
機能の追加やバグの修正をこまめにリリースできたのはこのサイクルのおかげですね。
基本であり重要な戦術
改善サイクルを頻繁に回すことも重要ですが、それ以前の基本的なことも重要でした。
先ほどのサイクルをより詳しく書くとこうなります。
詳しく説明します。
優先順位をつける
サイクルの「評価」にあたることですが、1つは優先順位をつけること。
バグ修正と一言でいっても、
- 重要なバグと、重要ではないバグ
- 緊急性が高いバグと、緊急性が低いバグ
など姿形が異なります。
また、当然バグ修正だけをやっていればいいわけではありません。バグを修正した上で、さらに便利な体験をしていただくための新機能を開発する必要があります。
そして、そこにも
- 必要な機能と、必要ではない機能
- 緊急性が高い機能と、緊急性が低い機能
があります。さらに、エディターの改善だけでなく他のDocBaseの機能についての改善も必要です。
それも限られたリソースの中で。
そのためには、タスクに優先順位をつけることが必須でした。やる価値が低そうなものや労力の割にリターンが少なそうなものは、優先順位を下げるかそもそもチケット化せずに後回しにしました。
ローマの哲人セネカもこう言っています。
ようするに、われわれは、なんの成果も得られない無駄な仕事をするべきではないし、得られる成果に見合わない仕事をするべきでもないのだ。
(「人生の短さについて 他二篇」光文社古典新訳文庫)

こいつは後回し
できるだけ最小限に
こちらも「評価」にあたることですが、できるだけ最小限に開発することも重要でした。
何か行動する際、人間どうしても「あれもこれも」と欲が出てしまいがちです。
例えば、僕は去年の4月から2ヶ月間国内を放浪しながら仕事をしていたのですが、各地の観光名所を「あれもこれも」と巡っているうちに疲れ果て、挙句に「やっぱ家が最高」となってしまいました。
開発についても同様です。「これもあった方が良さそう、あれもあった方が良さそう」と機能を付け加えているとタスクばかりが量産され、一生終わらないプロジェクトにだんだんと疲弊してしまいます。
そのため、本当に開発しなければならない機能を見極め、まずは最小限に抑えて開発することが重要でした。
セネカがなんと言っていたかもう忘れてしまった人に向けて、もう一度引用します。
ようするに、われわれは、なんの成果も得られない無駄な仕事をするべきではないし、得られる成果に見合わない仕事をするべきでもないのだ。

ボス戦の前にこうなるぞ
テストしよう
文字通り、サイクルの「テスト」にあたります。
当然ですが、機能追加やバグ修正のたびにテストを書いておくことも非常に重要でした。
テストを書く作業は、場合によっては正直非常に面倒で退屈です。
が、直したはずのバグが再発してしまわないためにはテストが必要です。
その退屈なテストコードは、将来ユーザーの皆様と開発メンバーの命を守ることでしょう。
ここでもう一度、セネカの言葉を思い出してください。
・・忘れた人へ。
ようするに、われわれは、なんの成果も得られない無駄な仕事をするべきではないし、得られる成果に見合わない仕事をするべきでもないのだ。

セーブは大事
終わりに
以上のようなプロセスでリッチテキストエディターの開発を進めてきました。
その中で「完成度がめきめき上がっていて、自社プロダクトも頑張らねばと思いながら使ってます。」という嬉しいフィードバックをいただくこともありました。
しかし、システムにバグはつきものです。
それに、今後もリッチテキストエディターの完成度を上げるだけでなく、編集体験の向上につながるような機能の追加や検索機能の改善などを予定しております。
引き続き、チーム一同がんばります。
この機会にぜひ、DocBaseのリッチテキストエディターを体験してみてください。
お読みいただいてありがとうございました。
マークダウン、皆さん使っているでしょうか。使っていますよね、GitHub(GFM)やSlack(一部記法)、個人的なメモアプリ等など、マークダウンを使えるサービスは多いので、使ったことがある人は多いんじゃないかと思います。
そして弊社のDocBaseというサービスは、マークダウンを使って情報共有をするサービスです。これも皆さん使っていますね?
この度は、そんなDocBaseのメモ編集画面で、ハイブリッドエディタなるものをリリースしました。これはDocBaseに存在したいくつもの不満、問題を解消してくれるもので、これが一体どういったもので、どうやって作られたのかを書いていきます。
ハイブリッドエディタとは??
「ハイブリッド」何やらガソリンと電気を使って動きそうな印象を受ける言葉ですが、もちろんそういった意味はありません。
次の動画を見てください。
左側がマークダウン、右側がHTMLのプレビューとなっています。よくあるマークダウンエディタに見えるかもしれません。
「うーん、ハイブリッドと言っても、普通じゃね?」と思ったそこのあなた!もう一度、よく見てみてください、右のプレビュー側をクリックして、直接クリックした位置の文章を編集していますよね。そしてその変更は左側のマークダウンに反映されています。
実は右側の表示はただのプレビューではなく、WYSIWYGエディターになっているんです。左側のテキストエディタがいつでも編集できる。さらに右側のWYSIWYGエディターも何時でも編集できる。これが「ハイブリッド」と名付けた所以です。
細かいことは置いておいて「ハイブリッド」って感じがしますよね。声に出したくなると思います。「ハイブリッド」「ハイブリッドエディタ」どうでしょうか?声に出しましたか?「俺は今日からハイブリッドエディタを使うぜ!」「俺、またなんかやっちゃいました?ただのハイブリッドエディタですけど」など、声に出して言ってみてください。かっこいいですよね。
DocBaseの従来の問題点
DocBaseの従来のエディタにはいくつかの問題点があり、それがUXの低下やサービスの質を低下させる原因になっていました。大まかには次のような問題点が上げられます。
CommonMarkに準規していない
マークダウンと言っても、それには統一的な仕様書が無かったです。そのために細かい動作は実装次第となっている部分があります。実際にDocBaseでも、GithubFlavoredMarkdown(GFM)というマークダウンの方言のパーサを使っており、しかもパーサ自体の開発、更新が終わっているバージョン古すぎるものを使っていました。
そして、そんな「マークダウンの仕様が無い状況を解決しよう」として策定されたCommonMarkという仕様があります。これが広く使われ出しており、これに従ってサービスを作ることによりCommonMarkに準規しているアプリやサービス間での情報のポータビリティが上がります。これはユーザにとっては非常に大きなメリットですよね。
けれども、DocBaseはCommonMarkには移行していませんでした。GFMに追加して差し込みメモ(#{}
を書くと他のメモを埋め込める機能)を使えるようにしたり、画像のマークダウン
を拡張して画像サイズ指定を可能にするなどの独自の拡張をしてしまっているために、単純にマークダウンパーサをCommonMarkパーサに変更すれば良いというものでは無かったのです。
ちょっとマークダウンの種類に関して整理しておきます。
- 従来のDocBase
- CommonMarkに準規する前のGFMに、差し込みメモや画像サイズ指定などの改造を加えた実装を使っていた
- 今後のDocBase
- CommonMarkに準規した後のGFMに、差し込みメモや画像サイズ指定などの改造を加えた実装を使うようにしたい
プレビューが遅い
従来の方法では、マークダウンをhttpでサーバに送り、サーバでマークダウンをパースしてからブラウザに返しているため通信の時間がかかりました。また、ブラウザからサーバにマークダウンを送信するタイミングは、サーバの負荷を考慮してユーザの入力が終わってから500ミリ秒経過後となっていました。そのため、ユーザが入力したマークダウンがHTML化され、それがブラウザ上で表示されるまでに数秒かかってしまっているのです。ユーザは、入力したマークダウンが想定した結果通りになるかどうかを確認するためには数秒待つ必要があるので、UXの低下を引き起こします。
マークダウンを学習する必要がある
そもそも、マークダウンを知らないと、サービスを使うことを躊躇してしまいます。マークダウンを知らないと使えないサービスというのは、サービスを使える人が限られてしまいます。これは情報共有サービスとしては致命的な問題です。情報共有サービスとしてはチームの誰もが、簡単に、情報を共有できるサービスである必要があります。
ハイブリッドエディタにむけて
これまでに上げたような問題を解決するためには何が必要なのかを考えました。
「CommonMarkに準規していない」この問題を解決する方法は単純で、パーサをCommonMarkにすることです。しかしそのパーサは、DocBaseの差し込みメモなどの独自実装に対応する必要があるため、パース部分がブラックボックスになっているようなパーサは使えません。AbstractSyntaxTree(AST)を組み立て、それに変更を加えることにより出力を柔軟に変更できる、そんなCommonMarkパーサのライブラリを探すことにしました。
次に、「プレビューが遅い」問題の解決方法を考えます。理想的にはユーザが入力した途端にプレビューが更新されて欲しいです。それにはサーバ側にパーサがあるのでは絶対にダメです。クライアント側にCommonMarkパーサがある必要があります。
最後に「マークダウンを学習する必要がある」の件。これを解決するには究極的には「マークダウンを書かなくても良いこと」です。つまりWYSIWYGエディタです。WYSIWYGエディタであれば、マークダウンの文法を知らなくても、UIによって見出しやリスト、装飾などを付けることもできれば完璧です。しかし、現在マークダウンエディタを気に入って使っているユーザはWYSIWYGは使いたくないかもしれません。それを両立する必要があります。
マークダウンとWYSIWYGを扱えるライブラリは、ProseMirrorやTOAST UI Editorなどが存在し、これらは、マークダウンとWYSIWYGを切り替えて使えます。
ただ、どうせなら切り替えるのではなく、同時に使いたいですよね!そう、ハイブリッドエディターとして最初に見せたように、プレビュー側を直接編集したいのです!それにはマークダウンのテキストエディタとWYSIWYGエディタを同時に扱える「ハイブリッドエディタ」を開発する必要があるのです!というわけで、WYSIWYGエディタをフルスクラッチで開発することにしました。
無謀だと思いましたか?
はい、そう思います。ちょっとチャレンジングで面白そうだったので開発を始めてみました。正直、開発初めて最初の1年ほどは、これを本当にリリースできる品質まで持って行けるのか不安でした。
パーサの選定
WYSIWYGエディタはフルスクラッチと言っても、CommonMarkパーサはさすがにライブラリを使います。独立した機能で、仕様もはっきりしていますからね。
パーサへの要件を整理しましょう。必要な要件はこのようになります。
- ASTを扱えるCommonMark+gfmパーサであること
- それはクライアント側で動作すること
クライアント側で動作するという要件があるので、JavaScriptを使うことが考えられます。そしてJavaScriptのCommonMarkパーサといえば、commonmark.jsですね。これはASTも取得でき、完全にCommonMark準規と、要件を満たしているように思えます。
ですが、DocBaseで投稿できるマークダウンは10万文字までという制約があります。はたしてcommonmark.jsは10万文字のパースという試練に耐えることができるのか・・・。10万文字規模のマークダウンをcommonmark.jsでパースしてみたところ、パースの度にブラウザがフリーズします。うーん、これでは文字入力の度にブラウザがフリーズしてしまいます。パーサの要件に「10万文字の文書を入力中にブラウザがフリーズしないこと」を追加しなければいけません。
このフリーズを解決するのにWASMを使うという案が上がりました。WASMで実行すれば非同期で処理されるので、パースに時間がかかったとしてもユーザの操作がフリーズすることは無くなります。WASMとして使えるマークダウンパーサを調査したところ、要件全てを満たしているであろうcomrakというRustのCommonMarkパーサが見つかったため、これをWASMとしてビルドして使用することにしました。
WYSIWYGどうする?
ここまでの話では、マークダウンパーサをCommonMark準規のものにしたというだけです。WYSIWYGエディタの話にはまだ入っていないですね。では、WYSIWYGエディタはどのように実装したら良いでしょうか。
ハイブリッドにするために、右側のプレビューのどこかを選択したらエディタのその位置を選択してほしい、逆に、左側のエディタのどこかを選択したら、プレビュー側のその位置を選択してほしいです。なので、マークダウン位置とHTML位置の双方向の対応付けが必要です。今回使用することにしたパーサのcomrakでは、--sourcepos
オプションを使うことにより、それぞれのHTMLタグにdata-sourcepos
という属性を埋め込んでくれる機能があります。
たとえば# heading
という文字列をパースした出力は<h1 data-sourcepos="1:1-1:9">heading</h1>
になります。これは、そのHTMLタグがマークダウンの何行目の何文字目から何行目の何文字目までに記載されたものなのかという情報が入っています。多少工夫が必要ですが、これでマークダウンとHTMLの対応付けをすることはできました。
空行の扱い
悩ましいのが空行の扱いです。実はCommonMarkは改行しただけでは成果物は改行されません。CommonMarkでは、その行の最後が2つ以上のスペース、もしくはバックスラッシュ\
で終わっている場合に改行タグが出力されるという仕様になっています。
それではさすがに使いにくいということで、GFMでは改行をしただけで改行タグが出力されます。便利ですね。ただそれは、2連続で改行をしたとしても、HTMLに改行タグが2つ入るわけではありません。1つになります。
これはWYSIWYGで編集するときに、非常に違和感を感じる原因になります。WYSIWYGを使っていて、改行を何度も入力しているにもかかわらず、改行が1回しか反映されないのはおかしいですよね?そのため、空行に改行を入れるように、パーサに渡す前のマークダウンに手を入れています。
その他諸々
ここまでくればそう悩ましい問題は少ないです。WYSIWYGに必要なこと、たとえば下記のようなことを使えるように実装していきます。
- 選択文字を太字にしたり色を付けたり装飾する機能
- UIによる画像のサイズ変更
- UIによるテーブル編集
- UIによるリストアイテムの並び変え
- 諸々・・
マークダウンエディタをハイブリッドにするために必要なこと
話をまとめます。DocBaseで言うハイブリッドエディタとは左側のテキストエディタの編集が即座に右側のプレビューに反映され、また逆に右側のプレビューを選択もできるし編集もできて、それが即座に左側のテキストエディタに反映されるものです。そしてそれを実現するために必要なことは
- ブラウザ上で高速にマークダウンをパースできるパーサ
- マークダウンとhtmlの位置の完全な対応付け
- そしてWYSIWYGを実装するための気合いと根性、時間とお金(2年かかった・・)
でした。このハイブリッドエディタはついにβ版ではなくなり、本リリースとなりました。さらなる進化をご期待ください。
クレイの asachun です。
ついに DocBase もダークテーマに対応しました!(長らくお待たせしました……!)
今回はデザイン・フロントエンドの観点から、どのようにダークテーマ対応を進めていったかご紹介します。
フロントエンド改修時にダークテーマ対応の話は出ていた
実はフロントエンド改修の段階でダークテーマ対応を検討し始めていました。ですが、フロントエンド改修が大きな作業のため、同時に進めることは避けていたのです。
ただフロントエンド改修の際に、ダークテーマ対応を見据えた仕組みも作っていただいていました。
他の作業の合間に少しずつダークテーマ対応を進め、この度リリースとなりました
デザインの段階でライト⇔ダークのカラーを定義
フロントエンド改修の際にデザインデータも Figma で作り直したのですが、そのときに汎用的なカラーはダークテーマ時のものも定義していました。
Figma でのダークテーマ制作の際には Dark mode swither プラグインに大変お世話になりました!
Color styles を定義するときに、Light/bg/base
のようにLight|Dark
を含めたスラッシュ区切りの名前にすると、プラグイン実行時に一発でダーク/ライトカラーを変換してくれます。
コンポーネント単位で実行すれば、Light
やDark
の含まれる複数の Cololr styels をいっぺんに変換できるので大変重宝しました。
(ときどき変換に失敗するときもあるのですが、1つ1つ切り替えるより断然楽です!)
あと Figma はコンポーネントを選択したら、子孫コンポーネントで使われてる色をすべて表示してくれるのがいいですよね。色の変更も簡単にできますし、この機能を考えた人は神だと思います。
テーマ切り替えの実装
テーマ切り替えの仕組みはパートナーのフロントエンドエンジニアの方に実装していただいたので、ブログ用の文章もご寄稿いただきました ありがとうございます!
(こちらのセクションはご寄稿いただいたものになります)
DocBase でのテーマ切り替えの実装には、styled-components がビルトイン機能として提供している ThemeProvider コンポーネントを使用しています。
フロントエンド改修のための技術選定の際(2020年頃)に、Sass から styled-components への移行を決定し、そのときにテーマ切り替えの仕組みも ThemeProvider
を使って導入しました。
この ThemeProvider
を使うと、前述のような汎用カラーの定義を元に、色の値だけが異なる同じ型のオブジェクトをテーマごとに用意することで(下記 lightTheme
と darkTheme
)、そのオブジェクトを切り替えるだけで簡単にテーマ管理ができるようになります。
const lightTheme = { /* ライトテーマの色指定 */ }
const darkTheme = { /* ダークテーマの色指定 */ }
const App = () => {
return (
<ThemeProvider theme={ theme === 'light' ? lightTheme : darkTheme }>
<FooComponent /> { /* ThemeProvider配下のコンポーネントがテーマ対応される */ }
</ThemeProvider>
)
}
コンポーネント固有のテーマ別の色指定
前述の ThemeProvider
を使った色(テーマ)の管理は、汎用カラーでどのコンポーネントからでも参照できるスコープになるので、いわばグローバル変数のような扱いになります。
ただ、実際のコンポーネント作成では、グローバル変数にする必要のないコンポーネント固有の色指定も存在し、その場合はグローバルスコープを避けてローカル変数のような扱いにしたいです。
そのような「色指定をコンポーネント内に閉じ込めたい」ケースでは、styled-components が提供している styled-theming というライブラリをベースに、DocBase 独自にカスタマイズした theming
関数を用意して対応しました。
const BarComponent = styled.div(() => {
// 独自関数themingを使って、コンポーネント内に閉じたテーマ別(light/dark)の色指定を行う
const colors = {
text: theming({
// そのコンポーネントでしか使用しない色をハードコーディング
light: '#f4f5f6',
dark: '#323233',
}),
bg: theming({
// 定義済みの汎用カラー(グローバル変数)を参照することも可能
light: c => c.blue_800,
dark: c => c.blue_100,
}),
}
return css`
color: ${colors.text};
background-color: ${colors.bg};
`
})
上記のように定義できる theming
関数を用意したことで、グローバルスコープの色指定が増え過ぎることを避け、そのコンポーネント内だけでテーマ別の色指定を完結できるようになりました。
また、TypeScript の型チェックやコード補完を利用することで、必ず light / dark の両方が色指定されていることを自動的にチェックできたり、定義済みの汎用カラーを補完候補から簡単に選べるようにもなりました。
現在の DocBase では、上述の ThemeProvider
コンポーネントと theming
関数の2種類を使い分けて、テーマの切り替えを実現しています。
よかったこと
先にライト・ダーク含めた汎用カラーを定義しておいたので、ダークテーマ対応が楽になった
フロントエンド改修の際に汎用カラーのライト・ダークテーマもある程度定義していました。
その際に、既存コンポーネントでもなるべく汎用カラーを使うよう修正し、新規コンポーネントも汎用カラーを使うようにしました。
(もちろん汎用カラーを使っていないコンポーネントもありますが)
このおかげで、ダークテーマ対応を始めたときには、汎用カラーを使ったコンポーネントはほとんど手を加える必要はありませんでした。
またなるべく汎用カラーを使うようにしたことで、デザインデータにありがちな「見た目はほとんど同じ色なのにカラーコードが違う」ミスをほぼ無くせました。
コンポーネントの色を決めるときはなるべく定義済みの Coloer styles を使用します
Storybook があった
フロントエンド改修の際に、主要なコンポーネントは Storybook に登録していました。
こちらのおかげで確認作業がだいぶ楽になりました……!
Color の変数を TypeScript オブジェクトにしたので候補から楽に選べる
「テーマ切り替えの実装」で書いていただいたように、Color の変数を TypeScript のオブジェクトとして定義しています。そのため、styled-components で利用する際に${theme.}
を打ち込んだだけで定義済みの変数がサジェストされるようになりました。
typo も防げますし、直感的に記述できるので、かなり開発体験もよくなったと思います!
大変だったこと
メモ本文の文字色を試行錯誤
DocBase には文字色を指定する機能があります。
選択した文字列を<span style="color:{{カラーコード}};"></span>
で囲むシンプルなものです。
それらの色は、ダークテーマに切り替えたときに著しく可読性が落ちるため、調整する必要がありました。
ダークテーマ時には文字色を反転→色相だけ戻す
こちらはエンジニアの方に「js で文字色を反転して、輝度を暗い背景に合わせたあと、色相だけ元に戻せばいいのでは?」とアイデアをいただきました。
白背景で可読性の高い文字色の輝度を反転させたら、そのまま暗い背景で見やすい輝度になるわけです。
実際には以下のように実装してもらいました。
- メモ本文内の
style
属性でcolor
が指定されているspan
要素を抽出 style
属性で指定されたcolor
の値を反転- 輝度の値が反転、色相が180度変わります
- 色相を再度180度回転させて元の色相に戻す
実装としてはPolished
ライブラリを使い、該当のカラーコードにcomplement(invert(${textColor}))
をかけています。
Polished とは、Sass の Mixins や functions を React でも使えるライブラリです。invert
は指定のカラーコードを反転した値、complement
は補色(いわゆる反対色)を返します。
そして After がこちら!
う〜〜〜〜ん! 緑とか紫は見やすくなったけどグレーとかピンクはまだ見づらい!
単純に反転+色相移動では足りないようです。
DocBase はテキストを読むサービスなので、文字と背景のコントラスト比4.5:1
は達成したいところです。
まずはライトテーマを微調整
そもそも、ライトテーマでもいくつかコントラスト比4.5:1
を達成していないものがあるので、合わせて調整しました。
(2番目のグレーは disable 状態など、読ませることを意識していない想定だったので対象外としています)
← Before After →
色の違いは少しわかりづらくなりましたが、見やすくなりました!
ピンクやオレンジ、黄色は明度を下げすぎると別の色になってしまうので、だいぶ調整に苦労しました。。
また、彩度が低いと反転したときに色の判別が難しくなるので、彩度を高めにしています。
ダークテーマの文字色調整
お次はダークテーマで文字色を反転したときの調整です。
complement(invert(${textColor}))
したときの色が全体的に暗く感じたので、Polished
ライブラリで使えるlighten
関数を追加しました。
lighten
は、指定した値に応じて明るくしたカラーコードを返してくれます。
値は0~1
の間で指定できるのですが、この調整もけっこう悩みました。。
明るくすればするほど可読性は上がるのですが、同時に白っぽくもなっていくため、色の判別がつきづらくなるデメリットがありました。
ひたすらブラウザ上で値の調整とリロードを繰り返し、最終的には以下の値になりました。
(この作業は丸1日ぐらいやっていた気がします……)
lighten(0.06, complement(invert(${textColor})))
そして実際の見え方はこちら!
全体的に見やすくなりましたね!
デザイナーも意外と泥臭い作業をしています。
終わりに
デザインの観点からダークテーマ対応について語ってみました。
個人的にはデザイン作業を Figma でやったことでかなり効率が上がったと思います。
ダークテーマについて、「ここが見づらい」などご意見があればお気軽にサポートまでご連絡ください!