# Fabric to Fluent UI theme map
## Goals
* Customers only need to provide the v8 theme.
* Customers currently providing v7 are not left behind and things still work.
* Components which consume v0 or v7 themes still work under the unified ThemeProvider.
### V8 and v7 theming are interoppable
1. We have a clear understanding of the v8 theme, naming principles, and how users can consume them. Otherwise we don't know what we're moving to. Tracking here: https://hackmd.io/3xpJ-Q5LS1OG7KbcyzqYFA
2. When a user passes in a Fluent UI v7 theme, we provide it to v7 components as we do today.
3. When a user passes in a Fluent UI v7 theme, we can generate the v8 theme. Otherwise new v8 components won't render correctly.
4. When a user passes in a Fluent UI v8 theme, we need to generate the v7 theme to ensure components can render within.
#### Open questions:
Today, customers can use any of the following to set a theme:
`loadTheme` - Loads a global theme. Uses `load-themed-styles` and will repopulate any sass styles which rely on LTS tokens.
`Customizations.applySettings({ theme: myTheme });` - Loads a global default theme but does not provide LTS tokens.
`<Customizer settings={{ theme: theme }}>...</Customizer>` - Provides a contextual theme.
> **Question**: What will happen under the hood when you use `<ThemeProvider theme={theme}>` ? While it's easy for us to host a customizer to provide contextual styling, what about the global APIs? Do we continue supporting changing the global theme?
**Answer**: while the apis can still be provided so that customers dependent on legacy ways of providing theme aren't broken, the ThemeProvider should not support loading global settings. It is designed to provide theme through context.
### V8 and v0 theming is interoppable
Note not all of these may need to apply. Because we have a little more control here, we could for example allow pass through behaviors for v0 theme properties. This would allow us to update components to use v8+ theme over time.
5. When a user passes in a Fluent UI v0 theme, we need to be able to provide it to v0 components as we do today.
6. When a user passes in a Fluent UI v0 theme, we can generate a v8 theme.
7. When a user passes in a Fluent UI v8 theme, we can generate a v0 theme.
## Palette colors in v7
Today we have code which can take a brand color, background color, and foreground color, and translate it into this set. We should be able to:
Take in palette, ensure it's fully qualified.`generateCompatPalette(theme);`
Ensure the semantic colors are populated:
`generateCompatSemanticColors(theme)`
Note: all compat scenarios should be opt in later once we've fully moved to v8 theming in components. A customer
Ensure the v8 colors are populated from palette if missing. `generateColors(theme)`
|From|To|Description|
|-|-|-|
|themeDarker|
|themeDark|
|themeDarkAlt|
|themePrimary|
|themeSecondary|
|themeTertiary|
|themeLight|
|themeLighter|
|themeLighterAlt|
|black|
|blackTranslucent40|
|neutralDark|
|neutralPrimary|
|neutralPrimaryAlt|
|neutralSecondary|
|neutralSecondaryAlt|
|neutralTertiary|
|neutralTertiaryAlt|
|neutralQuaternary|
|neutralQuaternaryAlt|
|neutralLight|
|neutralLighter|
|neutralLighterAlt|
|accent| deprecated
|white|
|whiteTranslucent40|
|yellowDark|
|yellow|
|yellowLight|
|orange|
|orangeLight|
|orangeLighter|
|redDark|
|red|
|magentaDark|
|magenta|
|magentaLight|
|purpleDark|
|purple|
|purpleLight|
|blueDark|
|blueMid|
|blue|
|blueLight|
|tealDark|
|teal|
|tealLight|
|greenDark|
|green|
|greenLight|
## Semantic background colors in v7
| From | To | Description |
| ----------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| bodyBackground | --colors-body-background |
| bodyBackgroundHovered | --colors-body-hovered-background |
| bodyBackgroundChecked | --colors-body-checked-background |
| bodyStandoutBackground | n/a | The standout color for highlighted content backgrounds. For highlighted content when there is no emphasis, use the neutral variant instead. This should be a shade darker than bodyBackground in light themes, and a shade lighter in inverted themes. |
| bodyFrameBackground | tbd | The color for chrome adjacent to an area with bodyBackground. This can be used to provide visual separation of zones when using stronger colors, when using a divider line is not desired. In most themes, this should match the color of bodyBackground. | See also bodyFrameDivider. | | |
| bodyFrameDivider | tbd | Used as the border between a zone with bodyFrameBackground and a zone with bodyBackground. If bodyBackground and bodyFrameBackground are different, this should be the same color as bodyFrameBackground in order to visually disappear. |
| bodyDivider | --colors-body-divider |
| disabledBackground | --colors-body-disabled-background |
| disabledBorder | --colors-body-disabled-border | The default color for border of disabled controls; e.g. disabled slider, disabled toggle border. |
| focusBorder | --colors-body-focusBorder |
| cardStandoutBackground | tbd |
| cardShadow | tbd |
| cardShadowHovered | tbd |
| variantBorder | tbd | The color of the border that provides contrast between an element, such as a card, and a standout background. |
| variantBorderHovered | tbd | Hover color of border that provides contrast between an element, such as a card, and a standout background. |
| defaultStateBackground | | Background color for default/empty state graphical elements; eg default icons, empty section that needs user to fill in content, placeholder graphics, empty seats, etc. |
| infoBackground | --colors-info-background |
| errorBackground | tbd |
| blockingBackground |
| warningBackground |
| severeWarningBackground |
| successBackground |
|
| infoIcon | deprecate
| errorIcon | deprecate
| blockingIcon | deprecate
| warningIcon | deprecate
| severeWarningIcon | deprecate
| successIcon | deprecate
|
| messageLink |
| messageLinkHovered |
|
| inputBorder |
| smallInputBorder |
|
| inputBorderHovered
| inputBackground | --color-neutral-background
| inputBackgroundChecked |
| inputBackgroundCheckedHovered |
| inputPlaceholderBackgroundChecked |
| inputForegroundChecked |
| inputFocusBorderAlt |
| inputIconDisabled |
| inputIcon |
| inputIconHovered |
|
| buttonBackground |
| buttonBackgroundChecked |
| buttonBackgroundHovered |
| buttonBackgroundCheckedHovered |
| buttonBackgroundDisabled |
| buttonBackgroundPressed |
| buttonBorder |
| buttonBorderDisabled |
|
| primaryButtonBackground |
| primaryButtonBackgroundHovered |
| primaryButtonBackgroundPressed |
| primaryButtonBackgroundDisabled |
| primaryButtonBorder |
|
| accentButtonBackground | deprecate
|
| menuBackground |
| menuDivider |
| menuIcon |
| menuHeader |
| menuItemBackgroundHovered |
| menuItemBackgroundPressed |
| menuItemText |
| menuItemTextHovered |
|
| listBackground |
| listText |
| listItemBackgroundHovered |
| listItemBackgroundChecked |
| listItemBackgroundCheckedHovered |
| listHeaderBackgroundHovered |
| listHeaderBackgroundPressed |
# Semantic text colors
| From | To | Description |
| ------------------------- | ------------------------------------ | ----------- |
| bodyText | --colors-body-text |
| bodyTextChecked | --colors-body-checked-text |
| bodySubtext | --colors-body-subtext |
| actionLink | tbd |
| actionLinkHovered | tbd |
| link | --colors-body-link |
| linkHovered | --colors-body-hovered-link |
| disabledText | |
| disabledBodyText | |
| disabledSubtext | |
| disabledBodySubtext | |
| errorText | |
| messageText | |
| inputText | |
| inputTextHovered | |
| inputPlaceholderText | |
| buttonText | --colors-neutral-text |
| buttonTextHovered | --colors-neutral-hovered-text |
| buttonTextPressed | --colors-neutral-pressed-text |
| buttonTextDisabled | --colors-neutral-disabled-text |
| buttonTextChecked | --colors-neutral-checked-text |
| buttonTextCheckedHovered | --colors-neutral-checkedHovered-text |
| primaryButtonText | --colors-brand-text |
| primaryButtonTextHovered | --colors-brand-hovered-text |
| primaryButtonTextPressed | --colors-brand-pressed-text |
| primaryButtonTextDisabled | --colors-brand-disabled-text |
| accentButtonText | |
| listText | |
| listTextColor | |
| warningText | |
| successText | |
## Workitems
For customizer scoped settings:
```
theme = {
components: {
PrimaryButton: {
styles: {},
variants: {...}
}
}
}
```
```
// Today:
<Customizer { ...azureCustomizations }></Customizer>
// Tomorrow:
<ThemeProvider theme={
components: azureCustomizations.scopedSettings
}>
// or an alternative:
createTheme(azureCustomizations) // which moves scoped settings into components
// or we just fix azureCustomizations ourselves to be azureTheme
```
Ship with v8:
1. Ensure ThemeProvider passes through v0 and v7 theme.
2. In order to support scoped customizations, theme.scopedSettings or theme.components is forwarded to Customizer scoped settings.
3. Updates to theme designer (update codepen snippet to use ThemeProvider) v7 theme (for v8.)
4. Button docs need to be updated.
Needs to go beyond:
3. Finalize converged theme.
4. Get `@fluentui/base-theme` package scaffolded and populated with createTheme (light/dark/hc).
5. Support v8 to v7 converter.
6. Support v8 to v0 converter.
7. Update theme designer to v8.
```js
import { colors } from '...';
mergeStyles({
background: colors.brand.background // var(--colors-brand-backghround)
})
```
```sass
@import "~@fluentui/...";
.foo {
background: var($colorsBrandBackground);
}
```
## References
Customers can use the ThemeProvider to provide a v7 theme, and v7 components will use it. It's a pass through.
They can also provide a v0 theme, and v0 components will use it, pass through.
If they provide a v8 theme, we will do the work to generate enough v0 and v7 theme content to have it work with either.
```
// V8 incoming theme
const theme = createTheme({
tokens: {
colors: {
brand: {
background: 'red'
}
}
},
components: {}
})
// This generates this theme object which works with v7 and v0
{
tokens: { ... },
palette: {
themePrimary: 'red',
},
semanticColor: {
primaryButtonBackground: 'red'
},
}
```
Then over time, we update components to use tokens.
When nothing uses palette or semanticColors, we can move the compat version of createTheme to /compat and update createTheme to only provide tokens.
### How does a user get eased into the theming story
Goals
* Easy to go from v7 to v8
* Good performance
* Button customization is clear
Before:
```jsx
const customizations = {
settings: {
theme: {
palette: {...}
}
},
scopedSettings: {
Checkbox: {
styles: {
root: {
background: 'red'
}
}
}
}
}
<Customizer {...customizations}>
<Checkbox label="foo"/>
</Customizer>
```
After:
* Customizer has been replaced with ThemeProvider
* ThemeProvider only takes theme; not global/scoped settings.
* The theme object has been extended to take component settings, which previously would have been "scoped settings".
Here's the translation:
```jsx
const theme: {
palette: {...}
components: {
Checkbox: {
styles: {
root: {
background: 'red'
}
}
}
}
};
<ThemeProvider theme={theme}>
<Checkbox label="foo" />
</ThemeProvider
```
Buttons are an exception to this. Style overrides like explained above create a large amount of customizability, but also create performance concerns. Because the `styles` prop can be function, it must be evaluated on each render. We try to optimize this by only evaluating styles on style prop mutations, but in practice this becomes fragile and easy to break.
Buttons have been redesigned to leverage tokens (css variables) as an interface for tweaking the look and feel of a component. They are defined using variants:
```jsx
import { colors, colorValues } from '@fluentui/themes';
const theme: {
palette: {...},
tokens: {
colors: {
brand: {}
}
},
variants: {
ThemeProvider: {
base: {
colors: {
brand: {}
}
}
},
Button: {
base: {
},
primary: {
background: 'red', // --button-background: 'red'
hovered: {
background: 'pink' // --button-hovered-background: 'pink'
}
},
flyout: {
width: '16px'
},
}
}
};
<ThemeProvider theme={theme}>
<Button variant="primary" />
</ThemeProvider>
```
If you were using `styled` overrides to customize the button, chances are that the tokens should provide a reasonable conversion path. See the available tokens list for Button [here](TODOlink).