Skip to content

Commit d800b17

Browse files
committed
custom-properties: extend ThemeProvider to insert CSS Custom Props
1 parent d533060 commit d800b17

File tree

5 files changed

+165
-20
lines changed

5 files changed

+165
-20
lines changed

packages/custom-properties/README.md

+92-16
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,116 @@
11
# @theme-ui/custom-properties
22

3-
Generate CSS custom properties for use with Theme UI.
3+
Extend [ThemeUI](https://theme-ui.com)'s core functionality with CSS Custom Properties.
44

5-
https://theme-ui.com
65

76
## Installation
87

98
```
109
yarn add @theme-ui/custom-properties
1110
```
1211

12+
## API
1313

14-
## Usage
14+
### toCustomProperties
1515

16-
Transform your Theme UI compliant theme config with the library:
16+
Transform your Theme UI compliant theme to an object of CSS Custom Properties.
1717

18-
```js
19-
const toCustomProperties = require('@theme-ui/custom-properties')
20-
const theme = require('../theme');
18+
**Type**: `Function`
2119

22-
module.exports = () => {
23-
const customProperties = toCustomProperties(theme, '🍭');
20+
**Parameters**:
21+
1. theme - The theme ui specification object
22+
2. prefix - An optional string prefix for the css custom property (_optional_)
2423

25-
return customProperties;
24+
**Returns**: `Object`
25+
```js
26+
{
27+
'--color-primary': '#2980b9',
28+
'--color-secondary': '#f7df1e',
29+
'--fontSize-0': 12,
30+
' -fontSize-1': 14,
31+
'--fontSize-2': 16,
32+
'--fontSize-3': 24,
33+
'--fontSize-4': 32,
34+
'--fontSize-5': 48,
35+
'--fontSize-6': 64
2636
}
2737
```
2838

39+
**Example**:
40+
```js
41+
import { toCustomProperties } from '@theme-ui/custom-properties';
42+
import theme from '../theme';
2943

30-
## Parameters
44+
const customProperties = toCustomProperties(theme, '🍭');
45+
console.log(customProperties);
46+
```
3147

32-
The @theme-ui/custom-properties function takes two parameters:
48+
### withCustomProperties
49+
Extend the base `ThemeProvider` to allow native styling by using CSS Custom Properties.
3350

34-
```js
35-
toCustomProperties( $theme, $prefix );
51+
**Type**: `Function`
52+
53+
**Parameters**:
54+
1. prefix - An optional string prefix for the css custom property (_optional_)
55+
56+
**Returns** a React Component which extends the default `ThemeProvider` by adding CSS Custom Properties to the wrapper element.
57+
58+
For example:
59+
60+
```jsx
61+
const ExtendedThemeProvider = withCustomProperties('app-name');
62+
63+
ReactDOM.render(
64+
<ExtendedThemeProvider theme={theme}>
65+
<p> Hello world! </p>
66+
</ExtendedThemeProvider>,
67+
root
68+
);
3669
```
3770

38-
1. theme - The theme ui specification object
39-
1. prefix - An optional prefix for the css custom property _optional_
71+
Then in CSS we can do something like:
4072

73+
```css
74+
p {
75+
color: var(--app-name-color-primary);
76+
background: var(--app-name-color-secondary);
77+
}
78+
```
79+
80+
These CSS Custom Properties are in total sync with the theme. Also, sub-theming works as expected.
81+
82+
```jsx
83+
const theme = {
84+
colors: {
85+
primary: 'red',
86+
secondary: 'blue'
87+
}
88+
};
89+
90+
const subTheme = {
91+
colors: {
92+
primary: 'orange'
93+
}
94+
};
95+
96+
const ExtendedThemeProvider = withCustomProperties('app-name');
97+
98+
ReactDOM.render(
99+
<ExtendedThemeProvider theme={theme}>
100+
<p> Hello world! </p> // red on a blue background
101+
102+
<ExtendedThemeProvider theme={subTheme}>
103+
<p> Hello Aliens! </p> // orange on a blue background
104+
</ExtendedThemeProvider>
105+
106+
</ExtendedThemeProvider>,
107+
root
108+
);
109+
```
110+
111+
```css
112+
p {
113+
color: var(--app-name-color-primary);
114+
background: var(--app-name-color-secondary);
115+
}
116+
```

packages/custom-properties/package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@theme-ui/custom-properties",
33
"description": "Generate CSS custom properties for use with Theme UI",
4-
"version": "0.4.0-alpha.3",
4+
"version": "0.5.0-alpha.1",
55
"source": "src/index.ts",
66
"main": "dist/index.js",
77
"module": "dist/index.esm.js",
@@ -18,8 +18,13 @@
1818
"dependencies": {
1919
"pluralize": "^8.0.0"
2020
},
21+
"peerDependencies": {
22+
"react": "^16.11.0",
23+
"theme-ui": "^0.3.1"
24+
},
2125
"devDependencies": {
2226
"@theme-ui/css": "^0.4.0-alpha.3",
27+
"@types/theme-ui": "^0.3.2",
2328
"@types/pluralize": "^0.0.29"
2429
}
2530
}

packages/custom-properties/src/index.ts

