LoginSignup
10
2

More than 1 year has passed since last update.

Clarity Design System って知ってる?

Last updated at Posted at 2022-12-09

こんにちわ!TUNA-JPの運営メンバーをしている @hirosat です。
本記事は、「TUNA-JP Advent Calendar 2022」の9日目のエントリです。

TL;DR (この記事の要約)

ClarityをReactで実装する方法を教えちゃいます

Clarity Design System もOSSだよ

Clarity Design System を一言でいうと、VMwareっぽいUI/UXが作れちゃう、Frontend用デザインテンプレートです!
GitHub によると、以下の通り。

Clarity Design System
Clarity is an open source design system that brings together UX guidelines, design resources, and coding implementations with Web Components. This repository includes everything you need to build, customize, test, and deploy Clarity. For complete documentation, visit the Clarity website.

(日本語訳)
Clarity は、UX ガイドライン、デザイン リソース、および Web コンポーネントによるコーディング実装をまとめたオープン ソースのデザイン システムです。このリポジトリには、Clarity の構築、カスタマイズ、テスト、および配備に必要なすべてのものが含まれています。完全なドキュメントについては、Clarity の Web サイトを参照してください。

また、Clarityは以下の5つのnpmパッケージとして公開されています。(と書いてますが、どうみても4つです :sweat_smile:

  • @cds/core : あらゆるJavaScriptフレームワークで動作するWeb Componentsが含まれている
  • @cds/angular : Angular 環境で、@cds/core を使用するためのパッケージ
  • @cds/react : React 環境で、@cds/core を使用するためのパッケージ
  • @cds/city : オープンソースの sans-serif 書体

ふむふむ。Reactで使うには、@cds/core / @cds/react / @cds/city があれば、良さそうですね。
詳細は、Clarityドキュメント を見ろ。と言われるので、飛んでみると・・・

Screen Shot 2022-12-04 at 14.44.18.png

んん?「Angular componentsと連携して・・・」とか書いてあるぞ。。もしかして、Angular専用?!?!
このドキュメントを読み進めても、Angularに関する話しか書いてありません。

分かりづらいけど、Reactにも使えそう

いきなり座礁に乗りかけましたが、私、すごいことを発見しちゃいました!なんと、

ざっとGitHubや公式サイトを探しましたが、こちらの core.clarity.design の方は、どこからもリンクがないんです!
このサイトは、react clarity をググって、いくつか見ているうちに気がつきました。

恐らくは、下記のような状況かと思います。(誰か詳しい人がいたら教えて下さいw)

  • Clatiryのcoreコンポーネント自体は、汎用的に作られていている。
  • 正式にサポートされているのは、Angularだけ(?)

という訳で、Reactの使い方も載っている、https://core.clarity.design/ をベースに解説いたします。

Reactの準備

何はともあれ、とりあえずClarityを使うためのReactアプリケーションを用意しましょう。
こういう時は定番の、create-react-appで、サクッと作ってしまうことがオススメです。

% npx create-react-app clarity-react-sample
(インストール処理は省略)
% cd clarity-react-sample
% npm start

すると、以下のようなサイトが、localhost:3000 として立ち上がります

ブラウザにも書いてあるとおり、以後、src/App.js を編集すれば画面が動的に変わるはずなので、ここに、Clarityを仕込んでいこうと思います。始めから作ってみたい人は、いったんここで、gitにpushしておきましょう。

Clarityの準備

Developing のページに、始め方が書いています。

1. 必要なClarityモジュールをインストール

ドキュメントでは、@cds/core@cds/city だけを最初にインストールしていますが、後ほど @cds/react もインストールすることになるので、ここで一緒にインストールしてしまいましょう。

% npm install @cds/core @cds/city @cds/react --save
(インストールされます)
% git diff package.json
diff --git a/package.json b/package.json
index a813a5d..6287915 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,9 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "@cds/city": "^1.1.0",
+    "@cds/core": "^6.2.2",
+    "@cds/react": "^6.2.2",
     "@testing-library/jest-dom": "^5.16.5",
     "@testing-library/react": "^13.4.0",
     "@testing-library/user-event": "^13.5.0",

2. スタイルシートの設定

ドキュメントには、HTMLで直接CSSを指定する方法と、Sass/Lessでインポートする方法が記載されています。
今回は、HTMLに記載しようと思うので、public/index.html に記載します。

% git diff public/index.html
diff --git a/public/index.html b/public/index.html
index aa069f2..5dd3477 100644
--- a/public/index.html
+++ b/public/index.html
@@ -24,9 +24,12 @@
       work correctly both with client-side routing and a non-root public URL.
       Learn how to configure a non-root public URL by running `npm run build`.
     -->
+    <link href="/node_modules/modern-normalize.css/modern-normalize.css" rel="stylesheet" />
+    <link href="/node_modules/@cds/core/global.min.css" rel="stylesheet" />
+    <link href="/node_modules/@cds/city/css/bundles/default.min.css" rel="stylesheet" />
     <title>React App</title>
   </head>
-  <body>
+  <body cds-text="body">
     <noscript>You need to enable JavaScript to run this app.</noscript>
     <div id="root"></div>
     <!--

React開発

src/App.js を編集し、ブラウザ確認しながら進めていきましょう。
基本的には、Reactに関する説明 を読みながら進めるのですが、サンプルが非常に良くないです。
例えば、Classで書かれた例があるのですが、今は関数コンポーネントが主流だったりします。(参考
なので、私の方でアレンジを加えながら解説します。

1. Buttonの実装

基本的には、冒頭で使うモジュールをimportして、コンテンツ内で呼び出すば、UIが表示されます。
注意点として、@cds/reactでは、パスカルケース(単語ごとに1文字目を大文字)に変換されるため、
本来のClarity coreは<cds-button>要素なのですが、Reactで使う時には、<CdsAlert>となります。

% git diff src/App.js
diff --git a/src/App.js b/src/App.js
index 3784575..559cbc9 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,11 +1,13 @@
 import logo from './logo.svg';
 import './App.css';
+import { CdsButton } from '@cds/react/button';

 function App() {
   return (
     <div className="App">
       <header className="App-header">
         <img src={logo} className="App-logo" alt="logo" />
+        <CdsButton>My button</CdsButton>
         <p>
           Edit <code>src/App.js</code> and save to reload.
         </p>

上記のように編集すると、以下のように画面内にボタンが表示されるはずです。

2. ボタンに機能を実装

フックを導入のドキュメントを参考にして、
ボタンをクリックするたびに数字があがっていくようにしてみました。
このように、Clarityモジュールであっても、他のパーツと同じように機能が実装できます。
git diff ではなく、全文掲載いたします。

import { useState } from 'react';
import logo from './logo.svg';
import './App.css';
import { CdsButton } from '@cds/react/button';

function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <CdsButton onClick={() => setCount(count + 1)}>
          Click me
        </CdsButton>
        <p>You clicked {count} times.</p>
      </header>
    </div>
  );
}

export default App;

ブラウザ上で、ボタンをクリックして、動作確認してみましょう

3. 好きなパーツを利用する

Componentsのメニュー以下に、各パーツの説明があるので、好きなように置いてみましょう!
今回は以下のパーツを使用してみました。

  • CdsButton
  • CdsTag
  • CdsBadge
  • CdsAlert
  • CdsIcon

下記にサンプルを示しますが、CdsIconは使用の仕方が面倒でした。
一度、@cds/core/icon (パスは、node_modules/@cds/core/icon/index.js)から利用したいアイコン(サンプルだと、userIconbugIcon)を呼び出して、ClarityIcons.addIcons(userIcon);のように呼び出し直す必要がありそうでした。
なお、Icon一覧は以下のページから確認できます。

import { useState } from 'react';
import './App.css';
import { CdsButton } from '@cds/react/button';
import { CdsTag } from '@cds/react/tag';
import { CdsBadge } from '@cds/react/badge';
import { CdsAlert, CdsAlertGroup } from '@cds/react/alert';
import { CdsIcon } from '@cds/react/icon';
import { ClarityIcons, userIcon, bugIcon } from '@cds/core/icon';
ClarityIcons.addIcons(userIcon);
ClarityIcons.addIcons(bugIcon);

function App() {
  const [count, setCount] = useState(0);
  const [show, setShow] = useState(false);
  return (
    <div>
      <h1>Clarity React samples!</h1>
      <h2 cds-text="section">Buttons</h2>
      <section cds-layout="horizontal gap:sm">
        <CdsButton status="primary">primary</CdsButton>
        <CdsButton status="success">success</CdsButton>
        <CdsButton status="danger">danger</CdsButton>
        <CdsButton status="danger" disabled>disabled</CdsButton>
        標準ボタン
      </section>
      <section cds-layout="horizontal gap:sm">
        <CdsButton action="outline">outline</CdsButton>
        <CdsButton action="outline" status="success">success</CdsButton>
        <CdsButton action="outline" status="danger">danger</CdsButton>
        <CdsButton action="outline" disabled>disabled</CdsButton>
        フチのみボタン
      </section>
      <section cds-layout="horizontal gap:sm">
        <CdsButton action="flat">flat</CdsButton>
        <CdsButton action="flat" disabled>flat disabled</CdsButton>
        フラットボタン
      </section>
      <h2 cds-text="section">Tags & Badges</h2>
      <section cds-layout="horizontal gap:sm">
        <CdsTag readonly status="info">Info</CdsTag>
        <CdsTag readonly status="success">Success</CdsTag>
        <CdsTag readonly status="warning">Warning</CdsTag>
        <CdsTag readonly status="danger">Danger</CdsTag>
        タグのみ
      </section>
      <section cds-layout="horizontal gap:sm">
        <CdsTag color="gray">Austin <CdsBadge>1</CdsBadge></CdsTag>
        <CdsTag color="purple">New York <CdsBadge>2</CdsBadge></CdsTag>
        <CdsTag color="blue">Palo Alto <CdsBadge>3</CdsBadge></CdsTag>
        <CdsTag color="orange">Ohio <CdsBadge>12</CdsBadge></CdsTag>
        <CdsTag color="light-blue">Seattle <CdsBadge>15</CdsBadge></CdsTag>
        タグ+バッジ
      </section>
      <section cds-layout="horizontal gap:sm">
        <CdsBadge status="info">2</CdsBadge>
        <CdsBadge status="success">3</CdsBadge>
        <CdsBadge status="warning">12</CdsBadge>
        <CdsBadge status="danger">15</CdsBadge>
        <CdsBadge color="gray">1</CdsBadge>
        <CdsBadge color="purple">1</CdsBadge>
        <CdsBadge color="blue">15</CdsBadge>
        <CdsBadge color="orange">2</CdsBadge>
        <CdsBadge color="light-blue">3</CdsBadge>
        バッジのみ
      </section>
      <h2 cds-text="section">Icons</h2>
      <section cds-layout="horizontal gap:sm">
        <CdsIcon size="lg" shape="user"></CdsIcon>
        <CdsIcon size="lg" shape="user" badge="info"></CdsIcon>
        <CdsIcon size="lg" shape="user" badge="success"></CdsIcon>
        <CdsIcon size="lg" shape="user" badge="danger"></CdsIcon>
        <CdsIcon size="lg" shape="user" badge="warning-triangle"></CdsIcon>
        userアイコン/フチのみ表示
      </section>
      <section cds-layout="horizontal gap:sm">
        <CdsIcon size="lg" shape="bug" solid></CdsIcon>
        <CdsIcon size="lg" shape="bug" solid badge="info"></CdsIcon>
        <CdsIcon size="lg" shape="bug" solid badge="success"></CdsIcon>
        <CdsIcon size="lg" shape="bug" solid badge="danger"></CdsIcon>
        <CdsIcon size="lg" shape="bug" solid badge="warning-triangle"></CdsIcon>
        bugアイコン/塗りつぶし
      </section>
      <h2 cds-text="section">Action Button</h2>
      <CdsButton onClick={() => {
        setCount(count + 1);
        setShow({ show: true });
      }}>You clicked {count} times.</CdsButton>
      <br></br>
      {show ? (
        <CdsAlertGroup status="warning">
          <CdsAlert onCloseChange={() => setShow({ show: false })} closable>
            You Voted
          </CdsAlert>
        </CdsAlertGroup>
      ) : ('')}
    </div>
  );
}

export default App;

画面は、以下のように変化するはずです。vSphere製品で見覚えのあるパーツが登場してきましたね!

4. UIの実装

最後に、vCenterっぽいレイアウトに挑戦してみましょう。

UI用のスタイルシートを追加

なんと、この話は https://clarity.design のサイトの方にしか書いていません。
Getting StartedページのHTML/CSS Frameworkのところをみると、@clr/ui の使用方法が記載されているので、読み込みましょう。
npmでインストールする方法と、直接CSSを読み込む方法がありますが、今回は後者でいきます。

<link rel="stylesheet" href="https://unpkg.com/@clr/ui/clr-ui.min.css" />

既存APPの退避

現在、src/App.js は、下記のような構造になっているかと思います。

import (※importしたいものを列挙);

function App() {
  return (
    ※既存APPの内容
  );
}

export default App;

これを、以下のように書き換えましょう。これからレイアウトを配置するために、既存のAPPを退避させました。

import (※importしたいものを列挙);

function Home() {
  return (
    ※既存APPの内容
  );
}
function App() {
  return (
    <div></div>
  );
}
export default App;

VMware風レイアウトに変更

再び、 https://core.clarity.design/ に戻り、作業を続けます。
Navigationのところにあるお好きなサンプルを App() のブロックに貼りましょう。
今回は、Sidnav + Sidenavのパターンを使用します。

また、ここからいくつかReact向けに直す必要があります。

  1. まず、各所にclass=という書き方がされているので、className=という書き方に一括置換します。
  2. <label for="...">といった記載は、<label htmlFor="...">に修正。
  3. <a href="javascript://">といった記載は、いったん<a href="#"> にする。

これで、Consoleからエラーは消えるはずです。
おぉ、vSphereっぽい画面になってきたぞ・・。
Screen Shot 2022-12-09 at 3.17.56.png

アイコンの修正

先ほどのCdsIconの話を参考にしながら、以下の箇所を直しましょう。

# Iconのインポート
+import { ClarityIcons, userIcon, bugIcon, vmBugIcon, cogIcon } from '@cds/core/icon';
+ClarityIcons.addIcons(vmBugIcon);
+ClarityIcons.addIcons(cogIcon);

# CdsIconに修正
+              <CdsIcon shape="vm-bug"></CdsIcon>
(中略)
+            <CdsIcon shape="cog"></CdsIcon>

退避したAPPを読み込み

className="content-area"がコンテンツを表示する場所なので、そこの中身を<Home />に差し替えましょう。
うまく行けば、以下のように表示されるはずです。

おぉ、まごうことなき、VMwareサイト!!!(笑)

ここまでのカスタマイズの成果をGitHubにあげておきました!
コード内容の確認など、お好きなようにお使い下さいませ:thumbsup:

あとがき

参照するサイトが一つにまとまってなくて、意外に大変でした。。
個人的には、割と良い記事ができあがったのではないかと思います。
それでは、また!

10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2