Skip to content

Commit

Permalink
Add useTheme hook for emotion-theming (#1499)
Browse files Browse the repository at this point in the history
* Add useTheme hook for emotion-theming

* Add changeset

* Small fixes to imports and docs

* Update theming.mdx
  • Loading branch information
tkh44 authored Sep 11, 2019
1 parent 1b38550 commit bfb4005
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 3 deletions.
4 changes: 4 additions & 0 deletions .changeset/weak-spies-help/changes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"releases": [{ "name": "emotion-theming", "type": "patch" }],
"dependents": []
}
1 change: 1 addition & 0 deletions .changeset/weak-spies-help/changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add useTheme React hook to emotion-theming
62 changes: 59 additions & 3 deletions docs/theming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,33 @@ npm install -S emotion-theming

Add `ThemeProvider` to the top level of your app and access the theme with `props.theme` in a styled component or provide a function that accepts the theme as the css prop. The api is laid out in detail [in the documentation](https://emotion.sh/docs/emotion-theming).

## Examples

### css prop

```jsx
// @live
/** @jsx jsx */
import { jsx } from '@emotion/core'
import { ThemeProvider } from 'emotion-theming'

const theme = {
colors: {
primary: 'hotpink'
}
}

render(
<ThemeProvider theme={theme}>
<div css={theme => ({ color: theme.colors.primary })}>
some other text
</div>
</ThemeProvider>
)
```

### styled

```jsx
// @live
/** @jsx jsx */
Expand All @@ -30,9 +57,38 @@ const SomeText = styled.div`
render(
<ThemeProvider theme={theme}>
<SomeText>some text</SomeText>
<div css={theme => ({ color: theme.colors.primary })}>
some other text
</div>
</ThemeProvider>
)
```

### useTheme hook

```jsx
// @live
/** @jsx jsx */
import { jsx } from '@emotion/core'
import { ThemeProvider, useTheme } from 'emotion-theming'

const theme = {
colors: {
primary: 'hotpink'
}
}

function SomeText (props) {
const theme = useTheme()
return (
<div
css={{ color: theme.colors.primary }}
{...props}
/>
)
}

render(
<ThemeProvider theme={theme}>
<SomeText>some text</SomeText>
</ThemeProvider>
)
```

35 changes: 35 additions & 0 deletions packages/emotion-theming/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ _`emotion-theming` is a theming library inspired by [styled-components](https://
- [API](#api)
- [ThemeProvider](#themeprovider-reactcomponenttype)
- [withTheme](#withthemecomponent-reactcomponenttype-reactcomponenttype)
- [useTheme](#usetheme)
- [Credits](#credits)
- [License](#license)

Expand Down Expand Up @@ -149,6 +150,40 @@ TellMeTheColor.propTypes = {
const TellMeTheColorWithTheme = withTheme(TellMeTheColor)
```

### useTheme

A React hook that provides the current theme as its value. If the theme is updated, the child component will be re-rendered accordingly.

```jsx
// @live
/** @jsx jsx */
import { jsx } from '@emotion/core'
import styled from '@emotion/styled'
import { ThemeProvider, useTheme } from 'emotion-theming'

const theme = {
colors: {
primary: 'hotpink'
}
}

function SomeText (props) {
const theme = useTheme()
return (
<div
css={{ color: theme.colors.primary }}
{...props}
/>
)
}

render(
<ThemeProvider theme={theme}>
<SomeText>some text</SomeText>
</ThemeProvider>
)
```

## Credits

Thanks goes to the [styled-components team](https://github.com/styled-components/styled-components) and [their contributors](https://github.com/styled-components/styled-components/graphs/contributors) who designed this API.
Expand Down
46 changes: 46 additions & 0 deletions packages/emotion-theming/__tests__/__snapshots__/use-theme.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Nested useTheme works 1`] = `
.emotion-1 {
color: green;
}
.emotion-1:hover {
color: darkgreen;
}
.emotion-0 {
color: lawngreen;
}
.emotion-0:hover {
color: seagreen;
}
<div
className="emotion-1"
>
Should be green
<div
className="emotion-0"
>
Should be lawngreen
</div>
</div>
`;

exports[`useTheme works 1`] = `
.emotion-0 {
color: green;
}
.emotion-0:hover {
color: darkgreen;
}
<div
className="emotion-0"
>
Should be green
</div>
`;
77 changes: 77 additions & 0 deletions packages/emotion-theming/__tests__/use-theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// @flow
/** @jsx jsx */
import 'test-utils/next-env'
import * as renderer from 'react-test-renderer'
import { jsx } from '@emotion/core'
import { useTheme, ThemeProvider } from 'emotion-theming'

test('useTheme works', () => {
function TestComponent(props) {
const theme = useTheme()
return (
<div
css={{ color: theme.lightGreen, '&:hover': { color: theme.darkGreen } }}
>
Should be green
</div>
)
}

expect(
renderer
.create(
<ThemeProvider theme={{ lightGreen: 'green', darkGreen: 'darkgreen' }}>
<TestComponent />
</ThemeProvider>
)
.toJSON()
).toMatchSnapshot()
})

test('Nested useTheme works', () => {
function TestComponent1(props) {
const theme = useTheme()
return (
<div
css={{ color: theme.lightGreen, '&:hover': { color: theme.darkGreen } }}
{...props}
/>
)
}

function NestedComponent(props) {
const theme = useTheme()
return (
<div
css={{
color: theme.lightGreen,
'&:hover': { color: theme.darkGreen }
}}
{...props}
/>
)
}

function TestComponent2(props) {
return (
<TestComponent1>
Should be green
<ThemeProvider
theme={{ lightGreen: 'lawngreen', darkGreen: 'seagreen' }}
>
<NestedComponent>Should be lawngreen</NestedComponent>
</ThemeProvider>
</TestComponent1>
)
}

expect(
renderer
.create(
<ThemeProvider theme={{ lightGreen: 'green', darkGreen: 'darkgreen' }}>
<TestComponent2 />
</ThemeProvider>
)
.toJSON()
).toMatchSnapshot()
})
1 change: 1 addition & 0 deletions packages/emotion-theming/src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @flow
export { default as ThemeProvider } from './theme-provider'
export { default as withTheme } from './with-theme'
export { default as useTheme } from './use-theme'
7 changes: 7 additions & 0 deletions packages/emotion-theming/src/use-theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @flow
import React from 'react'
import { ThemeContext } from '@emotion/core'

export default function useTheme() {
return React.useContext(ThemeContext)
}

0 comments on commit bfb4005

Please sign in to comment.