Segment Group
Organizes and navigates between sections in a view.
Anatomy
To set up the segmented control correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-part
attribute to help identify them in the DOM.
Examples
Learn how to use the SegmentGroup
component in your project. Let's take a look at the most basic example:
import { SegmentGroup } from '@ark-ui/react/segment-group' export const Basic = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] return ( <SegmentGroup.Root> <SegmentGroup.Indicator /> {frameworks.map((framework) => ( <SegmentGroup.Item key={framework} value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> ))} </SegmentGroup.Root> ) }
import { SegmentGroup } from '@ark-ui/solid/segment-group' import { Index } from 'solid-js' export const Basic = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] return ( <SegmentGroup.Root> <SegmentGroup.Indicator /> <Index each={frameworks}> {(framework) => ( <SegmentGroup.Item value={framework()}> <SegmentGroup.ItemText>{framework()}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> )} </Index> </SegmentGroup.Root> ) }
<script setup lang="ts"> import { SegmentGroup } from '@ark-ui/vue/segment-group' import { ref } from 'vue' const frameworks = ref(['React', 'Solid', 'Svelte', 'Vue']) </script> <template> <SegmentGroup.Root> <SegmentGroup.Indicator /> <SegmentGroup.Item v-for="framework in frameworks" :key="framework" :value="framework"> <SegmentGroup.ItemText>{{ framework }}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> </SegmentGroup.Root> </template>
<script lang="ts"> import { SegmentGroup } from '@ark-ui/svelte/segment-group' const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] </script> <SegmentGroup.Root> <SegmentGroup.Indicator /> {#each frameworks as framework} <SegmentGroup.Item value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> {/each} </SegmentGroup.Root>
Initial Value
To set a default segment on initial render, use the defaultValue
prop:
import { SegmentGroup } from '@ark-ui/react/segment-group' export const InitialValue = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] return ( <SegmentGroup.Root defaultValue="React"> <SegmentGroup.Indicator /> {frameworks.map((framework) => ( <SegmentGroup.Item key={framework} value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> ))} </SegmentGroup.Root> ) }
import { SegmentGroup } from '@ark-ui/solid/segment-group' import { Index } from 'solid-js' export const InitialValue = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] return ( <SegmentGroup.Root value="React"> <SegmentGroup.Indicator /> <Index each={frameworks}> {(framework) => ( <SegmentGroup.Item value={framework()}> <SegmentGroup.ItemText>{framework()}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> )} </Index> </SegmentGroup.Root> ) }
<script setup lang="ts"> import { SegmentGroup } from '@ark-ui/vue/segment-group' import { ref } from 'vue' const frameworks = ref(['React', 'Solid', 'Svelte', 'Vue']) </script> <template> <SegmentGroup.Root model-value="React"> <SegmentGroup.Indicator /> <SegmentGroup.Item v-for="framework in frameworks" :key="framework" :value="framework"> <SegmentGroup.ItemText>{{ framework }}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> </SegmentGroup.Root> </template>
<script lang="ts"> import { SegmentGroup } from '@ark-ui/svelte/segment-group' const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] </script> <SegmentGroup.Root defaultValue="React"> <SegmentGroup.Indicator /> {#each frameworks as framework (framework)} <SegmentGroup.Item value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> {/each} </SegmentGroup.Root>
Controlled Segment Group
To create a controlled SegmentGroup component, manage the current selected segment using the value
prop and update it when the onValueChange
event handler is called:
import { SegmentGroup } from '@ark-ui/react/segment-group' import { useState } from 'react' export const Controlled = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] const [value, setValue] = useState<string | null>('React') return ( <SegmentGroup.Root value={value} onValueChange={(e) => setValue(e.value)}> <SegmentGroup.Indicator /> {frameworks.map((framework) => ( <SegmentGroup.Item key={framework} value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> ))} </SegmentGroup.Root> ) }
import { SegmentGroup } from '@ark-ui/solid/segment-group' import { Index, createSignal } from 'solid-js' export const Controlled = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] const [value, setValue] = createSignal<string | null>('React') return ( <SegmentGroup.Root value={value()} onValueChange={(e) => setValue(e.value)}> <SegmentGroup.Indicator /> <Index each={frameworks}> {(framework) => ( <SegmentGroup.Item value={framework()}> <SegmentGroup.ItemText>{framework()}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> )} </Index> </SegmentGroup.Root> ) }
<script setup lang="ts"> import { SegmentGroup } from '@ark-ui/vue/segment-group' import { ref } from 'vue' const frameworks = ref(['React', 'Solid', 'Svelte', 'Vue']) const value = ref('React') </script> <template> <SegmentGroup.Root v-model="value"> <SegmentGroup.Indicator /> <SegmentGroup.Item v-for="framework in frameworks" :key="framework" :value="framework"> <SegmentGroup.ItemText>{{ framework }}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> </SegmentGroup.Root> </template>
<script lang="ts"> import { SegmentGroup } from '@ark-ui/svelte/segment-group' let value = $state<string | null>('React') const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] </script> <SegmentGroup.Root bind:value> <SegmentGroup.Indicator /> {#each frameworks as framework} <SegmentGroup.Item value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> {/each} </SegmentGroup.Root>
Disabled Segment
To disable a segment, simply pass the disabled
prop to the SegmentGroup.Item
component:
import { SegmentGroup } from '@ark-ui/react/segment-group' export const Disabled = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] return ( <SegmentGroup.Root defaultValue="React"> <SegmentGroup.Indicator /> {frameworks.map((framework) => ( <SegmentGroup.Item key={framework} value={framework} disabled={framework === 'Svelte'}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> ))} </SegmentGroup.Root> ) }
import { SegmentGroup } from '@ark-ui/solid/segment-group' import { Index } from 'solid-js' export const Disabled = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] return ( <SegmentGroup.Root value={'React'}> <SegmentGroup.Indicator /> <Index each={frameworks}> {(framework) => ( <SegmentGroup.Item value={framework()} disabled={framework() === 'Svelte'}> <SegmentGroup.ItemText>{framework()}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> )} </Index> </SegmentGroup.Root> ) }
<script setup lang="ts"> import { SegmentGroup } from '@ark-ui/vue/segment-group' import { ref } from 'vue' const frameworks = ref(['React', 'Solid', 'Svelte', 'Vue']) </script> <template> <SegmentGroup.Root model-value="React"> <SegmentGroup.Indicator /> <SegmentGroup.Item v-for="framework in frameworks" :key="framework" :value="framework" :disabled="framework === 'Svelte'" > <SegmentGroup.ItemText>{{ framework }}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> </SegmentGroup.Root> </template>
<script lang="ts"> import { SegmentGroup } from '@ark-ui/svelte/segment-group' const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] </script> <SegmentGroup.Root defaultValue="React"> <SegmentGroup.Indicator /> {#each frameworks as framework} <SegmentGroup.Item value={framework} disabled={framework === 'Svelte'}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> {/each} </SegmentGroup.Root>
Using the Root Provider
The RootProvider
component provides a context for the radio-group. It accepts the value of the useRadio-group
hook. You can leverage it to access the component state and methods from outside the radio-group.
import { SegmentGroup, useSegmentGroup } from '@ark-ui/react/segment-group' export const RootProvider = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] const segmentGroup = useSegmentGroup() return ( <> <button onClick={() => segmentGroup.focus()}>Focus</button> <SegmentGroup.RootProvider value={segmentGroup}> <SegmentGroup.Indicator /> {frameworks.map((framework) => ( <SegmentGroup.Item key={framework} value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> ))} </SegmentGroup.RootProvider> </> ) }
import { SegmentGroup, useSegmentGroup } from '@ark-ui/solid/segment-group' import { Index } from 'solid-js' export const RootProvider = () => { const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] const segmentGroup = useSegmentGroup() return ( <> <button onClick={() => segmentGroup().focus()}>Focus</button> <SegmentGroup.RootProvider value={segmentGroup}> <SegmentGroup.Indicator /> <Index each={frameworks}> {(framework) => ( <SegmentGroup.Item value={framework()}> <SegmentGroup.ItemText>{framework()}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> )} </Index> </SegmentGroup.RootProvider> </> ) }
<script setup lang="ts"> import { SegmentGroup, useSegmentGroup } from '@ark-ui/vue/segment-group' import { ref } from 'vue' const frameworks = ref(['React', 'Solid', 'Svelte', 'Vue']) const segmentGroup = useSegmentGroup() </script> <template> <button @click="segmentGroup.focus()">Focus</button> <SegmentGroup.RootProvider :value="segmentGroup"> <SegmentGroup.Indicator /> <SegmentGroup.Item v-for="framework in frameworks" :key="framework" :value="framework"> <SegmentGroup.ItemText>{{ framework }}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> </SegmentGroup.RootProvider> </template>
<script lang="ts"> import { SegmentGroup, useSegmentGroup } from '@ark-ui/svelte/segment-group' const frameworks = ['React', 'Solid', 'Svelte', 'Vue'] const id = $props.id() const segmentGroup = useSegmentGroup({ id }) </script> <button onclick={() => segmentGroup().focus()}>Focus</button> <SegmentGroup.RootProvider value={segmentGroup}> <SegmentGroup.Indicator /> {#each frameworks as framework} <SegmentGroup.Item value={framework}> <SegmentGroup.ItemText>{framework}</SegmentGroup.ItemText> <SegmentGroup.ItemControl /> <SegmentGroup.ItemHiddenInput /> </SegmentGroup.Item> {/each} </SegmentGroup.RootProvider>
If you're using the
RootProvider
component, you don't need to use theRoot
component.
API Reference
Root
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
defaultValue | string The initial value of the checked radio when rendered. Use when you don't need to control the value of the segment group. | |
disabled | boolean If `true`, the segment group will be disabled | |
form | string The associate form of the underlying input. | |
id | string The unique identifier of the machine. | |
ids | Partial<{ root: string label: string indicator: string item: (value: string) => string itemLabel: (value: string) => string itemControl: (value: string) => string itemHiddenInput: (value: string) => string }> The ids of the elements in the radio. Useful for composition. | |
name | string The name of the input fields in the radio (Useful for form submission). | |
onValueChange | (details: ValueChangeDetails) => void Function called once a radio is checked | |
orientation | 'horizontal' | 'vertical' Orientation of the segment group | |
readOnly | boolean Whether the checkbox is read-only | |
value | string The controlled value of the segment group |
Data Attribute | Value |
---|---|
[data-scope] | segment-group |
[data-part] | root |
[data-orientation] | The orientation of the segment-group |
[data-disabled] | Present when disabled |
Indicator
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
CSS Variable | Description |
---|---|
--transition-property | The transition property value for the Indicator |
--left | The left position value |
--top | The top position value |
--width | The width of the element |
--height | The height of the element |
Data Attribute | Value |
---|---|
[data-scope] | segment-group |
[data-part] | indicator |
[data-disabled] | Present when disabled |
[data-orientation] | The orientation of the indicator |
ItemControl
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | segment-group |
[data-part] | item-control |
[data-active] | Present when active or pressed |
ItemHiddenInput
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Item
Prop | Default | Type |
---|---|---|
value | string | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
disabled | boolean | |
invalid | boolean |
ItemText
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Label
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | segment-group |
[data-part] | label |
[data-orientation] | The orientation of the label |
[data-disabled] | Present when disabled |
RootProvider
Prop | Default | Type |
---|---|---|
value | UseRadioGroupReturn | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Accessibility
Complies with the Radio WAI-ARIA design pattern.
Keyboard Support
Key | Description |
---|---|
Tab | Moves focus to either the checked radio item or the first radio item in the group. |
Space | When focus is on an unchecked radio item, checks it. |
ArrowDown | Moves focus and checks the next radio item in the group. |
ArrowRight | Moves focus and checks the next radio item in the group. |
ArrowUp | Moves focus to the previous radio item in the group. |
ArrowLeft | Moves focus to the previous radio item in the group. |