🐦

LPやWeb製作を高速化するUIコンポーネント集を作った

2022/09/14に公開約6,400字

リンク

https://camome.net

https://preview.camome.net/templates/design-agency

コンポーネントの例

call to action

料金プラン

最新のブログ記事

概要とモチベーション

Camome UIはひとことで言うと「抽象度の高いUIコンポーネント集」です。

BootstrapやMUIなどのフレームワーク・ライブラリの類とは異なり、網羅的・汎用的なパーツを提供することが目的ではありません。つまり ButtonInput や、もう少しハイレベルな Navbar などを高いカスタマイズ性とともに提供するつもりはありません。

それよりも「LPのこの部分にコピペすればサクッと決まる」ような体験を重視しています。UIデザインといっても、多くの場合はそれほど変わったものが求められるわけではなく、使い回せるものが大半だと思います。

要するに「デザインの常套句」みたいなものが存在するわけです。Camome UIはそういう「よくある」デザインをたくさん収録することを目的としています。

プログラミングは得意でもデザインに回す余力がない人などに使ってもらえたらなと思います。

特徴

シンプルで使いやすいデザイン

当たり前ですが、あまり特徴的な見た目だと用途が狭くなるので、できるだけシンプルにしてあります。また、あまりカッコつけすぎず、古臭すぎないちょうどいいポイントを狙っています。

フレームワーク依存なし

生のHTML + CSSで提供しており、他のライブラリやバンドラーなどには依存していません。

ただ開発もHTMLとCSSの生打ちだとツラすぎるので、ReactとCSS Modulesでコンポジションを行い、Next.jsで静的アセットとして出力しています。(後述)

JavaScriptなし

今後変わるかもしれませんが、現状はJavaScriptを使用していません。ただそこにポリシーがあるわけではなく、ReactコードからVanilla JSをいい感じに出力する方法がパッと思いつかないだけです・・・。

それよりはReactコンポーネントライブラリとして提供したほうが楽そうですが、CSS Modulesをいい感じにバンドルするのもまた面倒くさそうです・・・。

日本語でも違和感が少ない

大半のUIライブラリやテンプレートなどは欧米言語向けなので(Ant Designは中国語もサポートしている思いますが)、そのまま日本語を入力するとバランスが悪くなったりすることが多い気がします(例えば見出しがやたらとデカくなったりします)。

Camome UIは最初から日本語を前提に開発されているので、少なくとも開発者(僕)の意図と異なったバランスにはなりません。

使いかた

グローバルなCSSファイル(リセット、デザイントークンなどを含む)に加えて、任意のコンポーネントのHTML + CSSファイルをプロダクトに導入するだけの単純な構成です。

以下のサンプルコードのようにBEMのクラス名がつけられているので、コンポーネント間で干渉することはない(はず)です。

サンプルHTML
<section class="stats1">
  <div class="stats1__inner">
    <div class="stats1__heading">
      <h2>説得力のあるデータがあります</h2>
      <p class="stats1__heading__sub">
        それといっしょにまっすぐに歩いていたのでした。ほんとうに幸になるなら、どんなことでもそれがはっきりしませんでした。
      </p>
    </div>
    <dl class="stats1__dataList">
      <div class="stats1__dataList__item">
        <dt>顧客満足度</dt>
        <dd>98%</dd>
      </div>
      <div class="stats1__dataList__item">
        <dt>同業者比コスト</dt>
        <dd>-18%</dd>
      </div>
      <div class="stats1__dataList__item">
        <dt>取引実績</dt>
        <dd>120社</dd>
      </div>
    </dl>
  </div>
</section>
サンプルCSS
.stats1 {
  background-color: var(--camome-colors-accent-900);
  width: 100%;
}
.stats1__inner {
  width: 100%;
  max-width: var(--camome-screen-xl);
  margin: 0 auto;
  padding: var(--camome-space-16) var(--camome-space-4);
  display: grid;
  grid-gap: var(--camome-space-6);
  gap: var(--camome-space-6);
}
.stats1__heading {
  display: grid;
  grid-gap: var(--camome-space-3);
  gap: var(--camome-space-3);
  text-align: center;
}
.stats1__heading h2 {
  font-size: var(--camome-fontSizes-3xl);
  font-weight: var(--camome-fontWeights-bold);
  color: var(--camome-colors-white);
}
.stats1__heading__sub {
  color: var(--camome-colors-gray-300);
}
.stats1__dataList {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: var(--camome-space-8);
  gap: var(--camome-space-8);
}
.stats1__dataList__item {
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
  justify-content: center;
  gap: var(--camome-space-0);
}
.stats1__dataList__item dd {
  font-size: var(--camome-fontSizes-6xl);
  font-weight: var(--camome-fontWeights-bold);
  color: var(--camome-colors-white);
}
@media screen and (max-width: 768px) {
  .stats1__dataList__item dd {
    font-size: var(--camome-fontSizes-4xl);
  }
}
@media screen and (max-width: 576px) {
  .stats1__dataList__item dd {
    font-size: var(--camome-fontSizes-6xl);
  }
}
.stats1__dataList__item dt {
  font-size: var(--camome-fontSizes-lg);
  color: var(--camome-colors-gray-300);
}
@media screen and (max-width: 768px) {
  .stats1__dataList__item dt {
    font-size: var(--camome-fontSizes-md);
  }
}
@media screen and (max-width: 576px) {
  .stats1__dataList__item dt {
    font-size: var(--camome-fontSizes-lg);
  }
  .stats1__dataList {
    grid-template-columns: repeat(1, 1fr);
  }
}

