-
Notifications
You must be signed in to change notification settings - Fork 221
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: Proof of concept of theming * refactor: Move all theming into a new folder in core * feat(core): Add the ability to override default Canvas theme * feat(core): Iterate on theme structure * feat(banner): Implement theming * feat(core): Add story for default theme * feat(core): Add helper to get theme if ThemeProvider doesn't exist * chore(avatar): Remove theme test component * feat: Add theme as a knob to customize in real time * fix: Add keys to resolve warning in storybook * docs(core): Add to CanvasProvider docs * docs(core): Update provider documenation * feat(core): Add breakpoints to theme * refactor(labs): Move theming to labs * chore: Restore InputProviderDecorator * docs: Update docs in core and labs core to reflect the move * fix(banner): Remove unnecessary console log * feat(labs): Add support for window theme object * docs(labs): Add breakpoints to theming docs * refactor(labs): Rename getTheme to useTheme so it's more hook-like * fix(labs): Lock the keys of breakpoints with as const * refactor(labs): Expand on the theme object * feat(labs): Add color expansion support to theme object * fix(labs): Fix type error in theme story * feat(labs): Prevent error from chroma on invalid input color * fix(labs): Only expand main color if the others aren't defined * feat(labs): Use enum for color direction to make shift fn more readable * fix(labs): Remove unnecessary breakpoints index signature * chore: Cleanup after rebase * refactor: Move useTheme into its own file * fix(labs): Allow createCanvasTheme to be called without a palette * docs(labs): Fix readme typo * refactor(labs): Decouple window theme from CanvasProvider * docs(labs): Document theme breakpoint functionality * feat(labs): Add styled function to avoid explicitly useTheme() call * fix(labs): Add missing window global after it got removed * test(labs): Add tests for useTheme and createCanvasTheme * chore: Undo formatting changes in storybook config * fix(labs): Use lodash merge instead of deepmerge * fix(labs): Add missing deps * docs: Update documentation * refactor(labs): Roll our own ThemeProvider * chore: Remove emotion-theming dep since we're no longer using it * fix: Lock emotion-theming at 10.0.10 * refactor(labs): Update window.wdCanvas.theme to match existing usage * chore: Update chroma-js version * feat(core): Make InputProvider noop if it's nested within another * fix(core): Add missing initializer to InputProvider * refactor(banner): Remove theme functionality from Banner for now * chore: Revert changes to avatar and banner
- Loading branch information
Showing
26 changed files
with
1,075 additions
and
57 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 |
---|---|---|
@@ -1,6 +1,23 @@ | ||
import type from './lib/type'; | ||
import space from './lib/space'; | ||
import CanvasProvider from './lib/CanvasProvider'; | ||
import {breakpoints, CanvasBreakpoints, BreakpointKey} from './lib/theming/breakpoints'; | ||
import createCanvasTheme from './lib/theming/createCanvasTheme'; | ||
import styled from './lib/theming/styled'; | ||
import useTheme from './lib/theming/useTheme'; | ||
|
||
export default type; | ||
export {type, space}; | ||
export { | ||
breakpoints, | ||
type, | ||
space, | ||
BreakpointKey, | ||
CanvasBreakpoints, | ||
CanvasProvider, | ||
createCanvasTheme, | ||
styled, | ||
useTheme, | ||
}; | ||
export * from './lib/type'; | ||
export * from './lib/theming/types'; | ||
export * from './lib/theming/theme'; |
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,24 @@ | ||
import * as React from 'react'; | ||
import {InputProvider} from '@workday/canvas-kit-react-core'; | ||
import {CanvasTheme} from './theming/types'; | ||
import {ThemeProvider, defaultCanvasTheme} from './theming/theme'; | ||
|
||
export interface CanvasProviderProps { | ||
theme: CanvasTheme; | ||
} | ||
|
||
export default class CanvasProvider extends React.Component<CanvasProviderProps> { | ||
static defaultProps = { | ||
theme: defaultCanvasTheme, | ||
}; | ||
|
||
render() { | ||
const {children, theme} = this.props; | ||
|
||
return ( | ||
<ThemeProvider value={theme}> | ||
<InputProvider>{children}</InputProvider> | ||
</ThemeProvider> | ||
); | ||
} | ||
} |
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,253 @@ | ||
# Canvas Kit Theming | ||
|
||
Canvas Kit Core contains wrappers and types to enabling theming of Canvas components. | ||
|
||
## Installation | ||
|
||
```sh | ||
yarn add @workday/canvas-kit-labs-react-core | ||
``` | ||
|
||
or | ||
|
||
```sh | ||
yarn add @workday/canvas-kit-labs-react-core | ||
``` | ||
|
||
## Usage | ||
|
||
Wrap all of your Canvas components with the `CanvasProvider` higher order component. Usually this | ||
would go in the highest level component of your application. This includes an | ||
[`InputProvider`](../../README.md#input-provider) and includes all global configuration needed for | ||
our Canvas Components. | ||
|
||
```tsx | ||
import * as React from 'react'; | ||
import {CanvasProvider} from '@workday/canvas-kit-labs-react-core'; | ||
|
||
<CanvasProvider>{/* All your components containing any Canvas components */}</CanvasProvider>; | ||
``` | ||
|
||
## Component Props | ||
|
||
### Required | ||
|
||
> None | ||
### Optional | ||
|
||
#### `theme: CanvasTheme` | ||
|
||
> The theme to be used throughout the children of the `CanvasProvider` component. | ||
Default: `defaultCanvasTheme` | ||
|
||
## Theme Object | ||
|
||
The Canvas theme is based on the following object: | ||
|
||
```ts | ||
export const defaultCanvasTheme: CanvasTheme = { | ||
palette: { | ||
primary: { | ||
lightest: colors.blueberry100, | ||
light: colors.blueberry200, | ||
main: colors.blueberry400, | ||
dark: colors.blueberry500, | ||
darkest: colors.blueberry600, | ||
contrast: colors.frenchVanilla100, | ||
}, | ||
alert: { | ||
lightest: colors.cantaloupe100, | ||
light: colors.cantaloupe300, | ||
main: colors.cantaloupe400, | ||
dark: colors.cantaloupe500, | ||
darkest: colors.cantaloupe600, | ||
contrast: colors.frenchVanilla100, | ||
}, | ||
error: { | ||
lightest: colors.cinnamon100, | ||
light: colors.cinnamon300, | ||
main: colors.cinnamon500, | ||
dark: colors.cinnamon600, | ||
darkest: '#80160E', | ||
contrast: colors.frenchVanilla100, | ||
}, | ||
success: { | ||
lightest: colors.greenApple100, | ||
light: colors.greenApple300, | ||
main: colors.greenApple600, | ||
dark: '', | ||
darkest: '', | ||
contrast: colors.frenchVanilla100, | ||
}, | ||
neutral: { | ||
lightest: colors.soap200, | ||
light: colors.soap300, | ||
main: colors.soap600, | ||
dark: colors.licorice300, | ||
darkest: colors.licorice400, | ||
contrast: colors.frenchVanilla100, | ||
}, | ||
common: { | ||
focusOutline: colors.blueberry400, | ||
}, | ||
}, | ||
breakpoints: { | ||
values: { | ||
zero: 0, | ||
s: 600, | ||
m: 960, | ||
l: 1280, | ||
xl: 1920, | ||
}, | ||
up, | ||
down, | ||
between, | ||
only, | ||
}, | ||
}; | ||
``` | ||
|
||
Any changes will be reflected across all supported components. You are also able to consume for your | ||
own use cases. | ||
|
||
## Custom Theme | ||
|
||
The `CanvasProvider` accepts a full or partial theme object to give a branded look to the component | ||
library. Pass your theme into `createCanvasTheme` and use the return value for the `theme` prop. | ||
|
||
If you only set a `main` color, the rest of the respective palette will be automatically generated | ||
(note text `contrast` color will always return white if not specified). | ||
|
||
Example: | ||
|
||
```tsx | ||
import { | ||
CanvasProvider, | ||
PartialCanvasTheme, | ||
createCanvasTheme, | ||
} from '@workday/canvas-kit-labs-react-core'; | ||
|
||
const theme: PartialCanvasTheme = { | ||
palette: { | ||
primary: { | ||
main: colors.cantaloupe400, | ||
}, | ||
}, | ||
}; | ||
|
||
<CanvasProvider theme={createCanvasTheme(theme)}> | ||
{/* Your app with Canvas components */} | ||
</CanvasProvider>; | ||
``` | ||
|
||
### Nesting Theme Providers | ||
|
||
It is possible to set a theme for a specific component or set of components within your React tree. | ||
This is generally discouraged for consistency reasons, but may be required in some contexts (a green | ||
`Switch` component for example). To do this, you must use the `ThemeProvider` component. The inner | ||
theme will override the outer theme. | ||
|
||
```tsx | ||
import * as React from 'react'; | ||
import {CanvasProvider, CanvasTheme, ThemeProvider} from '@workday/canvas-kit-labs-react-core'; | ||
import {Switch} from '@workday/canvas-kit-react-switch'; | ||
|
||
const theme: PartialCanvasTheme = { | ||
palette: { | ||
primary: { | ||
main: colors.greenApple400, | ||
}, | ||
}, | ||
}; | ||
|
||
<CanvasProvider> | ||
{/* All your components containing any Canvas components */} | ||
<ThemeProvider value={createCanvasTheme(theme)}> | ||
<Switch checked={true} /> | ||
</ThemeProvider> | ||
</CanvasProvider>; | ||
``` | ||
|
||
### Context Alternative | ||
|
||
If, for whatever reason, you're not able to use React Contexts, we offer an alternative. A good | ||
example of this is an app with many small React trees. | ||
|
||
Simply set your theme on the window object like so: | ||
|
||
```tsx | ||
// If using typescript, you will need to declare this on the window object | ||
declare global { | ||
interface Window { | ||
workday: { | ||
canvas: { | ||
theme?: CanvasTheme; | ||
}; | ||
}; | ||
} | ||
} | ||
|
||
const theme: PartialCanvasTheme = { | ||
palette: { | ||
primary: { | ||
main: colors.greenApple400, | ||
}, | ||
}, | ||
}; | ||
|
||
window.workday.canvas.theme = createCanvasTheme(theme); | ||
``` | ||
|
||
Note if any of the window object hasn't been defined, you will need to change your assignment. For | ||
example: | ||
|
||
```tsx | ||
window.workday = { | ||
canvas: { | ||
theme: createCanvasTheme(theme); | ||
} | ||
} | ||
``` | ||
|
||
If the theme is not available via a context, Canvas Kit components will attempt to pull it from this | ||
variable before falling back to the default theme. | ||
|
||
## Breakpoints | ||
|
||
Our breakpoint system is customized within the theme object. `theme.breakpoints.values` contains the | ||
various widths that our components adjust at: | ||
|
||
| Name | Size (px) | | ||
| ------ | --------- | | ||
| `zero` | 0 | | ||
| `s` | 600 | | ||
| `m` | 960 | | ||
| `l` | 1280 | | ||
| `xl` | 1920 | | ||
|
||
There are also several functions to help with generating media queries: | ||
|
||
#### `up: (key: BreakpointFnParam) => string` | ||
|
||
> Returns a media query reflecting your specified size and up. Works with the enum (e.g. | ||
> BreakpointKey.m) or the string (e.g. 'm'). Example: theme.breakpoints.up(BreakpointKey.m) => | ||
> '@media (min-width:960px)' | ||
#### `down: (key: BreakpointFnParam) => string` | ||
|
||
> Returns a media query reflecting your specified size and down. Works with the enum or the string | ||
> (e.g. 'm'). Example: theme.breakpoints.down(BreakpointKey.m) => '@media (max-width:1279.5px)' | ||
#### `between: (start: BreakpointFnParam, end: BreakpointFnParam) => string` | ||
|
||
> Returns a media query reflecting the sizes between your specified breakpoints. Works with the enum | ||
> or the string (e.g. 'm'). Example: theme.breakpoints.between(BreakpointKey.m, BreakpointKey.l) => | ||
> '@media (min-width:960px) and (max-width:1919.5px)' | ||
#### `only: (key: BreakpointFnParam) => string` | ||
|
||
> Returns a media query reflecting the size swithin your specified breakpoint. Works with the enum | ||
> or the string (e.g. 'm'). Example: theme.breakpointsonly(BreakpointKey.m) => '@media | ||
> (min-width:960px) and (max-width:1279.5px)' |
Oops, something went wrong.