コンテンツにスキップ

React 連携

React で Plain Elements を使う方法と、カスタムイベントの型付け。

トップレベルでインポートすると customElements.define が実行されます。そのため、次のようにクライアントコンポーネントから読み込みます。

ClientComponent.tsx
"use client";
import "plain-elements/dialog";
import "plain-elements/collapsible";

Next.js App Router では、"use client" を指定したコンポーネント内でインポートするか、{ ssr: false } を指定した dynamic import を使います。Server Component からはインポートしないでください。

JSX にはカスタム要素のタグを直接記述します。data-* 属性は、通常の JSX 属性として渡せます。

export function SettingsCollapsible() {
return (
<pe-collapsible>
<button type="button" data-collapsible-trigger>
Show details
</button>
<div data-collapsible-panel>Additional settings content.</div>
</pe-collapsible>
);
}

カスタムイベントはバブリングし、Shadow DOM の境界も越えます。document またはホスト要素の ref にイベントリスナーを登録してください。

"use client";
import { useEffect, useRef } from "react";
import "plain-elements/tabs";
export function AccountTabs() {
const hostRef = useRef<HTMLElement>(null);
useEffect(() => {
const host = hostRef.current;
if (!host) {
return;
}
const onChange = (event: CustomEvent) => {
// plain-elements 型読み込み時は CustomEvent<TabsEventDetail> として型付け。
console.log(event.detail.value);
};
host.addEventListener("pe-tabs:change", onChange);
return () => host.removeEventListener("pe-tabs:change", onChange);
}, []);
return (
<pe-tabs ref={hostRef}>
<div data-tabs-list aria-label="Account">
<button type="button" data-tabs-trigger="profile">
Profile
</button>
<button type="button" data-tabs-trigger="security">
Security
</button>
</div>
<section data-tabs-content="profile">Profile panel</section>
<section data-tabs-content="security">Security panel</section>
</pe-tabs>
);
}

ホスト要素の ref から、各コンポーネントのメソッドを呼び出せます。

hostRef.current?.open(); // Dialog, Popover, Tooltip, Collapsible
hostRef.current?.select("security"); // Tabs
console.log(hostRef.current?.isOpen); // 開閉できるコンポーネント

型を明示したい場合は、イベントの detail 型をインポートします。

import type { TabsEventDetail } from "plain-elements/tabs";

サブパスからインポートすると、使用するコンポーネントだけが登録されます。CSS はスタイリングを参照してください。