Commit dc15e96
authored
feat(Tabs, Android): handle
## Description
Adds support for `colorScheme` prop for `TabsHost` on Android.
This is a follow-up to
#3716 and
it follows
[RFC-0996](https://github.com/software-mansion/react-native-screens-labs/blob/main-issue-tracker/rfcs/0996-rtl-and-dark-mode.md).
Color scheme will be propagated down the hierarchy via custom solution
that mimics trait propagation on iOS. This solution is meant to be
reusable so that it can be later used in Stack v5 and Split.
## Changes
- handle `colorScheme` for Android
- `ColorSchemeProviding`, `ColorSchemeListener` interfaces
- reusable `ColorSchemeCoordinator`
- use `ColorSchemeCoordinator` in `TabsHost`
- adapt single feature test to Android
## Before & after - visual documentation
### Before
N/A - tabs would use system's or react-native's color scheme.
### After
https://github.com/user-attachments/assets/a6eba14f-33e4-4418-8a49-fd2cf02a3c57
## Test plan
Run `single-feature-tests/test-tabs-color-scheme.tsx`.
To test theme propagation you can use this test:
<details>
<summary>Theme propagation test</summary>
```tsx
import {
Appearance,
ColorSchemeName,
Platform,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import { Scenario } from '../../shared/helpers';
import { createAutoConfiguredTabs } from '../../shared/tabs';
import React, { useEffect, useState } from 'react';
import { SettingsPicker } from '../../../shared';
import { TabsHostProps } from 'react-native-screens';
import useTabsConfigState from '../../shared/hooks/tabs-config';
const SCENARIO: Scenario = {
name: 'Color Scheme',
key: 'test-tabs-color-scheme',
details: 'Tests how tabs handle system, React Native and prop color scheme.',
platforms: ['android', 'ios'],
AppComponent: App,
};
export default SCENARIO;
type InnerTabsParamList = {
Config: undefined;
Nested: undefined;
};
type TabsParamList = {
Config: undefined;
Nested: undefined;
};
// Inner tabs (one level deep)
function InnerConfigScreen() {
const [config, dispatch] = useTabsConfigState<InnerTabsParamList>();
return (
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
<View style={styles.section}>
<Text style={styles.heading}>Inner TabsHost color scheme</Text>
<SettingsPicker<NonNullable<TabsHostProps['colorScheme']>>
label={'colorScheme'}
value={config.colorScheme ?? 'inherit'}
onValueChange={function (value: TabsHostProps['colorScheme']): void {
dispatch({
type: 'tabBar',
config: {
colorScheme: value,
},
});
}}
items={['inherit', 'light', 'dark']}
/>
</View>
</ScrollView>
);
}
function InnerNestedScreen() {
return (
<View style={styles.containerCenter}>
<Text>Innermost screen</Text>
</View>
);
}
const InnerTabs = createAutoConfiguredTabs<InnerTabsParamList>({
Config: InnerConfigScreen,
Nested: InnerNestedScreen,
});
// Outer tabs
function NestedScreen() {
return (
<InnerTabs.Provider>
<InnerTabs.Autoconfig />
</InnerTabs.Provider>
);
}
function ConfigScreen() {
const [config, dispatch] = useTabsConfigState<TabsParamList>();
const [reactColorScheme, setReactColorScheme] =
useState<ColorSchemeName>('unspecified');
useEffect(() => {
dispatch({
type: 'tabScreen',
tabKey: 'Config',
config: {
safeAreaConfiguration: {
edges: {
bottom: true,
},
},
},
});
dispatch({
type: 'tabScreen',
tabKey: 'Nested',
config: {
safeAreaConfiguration: {
edges: {
bottom: true,
},
},
},
});
}, [dispatch]);
useEffect(() => {
Appearance.setColorScheme(reactColorScheme);
}, [reactColorScheme]);
return (
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
<View style={styles.section}>
<Text>
There are 3 sources of color scheme, in ascending order of precedence:
system, React Native and our property on TabsHost.
</Text>
</View>
<View style={styles.section}>
<Text style={styles.heading}>System color scheme</Text>
<Text>
Switch system color scheme via quick settings in notification drawer
(Android/iOS) or Cmd+Shift+A (iOS simulator).
</Text>
</View>
<View style={styles.section}>
<Text style={styles.heading}>React Native's color scheme</Text>
<SettingsPicker<ColorSchemeName>
label={'colorScheme'}
value={reactColorScheme}
onValueChange={function (value: ColorSchemeName): void {
setReactColorScheme(value);
}}
items={['unspecified', 'light', 'dark']}
/>
</View>
<View style={styles.section}>
<Text style={styles.heading}>Outer TabsHost color scheme</Text>
<SettingsPicker<NonNullable<TabsHostProps['colorScheme']>>
label={'colorScheme'}
value={config.colorScheme ?? 'inherit'}
onValueChange={function (value: TabsHostProps['colorScheme']): void {
dispatch({
type: 'tabBar',
config: {
colorScheme: value,
},
});
}}
items={['inherit', 'light', 'dark']}
/>
</View>
</ScrollView>
);
}
const Tabs = createAutoConfiguredTabs<TabsParamList>({
Config: ConfigScreen,
Nested: NestedScreen,
});
export function App() {
return (
<Tabs.Provider>
<Tabs.Autoconfig />
</Tabs.Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
containerCenter: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
content: {
padding: 20,
paddingTop: Platform.OS === 'android' ? 60 : undefined,
},
heading: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 5,
},
section: {
marginBottom: 10,
},
});
```
</details>
## Checklist
- [x] Included code example that can be used to test this change.
- [x] For visual changes, included screenshots / GIFs / recordings
documenting the change.
- [x] Ensured that CI passescolorScheme (dark mode) (#3723)1 parent 2c8c666 commit dc15e96
File tree
12 files changed
+237
-51
lines changed- android/src/main/java/com/swmansion/rnscreens/gamma
- common/colorscheme
- tabs/host
- apps/src/tests/single-feature-tests/tabs
- src
- components/tabs
- fabric/tabs
12 files changed
+237
-51
lines changedLines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
Lines changed: 120 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
Lines changed: 9 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
Lines changed: 38 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
20 | 24 | | |
21 | 25 | | |
22 | 26 | | |
| |||
35 | 39 | | |
36 | 40 | | |
37 | 41 | | |
| 42 | + | |
38 | 43 | | |
39 | 44 | | |
40 | 45 | | |
| |||
123 | 128 | | |
124 | 129 | | |
125 | 130 | | |
| 131 | + | |
126 | 132 | | |
127 | 133 | | |
128 | 134 | | |
| |||
161 | 167 | | |
162 | 168 | | |
163 | 169 | | |
164 | | - | |
165 | | - | |
166 | 170 | | |
167 | 171 | | |
168 | 172 | | |
| |||
185 | 189 | | |
186 | 190 | | |
187 | 191 | | |
| 192 | + | |
| 193 | + | |
188 | 194 | | |
189 | 195 | | |
190 | 196 | | |
| |||
230 | 236 | | |
231 | 237 | | |
232 | 238 | | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
233 | 244 | | |
234 | 245 | | |
235 | 246 | | |
| |||
239 | 250 | | |
240 | 251 | | |
241 | 252 | | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
242 | 258 | | |
243 | 259 | | |
244 | 260 | | |
| |||
392 | 408 | | |
393 | 409 | | |
394 | 410 | | |
395 | | - | |
396 | | - | |
397 | | - | |
398 | | - | |
| 411 | + | |
399 | 412 | | |
400 | 413 | | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
411 | | - | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
412 | 420 | | |
413 | | - | |
414 | | - | |
415 | | - | |
| 421 | + | |
| 422 | + | |
416 | 423 | | |
417 | 424 | | |
418 | | - | |
419 | | - | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
420 | 428 | | |
| 429 | + | |
| 430 | + | |
421 | 431 | | |
422 | 432 | | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
423 | 439 | | |
424 | 440 | | |
425 | 441 | | |
| |||
Lines changed: 14 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| 12 | + | |
11 | 13 | | |
12 | 14 | | |
13 | 15 | | |
| |||
81 | 83 | | |
82 | 84 | | |
83 | 85 | | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
84 | 98 | | |
85 | 99 | | |
86 | 100 | | |
| |||
Lines changed: 23 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
14 | | - | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
21 | | - | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
37 | 53 | | |
38 | 54 | | |
39 | 55 | | |
| |||
69 | 85 | | |
70 | 86 | | |
71 | 87 | | |
72 | | - | |
| 88 | + | |
73 | 89 | | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
| 90 | + | |
| 91 | + | |
78 | 92 | | |
79 | 93 | | |
80 | 94 | | |
81 | | - | |
82 | | - | |
83 | | - | |
| 95 | + | |
84 | 96 | | |
85 | 97 | | |
86 | 98 | | |
| |||
123 | 135 | | |
124 | 136 | | |
125 | 137 | | |
| 138 | + | |
126 | 139 | | |
127 | 140 | | |
128 | 141 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
57 | | - | |
58 | 57 | | |
59 | 58 | | |
60 | 59 | | |
| |||
0 commit comments