Skip to content

Commit

Permalink
custom-properties: extend ThemeProvider to insert CSS Custom Props
Browse files Browse the repository at this point in the history
  • Loading branch information
iampava committed Jun 5, 2020
1 parent d533060 commit b3c06c2
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 20 deletions.
108 changes: 92 additions & 16 deletions packages/custom-properties/README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,116 @@
# @theme-ui/custom-properties

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

https://theme-ui.com

## Installation

```
yarn add @theme-ui/custom-properties
```

## API

## Usage
### toCustomProperties

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

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

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

return customProperties;
**Returns**: `Object`
```js
{
'--color-primary': '#2980b9',
'--color-secondary': '#f7df1e',
'--fontSize-0': 12,
' -fontSize-1': 14,
'--fontSize-2': 16,
'--fontSize-3': 24,
'--fontSize-4': 32,
'--fontSize-5': 48,
'--fontSize-6': 64
}
```

**Example**:
```js
import { toCustomProperties } from '@theme-ui/custom-properties';
import theme from '../theme';

## Parameters
const customProperties = toCustomProperties(theme, '🍭');
console.log(customProperties);
```

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

```js
toCustomProperties( $theme, $prefix );
**Type**: `Function`

**Parameters**:
1. prefix - An optional string prefix for the css custom property (_optional_)

**Returns** a React Component which extends the default `ThemeProvider` by adding CSS Custom Properties to the wrapper element.

For example:

```jsx
const ExtendedThemeProvider = withCustomProperties('app-name');

ReactDOM.render(
<ExtendedThemeProvider theme={theme}>
<p> Hello world! </p>
</ExtendedThemeProvider>,
root
);
```

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

```css
p {
color: var(--app-name-color-primary);
background: var(--app-name-color-secondary);
}
```

These CSS Custom Properties are in total sync with the theme. Also, sub-theming works as expected.

```jsx
const theme = {
colors: {
primary: 'red',
secondary: 'blue'
}
};

const subTheme = {
colors: {
primary: 'orange'
}
};

const ExtendedThemeProvider = withCustomProperties('app-name');

ReactDOM.render(
<ExtendedThemeProvider theme={theme}>
<p> Hello world! </p> // red on a blue background

<ExtendedThemeProvider theme={subTheme}>
<p> Hello Aliens! </p> // orange on a blue background
</ExtendedThemeProvider>

</ExtendedThemeProvider>,
root
);
```

```css
p {
color: var(--app-name-color-primary);
background: var(--app-name-color-secondary);
}
```
7 changes: 6 additions & 1 deletion packages/custom-properties/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@theme-ui/custom-properties",
"description": "Generate CSS custom properties for use with Theme UI",
"version": "0.4.0-alpha.3",
"version": "0.5.0-alpha.1",
"source": "src/index.ts",
"main": "dist/index.js",
"module": "dist/index.esm.js",
Expand All @@ -18,8 +18,13 @@
"dependencies": {
"pluralize": "^8.0.0"
},
"peerDependencies": {
"react": "^16.11.0",
"theme-ui": "^0.3.1"
},
"devDependencies": {
"@theme-ui/css": "^0.4.0-alpha.3",
"@types/theme-ui": "^0.3.2",
"@types/pluralize": "^0.0.29"
}
}
36 changes: 35 additions & 1 deletion packages/custom-properties/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React, { useEffect, useRef } from 'react'
import pluralize from 'pluralize'
import { Theme } from '@theme-ui/css'
import { ThemeProvider } from 'theme-ui'
import { ThemeProviderProps, useThemeUI } from '@theme-ui/core'

interface CustomProperties {
[key: string]: string | number
}

export default (theme: Theme, prefix?: string) => {
export function toCustomProperties(theme: Theme, prefix?: string) {
const customProperties: CustomProperties = {}

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

return customProperties
}

export function withCustomProperties(prefix?: string) {
return function customThemeProvider(props: ThemeProviderProps) {
const ref = useRef<HTMLDivElement>(null)
const outerTheme = useThemeUI().theme

useEffect(() => {
if (!ref.current) {
return
}

const theme = typeof props.theme === 'function'
? props.theme(outerTheme)
: props.theme
const cssProperties = toCustomProperties(theme as Theme, prefix)

Object.entries(cssProperties).forEach(([key, value]) => {
ref.current!.style.setProperty(key, value.toString())
})
})

return React.createElement(
'div',
{
ref,
className: 'theme-ui-provider',
},
React.createElement(ThemeProvider, props)
)
}
}
2 changes: 1 addition & 1 deletion packages/custom-properties/test/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import toCustomProperties from '../src'
import { toCustomProperties } from '../src/index'

const theme = {
colors: {
Expand Down
32 changes: 31 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3378,6 +3378,13 @@
dependencies:
csstype "^2.6.9"

"@types/styled-system__css@*":
version "5.0.11"
resolved "https://registry.yarnpkg.com/@types/styled-system__css/-/styled-system__css-5.0.11.tgz#a9ff7e5d75e69a0d5ccff36acb4bbd491f1a9da9"
integrity sha512-hUieAt4sFS7zwbdU9Vlnn/c3vkfhTMhyiccYGpUSX96nJ4BF3NjLIjMu3cQOYS5EX4gPkHJZhkfdw41ov1NjhQ==
dependencies:
csstype "^2.6.6"

"@types/testing-library__dom@*":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/testing-library__dom/-/testing-library__dom-7.0.2.tgz#2906f8a0dce58b0746c6ab606f786bd06fe6940e"
Expand All @@ -3401,6 +3408,29 @@
"@types/testing-library__dom" "*"
pretty-format "^25.1.0"

"@types/theme-ui@*", "@types/theme-ui@^0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@types/theme-ui/-/theme-ui-0.3.2.tgz#f8e49734398725f72195866cdc2462a07743bf38"
integrity sha512-xAHYIyIsInPbcRf2YqCnioTmTsVjX+5fClO6NqwNORn0j9deGuSMp2gI8lPjm5b0eZwxM5ugExLbz01lxjjVqw==
dependencies:
"@emotion/serialize" "^0.11.15"
"@types/react" "*"
"@types/styled-system" "*"
"@types/styled-system__css" "*"
"@types/theme-ui__components" "*"
csstype "^2.6.6"

"@types/theme-ui__components@*":
version "0.2.5"
resolved "https://registry.yarnpkg.com/@types/theme-ui__components/-/theme-ui__components-0.2.5.tgz#65ef4e160e2e0cf7c52ae220f6579a707d33667d"
integrity sha512-qqhIJboXzGXE0ZpKRHrwQvRbuOAcGNyAWMPXXP2jGs65XcaTuDJJpz1Rx5JCaQ1h+Tt99uIriRzZRthWarh1wg==
dependencies:
"@emotion/core" "^10.0.0"
"@emotion/styled" "^10.0.0"
"@types/react" "*"
"@types/styled-system" "*"
"@types/theme-ui" "*"

"@types/tmp@^0.0.33":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
Expand Down Expand Up @@ -7629,7 +7659,7 @@ cssstyle@^1.0.0:
dependencies:
cssom "0.3.x"

csstype@^2.2.0, csstype@^2.5.7, csstype@^2.6.10, csstype@^2.6.9:
csstype@^2.2.0, csstype@^2.5.7, csstype@^2.6.10, csstype@^2.6.6, csstype@^2.6.9:
version "2.6.10"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==
Expand Down

0 comments on commit b3c06c2

Please sign in to comment.