diff --git a/package-lock.json b/package-lock.json
index 441e6a87..0a3e09e8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,7 @@
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.2",
"@types/react": "^17.0.33",
+ "@types/react-dom": "^17.0.11",
"@types/styled-components": "^5.1.15",
"@typescript-eslint/eslint-plugin": "^4.32.0",
"@typescript-eslint/parser": "^4.32.0",
@@ -7203,6 +7204,15 @@
"csstype": "^3.0.2"
}
},
+ "node_modules/@types/react-dom": {
+ "version": "17.0.11",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
+ "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/responselike": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
@@ -41957,6 +41967,15 @@
"csstype": "^3.0.2"
}
},
+ "@types/react-dom": {
+ "version": "17.0.11",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
+ "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/responselike": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
diff --git a/package.json b/package.json
index 1ff4aba7..9a0fa26d 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.2",
"@types/react": "^17.0.33",
+ "@types/react-dom": "^17.0.11",
"@types/styled-components": "^5.1.15",
"@typescript-eslint/eslint-plugin": "^4.32.0",
"@typescript-eslint/parser": "^4.32.0",
diff --git a/packages/emotion/src/colorModes.test.tsx b/packages/emotion/src/colorModes.test.tsx
index 1e78f859..5eb70523 100644
--- a/packages/emotion/src/colorModes.test.tsx
+++ b/packages/emotion/src/colorModes.test.tsx
@@ -1,37 +1,18 @@
/* eslint-env browser */
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
-import { th } from '@xstyled/system'
-import { x, ThemeProvider, ColorModeProvider } from '.'
+import { cleanup } from '@testing-library/react'
+import { x, ColorModeProvider } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
describe('colorModes', () => {
it('supports color modes', () => {
- const theme = {
- defaultColorModeName: 'dark',
- colors: {
- black: '#000',
- white: '#fff',
- red: '#ff0000',
- danger: th.color('red'),
- text: th.color('black'),
- modes: {
- dark: {
- red: '#ff4400',
- text: th.color('white'),
- },
- },
- },
- }
-
- render(
-
-
- Hello
-
- ,
+ renderWithTheme(
+
+ Hello
+
)
expect(document.body).toHaveClass('xstyled-color-mode-dark')
})
diff --git a/packages/emotion/src/createGlobalStyle.test.tsx b/packages/emotion/src/createGlobalStyle.test.tsx
index d0d57903..94cfd620 100644
--- a/packages/emotion/src/createGlobalStyle.test.tsx
+++ b/packages/emotion/src/createGlobalStyle.test.tsx
@@ -1,16 +1,11 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
-import { createGlobalStyle, ThemeProvider } from '.'
+import { cleanup } from '@testing-library/react'
+import { createGlobalStyle } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#createGlobalStyle', () => {
it('injects global styles', () => {
const GlobalStyle = createGlobalStyle`
@@ -18,12 +13,10 @@ describe('#createGlobalStyle', () => {
margin: 2;
}
`
- const { container } = render(
+ const { container } = renderWithTheme(
<>
-
-
-
-
+
+
>,
)
expect(container.firstChild).toHaveStyle(`
diff --git a/packages/emotion/src/css.test.tsx b/packages/emotion/src/css.test.tsx
index 8ce6d174..be922a59 100644
--- a/packages/emotion/src/css.test.tsx
+++ b/packages/emotion/src/css.test.tsx
@@ -1,20 +1,13 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
+import { cleanup } from '@testing-library/react'
import styled from '@emotion/styled'
-import { css, ThemeProvider } from '.'
+import { css } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
describe('#css', () => {
- const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
-
- {children}
-
- )
- }
-
it('transforms rules', () => {
const Dummy = styled.div`
${css`
@@ -23,11 +16,7 @@ describe('#css', () => {
margin-top: 2px;
`}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle(`
margin: 2px 8px 8px 8px;
padding: 4px;
@@ -40,11 +29,7 @@ describe('#css', () => {
margin: 1 2;
`}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: 4px 8px;')
})
@@ -55,11 +40,7 @@ describe('#css', () => {
margin: 1 ${two};
`}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: 4px 8px;')
})
@@ -69,25 +50,17 @@ describe('#css', () => {
margin: '1 2',
})}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: 4px 8px;')
})
it('accepts function', () => {
const Dummy = styled.div`
- ${css((p) => ({
+ ${css((_p) => ({
margin: '1 2',
}))}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: 4px 8px;')
})
@@ -99,11 +72,7 @@ describe('#css', () => {
styles: 'margin: 1 2;label:x;',
})}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: 4px 8px;')
})
})
diff --git a/packages/emotion/src/cx.test.tsx b/packages/emotion/src/cx.test.tsx
index 8539c77e..57a14621 100644
--- a/packages/emotion/src/cx.test.tsx
+++ b/packages/emotion/src/cx.test.tsx
@@ -2,16 +2,11 @@
import { jsx } from '@emotion/react'
import '@testing-library/jest-dom/extend-expect'
import { render, cleanup } from '@testing-library/react'
-import { css, cx, ThemeProvider } from '.'
+import { css, cx } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#cx', () => {
it('throws with string value', () => {
// @ts-expect-error Strings are not allowed
@@ -21,18 +16,16 @@ describe('#cx', () => {
})
it('handles css values', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container.firstChild).toHaveStyle(`
margin: 2px 8px 8px 8px;
@@ -41,19 +34,17 @@ describe('#cx', () => {
})
it('handles multiple css values', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container.firstChild).toHaveStyle(`
margin: 8px;
diff --git a/packages/emotion/src/jsx.test.tsx b/packages/emotion/src/jsx.test.tsx
index 01e0da50..d76619e8 100644
--- a/packages/emotion/src/jsx.test.tsx
+++ b/packages/emotion/src/jsx.test.tsx
@@ -1,35 +1,27 @@
/** @jsx jsx */
import '@testing-library/jest-dom/extend-expect'
import { render, cleanup } from '@testing-library/react'
-import { ThemeProvider } from '@emotion/react'
import { jsx, css } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#jsx', () => {
it('does nothing without css prop', () => {
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
})
it('handles css string', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container.firstChild).toHaveStyle(`
margin: 2px 8px 8px 8px;
@@ -38,20 +30,18 @@ describe('#jsx', () => {
})
it('handles array of css string', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container.firstChild).toHaveStyle(`
margin: 8px;
@@ -60,13 +50,11 @@ describe('#jsx', () => {
})
it('handles css objects', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container.firstChild).toHaveStyle(`
margin: 8px;
@@ -74,13 +62,11 @@ describe('#jsx', () => {
})
it('handles array of css objects', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container.firstChild).toHaveStyle(`
margin: 8px;
@@ -89,28 +75,24 @@ describe('#jsx', () => {
})
it('does not render children', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container).toHaveTextContent('')
})
it('renders a single child', () => {
- const { container } = render(
-
-
- ,
+ const { container } = renderWithTheme(
+
)
expect(container.querySelector('#test-p')).toHaveTextContent(
@@ -119,17 +101,15 @@ describe('#jsx', () => {
})
it('renders multiple children', () => {
- const { container } = render(
-
-
-
First testing paragraph
+ const { container } = renderWithTheme(
+
+
First testing paragraph
-
Second testing paragraph
-
- ,
+
Second testing paragraph
+
)
expect(container.querySelectorAll('.test-p')).toHaveLength(2)
diff --git a/packages/emotion/src/styled.test.tsx b/packages/emotion/src/styled.test.tsx
index 515ec2ef..42a55980 100644
--- a/packages/emotion/src/styled.test.tsx
+++ b/packages/emotion/src/styled.test.tsx
@@ -1,22 +1,16 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
import { render, cleanup } from '@testing-library/react'
-import { ThemeProvider } from '@emotion/react'
import styled, { css, keyframes } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#styled', () => {
it('supports basic tags', () => {
const Dummy = styled.div``
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
})
it('passes options through', () => {
@@ -39,11 +33,7 @@ describe.each([['div'], ['box']])('#styled.%s', (key) => {
padding: 1;
margin-top: 2px;
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle(`
margin: 2px 8px 8px 8px;
padding: 4px;
@@ -56,7 +46,7 @@ describe.each([['div'], ['box']])('#styled.%s', (key) => {
}
// @ts-ignore
const Dummy = styled[key]`
- color: red;
+ color: pink;
${
// @ts-ignore
(p) => css`
@@ -64,13 +54,9 @@ describe.each([['div'], ['box']])('#styled.%s', (key) => {
`
}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle(`
- color: red;
+ color: pink;
margin: 8px;
`)
})
@@ -98,38 +84,20 @@ describe.each([['div'], ['box']])('#styled.%s', (key) => {
})
it('reads value from the theme', () => {
- const theme = {
- colors: {
- primary: 'pink',
- },
- }
// @ts-ignore
const Dummy = styled[key]`
color: primary;
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('color: pink;')
})
it('handles negative values', () => {
- const theme = {
- space: {
- md: 10,
- },
- }
// @ts-ignore
const Dummy = styled[key]`
margin: -md;
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: -10px;')
})
@@ -138,11 +106,7 @@ describe.each([['div'], ['box']])('#styled.%s', (key) => {
const Dummy = styled[key]({
margin: '2',
})
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: 8px;')
})
@@ -151,11 +115,7 @@ describe.each([['div'], ['box']])('#styled.%s', (key) => {
const Dummy = styled[key](() => ({
margin: '2',
}))
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: 8px;')
})
@@ -193,23 +153,15 @@ describe.each([['div'], ['box']])('#styled.%s', (key) => {
describe('#styled.xxxBox', () => {
it('supports box tags', () => {
const Dummy = styled.box``
- const { container } = render(
-
-
- ,
- )
- expect(container.firstChild!.nodeName).toBe('DIV')
+ const { container } = renderWithTheme()
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('margin: 4px;')
})
it('supports xxxBox tags', () => {
const Dummy = styled.headerBox``
- const { container } = render(
-
-
- ,
- )
- expect(container.firstChild!.nodeName).toBe('HEADER')
+ const { container } = renderWithTheme()
+ expect(container.firstChild?.nodeName).toBe('HEADER')
expect(container.firstChild).toHaveStyle('margin: 4px;')
})
@@ -217,24 +169,16 @@ describe('#styled.xxxBox', () => {
const Dummy = styled.box`
margin: 2px;
`
- const { container } = render(
-
-
- ,
- )
- expect(container.firstChild!.nodeName).toBe('DIV')
+ const { container } = renderWithTheme()
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('margin: 4px;')
expect(container.firstChild).not.toHaveStyle('margin: 2px;')
})
it("doesn't forward attributes", () => {
const Dummy = styled.box``
- const { container } = render(
-
-
- ,
- )
- expect(container.firstChild!.nodeName).toBe('DIV')
+ const { container } = renderWithTheme()
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('margin: 4px;')
expect(container.firstChild).not.toHaveAttribute('margin')
})
@@ -244,7 +188,7 @@ describe('#styled.xxxBox', () => {
// This is not supported by Emotion
// @ts-expect-error
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle('margin: 4px;')
expect(container.firstChild).not.toHaveAttribute('margin')
})
diff --git a/packages/emotion/src/theme.test.tsx b/packages/emotion/src/theme.test.tsx
index b08ae3bf..53a041d9 100644
--- a/packages/emotion/src/theme.test.tsx
+++ b/packages/emotion/src/theme.test.tsx
@@ -1,14 +1,96 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
+import { render, cleanup, RenderOptions, RenderResult } from '@testing-library/react'
import { ThemeProvider } from '@emotion/react'
import { useTheme, useFontSize } from '.'
+// import original module declarations
+import '@xstyled/system'
+import '@emotion/react'
+import {
+ defaultTheme as xstyledDefaultTheme,
+ DefaultTheme as XStyledDefaultTheme,
+ th
+} from '@xstyled/system'
+
+import {
+ ITheme,
+} from '@xstyled/emotion'
+
+interface AppTheme extends ITheme, XStyledDefaultTheme {
+ fontSizes: XStyledDefaultTheme['fontSizes'] & {
+ md: string
+ }
+ colors: XStyledDefaultTheme['colors'] & {
+ primary: string
+ danger: any
+ text: any
+ red: string
+ modes: {
+ [key: string]: Partial
+ }
+ }
+ space: XStyledDefaultTheme['space'] & {
+ md: number
+ }
+}
+
+// and extend them!
+declare module '@xstyled/system' {
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
+ export interface Theme extends AppTheme {}
+}
+
+declare module '@emotion/react' {
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
+ export interface Theme extends AppTheme {}
+}
+
+const defaultTheme: XStyledDefaultTheme = xstyledDefaultTheme
+
+export const theme: AppTheme = {
+ ...defaultTheme,
+
+ defaultColorModeName: 'dark',
+ colors: {
+ ...defaultTheme.colors,
+ primary: 'pink',
+ black: '#000',
+ white: '#fff',
+ red: '#ff0000',
+ danger: th.color('red'),
+ text: th.color('black'),
+ modes: {
+ dark: {
+ red: '#ff4400',
+ text: th.color('white'),
+ },
+ },
+ },
+ space: {
+ ...defaultTheme.space,
+ md: 10,
+ 1: '4px',
+ 2: '8px'
+ },
+ fontSizes: {
+ ...defaultTheme.fontSizes,
+ md: '20px',
+ },
+} as const
+
+export const renderWithTheme = (
+ ui: React.ReactElement,
+ options?: Omit
+): RenderResult => render(
+ {ui},
+ options
+)
+
afterEach(cleanup)
describe('#useTheme', () => {
it('returns theme', () => {
- const theme = { foo: 'bar' }
const spy = jest.fn()
function ThemeLogger() {
const theme = useTheme()
@@ -17,10 +99,8 @@ describe('#useTheme', () => {
}, [theme])
return null
}
- render(
-
-
- ,
+ renderWithTheme(
+
)
expect(spy).toHaveBeenCalledWith(theme)
})
@@ -28,7 +108,6 @@ describe('#useTheme', () => {
describe('#useFontSize', () => {
it('gets value from theme', () => {
- const theme = { fontSizes: { md: '20px' } }
const spy = jest.fn()
function Logger() {
const fontSize = useFontSize('md')
@@ -37,10 +116,8 @@ describe('#useFontSize', () => {
}, [fontSize])
return null
}
- render(
-
-
- ,
+ renderWithTheme(
+
)
expect(spy).toHaveBeenCalledWith('20px')
})
diff --git a/packages/emotion/src/x.test.tsx b/packages/emotion/src/x.test.tsx
index 6a148d29..edae156c 100644
--- a/packages/emotion/src/x.test.tsx
+++ b/packages/emotion/src/x.test.tsx
@@ -1,17 +1,11 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
import { render, cleanup } from '@testing-library/react'
-import { ThemeProvider } from '@emotion/react'
import { x } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#x', () => {
it('creates system based components', () => {
const { container } = render()
@@ -25,7 +19,7 @@ describe('#x', () => {
// "as" is not supported with emotion
// @ts-expect-error
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle(`
margin: 2px;
padding: 1px;
@@ -38,7 +32,7 @@ describe('#x', () => {
Hello
,
)
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle(`
margin: 2px;
padding: 1px;
@@ -46,14 +40,12 @@ describe('#x', () => {
})
it('uses theme', () => {
- const { container } = render(
-
-
- Hello
-
- ,
+ const { container } = renderWithTheme(
+
+ Hello
+
)
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle(`
margin: 8px;
padding: 4px;
@@ -62,7 +54,7 @@ describe('#x', () => {
it('does not forward props', () => {
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('display: flex;')
expect(container.firstChild).not.toHaveAttribute('display')
expect(container.firstChild).toHaveAttribute('data-foo')
diff --git a/packages/styled-components/src/colorModes.test.tsx b/packages/styled-components/src/colorModes.test.tsx
index 1e78f859..5eb70523 100644
--- a/packages/styled-components/src/colorModes.test.tsx
+++ b/packages/styled-components/src/colorModes.test.tsx
@@ -1,37 +1,18 @@
/* eslint-env browser */
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
-import { th } from '@xstyled/system'
-import { x, ThemeProvider, ColorModeProvider } from '.'
+import { cleanup } from '@testing-library/react'
+import { x, ColorModeProvider } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
describe('colorModes', () => {
it('supports color modes', () => {
- const theme = {
- defaultColorModeName: 'dark',
- colors: {
- black: '#000',
- white: '#fff',
- red: '#ff0000',
- danger: th.color('red'),
- text: th.color('black'),
- modes: {
- dark: {
- red: '#ff4400',
- text: th.color('white'),
- },
- },
- },
- }
-
- render(
-
-
- Hello
-
- ,
+ renderWithTheme(
+
+ Hello
+
)
expect(document.body).toHaveClass('xstyled-color-mode-dark')
})
diff --git a/packages/styled-components/src/createGlobalStyle.test.tsx b/packages/styled-components/src/createGlobalStyle.test.tsx
index d886f625..9853da4e 100644
--- a/packages/styled-components/src/createGlobalStyle.test.tsx
+++ b/packages/styled-components/src/createGlobalStyle.test.tsx
@@ -1,16 +1,11 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
-import { createGlobalStyle, css, ThemeProvider } from '.'
+import { cleanup } from '@testing-library/react'
+import { createGlobalStyle, css } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#createGlobalStyle', () => {
it('injects global styles', () => {
const GlobalStyle = createGlobalStyle`
@@ -18,12 +13,10 @@ describe('#createGlobalStyle', () => {
margin: 2;
}
`
- const { container } = render(
+ const { container } = renderWithTheme(
<>
-
-
-
-
+
+
>,
)
expect(container.firstChild).toHaveStyle(`
@@ -40,12 +33,10 @@ describe('#createGlobalStyle', () => {
const GlobalStyle = createGlobalStyle`
${style}
`
- const { container } = render(
+ const { container } = renderWithTheme(
<>
-
-
-
-
+
+
>,
)
expect(container.firstChild).toHaveStyle(`
diff --git a/packages/styled-components/src/css.test.tsx b/packages/styled-components/src/css.test.tsx
index 9c257e27..b56cd2c0 100644
--- a/packages/styled-components/src/css.test.tsx
+++ b/packages/styled-components/src/css.test.tsx
@@ -1,17 +1,12 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
-import { css, ThemeProvider } from '.'
+import { cleanup } from '@testing-library/react'
+import { css } from '.'
import { scStyled as styled } from './scStyled'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#css', () => {
it('transforms rules', () => {
const Dummy = styled.div`
@@ -21,10 +16,8 @@ describe('#css', () => {
margin-top: 2px;
`}
`
- const { container } = render(
-
+ const { container } = renderWithTheme(
- ,
)
expect(container.firstChild).toHaveStyle(`
margin: 2px 8px 8px 8px;
@@ -38,10 +31,8 @@ describe('#css', () => {
margin: 1 2;
`}
`
- const { container } = render(
-
+ const { container } = renderWithTheme(
- ,
)
expect(container.firstChild).toHaveStyle('margin: 4px 8px;')
})
diff --git a/packages/styled-components/src/styled.test.tsx b/packages/styled-components/src/styled.test.tsx
index af4eedc9..da6e8ca1 100644
--- a/packages/styled-components/src/styled.test.tsx
+++ b/packages/styled-components/src/styled.test.tsx
@@ -1,8 +1,9 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
-import { ThemeProvider, keyframes } from 'styled-components'
+import { render, cleanup, } from '@testing-library/react'
+import { keyframes } from 'styled-components'
import styled, { css, system } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
@@ -50,36 +51,18 @@ describe('#styled', () => {
})
it('reads value from the theme', () => {
- const theme = {
- colors: {
- primary: 'pink',
- },
- }
const Dummy = styled.div`
color: primary;
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('color: pink;')
})
it('handles negative values', () => {
- const theme = {
- space: {
- md: 10,
- },
- }
const Dummy = styled.div`
margin: -md;
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle('margin: -10px;')
})
@@ -131,19 +114,10 @@ describe('#styled', () => {
})
it('works with system.apply', () => {
- const theme = {
- colors: {
- primary: 'pink',
- },
- }
const Dummy = styled.div`
${system.apply({ fontSize: 2, bg: 'primary' })}
`
- const { container } = render(
-
-
- ,
- )
+ const { container } = renderWithTheme()
expect(container.firstChild).toHaveStyle(`
font-size: 2px;
background-color: pink;
@@ -155,7 +129,7 @@ describe('#styled.xxx', () => {
it('supports basic tags', () => {
const Dummy = styled.div``
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
})
})
@@ -163,14 +137,14 @@ describe('#styled.xxxBox', () => {
it('supports box tags', () => {
const Dummy = styled.box``
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('margin: 1px;')
})
it('supports xxxBox tags', () => {
const Dummy = styled.aBox``
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle('margin: 1px;')
})
@@ -179,7 +153,7 @@ describe('#styled.xxxBox', () => {
margin: 2px;
`
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('margin: 1px;')
expect(container.firstChild).not.toHaveStyle('margin: 2px;')
})
@@ -187,7 +161,7 @@ describe('#styled.xxxBox', () => {
it("doesn't forward attributes", () => {
const Dummy = styled.box``
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('margin: 1px;')
expect(container.firstChild).not.toHaveAttribute('margin')
})
@@ -195,7 +169,7 @@ describe('#styled.xxxBox', () => {
it('supports as prop', () => {
const Dummy = styled.divBox``
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('HEADER')
+ expect(container.firstChild?.nodeName).toBe('HEADER')
expect(container.firstChild).toHaveStyle('margin: 1px;')
expect(container.firstChild).not.toHaveAttribute('margin')
})
@@ -203,7 +177,7 @@ describe('#styled.xxxBox', () => {
it('does not forward props', () => {
const Dummy = styled.divBox``
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('display: flex;')
expect(container.firstChild).not.toHaveAttribute('display')
expect(container.firstChild).toHaveAttribute('data-foo')
diff --git a/packages/styled-components/src/theme.test.tsx b/packages/styled-components/src/theme.test.tsx
index a9d241bb..aaa2f0d7 100644
--- a/packages/styled-components/src/theme.test.tsx
+++ b/packages/styled-components/src/theme.test.tsx
@@ -1,14 +1,95 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
-import { render, cleanup } from '@testing-library/react'
+import { render, cleanup, RenderOptions, RenderResult } from '@testing-library/react'
import { ThemeProvider } from 'styled-components'
import { useTheme, useFontSize } from '.'
+// import original module declarations
+import 'styled-components'
+import '@xstyled/system'
+import {
+ defaultTheme as xstyledDefaultTheme,
+ DefaultTheme as XStyledDefaultTheme,
+ th
+} from '@xstyled/system'
+import {
+ ITheme,
+} from '@xstyled/styled-components'
+
+interface AppTheme extends ITheme, XStyledDefaultTheme {
+ fontSizes: XStyledDefaultTheme['fontSizes'] & {
+ md: string
+ }
+ colors: XStyledDefaultTheme['colors'] & {
+ primary: string
+ danger: any
+ text: any
+ red: string
+ modes: {
+ [key: string]: Partial
+ }
+ }
+ space: XStyledDefaultTheme['space'] & {
+ md: number
+ }
+}
+
+// and extend them!
+declare module '@xstyled/system' {
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
+ export interface Theme extends AppTheme {}
+}
+declare module 'styled-components' {
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
+ export interface DefaultTheme extends AppTheme {}
+}
+
+const defaultTheme: XStyledDefaultTheme = xstyledDefaultTheme
+
+const theme: AppTheme = {
+ ...defaultTheme,
+
+ defaultColorModeName: 'dark',
+ colors: {
+ ...defaultTheme.colors,
+ primary: 'pink',
+ black: '#000',
+ white: '#fff',
+ red: '#ff0000',
+ danger: th.color('red'),
+ text: th.color('black'),
+ modes: {
+ dark: {
+ red: '#ff4400',
+ text: th.color('white'),
+ },
+ },
+ },
+ space: {
+ ...defaultTheme.space,
+ md: 10,
+ 1: '4px',
+ 2: '8px'
+ },
+ fontSizes: {
+ ...defaultTheme.fontSizes,
+ md: '20px',
+ },
+} as const
+
+
+export const renderWithTheme = (
+ ui: React.ReactElement,
+ options?: Omit
+): RenderResult => render(
+ {ui},
+ options
+)
+
afterEach(cleanup)
describe('#useTheme', () => {
it('returns theme', () => {
- const theme = { foo: 'bar' }
const spy = jest.fn()
function ThemeLogger() {
const theme = useTheme()
@@ -17,18 +98,13 @@ describe('#useTheme', () => {
}, [theme])
return null
}
- render(
-
-
- ,
- )
+ renderWithTheme()
expect(spy).toHaveBeenCalledWith(theme)
})
})
describe('#useFontSize', () => {
it('gets value from theme', () => {
- const theme = { fontSizes: { md: '20px' } }
const spy = jest.fn()
function Logger() {
const fontSize = useFontSize('md')
@@ -37,11 +113,7 @@ describe('#useFontSize', () => {
}, [fontSize])
return null
}
- render(
-
-
- ,
- )
+ renderWithTheme()
expect(spy).toHaveBeenCalledWith('20px')
})
})
diff --git a/packages/styled-components/src/x.test.tsx b/packages/styled-components/src/x.test.tsx
index f8bce9a1..b90f8f7b 100644
--- a/packages/styled-components/src/x.test.tsx
+++ b/packages/styled-components/src/x.test.tsx
@@ -1,17 +1,11 @@
import * as React from 'react'
import '@testing-library/jest-dom/extend-expect'
import { render, cleanup } from '@testing-library/react'
-import { ThemeProvider } from 'styled-components'
import { x } from '.'
+import { renderWithTheme } from './theme.test'
afterEach(cleanup)
-const SpaceTheme = ({ children }: { children: React.ReactNode }) => {
- return (
- {children}
- )
-}
-
describe('#x', () => {
it('creates system based components', () => {
const { container } = render()
@@ -23,7 +17,7 @@ describe('#x', () => {
it('supports "as" prop', () => {
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle(`
margin: 2px;
padding: 1px;
@@ -36,7 +30,7 @@ describe('#x', () => {
Hello
,
)
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle(`
margin: 2px;
padding: 1px;
@@ -44,14 +38,12 @@ describe('#x', () => {
})
it('uses theme', () => {
- const { container } = render(
-
-
- Hello
-
- ,
+ const { container } = renderWithTheme(
+
+ Hello
+
)
- expect(container.firstChild!.nodeName).toBe('A')
+ expect(container.firstChild?.nodeName).toBe('A')
expect(container.firstChild).toHaveStyle(`
margin: 8px;
padding: 4px;
@@ -60,7 +52,7 @@ describe('#x', () => {
it('does not forward props', () => {
const { container } = render()
- expect(container.firstChild!.nodeName).toBe('DIV')
+ expect(container.firstChild?.nodeName).toBe('DIV')
expect(container.firstChild).toHaveStyle('display: flex;')
expect(container.firstChild).not.toHaveAttribute('display')
expect(container.firstChild).toHaveAttribute('data-foo')
diff --git a/packages/system/src/styles/flexbox-grids.test.ts b/packages/system/src/styles/flexbox-grids.test.ts
index 190e091a..fed896ab 100644
--- a/packages/system/src/styles/flexbox-grids.test.ts
+++ b/packages/system/src/styles/flexbox-grids.test.ts
@@ -14,6 +14,8 @@ const theme = {
describe('#flexboxGrids', () => {
it('supports row', () => {
+ expect(flexboxGrids({ row: false })).toEqual({})
+
expect(flexboxGrids({ row: true })).toEqual({
boxSizing: 'border-box',
flexGrow: 1,
@@ -48,6 +50,8 @@ describe('#flexboxGrids', () => {
flex: '0 0 33.3333%',
})
+ expect(flexboxGrids({ col: false })).toEqual({})
+
expect(flexboxGrids({ col: true })).toEqual({
boxSizing: 'border-box',
flexBasis: 0,
diff --git a/packages/system/src/styles/flexbox-grids.ts b/packages/system/src/styles/flexbox-grids.ts
index 8c342390..16a43b27 100644
--- a/packages/system/src/styles/flexbox-grids.ts
+++ b/packages/system/src/styles/flexbox-grids.ts
@@ -4,16 +4,16 @@ import { style, createStyleGenerator, reduceVariants, compose } from '../style'
import { getPercent } from './units'
export interface RowProps {
- row?: SystemProp
+ row?: SystemProp
}
export const row = style({
prop: 'row',
- css: () => ({
+ css: value => value ? {
boxSizing: 'border-box',
flexGrow: 1,
flexWrap: 'wrap',
display: 'flex',
- }),
+ } : {},
})
const getColStyle = (
@@ -47,7 +47,7 @@ const getColStyle = (
}
export interface ColProps {
- col?: SystemProp
+ col?: SystemProp
}
export const col = createStyleGenerator({
getStyle: (props) => {
@@ -59,6 +59,10 @@ export const col = createStyleGenerator({
maxWidth: '100%',
}
+ if (value === false) {
+ return null
+ }
+
if (obj(value)) {
const breakpointsStyle = reduceVariants(
props,
diff --git a/packages/system/src/styles/index.test.ts b/packages/system/src/styles/index.test.ts
index 5e6cdac6..d3d25518 100644
--- a/packages/system/src/styles/index.test.ts
+++ b/packages/system/src/styles/index.test.ts
@@ -15,7 +15,7 @@ describe('#system', () => {
spaceY: { _: 3, sm: 0 },
spaceX: { sm: 4 },
})
- const keys = Object.keys(res)
+ const keys = Object.keys(res ?? {})
expect(keys).toEqual([
'display',
'& > :not([hidden]) ~ :not([hidden])',
diff --git a/packages/system/src/types.ts b/packages/system/src/types.ts
index 4a6eba54..18b9da31 100644
--- a/packages/system/src/types.ts
+++ b/packages/system/src/types.ts
@@ -81,6 +81,9 @@ export type ThemeProp = {
export type SystemProp =
| TType
| ThemeProp
+ | string
+ | number
+ | false
export type CSSOption = string | string[] | Mixin
@@ -129,7 +132,7 @@ export type ThemeNamespaceValue<
> = SynthesizedPath
export interface ThemeGetter {
- (value: T, defaultValue?: CSSScalar): (props: Props) => CSSScalar
+ (value: T | string | number | boolean, defaultValue?: CSSScalar): (props: Props) => CSSScalar
meta: {
name?: string
transform?: TransformValue
diff --git a/website/pages/docs/core-concepts/typescript.mdx b/website/pages/docs/core-concepts/typescript.mdx
index 76e26ad5..129609bd 100644
--- a/website/pages/docs/core-concepts/typescript.mdx
+++ b/website/pages/docs/core-concepts/typescript.mdx
@@ -65,9 +65,7 @@ declare module '@xstyled/system' {
export interface Theme extends AppTheme {}
}
declare module '@emotion/react' {
- export interface Theme extends XStyledDefaultTheme {
- /* Customize your theme */
- }
+ export interface Theme extends AppTheme {}
}
```