23ad7283d0 | ||
---|---|---|
.. | ||
config | ||
etc | ||
jest | ||
src | ||
.eslintignore | ||
.eslintrc.js | ||
.npmignore | ||
CHANGELOG.json | ||
CHANGELOG.md | ||
README.md | ||
babel.config.js | ||
just.config.js | ||
package.json | ||
tsconfig.json |
README.md
Theming React Native
This package serves as an entry point which aggregates and re-exports some of the various features in this repo for those who want to quickly get started.
Getting Started
Update package.json & install dependencies
You may want a few different packages from this repo. Let's start with the following:
@uifabricshared/theming-react-native
@fluentui-react-native/themed-stylesheets
for styling react-native's primitives components.
E.g. In your package.json file:
{
"name": "my-app",
"version": "0.10.17",
"description": "An app with lots of cool features",
"main": "lib/index.js",
"dependencies": {
"@uifabricshared/theming-react-native": "^0.2.0",
"@fluentui-react-native/themed-stylesheet": "^0.2.0"
}
}
And then run yarn
, npm install
, rush install
, or an equivalent command to update your node_modules.
The ThemeProvider
All consumers of these theming packages will want at least one ThemeProvider
in their tree. Descendents of a ThemeProvider
will have access to the current theme object via a react context.
Property | Type | Description |
---|---|---|
theme | string? | Changes the ThemeContext.Value to the Theme object in the current registry with the given name. If unspecified, or set to '', the default theme will be used. |
registry | ThemeRegistry? | Changes the theme registry context (which also changes the theme to this registry's default theme if no theme prop is provided). The active theme registry will be used for all Theme lookups performed by this and descendant ThemeProviders . Most consumers will want at least one ThemeProvider near the root of their Component tree that specifies the primary registry. |
Accessing the ThemeContext
Once you've added a ThemeProvider to your tree, functional component descendents will have access to the Theme context via the useTheme hook. To access the theme from within a functional component, see below:
// MyComponent.tsx
import * as React from 'react';
import { useTheme } from '@uifabricshared/theming-react-native';
export const MyComponent: React.FunctionComponent = (_props: {}) => {
// This hook retrieves the theme from the context set by the nearest parent ThemeProvider
const theme = useTheme();
const themeColor = theme.colors.bodyText;
return <SomeComponent color={themeColor} />;
};
If you're writing class components instead of functional components, you'll need use the ThemeContext.Consumer
directly like so:
// OtherComponent.tsx
import * as React from 'react';
import { ThemeContext, ITheme } from '@uifabricshared/theming-react-native';
export class OtherComponent extends React.Component {
public render(): JSX.Element {
return (
<ThemeContext.Consumer>
{(theme: ITheme) => {
const themeColor = theme.colors.bodyText;
return <SomeComponent color={themeColor} />;
}}
</ThemeContext.Consumer>
);
}
}
Using a ThemeRegistry with a ThemeProvider
While a 'greenfield' app developer might be fine without setting a ThemeRegistry with their ThemeProvider, any 'brownfield' app where there are multiple islands of react-native UI being hosted which use the same JavaScript host instance may want to avoid leaking theme information into the other islands of UX. Creating your own ThemeRegistry and providing this as additional context near the root of your component tree can help you manage this behavior.
Note: Many users will only need a single theme registry. This should be provided to the top ThemeProvider which is above all other ThemeProviders and theme-aware UI. Subsequent ThemeProviders will be used to change the Theme context.
// App.tsx
import { ThemeProvider, createPlatformThemeRegistry } from '@uifabricshared/theming-react-native';
import { MyAppImpl } from './MyAppImpl';
export const myThemeRegistry = createPlatformThemeRegistry();
export default function App() {
return (
<ThemeProvider registry={myThemeRegistry}>
<MyAppImpl />
</ThemeProvider>
);
}
The ThemeRegistry is a crucial piece. It's responsible for
- Initializing theme object with platform defaults from the Native Module
- Listening to the Theming Native Module for changes to the platform theme
- Updating dependent themes as parent themes change (such as a platform theme change)
You can read more about the ThemeRegistry here.
Theme-aware Primitives
Create a Themed Stylesheet
The themed-stylesheet
package allows you to author View/Text/Image Style objects similar to StyleSheet.create(...);
. You can learn more at the themed-stylesheet's README
// styles.ts
import { ITheme } from '@uifabricshared/theming-react-native';
export const getThemedStyles = themedStyleSheet((t: ITheme) => {
return {
style1: {
backgroundColor: t.colors.background,
borderStyle: 'solid',
borderWidth: 1,
},
style2: {
backgroundColor: t.colors.primaryButtonBackground,
borderStyle: 'solid',
borderWidth: 1,
},
};
});
Using the hook with themed stylesheets
// MyAppImpl.tsx
import * as React from 'react';
import { Text, ViewProps } from 'react-native';
import { useTheme } from '@uifabricshared/theming-react-native';
import { getThemedStyles } from './styles';
export const ThemedView: React.FunctionComponent<ViewProps> = (p: ViewProps) => {
const { userStyle, ...rest } = p;
const theme = useTheme();
const styles = getThemedStyles(theme);
return <View styles={[userStyle, styles.style1]} {...rest} />;
};
export const MyAppImpl = () => {
return (
<ThemedView>
<Text>Hello, World!</Text>
</ThemedView>
);
};
Using different Platform Themes
Certain platforms will have multiple platform theme definitions. If you want the default theme to be initialized with a specific platform theme, or want to use a different platform theme for a portion of your UI, you can get the platform themes through the ThemingModuleHelper.
// App.tsx
import { ThemeProvider, createPlatformThemeRegistry, ThemingModuleHelper } from '@uifabricshared/theming-react-native';
// Initializes the Default Theme with the 'TaskPane' platform theme, implicitly pulled from ThemingModuleHelper
export const myThemeRegistry = createPlatformThemeRegistry('TaskPane');
// Get the 'TaskPaneCard' theme from the ThemingModuleHelper
const taskPaneCardTheme = ThemingModuleHelper.createPlatformThemeDefinition('TaskPaneCard');
// Registers it with the name 'PlatformTaskPaneCard'
myThemeRegistry.registerTheme(taskPaneCardTheme, 'PlatformTaskPaneCard');
export default function App() {
return (
<ThemeProvider registry={myThemeRegistry}>
<SomeComponent />
<ThemeProvider theme="PlatformTaskPaneCard">
<SomeComponent />
</ThemeProvider>
</ThemeProvider>
);
}