Skip to main content

Segmented Toggle in React Native

Image of Madeline Watts
Madeline Watts
Software Engineer
Hello! I'm Madeline, the founder of AppHelion and full time app developer. I have developed and published several apps using a variety of frameworks and I started AppHelion to share what I've learned!

Last updated: June 2025

GitHubView on GitHub

In this tutorial, we’ll walk through creating a simple and customizable segmented toggle component. This component is perfect for forms, filters, tabbed views, and more!

Here's what we're making:

Segmented Toggle
  1. Import React Native Components

At the top of your component file (mine is SegmentToggle.tsx), you will import the following:

import React, {useState} from 'react';
import {View, Text, TouchableOpacity, StyleSheet} from 'react-native';
  1. Define State Variables

This is where you'll define the selected state variable, with values/labels associated with each side of the toggle.

const [selected, setSelected] = useState<'option 1' | 'option 2'>('option 1');

Selected can only be equal to option 1 or option 2. One side of the toggle will always be selected.

  1. Component and Styles

Now we are ready to start building out our segmented toggle. We'll start with the left side of the toggle.

First we are going to add a View and add styles.container

<View style={styles.container}>
// ...
</View>

styles.container:

const styles = StyleSheet.create({
container: {
flexDirection: 'row',
},
})

Explanation

  • flexDirection: 'row',: aligns both sides of the toggle next to each other (instead of stacking them vertically)

Next, we will create the left side (segment) of the toggle:

  1. We will add a TouchableOpacity to handle the left side of the toggle being selected:
//...
<TouchableOpacity
style={[
styles.segment,
selected === 'option 1'
? styles.selectedSegment
: styles.unselectedSegment,
styles.leftSegment,
]}
onPress={() => setSelected('option 1')}>
// ...
</TouchableOpacity>
  • selected === 'option 1' ? styles.selectedSegment : styles.unselectedSegment: sets the style based on whether or not this side is selected using the selected state variable
  • styles.leftSegment: gives left side specific styling
  • onPress={() => setSelected('option 1')}: sets the selected variable to option 1 and deselects option 2 when the left side of the toggle is pressed

styles.segment

Each side of the toggle has three styles applied: one for layout (segment), one for selection state (selectedSegment / unselectedSegment), and one for shape (leftSegment / rightSegment).”

segment: {
paddingVertical: 10,
paddingHorizontal: 25,
flex: 1,
alignItems: 'center',
},
selectedSegment: {
backgroundColor: '#9E9E9E',
},
unselectedSegment: {
backgroundColor: '#EEEEEE',
},
leftSegment: {
borderTopLeftRadius: 40,
borderBottomLeftRadius: 40,
},
  • segment: gives the segment some horizontal and vertical spacing, allows it to use up all of the available space designated for it (flex: 1), and centers it within the segment
  • selectedSegment: background color for the selected segment side
  • unselectedSegment: background color for the unselected segment side
  • leftSegment: rounds the top left and bottom left corners while keeping the top right and bottom right the same

At this point the toggle looks like this:

Segmented Toggle (left side)
  1. Segment Text:

Now we will add the text to the left side of the toggle:

Text

<TouchableOpacity //...>
<Text
style={
selected === 'option 1' ? styles.selectedText : styles.unselectedText
}>
Option 1
</Text>
</TouchableOpacity>

The Text style is determined by the selected variable. Just like above with the TouchableOpacity, the text will appear slightly different depending on if it's side of the segment is selected or not.

Styles:

selectedText: {
fontWeight: '600',
color: 'black',
},
unselectedText: {
color: 'black',
opacity: 0.7,
},
  • selectedText: bold, black text
  • unselectedText: still black text but slightly transparent

Now the toggle looks like this:

Segmented Toggle (left side with Text)

To add the right side, we will just add another TouchableOpacity and Text components and the corresponding styles for the right side:

<TouchableOpacity
style={[
styles.segment,
selected === 'option 2'
? styles.selectedSegment
: styles.unselectedSegment,
styles.rightSegment,
]}
onPress={() => setSelected('option 2')}>
<Text
style={
selected === 'option 2' ? styles.selectedText : styles.unselectedText
}>
Option 2
</Text>
</TouchableOpacity>

This is the same code as above but with a few tweaks:

  • option 2 replaces options 1
  • rightSegment is used instead of leftSegment

rightSegment All we need to add now is a style for the right side segment:

rightSegment: {
borderTopRightRadius: 40,
borderBottomRightRadius: 40,
},
  • Same as leftSegment except it rounds out the top right and bottom right corners instead of the left side corners (this creates a "pill" shape)
Segmented Toggle (right side selected)

Complete Component File

Here is the complete component:

import React, { useState } from "react";
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";

const SegmentToggle = () => {
const [selected, setSelected] = useState<"option 1" | "option 2">("option 1");

return (
<View style={styles.container}>
<TouchableOpacity
style={[
styles.segment,
selected === "option 1"
? styles.selectedSegment
: styles.unselectedSegment,
styles.leftSegment,
]}
onPress={() => setSelected("option 1")}
>
<Text
style={
selected === "option 1"
? styles.selectedText
: styles.unselectedText
}
>
Option 1
</Text>
</TouchableOpacity>

<TouchableOpacity
style={[
styles.segment,
selected === "option 2"
? styles.selectedSegment
: styles.unselectedSegment,
styles.rightSegment,
]}
onPress={() => setSelected("option 2")}
>
<Text
style={
selected === "option 2"
? styles.selectedText
: styles.unselectedText
}
>
Option 2
</Text>
</TouchableOpacity>
</View>
);
};

const styles = StyleSheet.create({
container: {
flexDirection: "row",
},
segment: {
paddingVertical: 10,
paddingHorizontal: 25,
flex: 1,
alignItems: "center",
},
selectedSegment: {
backgroundColor: "#9E9E9E",
},
unselectedSegment: {
backgroundColor: "#EEEEEE",
},
selectedText: {
fontWeight: "600",
color: "black",
},
unselectedText: {
color: "#000",
opacity: 0.7,
},
leftSegment: {
borderTopLeftRadius: 40,
borderBottomLeftRadius: 40,
},
rightSegment: {
borderTopRightRadius: 40,
borderBottomRightRadius: 40,
},
});

export default SegmentToggle;