Web標準しか使用していないため、ReactなどのJSフレームワークに導入することもそれほど面倒ではないと思います。

https://camome.net/docs/guides/usage

詳細は上記のドキュメントを参照してください。

どうやって開発したか

Camome UIの特徴を紹介してきましたが、ここからはどうやってこのコンポーネント集を開発しているかを説明します。

Next.js + CSS Modules --> HTML + CSSを生成

HTMLとCSSを生で書き続けるのは大変です。例えば Button はいろんなコンポーネントで使い回されているので、少しの変更でも影響する全ファイルを書き直す必要があります。

Camome UIではReactをCSS Modulesでスタイリングすることでそういった煩雑さを解消しています。

CSS Modulesによるスコープの付与

css-loader の設定によって、クラス名の頭にコンポーネントのファイル名を付加することで、HTML + CSSに書き出した際にもコンポーネントごとにスコープを閉じることができます。

Card.scss
.container {
  padding: 2rem;
}
.heading {
  font-weight: bold;
}

/* ファイル名のprefixでスコープが閉じられる
  <div class="Card__container">
    <h2 class="Card__heading">見出し</h2>
  </div>
*/

Next.jsによる静的レンダリング

公開するコンポーネントはNext.jsの pages/ ディレクトリに配置しています。

これによって next export コマンドで静的アセット(HTML + CSS + JS)としてレンダリングされるので、あとは各ページのHTMLファイルから参照しているCSSファイルを収集するだけです。HTMLから余計な head 要素などもクレンジングする必要もあります。

こういった作業にはjsdomを使いました。また、書き出されたHTMLは微妙に崩れているので、PrettierのJS APIでフォーマットしてあります。

プレビュー

Next.jsのページに置いてあるコンポーネントは、当たり前ですが本来の目的どおりWebページとして閲覧できます。

これをドキュメント内のプレビュー画面としても利用しています。 preview.camome.net というサブドメイン上で配信しており、 camome.net のドキュメントに iframe で埋め込んであります。

ドキュメントのプレビュー

ドキュメント

ドキュメント(ドキュメンテーションズ?)はDocusaurusを使っています。

UIコンポーネント集としてはもっと良い表示方法があるとは思うし、カスタマイズするならDocusaurusじゃなくても良い気もしますが、少なくともここまで作成するのはかなり楽でした。より文字情報主体のdocsを構築するなら文句なくオススメだと思います。

HTMLとCSSコードを含む各コンポーネントのページは、Next.jsで静的に出力されたソースを元に自動生成しています。つまりMarkdownファイルはgitに含まれておらず、ビルド時に毎回生成されます。

pnpm Workspaceによるモノリポ

  • Next.jsによる静的ファイル出力 + プレビュー
  • Docusaurusによるドキュメントサイト

この2つのアプリケーションは、pnpm Workspaceを利用したモノリポで管理しています。

以下のようなyamlファイルをプロジェクトルートに追加するだけでモノリポ化でき、いまのところはかなり快適な開発体験を得られています。

pnpm-workspace.yaml
packages:
  - apps/*

Vercelのモノリポ対応もかなり進んでいるようなので、基本的にはルートディレクトリを指定するだけで適切にビルドしてくれます。

まとめ

コンポーネントは今後も追加していく予定です。現在はLPで使えるパーツがメインですが、もっとWebアプリに使えそうなものも増やしていこうと思っています。

コンポーネントの追加などの情報はこちらのメーリングリストで配信予定です。

ドキュメントとデモサイトは以下のリンクから↓

https://camome.net

https://preview.camome.net/templates/design-agency
GitHubで編集を提案

Discussion

ログインするとコメントできます