Divider
Dividers
A one-pixel outline-variant rule on either axis, rendered as a native separator.
Full-width rule between sections.
The same rule, inset from the leading edge by composition rather than by a prop.
- Grammar
- Listening
- Reading
12 lessons
Edited 2m ago
import { Fragment } from 'react'
import {
Divider,
ListItem,
Surface,
Text,
} from '@language-lit/material3-expressive'
export function DividerExample() {
const lessons = ['Grammar', 'Listening', 'Reading']
return (
<Surface
as="section"
aria-labelledby="divider-example-title"
color="surface-container-low"
shape="extra-large"
className="divider-example"
>
<Text
as="h2"
id="divider-example-title"
variant="titleLarge"
emphasis="emphasized"
>
Dividers
</Text>
<Text as="p" variant="bodyMedium">
A one-pixel outline-variant rule on either axis, rendered as a native
separator.
</Text>
<div className="divider-example__stack">
<Text as="p" variant="bodyMedium">
Full-width rule between sections.
</Text>
<Divider />
<Text as="p" variant="bodyMedium">
The same rule, inset from the leading edge by composition rather than
by a prop.
</Text>
<Divider className="divider-example__inset" />
</div>
<ul className="divider-example__list">
{lessons.map((lesson, index) => (
<Fragment key={lesson}>
<ListItem as="li" headline={lesson} />
{index < lessons.length - 1 && <Divider as="li" />}
</Fragment>
))}
</ul>
<div className="divider-example__row">
<Text as="span" variant="labelLarge">
Draft
</Text>
<Divider orientation="vertical" />
<Text as="span" variant="labelLarge">
12 lessons
</Text>
<Divider orientation="vertical" />
<Text as="span" variant="labelLarge">
Edited 2m ago
</Text>
</div>
</Surface>
)
}Dividerはリストやレイアウトの内容をグループ化する細い線です。既定ではネイティブの<hr>を描画します。orientationで横向きと縦向きを切り替え、色と太さはpropsではなくコンポーネントトークンから取得します。
import { Divider, ListItem } from '@language-lit/material3-expressive'
import '@language-lit/material3-expressive/styles.css'
// A full-width rule between sections.
<Divider />
// Between list items, where `hr` would be invalid HTML.
<ul>
<ListItem as="li" headline="Inbox" />
<Divider as="li" />
<ListItem as="li" headline="Archive" />
</ul>
// Between controls in a flex row.
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<span>Draft</span>
<Divider orientation="vertical" />
<span>Edited 2m ago</span>
</div>
// A rule the grouping already conveys, hidden from assistive technology.
<Divider decorative />仕様
orientationで軸を選びます。既定値は"horizontal"です。横向きのDividerはインライン方向いっぱいに広がり、ブロック方向の太さを持ちます。縦向きではこの関係が入れ替わります。
どちらの向きもstretchで広がるため、インライン余白を付けると親要素からはみ出すのではなく線が短くなります。これはインセットの指定方法です。横向きのDividerはblock、flex-column、gridの親要素いっぱいに広がります。縦向きは、サイズが制約された親要素の交差軸に沿ってalign-self: stretchで広がるため、flexまたはgridの親要素か、明示的なブロックサイズが必要です。高さが自動のblockコンテナーでは縮みます。これはMaterialソースのfillMaxHeight()と同じ制約です。
asで要素を選びます。既定値は"hr"です。<ul>や<ol>内では"li"を使ってください。これらの要素内に許可されるのはliとスクリプト対応要素なので、リスト項目の間にhrを置くのは無効なマークアップです。どちらも受け付けないレイアウトでは"div"を使います。
純粋に視覚的な線をアクセシビリティツリーから隠すにはdecorativeを指定します。MaterialのDividerは装飾だけでなくコンテンツのグループ化も担うため、既定ではセマンティックです。
コンポーネントは子要素を描画しません。Dividerは空の線で、既定要素はvoid要素です。classNameはライブラリのクラスの後に結合され、styleとその他のネイティブ属性はそのまま渡されます。refは描画された要素を参照します。
アクセシビリティ
既定の<hr>には暗黙のseparatorロールがあるため、コンポーネントは重ねて明示せずブラウザーに任せます。divとliにはrole="separator"を明示します。縦向きの区切りにはaria-orientation="vertical"を付けます。横向きの場合はロールの暗黙値と同じなので指定しません。
decorativeを指定すると、暗黙ロールを除く必要があるhrとliにはrole="none"を出力し、暗黙ロールがないdivには何も指定しません。装飾用のDividerはロールを公開しないため、その方向を示すaria-orientationも持ちません。
Dividerにフォーカスは当たらず、キーボード操作もありません。強制カラー表示では作者指定の背景色が上書きされるため、線が消えないようCanvasTextで再描画します。
トークンとソースの境界
Materialソースの生成DividerTokensが宣言し、実際に読み取る2つのロールに対応します。
| トークン | 既定値 |
|---|---|
--m3e-comp-divider-color | sys.color.outlineVariant |
--m3e-comp-divider-thickness | 1px |
Materialのソースでは、太さと色を呼び出しごとのパラメーターとして受け取ります。このライブラリでは代わりにトークンとして公開します。インスタンスごとの任意の値を出力するにはインラインスタイルが必要ですが、スコープ付きのカスタムプロパティならテーマと合成でき、Material3Providerの入れ子やサーバーレンダリングにも対応します。
インデントはpropではなく組み合わせによって指定します。Dividerにインライン余白を付けるか、コンテナーにpaddingを設定してください。これは、Dividerの外側にpadding修飾子を付けて、サイズを変えずにインデント内部で線が短くなることを確認するソースのテストに沿っています。背景色はpadding領域いっぱいに描画されるため、Divider自体のpaddingではインセットを表現できません。
Dp.Hairlineは再現しません。これは密度スケーリングを避け、物理ピクセル1つ分を描画するためのものです。CSSピクセルはすでに密度に依存せず、ソース自身のhairlineテストでも現行のコンポーザブルは高さ0でレイアウトされます。
Tabsでは、tablistの子要素にrole="tab"だけを持たせるため、Dividerを使わずtablist下端のborderとして線を描画します。--m3e-comp-tabs-divider-*トークンは同じ仕様値を持つため、片方のタブ行の見た目を変更しても、両者に異なる値を適用せずに済みます。