@coinbase/cds-mcp-server 8.48.3 → 8.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  <!-- template-start -->
10
10
 
11
+ ## 8.49.0 ((2/26/2026, 04:03 PM PST))
12
+
13
+ This is an artificial version bump with no new change.
14
+
11
15
  ## 8.48.3 ((2/25/2026, 08:36 PM PST))
12
16
 
13
17
  This is an artificial version bump with no new change.
@@ -10,10 +10,12 @@ import { PeriodSelector } from '@coinbase/cds-mobile-visualization'
10
10
 
11
11
  ## Examples
12
12
 
13
- ### Basic Example
13
+ PeriodSelector is a specialized [SegmentedTabs](/components/navigation/SegmentedTabs) optimized for chart time-period selection. It provides a transparent background, primary wash active state, and full-width layout by default.
14
+
15
+ ### Basics
14
16
 
15
17
  ```jsx
16
- function BasicExample() {
18
+ function Example() {
17
19
  const tabs = [
18
20
  { id: '1H', label: '1H' },
19
21
  { id: '1D', label: '1D' },
@@ -29,12 +31,12 @@ function BasicExample() {
29
31
  }
30
32
  ```
31
33
 
32
- ### Minimum Width
34
+ ### Sizing
33
35
 
34
- You can set the `width` prop to `fit-content` to make the period selector as small as possible.
36
+ Set `width` to `fit-content` to make the selector only as wide as its content, and use `gap` to control spacing between tabs.
35
37
 
36
38
  ```jsx
37
- function MinimumWidthExample() {
39
+ function Example() {
38
40
  const tabs = [
39
41
  { id: '1W', label: '1W' },
40
42
  { id: '1M', label: '1M' },
@@ -55,16 +57,49 @@ function MinimumWidthExample() {
55
57
  }
56
58
  ```
57
59
 
58
- ### Many Periods with Overflow
60
+ ### Live Indicator
61
+
62
+ Use the `LiveTabLabel` component (exported from PeriodSelector) to indicate a live data period. Pair it with a conditional `activeBackground` to visually differentiate the live state.
63
+
64
+ ```jsx
65
+ function Example() {
66
+ const tabs = useMemo(
67
+ () => [
68
+ { id: '1H', label: <LiveTabLabel /> },
69
+ { id: '1D', label: '1D' },
70
+ { id: '1W', label: '1W' },
71
+ { id: '1M', label: '1M' },
72
+ { id: '1Y', label: '1Y' },
73
+ { id: 'All', label: 'All' },
74
+ ],
75
+ [],
76
+ );
77
+
78
+ const [activeTab, setActiveTab] = useState(tabs[0]);
79
+ const isLive = useMemo(() => activeTab?.id === '1H', [activeTab]);
80
+
81
+ const activeBackground = useMemo(() => (isLive ? 'bgNegativeWash' : 'bgPrimaryWash'), [isLive]);
82
+
83
+ return (
84
+ <PeriodSelector
85
+ activeBackground={activeBackground}
86
+ activeTab={activeTab}
87
+ onChange={setActiveTab}
88
+ tabs={tabs}
89
+ />
90
+ );
91
+ }
92
+ ```
93
+
94
+ ### Overflow
95
+
96
+ When there are too many tabs to fit in a single row, wrap the selector in a horizontal `ScrollView` with an optional action button.
59
97
 
60
98
  ```jsx
61
- function ManyPeriodsExample() {
99
+ function Example() {
62
100
  const tabs = useMemo(
63
101
  () => [
64
- {
65
- id: '1H',
66
- label: <LiveTabLabel />,
67
- },
102
+ { id: '1H', label: <LiveTabLabel /> },
68
103
  { id: '1D', label: '1D' },
69
104
  { id: '1W', label: '1W' },
70
105
  { id: '1M', label: '1M' },
@@ -110,149 +145,17 @@ function ManyPeriodsExample() {
110
145
  }
111
146
  ```
112
147
 
