Skip to content

Commit

Permalink
Update theme documentation (microsoft#1438)
Browse files Browse the repository at this point in the history
* Replace some photos

* Replace some photos

* Rewrite some parts

* Some rewrite

* Better examples

* Small fixes

* Add more detail

* Edits

* Edits

* Edits

* Address feedback
  • Loading branch information
rurikoaraki authored Feb 15, 2022
1 parent ffd67ea commit 6a28406
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 100 deletions.
23 changes: 13 additions & 10 deletions docs/pages/Theming/Basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ If you're using FURN components, a benefit of using a theme is that FURN compone

If you're using FURN inside of an Office host, the theme on the win32 platform will also have access to palettes from Office.

## Applying a FURN theme
## Creating a FURN theme

Below are the steps outlining how to use FURN's theming system.
We have default themes for each platform. See [this page](./DefaultThemes.md) for how to get the default theme for a particular platform. These can also be used as a basis for a custom theme. For more information about customizing themes, take a look at [Custom Themes](./CustomTheme.md).

### ThemeProvider
## Applying a FURN theme

The available theme is defined by the `ThemeProvider`. It takes in a `ThemeReference` as a value.
### Populating the Theme

A `ThemeReference` is a class that creates a theme based on either another `Theme` or a parent `ThemeReference`. You can learn more about `ThemeReference` [here](https://github.com/microsoft/fluentui-react-native/blob/master/packages/framework/theme/README.md). We have a built in `ThemeReference` which you can access by calling `createDefaultTheme()`
The theme is made available by the `ThemeProvider`. It takes in a `ThemeReference` as a value, which is the object created by the functions referenced in the pages above.

```tsx
import { ThemeProvider } from '@fluentui-react-native/theme';
Expand All @@ -46,22 +46,25 @@ export const App = () => {
};
```

For more information about customizing themes, take a look at [Custom Themes](./CustomTheme.md). For information about our default themes, take a look at [Default Themes](./DefaultThemes.md).

### Accessing theme properties

You can use the `useFluentTheme()` hook to get the current theme inside a component.
You can use the `useFluentTheme()` hook to get the current theme inside a component. The hook must be used in a component that is under the `ThemeProvider` in the component tree, since it grabs the `context` from the `ThemeProvider`. If you try to access the theme outside of a `ThemeProvider`, you will get a hardcoded fallback theme.

```tsx
import { useFluentTheme } from '@fluentui-react-native/framework';
import { Text } from 'react-native';

export const Component = () => {
export const AppContent = () => {
const theme = useFluentTheme();

return <Text color={theme.colors.bodyText}>Hello World!</Text>;
};
```

The component will rerender if the theme is invalidated.
This is useful if you are styling a stock React Native component, or want to override the default style of a FURN component. It is not necessary if you are using the default style of a FURN component.

If you'd prefer to put the component's styles into a `StyleSheet` instead of accessing the `theme` directly, you can use [themed `StyleSheets`](./ThemedStylesheet.md)

## Testing a FURN theme

See [this page](../Testing/TestingThemesWin32.md) for information about testing themes.
218 changes: 128 additions & 90 deletions docs/pages/Theming/CustomTheme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,139 +2,177 @@

One of the powerful aspects of FURN theming is that it is heavily customizable. We recognize that users may have a need to change various parts of default themes, so we allow for several ways to specify overrides.

You can create a custom theme by either building on top of an existing `ThemeReference` or building one from scratch. This then can be used by [passing it into our `ThemeProvider`](./Basics.md), which makes the theme available for all child components of the provider.
## Creating a custom theme

## Different aspects of customization
There are two ways to make a custom theme: you can tack onto an existing one using `ThemeRecipes`, or create one from scratch. Generally it's easier to extend one of the default ones we provide.

There's two main ways to customize a FURN theme - you can specify how to customize components, or you can customize theme tokens directly by overriding certain tokens.
### Extending an existing `ThemeReference`

### Components
We have a concept of `ThemeRecipes` which allow for layering of partial theme objects to create the ultimately desired theme. `ThemeRecipes` are functions which take a `Theme` and spit out a [`PartialTheme`](../../../packages/theming/theme-types/src/Theme.types.ts), which is then deep merged into the base theme object.

The FURN theme has a components property which can be used to customize components:
You can extend one of our default themes by creating a `ThemeReference` using the default theme as the base theme, and then add your customization as a `ThemeRecipe`:

```ts
interface Theme {
...
components: {
[key: string]: object,
};
...
}
```

<font size=1>(Taken from the [`Theme` type definition](https://github.com/microsoft/fluentui-react-native/blob/master/packages/theming/theme-types/src/Theme.types.ts).)</font>
import { ThemeReference, ThemeProvider } from '@fluentui-react-native/theme';
import { createDefaultTheme } from '@fluentui-react-native/default-theme';
import { Theme } from '@fluentui-react-native/framework';

In order to have the theme override a particular component's styling, you'll need to specify a component's name and provide some overrides for the component's settings. The settings are an object that specifies how a component's tokens or slot's style are filled out.
const theme = new ThemeReference(createDefaultTheme(),
() => { return {{ colors: { buttonBackground: 'red' }}}}, // overrides the buttonBackground color token, all other colors are kept in tact
(theme: Theme) => {
return {
{ colors: { neutralBackground1: theme.colors.buttonBackground }}, // This is now red, because theme has previous recipe applied
{ spacing: s1: '10px' }
}},
// other recipes
);

```ts
components: {
<ComponentName>: {
<tokenName>: <overrideValue>
},
},
// Use created theme reference in ThemeProvider
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
```

For example, if you want to change the settings on the [Button component](https://github.com/microsoft/fluentui-react-native/blob/master/packages/components/Button/src/Button.settings.ts), you could do something like the following:
A good example of a custom theme from our repo is [the Caterpillar theme in the Tester App](../../../apps/fluent-tester/src/FluentTester/theme/applyTheme.ts).

```ts
components: {
Button: {
tokens: {
backgroundColor: 'primaryButtonBackground', // Different semantic color
color: 'neutralBackground1', // Alias token
},
_overrides:{
tokens:{
hovered: {
backgroundColor: theme.host.colors['AppShade10'], // Get brand color from host
color: theme.host.colors['Gray96'], // Get gray from host
borderColor: theme.host.palette.Bkg, // Get entry from palette from host
},
},
}
},
},
```
### `ThemeReference` from scratch

You can see what settings can be customized by looking at a component's settings, styling, or tokens file.
You can create your own `ThemeReference` and pass it into the `ThemeProvider`. To create a `ThemeReference` you'll need to create a new instance of `ThemeReference`. You can find the type definition [here](https://github.com/microsoft/fluentui-react-native/blob/master/packages/framework/theme/src/themeReference.ts).

## Theme property customization

There's two ways to customize a FURN theme's properties:

The advantage of this approach is that the customizations are targetted to a particular component, so the changes are localized.
1. Customize theme tokens directly by overriding certain tokens (recommended)
2. Specify how to customize FURN components for the whole theme

### Changing theme tokens directly

Theme tokens can be overridden directly as well. You can specify different color values for a particular set of color entries, add to the set of colors, or have different values for particular typography variants. You can see what can be overridden by looking at the [Theme type definition](https://github.com/microsoft/fluentui-react-native/blob/master/packages/theming/theme-types/src/Theme.types.ts).
Theme tokens can be overridden directly. You can specify different values for theme entries and add to the set of colors. You can see what can be overridden by looking at the [Theme type definition](https://github.com/microsoft/fluentui-react-native/blob/master/packages/theming/theme-types/src/Theme.types.ts).

This approach can be preferred if you need the customizations to be applied to all components.
This approach is useful if you need the customizations to be applied to all components.

#### Color example

```ts
color: {
buttonBackground: 'red',
neutralForeground1: theme.host.palette.Bkg,
otherToken: theme.colors.themePrimary,
}
(theme: Theme) => {
return {
colors: {
buttonBackground: 'red',
neutralForeground1: theme.host.palette.Bkg,
otherToken: theme.colors.themePrimary,
}
}
},
```

#### Typography example

```ts
typography: {
sizes: {
caption: 6,
},
weights: {
semiBold: '300',
},
families: {
cursive: 'Segoe UI',
},
variants: {
heroLargeSemibold: { face: 'cursive', size: 'heroLarge', weight: 'semiBold' }
(theme: Theme) => {
return {
typography: {
sizes: {
caption: 6,
},
weights: {
semiBold: '300',
},
families: {
cursive: 'Segoe UI',
},
variants: {
heroLargeSemibold: { face: 'cursive', size: 'heroLarge', weight: 'semiBold' }
}
}
}
}
},
```

#### Spacing example

```ts
spacing: {
s1: '10px';
}
(theme: Theme) => {
return {
spacing: {
s1: '10px';
}
}
},
```

## Creating a custom `ThemeReference`
### Components (Only for FURN components)

There are two ways to make a custom `ThemeReference`: you can tack onto an existing one using `ThemeRecipes`, or create one from scratch. Generally it's easier to extend one of the default ones we provide.
The FURN theme has a components property which can be used to customize all instances of a FURN component used under the theme:

### Theme reipces
```ts
interface Theme {
...
components: {
[key: string]: object,
};
...
}
```

<font size=1>(Taken from the [`Theme` type definition](https://github.com/microsoft/fluentui-react-native/blob/master/packages/theming/theme-types/src/Theme.types.ts).)</font>

We have a concept of `ThemeRecipes` which allow for layering of partial theme objects to create the ultimately desired theme. `ThemeRecipes` are functions which take a `Theme` and spit out a `PartialTheme`, which is then deep merged into the base them object.
NOTE: If you would prefer to customize one instance of a FURN component instead, use [the customize API](../../../packages/framework/composition/README.md).

You can extend one of our default themes by creating a `ThemeReference` using the default theme as the base theme, and then your customization as a `ThemeRecipe`:
In order to have the theme override a particular component's styling, you'll need to specify a component's name and provide some overrides for the component's tokens. The object specifies how a component's tokens should be overridden.

```ts
import { ThemeReference, ThemeProvider } from '@fluentui-react-native/theme';
import { createDefaultTheme } from '@fluentui-react-native/default-theme';
components: {
<ComponentName>: {
<tokenName>: <overrideValue>
},
},
```

const theme = new ThemeReference(createDefaultTheme(),
() => { return {{ colors: { buttonBackground: 'red' }}}}, // overrides the buttonBackground color token, all other colors are kept in tact
(theme) => {
return {
{ colors: { neutralBackground1: theme.colors.buttonBackground }}, // This is now red, because theme has previous recipe applied
{ spacing: s1: '10px' }
}},
// other recipes
);
For example, if you want to change the tokens on the [Button component](https://github.com/microsoft/fluentui-react-native/blob/master/packages/components/Button) for the whole theme, you could do something like the following:

// Use created theme reference in ThemeProvider
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
```ts
(theme: Theme) => {
return {
components: {
Button: {
backgroundColor: 'primaryButtonBackground', // Different semantic color
color: 'neutralBackground1', // Alias token
hovered: {
backgroundColor: theme.host.colors['AppShade10'], // Get brand color from host
color: theme.host.colors['Gray96'], // Get gray from host
borderColor: theme.host.palette.Bkg, // Get entry from palette from host
},
},
}
}
},
```

A good example from our repo is [the Office theme](https://github.com/microsoft/fluentui-react-native/blob/master/packages/theming/win32-theme/src/createOfficeTheme.ts).
You can see what settings can be customized by looking at a component's settings, styling, or tokens file.

### `ThemeReference` from scratch
For an example on the older framework:

You can create your own `ThemeReference` and pass it into the `ThemeProvider`. To create a `ThemeReference` you'll need to define the base, and add any ThemeRecipes you'd like. You can find the type definition [here](https://github.com/microsoft/fluentui-react-native/blob/master/packages/framework/theme/src/themeReference.ts).
```ts
(theme: Theme) => {
return {
components: {
Button: {
tokens: {
backgroundColor: 'primaryButtonBackground', // Different semantic color
color: 'neutralBackground1', // Alias token
},
_overrides:{
tokens:{
hovered: {
backgroundColor: theme.host.colors['AppShade10'], // Get brand color from host
color: theme.host.colors['Gray96'], // Get gray from host
borderColor: theme.host.palette.Bkg, // Get entry from palette from host
},
},
}
},
},
}
},
```
Binary file modified docs/pages/Theming/assets/android.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/pages/Theming/assets/default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/pages/Theming/assets/win32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6a28406

Please sign in to comment.