MudBlazor にはファイル選択のコンポーネントはないっぽい
C# でシングルページ Web アプリケーション (いわゆる "SPA") を実装できる技術、Blazor に関する話題。
前回の投稿で、Blazor 用の Material Design な UI コンポーネントライブラリとして、"MudBlazor" を紹介しました。
MudBlazor を使えば、例えばユーザーのアバター画像ファイルを設定してもらう、といったようなページも、下図のようにそれなりにかっこよく作ることが容易になります。
しかし、上図でわかりますが、ファイル選択のコンポーネントは MudBlazor に用意がないようで、そのため、Blazor 標準の <InputFile/>
コンポーネント (DOM 上は素の <input type="file"/>
としてレンダリングされる) をそのまま配置するだけになっており、ちょっとイケてないです。
そこでもうちょっと頑張って自分で実装を加えることで、下図のようにしてみたいと思います。
※下記 URL で実際に動作するライブデモを公開しています。
基本コンセプトは簡単 ― <label/>
要素を使う
基本コンセプトは簡単です。
<InputFile/>
コンポーネントは非表示にしておき、代わりに、その <InputFile/>
コンポーネントにリンクする <label/>
要素を配置・表示しておく、というものです。
このためには、<InputFile/>
コンポーネントには id
属性を適切に設定しておき、続く <label/>
要素の for
属性にて、<InputFile/>
コンポーネントに設定した id 値を指定します。
<InputFile id="avatar-picture-inputfile" Style="display:none;" .../>
<Label for="avatar-picture-inputfile">
ファイル選択
</Label>
そうすることで、その <label/>
要素をクリックすると、表示上は見えなくなっている <input type="file"/>
要素をクリックしたのと同じ挙動になります。
こうすることで、<input type="file"/>
要素の見た目をいろいろいじるのは難しいところ、代わりに設けた <label/>
要素であれば、その見た目をいい感じにイジれるようになります。
見た目を Material Design な感じにする
ということで早速、"ファイル選択" label 要素を、MudBlazor 提供のボタンコントロールと同じ見た目にしてみます。
MudBlazor の設計・実装のおかげで、これは簡単です。
<label/>
要素に対し、MudBlazor 由来の CSS クラス名を設定するだけです。
今回のケースでは、配色は Primary
、外観は Filled
、サイズは中のボタンと同じにしたかったため、以下の CSS クラス名を <label/>
要素に適用しました。
- mud-button-root
- mud-button
- mud-button-filled
- mud-button-filled-primary
- mud-button-filled-size-medium
- mud-ripple
...
<Label ... class="mud-button-root mud-button mud-button-filled mud-button-filled-primary mud-button-filled-size-medium mud-ripple">
ファイル選択
</Label>
こうして CSS クラス名を指定するだけで、<label/>
要素の見た目が、まるっきり、MudBlazor のボタンコントロールと同じにできました。
クリックすると、ちゃんとリップル効果も再現されます。
入力フィールドっぽくしてみる
大抵の要件では、以上で完了と思います。
が、今回はもう少し踏み込んで、このファイル選択用のユーザーインターフェースを、MudBlazor 提供のテキスト入力コンポーネントっぽく拡張してみます。
具体的には以下の表示要素を付け加えます。
- 入力項目の名称を表示するキャプション
- 選択されたファイル名を表示する入力フィールド ("入力" はできないけど)
- ヘルプテキスト
入力項目の名称を表示するキャプション
MudBlazor の入力系コンポーネントに表示される入力項目名のキャプションと、同じ見た目のテキストを表示するには、MudBlazor の <MudText/>
コンポーネントが使えます。
この <MudText/>
コンポーネントの Typo
属性に、Typo.caption
を指定すれば OK です。
<MudText Typo="Typo.caption">
アバター画像ファイル
</MudText>
選択されたファイル名を表示する入力フィールド
これはファイル選択のコンポーネントなので、キーボードから何かテキストを入力するわけではありません。
代わりに、ぱっと見、テキスト入力コンポーネントっぽい見た目で、選択されたファイル名を表示するようにします。
ただのテキスト (選択されたファイルの名前) の表示ですから、先のファイル選択ボタンを <label/>
要素で実装したのと同じように、こちらも <label/>
要素で実現します。
外観の調整ではとりわけ、入力フィールドっぽさを醸し出す、灰色の下線の実装がキモです。
この下線の色の指定は、幸い、MudBlazor が配色情報を CSS 変数として実装していることから、自前の CSS スタイルシート中からも参照可能です。
具体的には、--mud-palette-lines-inputs
という CSS 変数名で、入力フィールドの下線の色を参照可能です。
なので、自前の要素で、入力フィールドっぽい下線を引くには、以下のような CSS スタイルを適用すれば OK です。
border-bottom: solid 1px var(--mud-palette-lines-inputs);
ヘルプテキスト
MudBlazor の入力系コンポーネントの下部に表示されるヘルプテキストと、同じ見た目のテキストを表示するには、任意の HTML 要素に対し、mud-input-helper-text
CSS クラスを適用すれば OK です。
<div class="mud-input-helper-text">
ファイルサイズは 512KB までです。
</div>
エラー表示も統合
以上まで実装すると、ファイル種類やサイズについての入力検証結果を、MudBlazor の他の入力フィールド系と同じように、ヘルプテキスト欄に検証エラーメッセージを表示するようにもできます (下図)。
なお、上図のような入力検証エラー表示にあたり、キャプションや下線、ヘルプテキストの色も変えていますが、この配色も、MudBlazor 由来の CSS 変数で参照・使用できます。
具体的には、CSS 変数 --mud-palette-error
を参照することでエラー系の色を参照できます。
まとめ
以上のように少々の手間をかけることで、MudBlazor の他のコンポーネントと並べても違和感のない、見た目 Material Design っていう感じの、ファイル選択のユーザーインターフェースが作れるようになります。
実際の作例全体のサンプルプログラムを、下記 GitHub リポジトリで公開しています。
素の <InputFile/>
コンポーネントを配置しているだけの状態から、順に変更を積んでいく様子を 1 コミットずつ残しています。
各コミット間の差分など参考になればと思います。
また、MudBlazor は配色情報を CSS 変数で定義・実装してくれています。
そのお陰で、MudBlazor のテーマシステムにより具体的な配色が変更・カスタマイズされても、今回紹介の実装は何も変更することなく、テーマ配色に追随するのもうれしいところです。
ただし、今回紹介のファイル選択ユーザーインターフェースには、大きな弱点・難点があります。
それは、キーボードから操作できないということです。
まず<label/>
要素にフォーカスがあたりません。
もっとも、この点については、tabindex="0"
などと、tabindex
属性を <label/>
要素に指定することでフォーカスがあたるようにはなります。
しかしその先、例えばキーボードのスペースキーの打鍵などでは、ファイル選択のダイアログが開くことがありません。
ここで詰んでしまいます。
この一点、キーボードからの操作ができなくなる点が許容できれば、Material Design なファイル選択のユーザーインターフェースを実現可能、ということになるでしょう。
以上、Learn, Practice, Share!