Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/6.x/docs/guides/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,54 @@ const theme = {
style={{ fontSize: 16, color: '#1C1B1F' }}
/>
```

### Switch

#### Explicit operability

A `Switch` now has to declare how it can be operated. Previously a switch with no `onValueChange` still rendered as an enabled, focusable control that did nothing when activated, and screen readers announced it as operable.

Pass `onValueChange` to make it interactive, or mark it `readOnly` or `disabled` to render it as a state indicator. A read-only switch keeps its enabled appearance and is still announced with its on/off state, but it is neither focusable nor pressable — it is not reported as disabled.

```tsx
// Before (v5) — an enabled switch that does nothing
<Switch value={isDarkTheme} />

// After (v6) — say which it is
<Switch value={isDarkTheme} onValueChange={setIsDarkTheme} />
<Switch value={isDarkTheme} readOnly />
<Switch value={isDarkTheme} disabled />
```

This most often shows up where the switch sits inside a row that owns the press:

```tsx
// After (v6)
<TouchableRipple onPress={toggleTheme}>
<View style={styles.row}>
<Text>Dark Theme</Text>
<View pointerEvents="none">
<Switch value={isDarkTheme} readOnly />
</View>
</View>
</TouchableRipple>
```

#### Selected icon color

The icon inside a selected switch now uses `onPrimaryContainer` instead of `primary`, matching the Material Design 3 spec and improving its contrast against the handle. If you theme `Switch` with a partial `theme.colors` override, add `onPrimaryContainer` alongside the roles you already override — omitted roles fall back to the app theme, which would leave the icon in the default palette.

```diff
const switchTheme = {
colors: {
primary: theme.colors.tertiary,
onPrimary: theme.colors.onTertiary,
primaryContainer: theme.colors.tertiaryContainer,
+ onPrimaryContainer: theme.colors.onTertiaryContainer,
},
};
```

#### Touch target height

`Switch` now reserves the 48dp minimum touch target Material Design requires, so it occupies 48dp of height instead of 40dp. Nothing painted changed size — the track is still 52×32 — but rows containing a switch may become slightly taller.
12 changes: 6 additions & 6 deletions example/src/DrawerItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ function DrawerItems() {
<View style={[styles.preference, styles.v3Preference]}>
<Text variant="labelLarge">Use Dynamic Theme</Text>
<View pointerEvents="none">
<Switch value={shouldUseDynamicTheme} />
<Switch value={shouldUseDynamicTheme} readOnly />
</View>
</View>
</TouchableRipple>
Expand All @@ -187,7 +187,7 @@ function DrawerItems() {
<View style={[styles.preference, styles.v3Preference]}>
<Text variant="labelLarge">Dark Theme</Text>
<View pointerEvents="none">
<Switch value={isDarkTheme} />
<Switch value={isDarkTheme} readOnly />
</View>
</View>
</TouchableRipple>
Expand All @@ -196,7 +196,7 @@ function DrawerItems() {
<View style={[styles.preference, styles.v3Preference]}>
<Text variant="labelLarge">RTL</Text>
<View pointerEvents="none">
<Switch value={isRTL} />
<Switch value={isRTL} readOnly />
</View>
</View>
</TouchableRipple>
Expand All @@ -205,7 +205,7 @@ function DrawerItems() {
<View style={[styles.preference, styles.v3Preference]}>
<Text variant="labelLarge">Collapsed drawer *</Text>
<View pointerEvents="none">
<Switch value={collapsed} />
<Switch value={collapsed} readOnly />
</View>
</View>
</TouchableRipple>
Expand All @@ -214,7 +214,7 @@ function DrawerItems() {
<View style={[styles.preference, styles.v3Preference]}>
<Text variant="labelLarge">Custom font *</Text>
<View pointerEvents="none">
<Switch value={customFontLoaded} />
<Switch value={customFontLoaded} readOnly />
</View>
</View>
</TouchableRipple>
Expand All @@ -225,7 +225,7 @@ function DrawerItems() {
{isIOS ? 'Highlight' : 'Ripple'} effect *
</Text>
<View pointerEvents="none">
<Switch value={rippleEffectEnabled} />
<Switch value={rippleEffectEnabled} readOnly />
</View>
</View>
</TouchableRipple>
Expand Down
2 changes: 1 addition & 1 deletion example/src/Examples/FABExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ const FABExample = () => {
title="Show FAB"
right={() => (
<View pointerEvents="none">
<Switch value={showFab} />
<Switch value={showFab} readOnly />
</View>
)}
onPress={() => setShowFab((v) => !v)}
Expand Down
5 changes: 5 additions & 0 deletions example/src/Examples/SwitchExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const SwitchExample = () => {
primary: theme.colors.tertiary,
onPrimary: theme.colors.onTertiary,
primaryContainer: theme.colors.tertiaryContainer,
onPrimaryContainer: theme.colors.onTertiaryContainer,
secondary: theme.colors.tertiary,
},
}),
Expand Down Expand Up @@ -88,6 +89,10 @@ const SwitchExample = () => {
/>
</Row>

<Row label="Read-only">
<Switch value={defaultOn} readOnly />
</Row>

<View
style={[
styles.separator,
Expand Down
2 changes: 1 addition & 1 deletion example/src/Examples/TextInputExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const TextInputDemo = ({ variant }: TextInputDemoProps) => {
<View style={styles.switchRow}>
<Text variant="bodyMedium">{label}</Text>
<View pointerEvents="none">
<Switch value={controls[key]} />
<Switch value={controls[key]} readOnly />
</View>
</View>
</TouchableRipple>
Expand Down
Loading