Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: move theming to core and pass theme to options (#11707)
This moves theming logic to `@react-navigation/core`. So we can now pass the `theme` to the `options` and `screenOptions` callbacks. As `options`. Often specifies UI elements and styles, it's nice to have theme available there.
- Loading branch information
Showing
15 changed files
with
223 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { render } from '@testing-library/react-native'; | ||
import * as React from 'react'; | ||
|
||
import { BaseNavigationContainer } from '../BaseNavigationContainer'; | ||
import { Screen } from '../Screen'; | ||
import { useTheme } from '../theming/useTheme'; | ||
import { useNavigationBuilder } from '../useNavigationBuilder'; | ||
import { MockRouter } from './__fixtures__/MockRouter'; | ||
|
||
it('can get current theme with useTheme', () => { | ||
const TestNavigator = (props: any): any => { | ||
const { state, descriptors } = useNavigationBuilder(MockRouter, props); | ||
|
||
return state.routes.map((route) => descriptors[route.key].render()); | ||
}; | ||
|
||
const Test = () => { | ||
const theme = useTheme(); | ||
|
||
expect(theme).toEqual({ | ||
colors: { | ||
primary: 'tomato', | ||
}, | ||
}); | ||
|
||
return null; | ||
}; | ||
|
||
// Incomplete theme for testing | ||
const theme: any = { | ||
colors: { | ||
primary: 'tomato', | ||
}, | ||
}; | ||
|
||
render( | ||
<BaseNavigationContainer theme={theme}> | ||
<TestNavigator> | ||
<Screen name="foo" component={Test} /> | ||
</TestNavigator> | ||
</BaseNavigationContainer> | ||
); | ||
}); | ||
|
||
it("throws if theme isn't passed to BaseNavigationContainer", () => { | ||
const TestNavigator = (props: any): any => { | ||
const { state, descriptors } = useNavigationBuilder(MockRouter, props); | ||
|
||
return state.routes.map((route) => descriptors[route.key].render()); | ||
}; | ||
|
||
const Test = () => { | ||
// eslint-disable-next-line react-hooks/rules-of-hooks | ||
expect(() => useTheme()).toThrow("Couldn't find a theme"); | ||
|
||
return null; | ||
}; | ||
|
||
render( | ||
<BaseNavigationContainer> | ||
<TestNavigator> | ||
<Screen name="foo" component={Test} /> | ||
</TestNavigator> | ||
</BaseNavigationContainer> | ||
); | ||
}); | ||
|
||
it('throws if useTheme is used without BaseNavigationContainer', () => { | ||
const Test = () => { | ||
// eslint-disable-next-line react-hooks/rules-of-hooks | ||
expect(() => useTheme()).toThrow("Couldn't find a theme"); | ||
|
||
return null; | ||
}; | ||
|
||
render(<Test />); | ||
}); | ||
|
||
it('passes theme to options prop', () => { | ||
const TestNavigator = (props: any): any => { | ||
const { state, descriptors } = useNavigationBuilder(MockRouter, props); | ||
|
||
expect(descriptors[state.routes[0].key].options).toEqual({ | ||
title: 'tomato', | ||
}); | ||
|
||
return null; | ||
}; | ||
|
||
// Incomplete theme for testing | ||
const theme: any = { | ||
colors: { | ||
primary: 'tomato', | ||
}, | ||
}; | ||
|
||
render( | ||
<BaseNavigationContainer theme={theme}> | ||
<TestNavigator> | ||
<Screen | ||
name="foo" | ||
component={React.Fragment} | ||
options={({ theme }: any) => ({ title: theme.colors.primary })} | ||
/> | ||
</TestNavigator> | ||
</BaseNavigationContainer> | ||
); | ||
}); | ||
|
||
it('passes theme to screenOptions prop', () => { | ||
const TestNavigator = (props: any): any => { | ||
const { state, descriptors } = useNavigationBuilder(MockRouter, props); | ||
|
||
expect(descriptors[state.routes[0].key].options).toEqual({ | ||
title: 'tomato', | ||
}); | ||
|
||
expect(descriptors[state.routes[1].key].options).toEqual({ | ||
title: 'tomato', | ||
}); | ||
|
||
return null; | ||
}; | ||
|
||
// Incomplete theme for testing | ||
const theme: any = { | ||
colors: { | ||
primary: 'tomato', | ||
}, | ||
}; | ||
|
||
render( | ||
<BaseNavigationContainer theme={theme}> | ||
<TestNavigator | ||
screenOptions={({ theme }: any) => ({ title: theme.colors.primary })} | ||
> | ||
<Screen name="foo" component={React.Fragment} /> | ||
<Screen name="bar" component={React.Fragment} /> | ||
</TestNavigator> | ||
</BaseNavigationContainer> | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import * as React from 'react'; | ||
|
||
export const ThemeContext = React.createContext< | ||
ReactNavigation.Theme | undefined | ||
>(undefined); | ||
|
||
ThemeContext.displayName = 'ThemeContext'; |
3 changes: 1 addition & 2 deletions
3
...ages/native/src/theming/ThemeProvider.tsx → packages/core/src/theming/ThemeProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.