この記事の概要
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:
これらを用いると、狙ったスタイリングもしやすいかと思います。
参考
-
すみません。型を見る限りそのように見えるものの、ちゃんと検証できてはいません。 ↩