+35-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import React, { useEffect, useRef } from 'react'
12
import pluralize from 'pluralize'
23
import { Theme } from '@theme-ui/css'
4+
import { ThemeProvider } from 'theme-ui'
5+
import { ThemeProviderProps, useThemeUI } from '@theme-ui/core'
36

47
interface CustomProperties {
58
[key: string]: string | number
69
}
710

8-
export default (theme: Theme, prefix?: string) => {
11+
export function toCustomProperties(theme: Theme, prefix?: string) {
912
const customProperties: CustomProperties = {}
1013

1114
const generateProperties = (object: object, previousKey?: string) => {
@@ -36,3 +39,34 @@ export default (theme: Theme, prefix?: string) => {
3639

3740
return customProperties
3841
}
42+
43+
export function withCustomProperties(prefix?: string) {
44+
return function customThemeProvider(props: ThemeProviderProps) {
45+
const ref = useRef<HTMLDivElement>(null)
46+
const outerTheme = useThemeUI().theme
47+
48+
useEffect(() => {
49+
if (!ref.current) {
50+
return
51+
}
52+
53+
const theme = typeof props.theme === 'function'
54+
? props.theme(outerTheme)
55+
: props.theme
56+
const cssProperties = toCustomProperties(theme as Theme, prefix)
57+
58+
Object.entries(cssProperties).forEach(([key, value]) => {
59+
ref.current!.style.setProperty(key, value.toString())
60+
})
61+
})
62+
63+
return React.createElement(
64+
'div',
65+
{
66+
ref,
67+
className: 'theme-ui-provider',
68+
},
69+
React.createElement(ThemeProvider, props)
70+
)
71+
}
72+
}

packages/custom-properties/test/test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import toCustomProperties from '../src'
1+
import { toCustomProperties } from '../src'
22

33
const theme = {
44
colors: {

yarn.lock

+31-1
Original file line numberDiff line numberDiff line change
@@ -3378,6 +3378,13 @@
33783378
dependencies:
33793379
csstype "^2.6.9"
33803380

3381+
"@types/styled-system__css@*":
3382+
version "5.0.11"
3383+
resolved "https://registry.yarnpkg.com/@types/styled-system__css/-/styled-system__css-5.0.11.tgz#a9ff7e5d75e69a0d5ccff36acb4bbd491f1a9da9"
3384+
integrity sha512-hUieAt4sFS7zwbdU9Vlnn/c3vkfhTMhyiccYGpUSX96nJ4BF3NjLIjMu3cQOYS5EX4gPkHJZhkfdw41ov1NjhQ==
3385+
dependencies:
3386+
csstype "^2.6.6"
3387+
33813388
"@types/testing-library__dom@*":
33823389
version "7.0.2"
33833390
resolved "https://registry.yarnpkg.com/@types/testing-library__dom/-/testing-library__dom-7.0.2.tgz#2906f8a0dce58b0746c6ab606f786bd06fe6940e"
@@ -3401,6 +3408,29 @@
34013408
"@types/testing-library__dom" "*"
34023409
pretty-format "^25.1.0"
34033410

3411+
"@types/theme-ui@*", "@types/theme-ui@^0.3.2":
3412+
version "0.3.2"
3413+
resolved "https://registry.yarnpkg.com/@types/theme-ui/-/theme-ui-0.3.2.tgz#f8e49734398725f72195866cdc2462a07743bf38"
3414+
integrity sha512-xAHYIyIsInPbcRf2YqCnioTmTsVjX+5fClO6NqwNORn0j9deGuSMp2gI8lPjm5b0eZwxM5ugExLbz01lxjjVqw==
3415+
dependencies:
3416+
"@emotion/serialize" "^0.11.15"
3417+
"@types/react" "*"
3418+
"@types/styled-system" "*"
3419+
"@types/styled-system__css" "*"
3420+
"@types/theme-ui__components" "*"
3421+
csstype "^2.6.6"
3422+
3423+
"@types/theme-ui__components@*":
3424+
version "0.2.5"
3425+
resolved "https://registry.yarnpkg.com/@types/theme-ui__components/-/theme-ui__components-0.2.5.tgz#65ef4e160e2e0cf7c52ae220f6579a707d33667d"
3426+
integrity sha512-qqhIJboXzGXE0ZpKRHrwQvRbuOAcGNyAWMPXXP2jGs65XcaTuDJJpz1Rx5JCaQ1h+Tt99uIriRzZRthWarh1wg==
3427+
dependencies:
3428+
"@emotion/core" "^10.0.0"
3429+
"@emotion/styled" "^10.0.0"
3430+
"@types/react" "*"
3431+
"@types/styled-system" "*"
3432+
"@types/theme-ui" "*"
3433+
34043434
"@types/tmp@^0.0.33":
34053435
version "0.0.33"
34063436
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
@@ -7629,7 +7659,7 @@ cssstyle@^1.0.0:
76297659
dependencies:
76307660
cssom "0.3.x"
76317661

7632-
csstype@^2.2.0, csstype@^2.5.7, csstype@^2.6.10, csstype@^2.6.9:
7662+
csstype@^2.2.0, csstype@^2.5.7, csstype@^2.6.10, csstype@^2.6.6, csstype@^2.6.9:
76337663
version "2.6.10"
76347664
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
76357665
integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==

0 commit comments

Comments
 (0)