出典:Calcite Design System - core concepts
Calcite Components は、Stencil.js を使用して構築された、再利用可能な Web コンポーネントのライブラリです。Calcite Components を使用すると、ブランド力のある、軽量でアクセスしやすい Web アプリケーションをすばやく構築できます。
Web コンポーネントはブラウザのネイティブ規格であり、Calcite Components で開発するために必要な技術的概念の多くは、このライブラリに固有のものではありません。このページでは、効果的な開発を行うために必要な、Web の主要コンセプトを紹介しています。さらに詳しい情報について、このページにあるすべての概念は、MDN Web Docs やその他の Web 標準ドキュメントのソースで見つけることができます。
カスタム要素は、Web コンポーネント標準の一部であり、HTML と任意の JavaScript ライブラリまたは Web フレームワークを使用して、モダン ブラウザ全体で動作します。カスタム要素は機能をカプセル化するため、他のコードとのコンフリクトを防ぐことができます。
Calcite Components はカスタム要素であり、ネイティブの HTML 要素と同様に使用することができます。
<calcite-tip heading="Platypus"></calcite-tip>
スロットはプレースホルダー要素であり、スロットの名前を参照することで独自のコンテンツを追加することができます。スロットは一般的な Web コンポーネントの概念であり、あなたもすでに使用している可能性があります。例えば、次のような HTML を考えてみましょう。
<select>
<option value="platypus">Platypus</option>
<option value="sloth">Sloth</option>
<option value="armadillo">Nine-banded armadillo</option>
</select>
Web コンポーネントの用語で、option
要素は select
のデフォルト スロットに配置されます。また、「Platypus」、「Sloth」、「Nine-banded」のテキストは、それぞれの option
のデフォルト スロットに配置されます。
また、多くの Calcite Components は、デフォルトのスロットを利用しています。例えば、下の calcite-tip
では、デフォルトのスロットに p
コンテンツが追加されています。
<calcite-tip heading="Platypus">
<img slot="thumbnail" src="platypus.jpg" alt="A platypus sensing its prey using electrical fields." />
<p>A platypus is a mammal with a bill, similar to a duck. They use their bill to sense prey via electrolocation.</p>
</calcite-tip>
多くの場合、デフォルトのスロットがあれば十分です。しかし、コンポーネントが複雑になればなるほど、子要素の位置やスタイルを変える必要が出てきます。そこで活躍するのがネームドスロットです。上の例では、チップの thumbnail
スロットに画像が配置されています。これは、画像がデフォルトスロットの要素とは異なる方法で処理されるべきであることをコンポーネントに通知するものです。
もしコンポーネントにスロットがあれば、slots for calcite-card
のように、ドキュメントに記載されます。また詳細については、slots on MDN で学ぶこともできます。
カスタム要素はカプセル化され、そのマークアップ構造、スタイル、動作はページ上の他のコードから隠され、分離された状態に保たれます。Shadow DOM は、カスタム要素をカプセル化する仕組みです。その結果、Shadow DOM は Web コンポーネントの DOM 要素を隠して分離するため、ブラウザでレンダリングされますが、他のコードとぶつかることはありません。
Shadow DOM のカプセル化により、アプリケーション間で永続的なスタイルと機能を実現し、ユーザーに一貫したユーザー エクスペリエンスを提供することができます。
Calcite Components は、スタイルを上書きするための CSS 変数を提供しています。Web コンポーネントの Shadow DOM のため、CSS 変数がないと簡単にスタイルを変更することができません。トークンには CSS 変数があり、color や typography など、デザインシステム全体で使用されます。
さらに、一部の Calcite Components には、コンポーネント固有のスタイルを変更するための独自の CSS 変数があります。これらの CSS 変数は、CSS variables for cacite-loader
のように、コンポーネントのドキュメントで見つけることができます。
使用例としては、CSS 変数を使用して、calcite-notice
の前景色と文字色を入れ替えることができます。
calcite-notice {
--calcite-ui-foreground-1: #151515;
--calcite-ui-text-1: #ffffff;
}
CSS variable MDN documentation に、機能の詳細が説明されています。
Web コンポーネントはプレーンな HTML 要素として始まり、その実装がブラウザで定義されると同時にアップグレードされます。Calcite Components は、インポートされ、アプリケーションで使用されると、自動的に定義されます。しかし、特定のコードを実行する前に、コンポーネントが定義されるまで待つ必要がある場合があります。
Stencil.js では、コンポーネントとそのすべての子コンポーネントのハイドレーションが終了したときに、フラグを追加するオプションが用意されています。これにより、様々なコンポーネントのダウンロードとレンダリングが非同期に行われるため、FOUC(Flash of Unstyled Content)を防止することができます。Calcite Components では、一度ハイドレーションされたコンポーネントに calcite-hydrated
というCSSクラスが追加され、アプリケーションをデバッグする際に便利です。
customElementRegistry
インターフェースの whenDefined()
メソッドは、指定された要素が定義されたときに満たされる Promise を返します。
Promise が満たされると、次のようにコンポーネントの定義を必要とするコードを実行できるようになります。
customElements.whenDefined("calcite-button").then(() => document.querySelector("calcite-button").setFocus());
コンポーネントがいつレンダリングされるかを決定するには、Stencilの componentOnReady()
メソッドを使用します。このメソッドは、componentDidLoad()
ライフサイクルメソッドが起動した後に解決される Promise を返します。これは、コンポーネントのメソッドを使用する前にコンポーネントがロードされていることを確認する場合や、あるコンポーネントが他のコンポーネントに依存している場合に便利です。
例えば、他のコンポーネントのレンダリングが終了するまで、calcite-loader
を表示させたい場合があります。
(async () => {
await customElements.whenDefined("calcite-alert");
await document.querySelector("calcite-alert").componentOnReady();
document.querySelector("calcite-loader").hidden = true;
})();
requestAnimationFrame
のコールバックとしてコンポーネントのメソッドを呼び出すことで、コンポーネントの状態でユーザー インターフェースが更新されます。例えば、ユーザーの閲覧履歴に基づいて、calcite-stepper
の現在のステップを設定したい場合、goToStep()
メソッドを使うことができます。
(async () => {
await customElements.whenDefined("calcite-stepper");
const el = await document.querySelector("calcite-stepper").componentOnReady();
requestAnimationFrame(() => el.goToStep(3));
})();
Calcite Components は、CustomEvent()
コンストラクターを使用してイベントの作成とトリガーを行います。
CustomEvent
は Event
と似たような振る舞いをします。これは button
をクリックしたときなどの HTML 要素から放出されます。例えば、イベント ペイロードの target
プロパティで要素にアクセスすることは可能です。また、一部の CustomEvent
のペイロードは、detail
プロパティにイベント固有の情報を含みます。
コンポーネントのドキュメント ページを表示すると、calcite-pagination
event のようなイベントを持つかどうかを確認することができます。
document.addEventListener("calcitePaginationChange", event => {
console.log(`Starting item number on the page: ${event.target.startItem}`);
});
フォーム送信時に適切に値を渡すためには、フォーム内の各コンポーネントに name
属性を設定する必要があります。例えば、Input Date Picker
と Text Area
に name
属性を追加します。
<form>
<calcite-label>
Observation date:
<calcite-input-date-picker name="observation-date"></calcite-input-date-picker>
</calcite-label>
<calcite-label>
Observation notes:
<calcite-text-area name="observation-notes" placeholder="Observation notes" max-length="250"></calcite-text-area>
</calcite-label>
<calcite-button type="submit">Submit</calcite-button>
</form>
フォームに関するその他の考慮事項については、フォームのアクセシビリティを参照してください。
Calcite Components には明暗モードがあり、対応する CSS クラス calcite-mode-light
と calcite-mode-dark
を使って変更できる。calcite-mode-auto
クラスもあり、ブラウザの prefers-color-scheme
CSS メディアクエリに従うことで、明るいモードと暗いモードのどちらを使用するかを決定します。
要素に モード クラスを設定すると、その子ノードもすべて変更されます。したがって、アプリケーション全体を明るい状態から暗い状態に切り替えるには、次のようにします。
<body class="calcite-mode-dark">
<!-- Your application content -->
</body>