2021年末最新バージョンの Riot.js で汎用的なボタンコンポーネントを作ってみる

2021/12/11に公開

一週間遅れですが、、、 2021年 Riot.js アドベントカレンダー の 5 日目の記事です!

よくある汎用的なボタンコンポーネントを作る。

とりあえず、最初に結論ですが、実際に作ったものがこちらです。

https://plnkr.co/edit/LFKRthkkfym6SZzM?preview

やりたかったこととしては

  • 見た目は一緒だが用途に合わせてマークアップを abutton を選べるボタンコンポーネント
  • Material Icons の任意のアイコンを表示することもできる

みたいな、自分が普段よく作る汎用的なボタンのようなものを効率的に作ることを Riot.js でやってみます。

見た目は一緒だけど、ものによって a だったり button だったりするボタンコンポーネント

ボタン的な見え方をするものって、役割によってマークアップを a にしたり button にしたいことがあります。
シンプルな見た目のボタンなら、CSS のための class の値だけはそのままにマークアップを変えるだけなので大した手間はないと思いますが、
ちょっと手の込んだデザインのボタンだと、内部にちょっと込み入った構造が必要だったりすると、 Riot.js の場合、

<my-button>
  <a href="" if="{props.tagName === 'a'}">
    <!-- 中略:ボタンデザインのためのいろんな要素 -->
  </a>
  <button if="{props.tagName === 'button'}">
    <!-- 中略:ボタンデザインのためのいろんな要素(上記の a タグの中身とほぼ一緒) -->
  </button>
</my-button>

みたいな感じで、ほぼ同じ内部の構造を2ヶ所に書かなくてはならなくてあまり効率的ではありません。

そこで、まず最初に a-or-button という、状況によって a になったり button になったりするだけのコンポーネントを作ります。

a-or-button.riot.html の中身

<a-or-button>
  <a
    if="{ props.dataHref }"
    href="{ props.dataHref }"
    class="{ props.dataClass }"
  >
    <slot />
  </a>
  <button if="{ !props.dataHref }" class="{ props.dataClass }">
    <slot />
  </button>
</a-or-button>

これは実際にはこんな感じで使います。

<a-or-button data-href="href属性に入れたい値" data-class="class属性に入れたい値"></a-or-button>

data-href があると a タグ、なければ button タグになります。

アイコンとテキストを持ったボタンコンポーネント

次に、上記の a-or-button タグを内包する、実際のボタンコンポーネントを作ってみます。
シンプルなボタンだとあんまり意味がないので、とりあえず、アイコンとテキストがボタンの中で並ぶようなものにしてみました。

ui-button.riot.html の中身

<ui-button>
  <a-or-button data-href="{props.dataHref}" data-class="c-button">
    <div class="o-layout o-layout--cross-axis-center">
      <div if="{ props.dataIcon }">
        <span class="material-icons c-button__icon">{props.dataIcon}</span>
      </div>
      <div><slot /></div>
    </div>
  </a-or-button>
</ui-button>

a-or-button コンポーネントのおかげで、内部の構造の記述を一つにまとめて、すっきり書けるようになりました。

CSS の説明は今回割愛しますが、コンポーネントとしてはこんな感じで使います。

<ui-button data-href="hrefに入れたい値" data-icon="アイコン名(Material Icons)">ボタン内のテキスト</ui-button>

なお、Riot.js の if 属性値を使って、 data-icon がなければアイコンは非表示になるようにしてあります。

まとめ

Riot.js はインブラウザコンパイルでも使えて、また覚えることがとても少なく、デザイナーのじぶんでも手軽にコンポーネントベースで制作ができるライブラリです。

以前に Riot.js に対する想いを記事にしてから、あっという間に半年も経ってることに愕然としてますが(時間経つの早すぎ…)
また少しでも Riot.js の情報が Web 上に増えてくれれば、という想いでアドベントカレンダー作成し、今回は少し実践的な内容を記事にしてみました。

デザイナー目線のアレンジ方法なので、もっとこうやればいいのに、みたいなことや、逆に「他のライブラリならこういう機能あるけど Riot.js だったらどうすんの?」みたいな疑問などあればぜひコメントください。
(幸か不幸かアドベントカレンダーまだまだスカスカなので、良いツッコミや質問いただけたら、他の日の記事のネタにさせていただく…かも😎)

ということで、ひとまずここまでお読みいただきありがとうございました。✊

Discussion