113
- ### Live Indicator
114
-
115
- ```jsx
116
- function LiveExample() {
117
- const tabs = useMemo(
118
- () => [
119
- // LiveTabLabel is exported from PeriodSelector
120
- { id: '1H', label: <LiveTabLabel /> },
121
- { id: '1D', label: '1D' },
122
- { id: '1W', label: '1W' },
123
- { id: '1M', label: '1M' },
124
- { id: '1Y', label: '1Y' },
125
- { id: 'All', label: 'All' },
126
- ],
127
- [],
128
- );
129
-
130
- const [activeTab, setActiveTab] = useState(tabs[0]);
131
- const isLive = useMemo(() => activeTab?.id === '1H', [activeTab]);
132
-
133
- const activeBackground = useMemo(() => (isLive ? 'bgNegativeWash' : 'bgPrimaryWash'), [isLive]);
134
-
135
- return (
136
- <PeriodSelector
137
- activeBackground={activeBackground}
138
- activeTab={activeTab}
139
- onChange={setActiveTab}
140
- tabs={tabs}
141
- />
142
- );
143
- }
144
- ```
145
-
146
148
  ### Customization
147
149
 
148
150
  #### Custom Colors
149
151
 
150
- ```jsx
151
- function ColoredBTCExample() {
152
- const btcColor = assets.btc.color;
153
-
154
- // Custom active indicator with BTC color
155
- const BTCActiveIndicator = memo((props) => {
156
- const theme = useTheme();
157
- const { activeTab } = useTabsContext();
158
- const isLive = useMemo(() => activeTab?.id === '1H', [activeTab]);
159
-
160
- const backgroundColor = useMemo(
161
- () => (isLive ? theme.color.bgNegativeWash : `${btcColor}1A`),
162
- [isLive, theme.color.bgNegativeWash],
163
- );
164
-
165
- return <PeriodSelectorActiveIndicator {...props} background={backgroundColor} />;
166
- });
167
-
168
- // Custom tab component with BTC color
169
- const BTCTab = memo(
170
- forwardRef(({ label, ...props }, ref) => {
171
- const { activeTab } = useTabsContext();
172
- const isActive = activeTab?.id === props.id;
173
- const theme = useTheme();
174
-
175
- const wrappedLabel =
176
- typeof label === 'string' ? (
177
- <Text font="label1" dangerouslySetColor={isActive ? btcColor : theme.color.fg}>
178
- {label}
179
- </Text>
180
- ) : (
181
- label
182
- );
183
-
184
- return <SegmentedTab ref={ref} label={wrappedLabel} {...props} />;
185
- }),
186
- );
187
-
188
- // Custom live label with BTC color
189
- const BTCLiveLabel = memo(
190
- forwardRef(({ label = 'LIVE', font = 'label1', hideDot, style, ...props }, ref) => {
191
- const theme = useTheme();
192
-
193
- const dotStyle = useMemo(
194
- () => ({
195
- width: theme.space[1],
196
- height: theme.space[1],
197
- borderRadius: 1000,
198
- marginRight: theme.space[0.75],
199
- backgroundColor: btcColor,
200
- }),
201
- [theme.space],
202
- );
203
-
204
- return (
205
- <View
206
- ref={ref}
207
- style={[
208
- {
209
- flexDirection: 'row',
210
- alignItems: 'center',
211
- },
212
- style,
213
- ]}
214
- >
215
- {!hideDot && <View style={dotStyle} />}
216
- <Text font={font} style={{ color: btcColor }} {...props}>
217
- {label}
218
- </Text>
219
- </View>
220
- );
221
- }),
222
- );
223
-
224
- const tabs = [
225
- { id: '1H', label: <BTCLiveLabel /> },
226
- { id: '1D', label: '1D' },
227
- { id: '1W', label: '1W' },
228
- { id: '1M', label: '1M' },
229
- { id: '1Y', label: '1Y' },
230
- { id: 'All', label: 'All' },
231
- ];
232
- const [activeTab, setActiveTab] = useState(tabs[0]);
233
-
234
- return (
235
- <PeriodSelector
236
- TabComponent={BTCTab}
237
- TabsActiveIndicatorComponent={BTCActiveIndicator}
238
- activeTab={activeTab}
239
- onChange={setActiveTab}
240
- tabs={tabs}
241
- />
242
- );
243
- }
244
- ```
245
-
246
- #### Custom Colors Excluding Live
247
-
248
- Customize colors for regular periods while keeping the default red styling for live periods.
152
+ Use `TabComponent` and `TabsActiveIndicatorComponent` to fully brand the selector. This example applies a custom asset color to both the active indicator background and the tab text, while keeping the default red styling for live periods.
249
153
 
