この記事の概要
Ark UIのSelectコンポーネントには単体のSelectとFiledに属すSelectが存在します。
これらの違いと使い分けを備忘録がてら記事にしました。
Ark UIは色々なフレームワークで使えますが、この記事での例示コードはReactです。
結論
通常のselect要素の見た目、使い勝手で十分な際はField.Selectを。
見た目や出現時のアニメーション、選択していることの示し方などにこだわりたいときはSelectを選ぶと良いと思います。
| メリット | デメリット | |
|---|---|---|
| Field.Select | コードがシンプルで見やすい・分かりやすい | 通常のselect要素とoption要素でできること以上のことは無い |
| Select | 表示の仕方やアニメーションなど細かい箇所にこだわれる | 単なるselectとして使うには複雑な箇所が多い |
両者の違い
説明のしやすさの都合上、Field.Selectから説明します。
Field.Select
exampleのコードは以下のようになっています。
import { Field } from '@ark-ui/react/field'
export const Select = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Select>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
-
Filed.Root-
Filed関連のpropsを伝播させるためのprovider
-
-
Field.Label- idやdata属性などが良い感じに付与された
label要素
- idやdata属性などが良い感じに付与された
-
Filed.Select-
idやdata属性などが良い感じに付与されたselect要素
-
-
Filed.HelperText,Field.ErrorText- 今回の話にはほぼ関係ないので省略
- ErrorTextに関しての記事を別で書いているので良ければこちらもご覧ください
つまり、最終的なマークアップとしてはdivの中にlabelとselectと少々のテキスト系要素が入っているだけです。
何もせずともlabelとselectを紐づけてくれるなど気が利いてはいますが、実態としては単なるselect要素でしかない、と言えます。
Select
exampleのコードは以下のようになっています。
import { Portal } from '@ark-ui/react/portal'
import { Select, createListCollection } from '@ark-ui/react/select'
import { ChevronDownIcon } from 'lucide-react'
export const Basic = () => {
const collection = createListCollection({ items: ['React', 'Solid', 'Vue'] })
return (
<Select.Root collection={collection}>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
{collection.items.map((item) => (
<Select.Item key={item} item={item}>
<Select.ItemText>{item}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
))}
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
Field.Selectとはコードの長さがだいぶ違います。
すべてを説明するとかなり長くなってしまうので、かいつまんで記載します。
-
Select.Root-
Select関連のpropsを伝播させるためのprovider
-
-
Select.Controlとその配下- ざっくり言えば、これらの要素がクリックされると選択肢一覧が表示される
-
Select.ValueTextやSelect.Indicatorはあくまで「よくある要素」として使われているに過ぎないというか、どれかを無くしても問題なく動作する
-
PortalやSelect.Positioner- Ark UIの
Selectは通常のselect要素とは違い、ポップオーバー的にoption群が表示される - そのため、それらの位置を制御するようなもの
- Ark UIの
-
Select.Contentとその配下- 通常の
selectでいうoption要素達
- 通常の
またreturnの前にcreateListCollectionという関数を使ってcollectionを定義しています。
単なる配列やオブジェクトを渡してもダメで、こちらの関数を通してからSelectに渡す必要があります。
これのおかげで複数選択ができたり前後のオプションの情報を得たり、色々なことができるようになっている、ように見えます1。
Selectのおまけ
Select.Positionerのスタイルには、親要素の幅・画面上で表示できる幅と高さが計算され、以下のCSSカスタムプロパティに渡ります。
--reference-width:
--available-width:
--available-height:
これらを用いると、狙ったスタイリングもしやすいかと思います。
参考
-
すみません。型を見る限りそのように見えるものの、ちゃんと検証できてはいません。 ↩