Skip to content

Commit 7a93290

Browse files
matyasfHerrTopi
authored andcommitted
docs(many): reorganize docs pages
remove packages menu point, because they dont add extra info add the documentation of emotion to the developer guide, reorganize theming docs move testing menu to the Contributor guides submenu
1 parent 6ac2fc5 commit 7a93290

File tree

137 files changed

+660
-1257
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+660
-1257
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
---
2+
title: Theming engine basics
3+
category: Contributor Guides/theming
4+
order: 1
5+
---
6+
7+
## InstUI's theming engine
8+
9+
InstUI's theming engine allows each UI component can to be used in isolation and support multiple themes, including dynamic themes provided at runtime, while still working within a system of components that use a shared global theme. It uses the [Emotion design library's](https://emotion.sh/) under the hood to convert JavaScript objects to CSS.
10+
11+
### Motivation
12+
13+
1. Two-tiered theme variable system: system-wide variables + component level variables. With this variable system, components can be themed, tested, and rendered in isolation from the rest of the system, and we can mitigate issues that may arise with system-wide theme updates.
14+
15+
2. Runtime theme application and definition: to apply user/account level themes without using the CSS cascade.
16+
17+
3. Prevent CSS Cascade bugs: All components should specify variants via props or component level theme variables only (no className or style overrides) with a clear API and should not rely on any external styles.
18+
19+
4. Theme variables should be accessible in JS.
20+
21+
5. All component styles should be scoped to the component.
22+
23+
6. Pre-render/server-side render support (inline critical CSS).
24+
25+
7. Use a popular, well maintained and broadly adopted JS design and theming library that supports runtime theme switching ([Emotion](https://emotion.sh/)).
26+
27+
### InstUISettingsProvider
28+
29+
`InstUISettingsProvider` is a React component, which wraps Emotion's own `ThemeProvider`.
30+
31+
It accepts a `theme` prop, which should be an Instructure UI theme.
32+
33+
It can be used in two ways. On the top level, you can provide the theme for the whole application or nested anywhere inside it. You can also provide an object with theme or component theme overrides.
34+
35+
**For detailed usage info and examples, see the [InstUISettingsProvider](#InstUISettingsProvider) documentation page.**
36+
37+
```jsx
38+
---
39+
type: code
40+
---
41+
import Button from './Button'
42+
import { InstUISettingsProvider } from '@instructure/emotion'
43+
import { canvasHighContrast } from '@instructure/ui-themes'
44+
45+
const RenderApp = () => {
46+
return (
47+
<InstUISettingsProvider theme={canvasHighContrast}>
48+
<Button />
49+
</InstUISettingsProvider>
50+
)
51+
}
52+
```
53+
54+
### Theme overrides
55+
56+
A themeable component’s theme can be configured by wrapping it in an [InstUISettingsProvider](#InstUISettingsProvider) component, and/or set explicitly via its `themeOverride` prop.
57+
58+
#### themeOverride prop
59+
60+
The themeable components accept a `themeOverride` prop which lets you override it's component theme object. It accepts an override object or a function, which has the current `componentTheme` as its parameter.
61+
62+
**See more on the [withStyle](#withStyle/#applying-themes) and [Using theme overrides](/#using-theme-overrides) doc pages for more info.**
63+
64+
```js
65+
---
66+
type: example
67+
---
68+
<div>
69+
<Button color='primary' themeOverride={{ primaryBackground: "purple" }}>
70+
Button
71+
</Button>
72+
<Button
73+
color='primary'
74+
margin="0 0 0 small"
75+
themeOverride={(componentTheme) => ({
76+
primaryBackground: componentTheme.successBackground,
77+
primaryBorderColor: componentTheme.successBorderColor
78+
})}
79+
>
80+
Button
81+
</Button>
82+
<Button
83+
color='primary'
84+
margin="0 0 0 small"
85+
themeOverride={(_componentTheme, currentTheme) => ({
86+
primaryBackground: currentTheme.colors.primitives.orange57,
87+
primaryBorderColor: '#00AAA4',
88+
borderWidth: currentTheme.borders.widthLarge,
89+
borderStyle: 'dashed'
90+
})}
91+
>
92+
Button
93+
</Button>
94+
</div>
95+
```
96+
97+
### Global styles
98+
99+
Write your global styles in the `styles.js` file on a "globalStyles" key. You don't have to add labels to global styles.
100+
101+
```js
102+
---
103+
type: code
104+
---
105+
// styles.js
106+
107+
return {
108+
globalStyles: {
109+
'.CodeMirror': {
110+
height: 'auto',
111+
background: componentTheme.background
112+
// ...
113+
}
114+
}
115+
}
116+
```
117+
118+
In the `index.js`, import `Global` from `@instructure/emotion`, which is equivalent to the [Global](https://emotion.sh/docs/globals) component of Emotion.js.
119+
120+
In the render method, use the `<Global>` component and pass the the "globalStyles" as its `styles={}` property.
121+
122+
```jsx
123+
---
124+
type: code
125+
---
126+
// index.js
127+
128+
import { withStyle, Global } from '@instructure/emotion'
129+
130+
// ...
131+
132+
render() {
133+
const { styles } = this.props
134+
135+
return (
136+
<div css={styles.codeEditor}>
137+
<Global styles={styles.globalStyles} />
138+
// ...
139+
</div>
140+
)
141+
}
142+
```
143+
144+
### Keyframes
145+
146+
Animations are handled with Emotion's [keyframes](https://emotion.sh/docs/keyframes) helper.
147+
148+
Import `keyframes` from `@instructure/emotion` in the `styles.js` file.
149+
150+
Define the animation on the top of the page as a `const` and use it in your style object where needed. **Make sure that it is defined outside of the `generateStyle` method, otherwise it is causing problems with style recalculation.**
151+
152+
```js
153+
---
154+
type: code
155+
---
156+
// styles.js
157+
158+
import { keyframes } from '@instructure/emotion'
159+
160+
const pulseAnimation = keyframes`
161+
to {
162+
transform: scale(1);
163+
opacity: 0.9;
164+
}`
165+
166+
const generateStyle = (componentTheme, props, state) => {
167+
// ...
168+
169+
return {
170+
componentClass: {
171+
// ...
172+
animationName: pulseAnimation
173+
}
174+
}
175+
}
176+
```
177+
178+
### Writing theme tests
179+
180+
For components with theme tests, you can use `generateComponentTheme` from `theme.js` to get the theme variables.
181+
182+
Import the themes needed for your test, and pass them to the generator.
183+
184+
```js
185+
---
186+
type: code
187+
---
188+
import { canvas, canvasHighContrast } from '@instructure/ui-themes'
189+
import generateComponentTheme from '../theme'
190+
191+
describe('YourComponent.theme', () => {
192+
describe('with canvas theme', () => {
193+
const variables = generateComponentTheme(canvas)
194+
195+
describe('default', () => {
196+
it('should ensure background color and text color meet 3:1 contrast', () => {
197+
expect(contrast(variables.background, variables.color)).to.be.above(3)
198+
})
199+
})
200+
})
201+
describe('with the "canvas-high-contrast" theme', () => {
202+
const variables = generateComponentTheme(canvasHighContrast)
203+
204+
describe('default', () => {
205+
it('should ensure background color and text color meet 4.5:1 contrast', () => {
206+
expect(contrast(variables.background, variables.color)).to.be.above(4.5)
207+
})
208+
})
209+
})
210+
})
211+
```

0 commit comments

Comments
 (0)