250
154
  ```jsx
251
- function ColoredExcludingLiveExample() {
155
+ function Example() {
252
156
  const btcColor = assets.btc.color;
253
157
 
254
- // Custom active indicator that only applies BTC color to non-live periods
255
- const BTCActiveExcludingLiveIndicator = memo((props) => {
158
+ const BTCActiveIndicator = memo((props) => {
256
159
  const theme = useTheme();
257
160
  const { activeTab } = useTabsContext();
258
161
  const isLive = useMemo(() => activeTab?.id === '1H', [activeTab]);
@@ -265,7 +168,6 @@ function ColoredExcludingLiveExample() {
265
168
  return <PeriodSelectorActiveIndicator {...props} background={backgroundColor} />;
266
169
  });
267
170
 
268
- // Custom tab component with BTC color
269
171
  const BTCTab = memo(
270
172
  forwardRef(({ label, ...props }, ref) => {
271
173
  const { activeTab } = useTabsContext();
@@ -293,12 +195,12 @@ function ColoredExcludingLiveExample() {
293
195
  { id: '1Y', label: '1Y' },
294
196
  { id: 'All', label: 'All' },
295
197
  ];
296
- const [activeTab, setActiveTab] = useState(tabs[0]);
198
+ const [activeTab, setActiveTab] = useState(tabs[1]);
297
199
 
298
200
  return (
299
201
  <PeriodSelector
300
202
  TabComponent={BTCTab}
301
- TabsActiveIndicatorComponent={BTCActiveExcludingLiveIndicator}
203
+ TabsActiveIndicatorComponent={BTCActiveIndicator}
302
204
  activeTab={activeTab}
303
205
  onChange={setActiveTab}
304
206
  tabs={tabs}
@@ -402,6 +304,7 @@ function ColoredExcludingLiveExample() {
402
304
  | `right` | `string \| number` | No | `-` | - |
403
305
  | `rowGap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
404
306
  | `style` | `false \| RegisteredStyle<ViewStyle> \| WithAnimatedObject<ViewStyle> \| Value \| AnimatedInterpolation<string \| number> \| WithAnimatedArray<ViewStyle \| Falsy \| RegisteredStyle<ViewStyle> \| RecursiveArray<ViewStyle \| Falsy \| RegisteredStyle<ViewStyle>> \| readonly (ViewStyle \| Falsy \| RegisteredStyle<ViewStyle>)[]> \| null` | No | `-` | - |
307
+ | `styles` | `{ root?: StyleProp<ViewStyle>; tab?: StyleProp<ViewStyle>; activeIndicator?: StyleProp<ViewStyle>; }` | No | `-` | Custom styles for individual elements of the SegmentedTabs component |
405
308
  | `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Used to locate this view in end-to-end tests. |
406
309
  | `textAlign` | `left \| right \| auto \| center \| justify` | No | `-` | - |
407
310
  | `textDecorationLine` | `none \| underline \| line-through \| underline line-through` | No | `-` | - |
@@ -414,3 +317,12 @@ function ColoredExcludingLiveExample() {
414
317
  | `zIndex` | `number` | No | `-` | - |
415
318
 
416
319
 
320
+ ## Styles
321
+
322
+ | Selector | Static class name | Description |
323
+ | --- | --- | --- |
324
+ | `root` | `-` | Root container element |
325
+ | `tab` | `-` | Tab element |
326
+ | `activeIndicator` | `-` | Active indicator element |
327
+
328
+
@@ -10,9 +10,13 @@ import { SegmentedTabs } from '@coinbase/cds-mobile/tabs/SegmentedTabs'
10
10
 
11
11
  ## Examples
12
12
 
13
- ### Basic Example
13
+ SegmentedTabs is a controlled component that uses `activeTab` and `onChange` to manage selection state.
14
14
 
15
- Use the `onChange` prop to listen and make changes to the `activeTab` state.
15
+ ### Basics
16
+
17
+ #### Initial Value
18
+
19
+ You can set any tab as the initial active tab by passing it to the `activeTab` state.
16
20
 
17
21
  ```jsx
