Skip to content

Commit

Permalink
Merge pull request #708 from epilande/ts-theme-provider
Browse files Browse the repository at this point in the history
Convert @theme-ui/theme-provider to TypeScript
  • Loading branch information
hasparus authored May 11, 2020
2 parents 5d5108d + b5a664d commit 076cd7b
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 62 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Make ThemeProvider `theme` prop required
- Removes overriding property on editor combobox
- Adjust media query sort logic #600
- Fixed link to Gatsby Plugin page in `getting-started` page. Issue #602
Expand Down
2 changes: 1 addition & 1 deletion examples/codesandbox-starter/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { jsx, Layout, Styled } from 'theme-ui'

function App() {
return (
<ThemeProvider>
<ThemeProvider theme={{}}>
<Layout sx={{ p: 3 }}>
<Reset />
<Styled.h1 sx={{ color: 'primary', mb: 3 }}>Hello Theme UI</Styled.h1>
Expand Down
12 changes: 6 additions & 6 deletions packages/color-modes/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ test('useColorMode updates color mode state', () => {
)
}
const tree = render(
<ThemeProvider>
<ThemeProvider theme={{}}>
<ColorModeProvider>
<Button />
</ColorModeProvider>
Expand Down Expand Up @@ -182,7 +182,7 @@ test('uses default mode', () => {
return <button children="test" />
}
const tree = render(
<ThemeProvider>
<ThemeProvider theme={{}}>
<ColorModeProvider>
<Button />
</ColorModeProvider>
Expand All @@ -200,7 +200,7 @@ test('initializes mode based on localStorage', () => {
return <button children="test" />
}
const tree = render(
<ThemeProvider>
<ThemeProvider theme={{}}>
<ColorModeProvider>
<Button />
</ColorModeProvider>
Expand Down Expand Up @@ -237,7 +237,7 @@ test('retains initial context', () => {
return false
}
render(
<ThemeProvider>
<ThemeProvider theme={{}}>
<ColorModeProvider>
<Consumer />
</ColorModeProvider>
Expand Down Expand Up @@ -340,7 +340,7 @@ test('does not initialize mode from prefers-color-scheme media query when useCol
return false
}
render(
<ThemeProvider>
<ThemeProvider theme={{}}>
<ColorModeProvider>
<Consumer />
</ColorModeProvider>
Expand Down Expand Up @@ -606,7 +606,7 @@ test('warns when localStorage is disabled', () => {
}

render(
<ThemeProvider>
<ThemeProvider theme={{}}>
<ColorModeProvider>
<Consumer />
</ColorModeProvider>
Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ export const jsx: typeof React.createElement = (type, props, ...children) =>

export interface ContextValue {
__EMOTION_VERSION__: string
theme: Theme | null
theme: Theme
colorMode?: string
setColorMode?: () => void
}
export const Context = React.createContext<ContextValue>({
__EMOTION_VERSION__,
theme: null,
theme: {},
})

export const useThemeUI = () => React.useContext(Context)
Expand Down Expand Up @@ -76,7 +78,7 @@ interface BaseProviderProps {
const BaseProvider: React.FC<BaseProviderProps> = ({ context, children }) =>
jsx(
EmotionContext.Provider,
{ value: context.theme! },
{ value: context.theme },
jsx(Context.Provider, {
value: context,
children,
Expand All @@ -103,7 +105,7 @@ export function ThemeProvider({ theme, children }: ThemeProviderProps) {

const context =
typeof theme === 'function'
? { ...outer, theme: theme(outer.theme!) }
? { ...outer, theme: theme(outer.theme) }
: merge.all<ContextValue>({}, outer, { theme })

return jsx(BaseProvider, { context }, children)
Expand Down
42 changes: 19 additions & 23 deletions packages/core/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ import renderer from 'react-test-renderer'
import { render, fireEvent, cleanup, act } from '@testing-library/react'
import { matchers } from 'jest-emotion'
import mockConsole from 'jest-mock-console'
import {
jsx,
Context,
useThemeUI,
merge,
ThemeProvider,
} from '../src'
import { jsx, Context, useThemeUI, merge, ThemeProvider } from '../src'

afterEach(cleanup)

Expand All @@ -21,7 +15,7 @@ const renderJSON = el => renderer.create(el).toJSON()
describe('ThemeProvider', () => {
test('renders', () => {
const json = renderJSON(
<ThemeProvider>
<ThemeProvider theme={{}}>
<h1>Hello</h1>
</ThemeProvider>
)
Expand All @@ -35,7 +29,7 @@ describe('ThemeProvider', () => {
value={{
emotionVersion: '9.0.0',
}}>
<ThemeProvider>Conflicting versions</ThemeProvider>
<ThemeProvider theme={{}}>Conflicting versions</ThemeProvider>
</Context.Provider>
)
expect(console.warn).toBeCalled()
Expand Down Expand Up @@ -104,20 +98,21 @@ describe('ThemeProvider', () => {
cards: {
default: {
border: t => `1px solid ${t.colors.primary}`,
}
}
},
},
}
const json = renderJSON(
jsx(ThemeProvider, { theme },
jsx(
ThemeProvider,
{ theme },
jsx('div', {
sx: {
variant: 'cards.default',
}
},
})
)
)
expect(json).toHaveStyleRule('border', '1px solid tomato')

})
})

Expand Down Expand Up @@ -151,13 +146,15 @@ describe('jsx', () => {

test('css prop accepts functions', () => {
const json = renderJSON(
jsx(ThemeProvider, {
theme: {
colors: {
primary: 'tomato',
}
}
},
jsx(
ThemeProvider,
{
theme: {
colors: {
primary: 'tomato',
},
},
},
jsx('div', {
css: t => ({
color: t.colors.primary,
Expand Down Expand Up @@ -338,7 +335,7 @@ describe('useThemeUI', () => {
theme={{
colors: {
text: 'tomato',
}
},
}}>
<GetContext />
</ThemeProvider>
Expand All @@ -347,4 +344,3 @@ describe('useThemeUI', () => {
expect(context.theme.colors.text).toBe('tomato')
})
})

4 changes: 2 additions & 2 deletions packages/css/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"types": "dist/index.d.ts",
"sideEffects": false,
"scripts": {
"prepare": "microbundle --no-compress",
"watch": "microbundle watch --no-compress"
"prepare": "microbundle --no-compress --tsconfig tsconfig.json",
"watch": "microbundle watch --no-compress --tsconfig tsconfig.json"
},
"author": "Brent Jackson",
"license": "MIT",
Expand Down
6 changes: 2 additions & 4 deletions packages/css/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import * as CSS from 'csstype'

import { SystemStyleObject, UseThemeFunction, Theme } from './types'
import { CSSObject, SystemStyleObject, UseThemeFunction, Theme } from './types'

export * from './types'

Expand Down Expand Up @@ -256,7 +254,7 @@ type CssPropsArgument = { theme: Theme } | Theme

export const css = (args: SystemStyleObject = {}) => (
props: CssPropsArgument = {}
): CSS.Properties => {
): CSSObject => {
const theme: Theme = {
...defaultTheme,
...('theme' in props ? props.theme : props),
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/pages/guides/mdx-layout-components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ As an example, create a new component with the `ThemeProvider` and a wrapping `<
import { jsx, ThemeProvider } from 'theme-ui'

export default props => (
<ThemeProvider>
<ThemeProvider theme={{}}>
<div {...props} />
</ThemeProvider>
)
Expand Down
6 changes: 4 additions & 2 deletions packages/theme-provider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
"version": "0.4.0-alpha.1",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"source": "src/index.ts",
"types": "dist/index.d.ts",
"sideEffects": false,
"scripts": {
"prepare": "microbundle --no-compress",
"watch": "microbundle watch --no-compress"
"prepare": "microbundle --no-compress --tsconfig tsconfig.json",
"watch": "microbundle watch --no-compress --tsconfig tsconfig.json"
},
"dependencies": {
"@emotion/core": "^10.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { jsx, useThemeUI, ThemeProvider as CoreProvider } from '@theme-ui/core'
import { css } from '@theme-ui/css'
import {
jsx,
useThemeUI,
ThemeProvider as CoreProvider,
IntrinsicSxElements,
} from '@theme-ui/core'
import { css, Theme } from '@theme-ui/css'
import { ColorModeProvider } from '@theme-ui/color-modes'
import { MDXProvider } from '@theme-ui/mdx'
import { Global } from '@emotion/core'

const BodyStyles = () =>
jsx(Global, {
styles: theme => {
if (theme.useBodyStyles === false || (theme.styles && !theme.styles.root))
styles: emotionTheme => {
const theme = emotionTheme as Theme
if (
theme.useBodyStyles === false ||
(theme.styles && !theme.styles.root)
) {
return false
const boxSizing = theme.useBorderBox === false ? null : 'border-box'
}
const boxSizing = theme.useBorderBox === false ? undefined : 'border-box'

return css({
'*': {
Expand All @@ -23,7 +33,17 @@ const BodyStyles = () =>
},
})

export const ThemeProvider = ({ theme, components, children }) => {
interface ThemeProviderProps {
theme: Theme
children?: React.ReactNode
components?: { [key in keyof IntrinsicSxElements]?: React.ReactNode }
}

export const ThemeProvider: React.FC<ThemeProviderProps> = ({
theme,
components,
children,
}) => {
const outer = useThemeUI()

if (typeof outer.setColorMode === 'function') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/** @jsx jsx */
import React from 'react'
import { jsx } from '@theme-ui/core'
import { mdx } from '@mdx-js/react'
import renderer from 'react-test-renderer'
Expand All @@ -15,7 +14,7 @@ const renderJSON = el => renderer.create(el).toJSON()

test('renders', () => {
const json = renderJSON(
<ThemeProvider>
<ThemeProvider theme={{}}>
<h1>Hello</h1>
</ThemeProvider>
)
Expand All @@ -29,6 +28,8 @@ test('renders with theme', () => {
useCustomProperties: false,
colors: {
primary: 'tomato',
background: 'white',
text: 'black',
},
}}>
<h1 sx={{ color: 'primary' }}>Hello</h1>
Expand Down Expand Up @@ -82,7 +83,7 @@ test('renders with nested provider', () => {
})

test('renders with custom components', () => {
const h1 = props => <pre {...props} />
const h1 = (props: any) => <pre {...props} />

const json = renderJSON(
<ThemeProvider
Expand Down Expand Up @@ -136,7 +137,7 @@ test('renders global styles', () => {

test('resets body margin', () => {
const root = render(
<ThemeProvider>
<ThemeProvider theme={{}}>
<h1>Hello</h1>
</ThemeProvider>
)
Expand Down
4 changes: 4 additions & 0 deletions packages/theme-provider/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../core/tsconfig.json",
"include": ["src/**/*.ts", "src/**/*.tsx"]
}
Loading

1 comment on commit 076cd7b

@hasparus
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously merging a PR that passes checks fails checks on master. I'll fix it in a minute.

Please sign in to comment.