18
22
  function Example() {
@@ -34,9 +38,7 @@ function Example() {
34
38
  }
35
39
  ```
36
40
 
37
- ### With Initial Value
38
-
39
- You can set any tab as the initial active tab.
41
+ SegmentedTabs can also start with no active selection by passing `null`.
40
42
 
41
43
  ```jsx
42
44
  function Example() {
@@ -45,7 +47,7 @@ function Example() {
45
47
  { id: 'sell', label: 'Sell' },
46
48
  { id: 'convert', label: 'Convert' },
47
49
  ];
48
- const [activeTab, updateActiveTab] = useState(tabs[1]); // Start with 'Sell'
50
+ const [activeTab, updateActiveTab] = useState(null);
49
51
  const handleChange = useCallback((activeTab) => updateActiveTab(activeTab), []);
50
52
  return (
51
53
  <SegmentedTabs
@@ -58,9 +60,9 @@ function Example() {
58
60
  }
59
61
  ```
60
62
 
61
- ### No Initial Value
63
+ #### Disabled
62
64
 
63
- SegmentedTabs can start with no active selection.
65
+ The entire component can be disabled with the `disabled` prop.
64
66
 
65
67
  ```jsx
66
68
  function Example() {
@@ -69,12 +71,13 @@ function Example() {
69
71
  { id: 'sell', label: 'Sell' },
70
72
  { id: 'convert', label: 'Convert' },
71
73
  ];
72
- const [activeTab, updateActiveTab] = useState(null); // No initial selection
74
+ const [activeTab, updateActiveTab] = useState(tabs[0]);
73
75
  const handleChange = useCallback((activeTab) => updateActiveTab(activeTab), []);
74
76
  return (
75
77
  <SegmentedTabs
76
78
  accessibilityLabel="Switch token action views"
77
79
  activeTab={activeTab}
80
+ disabled
78
81
  onChange={handleChange}
79
82
  tabs={tabs}
80
83
  />
@@ -82,15 +85,13 @@ function Example() {
82
85
  }
83
86
  ```
84
87
 
85
- ### Disabled State
86
-
87
- You can disable the entire SegmentedTabs component.
88
+ Individual tabs can also be disabled while keeping others interactive.
88
89
 
89
90
  ```jsx
90
91
  function Example() {
91
92
  const tabs = [
92
93
  { id: 'buy', label: 'Buy' },
93
- { id: 'sell', label: 'Sell' },
94
+ { id: 'sell', label: 'Sell', disabled: true },
94
95
  { id: 'convert', label: 'Convert' },
95
96
  ];
96
97
  const [activeTab, updateActiveTab] = useState(tabs[0]);
@@ -99,7 +100,6 @@ function Example() {
99
100
  <SegmentedTabs
100
101
  accessibilityLabel="Switch token action views"
101
102
  activeTab={activeTab}
102
- disabled
103
103
  onChange={handleChange}
104
104
  tabs={tabs}
105
105
  />
@@ -107,15 +107,17 @@ function Example() {
107
107
  }
108
108
  ```
109
109
 
110
- ### Disabled Individual Tab
110
+ ### Styling
111
+
112
+ #### Border Radius
111
113
 
112
- Individual tabs can be disabled while keeping others interactive.
114
+ Set `borderRadius` to change the shape of both the container and the active indicator.
113
115
 
114
116
  ```jsx
115
117
  function Example() {
116
118
  const tabs = [
117
119
  { id: 'buy', label: 'Buy' },
118
- { id: 'sell', label: 'Sell', disabled: true },
120
+ { id: 'sell', label: 'Sell' },
119
121
  { id: 'convert', label: 'Convert' },
120
122
  ];
121
123
  const [activeTab, updateActiveTab] = useState(tabs[0]);
@@ -124,6 +126,7 @@ function Example() {
124
126
  <SegmentedTabs
125
127
  accessibilityLabel="Switch token action views"
126
128
  activeTab={activeTab}
129
+ borderRadius={300}
127
130
  onChange={handleChange}
128
131
  tabs={tabs}
129
132
  />
@@ -131,26 +134,76 @@ function Example() {
131
134
  }
132
135
  ```
133
136
 
134
- ### Custom Tab Component
135
-
136
- You can customize individual tabs by providing a custom `Component` for specific tabs.
137
+ Use the `styles` prop to set a different `borderRadius` on the active indicator than the outer container, with `padding` to create an inset effect.
137
138
 
138
139
  ```jsx
139
140
  function Example() {
140
- const CustomSegmentedTabColor = useCallback(
141
- (props) => <SegmentedTab {...props} activeColor="fgWarning" color="bgPrimary" font="label2" />,
142
- [],
141
+ const theme = useTheme();
142
+ const tabs = [
143
+ { id: 'buy', label: 'Buy' },
144
+ { id: 'sell', label: 'Sell' },
145
+ { id: 'convert', label: 'Convert' },
146
+ ];
147
+ const [activeTab, updateActiveTab] = useState(tabs[0]);
148
+ const handleChange = useCallback((activeTab) => updateActiveTab(activeTab), []);
149
+ return (
150
+ <SegmentedTabs
151
+ accessibilityLabel="Switch token action views"
152
+ activeTab={activeTab}
153
+ borderRadius={300}
154
+ onChange={handleChange}
155
+ padding={0.5}
156
+ styles={{
157
+ activeIndicator: { borderRadius: theme.borderRadius[200] },
158
+ }}
159
+ tabs={tabs}
160
+ />
143
161
  );
162
+ }
163
+ ```
144
164
 
145
- const CustomSegmentedTabFont = useCallback(
146
- (props) => <SegmentedTab {...props} font="label2" />,
147
- [],
165
+ #### Labels
166
+
167
+ Labels can be customized with any `ReactNode`, including instances of `Icon`.
168
+
169
+ ```jsx
170
+ import {
171
+ interpolateColor,
172
+ runOnJS,
173
+ useAnimatedReaction,
174
+ useSharedValue,
175
+ withSpring,
176
+ } from 'react-native-reanimated';
177
+ import { tabsSpringConfig } from '@coinbase/cds-mobile/tabs/Tabs';
178
+
179
+ function ColoredIcon({ tabId, name }) {
180
+ const { activeTab } = useTabsContext();
181
+ const isActive = activeTab?.id === tabId;
182
+ const theme = useTheme();
183
+
184
+ const progress = useSharedValue(isActive ? 1 : 0);
185
+ const [color, setColor] = useState(isActive ? theme.color.fgInverse : theme.color.fg);
186
+
187
+ useEffect(() => {
188
+ progress.value = withSpring(isActive ? 1 : 0, tabsSpringConfig);
189
+ }, [isActive, progress]);
190
+
191
+ useAnimatedReaction(
192
+ () => interpolateColor(progress.value, [0, 1], [theme.color.fg, theme.color.fgInverse]),
193
+ (newColor) => {
194
+ runOnJS(setColor)(newColor);
195
+ },
148
196
  );
149
197
 
198
+ return <Icon active name={name} size="s" styles={{ icon: { color } }} />;
199
+ }
200
+
201
+ function Example() {
202
+ const theme = useTheme();
150
203
  const tabs = [
151
- { id: 'buy', label: 'Buy', Component: CustomSegmentedTabColor },
152
- { id: 'sell', label: 'Sell', Component: CustomSegmentedTabFont },
153
- { id: 'convert', label: 'Convert', Component: CustomSegmentedTabColor },
204
+ { id: 'buy', label: <ColoredIcon name="chartLine" tabId="buy" /> },
205
+ { id: 'sell', label: <ColoredIcon name="chartCandles" tabId="sell" /> },
206
+ { id: 'convert', label: <ColoredIcon name="chartBar" tabId="convert" /> },
154
207
  ];
155
208
  const [activeTab, updateActiveTab] = useState(tabs[0]);
156
209
  const handleChange = useCallback((activeTab) => updateActiveTab(activeTab), []);
@@ -158,16 +211,23 @@ function Example() {
158
211
  <SegmentedTabs
159
212
  accessibilityLabel="Switch token action views"
160
213
  activeTab={activeTab}
214
+ borderRadius={300}
215
+ gap={0.5}
161
216
  onChange={handleChange}
217
+ padding={0.5}
218
+ styles={{
219
+ activeIndicator: { borderRadius: theme.borderRadius[200] },
220
+ }}
162
221
  tabs={tabs}
222
+ width="fit-content"
163
223
  />
164
224
  );
165
225
  }
166
226
  ```
167
227
 
168
- ### Custom Active Indicator
228
+ ### Custom Components
169
229
 
170
- You can customize the active indicator component and overall styling.
230
+ Use `TabComponent` and `TabsActiveIndicatorComponent` to fully customize the tabs and active indicator. Individual tabs can also be customized by providing a `Component` in the tab definition.
171
231
 
172
232
  ```jsx
173
233
  function Example() {
@@ -175,7 +235,7 @@ function Example() {
175
235
  <TabsActiveIndicator activeTabRect={activeTabRect} background="bgOverlay" />
176
236
  );
177
237
 
178
- const AnotherCustomSegmentedTab = ({ id, label, disabled }) => {
238
+ const CustomTab = ({ id, label, disabled }) => {
179
239
  const { activeTab } = useTabsContext();
180
240
  const isActive = activeTab?.id === id;
181
241
  const renderedLabel = (
@@ -201,7 +261,7 @@ function Example() {
201
261
  borderRadius={0}
202
262
  onChange={handleChange}
203
263
  tabs={tabs}
204
- TabComponent={AnotherCustomSegmentedTab}
264
+ TabComponent={CustomTab}
205
265
  TabsActiveIndicatorComponent={CustomActiveIndicator}
206
266
  />
207
267
  );
@@ -302,6 +362,7 @@ function Example() {
302
362
  | `right` | `string \| number` | No | `-` | - |
303
363
  | `rowGap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
304
364
  | `style` | `false \| RegisteredStyle<ViewStyle> \| Value \| AnimatedInterpolation<string \| number> \| WithAnimatedObject<ViewStyle> \| WithAnimatedArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>> \| readonly (Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>)[]> \| null` | No | `-` | - |
365
+ | `styles` | `{ root?: StyleProp<ViewStyle>; tab?: StyleProp<ViewStyle>; activeIndicator?: StyleProp<ViewStyle>; }` | No | `-` | Custom styles for individual elements of the SegmentedTabs component |
305
366
  | `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Used to locate this view in end-to-end tests. |
306
367
  | `textAlign` | `left \| right \| auto \| center \| justify` | No | `-` | - |
307
368
  | `textDecorationLine` | `none \| underline \| line-through \| underline line-through` | No | `-` | - |
@@ -314,3 +375,12 @@ function Example() {
314
375
  | `zIndex` | `number` | No | `-` | - |
315
376
 
316
377
 
378
+ ## Styles
379
+
380
+ | Selector | Static class name | Description |
381
+ | --- | --- | --- |
382
+ | `root` | `-` | Root container element |
383
+ | `tab` | `-` | Tab element |
384
+ | `activeIndicator` | `-` | Active indicator element |
385
+
386
+
@@ -226,6 +226,26 @@ function Example() {
226
226
  }
227
227
  ```
228
228
 
229
+ ### Custom Border Radius
230
+
231
+ Use `borderRadius` to customize the shape of both the handle and the background. Token values are resolved through the theme, so the handle and background always match.
232
+
233
+ ```jsx
234
+ function Example() {
235
+ const [checked, setChecked] = useState(false);
236
+
237
+ return (
238
+ <SlideButton
239
+ checked={checked}
240
+ onChange={setChecked}
241
+ uncheckedLabel="Swipe to confirm"
242
+ checkedLabel="Confirming..."
243
+ borderRadius={200}
244
+ />
245
+ );
246
+ }
247
+ ```
248
+
229
249
  ### Custom Background and Handle Components
230
250
 
231
251
  You can fully customize the background and handle by providing your own components via `SlideButtonBackgroundComponent` and `SlideButtonHandleComponent`. Your components receive typed props (`SlideButtonBackgroundProps` and `SlideButtonHandleProps`) including a `progress` spring value and the current `checked` state.
@@ -197,7 +197,7 @@ render(<Example />);
197
197
  | `disabled` | `boolean` | No | `-` | Disable interactions on all the tabs. |
198
198
  | `gap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `1` | The spacing between Tabs |
199
199
  | `ref` | `null \| (instance: View \| null) => void \| MutableRefObject<View \| null>` | No | `-` | - |
200
- | `styles` | `{ root?: StyleProp<ViewStyle>; tabs?: StyleProp<ViewStyle>; }` | No | `-` | - |
200
+ | `styles` | `({ root?: StyleProp<ViewStyle>; tab?: StyleProp<ViewStyle>; activeIndicator?: StyleProp<ViewStyle>; } & { root?: StyleProp<ViewStyle>; tabs?: StyleProp<ViewStyle>; })` | No | `-` | Custom styles for individual elements of the Tabs component |
201
201
  | `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
202
202
  | `width` | `string \| number` | No | `-` | The width of the scroll container, defaults to 100% of the parent container If the tabs are wider than the width of the container, paddles will be shown to scroll the tabs. |
203
203
 
@@ -207,6 +207,8 @@ render(<Example />);
207
207
  | Selector | Static class name | Description |
208
208
  | --- | --- | --- |
209
209
  | `root` | `-` | Root container element |
210
+ | `tab` | `-` | Tab element |
211
+ | `activeIndicator` | `-` | Active indicator element |
210
212
  | `tabs` | `-` | Tabs root element |
211
213
 
212
214