Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add theme-aware Global component #2385

Merged
merged 10 commits into from
Jan 22, 2023
Merged
2 changes: 2 additions & 0 deletions examples/next/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { Button, useColorMode } from 'theme-ui'

const Header = () => {
const [colorMode, setColorMode] = useColorMode()

return (
<header>
<Button
suppressHydrationWarning
onClick={() => setColorMode(colorMode === 'light' ? 'dark' : 'light')}
>
Toggle {colorMode === 'light' ? 'Dark' : 'Light'}
Expand Down
1 change: 1 addition & 0 deletions examples/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@mdx-js/loader": "^2.1.2",
"@mdx-js/react": "^2.1.2",
"@next/mdx": "^12.0.7",
"@theme-ui/css": "workspace:^",
"next": "^12.1.0",
"react": "^18",
"react-dom": "^18",
Expand Down
2 changes: 2 additions & 0 deletions examples/next/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Head from 'next/head'
import About from '../components/about.mdx'
import { Global } from 'theme-ui'

export default function Page() {
return (
<>
<Head>
<title>Next.js Theme UI</title>
</Head>
<Global styles={{ h1: { color: 'salmon !important' } }} />
<About />
</>
)
Expand Down
1 change: 1 addition & 0 deletions packages/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@theme-ui/core": "workspace:^",
"@theme-ui/components": "workspace:^",
"@theme-ui/css": "workspace:^",
"@theme-ui/global": "workspace:^",
"@theme-ui/match-media": "workspace:^",
"@theme-ui/mdx": "workspace:^",
"@theme-ui/presets": "workspace:^",
Expand Down
32 changes: 16 additions & 16 deletions packages/docs/src/pages/guides/global-styles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,34 @@ title: 'Global Styles'

# Global Styles

Use the Emotion `Global` component to add global CSS with theme-based values.
Theme UI offers a `Global` component (that wraps Emotion’s) for adding global
CSS with theme-based values.

By default, the `ThemeProvider` component will apply styles in `theme.styles.root` to the `<html>` element.
It will also apply `color` and `background-color` styles based on `theme.colors.text` and `theme.colors.background` respectively.
By default (or, unless the
[`useRootStyles` configuration option](/theming#configuration-flags)is
disabled), the `ThemeProvider` component will apply styles in
`theme.styles.root` to the `<html>` element. It will also apply `color` and
`background-color` styles based on `theme.colors.text` and
`theme.colors.background` respectively.

<Note>
Generally, you should try to avoid adding CSS to global scope. Many styles can
be safely encapsulated into a component without the need for global styles.
</Note>

```jsx
import { Global } from '@emotion/react'
import { Global } from 'theme-ui'

export default (props) => (
<Global
styles={(theme) => ({
'*': {
boxSizing: 'border-box',
styles={{
button: {
m: 0,
bg: 'primary',
color: 'background',
border: 0,
},
})}
}}
/>
)
```

<Note>

If you are upgrading from a version of theme-ui older that v0.6.0, be aware the import
package has changed from `@emotion/core` to `@emotion/react`. For more information see
the [Migration Notes for 0.6](https://theme-ui.com/migrating/#breaking-changes).

</Note>
7 changes: 7 additions & 0 deletions packages/docs/src/pages/packages/global.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: '@theme-ui/global'
---

import Readme from '@theme-ui/global/README.md'

<Readme />
1 change: 1 addition & 0 deletions packages/docs/src/sidebar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
- [@theme-ui/core](/packages/core)
- [@theme-ui/components](/packages/components)
- [@theme-ui/mdx](/packages/mdx)
- [@theme-ui/global](/packages/global)
- [@theme-ui/presets](/packages/presets)
- [@theme-ui/prism](/packages/prism)
- [@theme-ui/color](/packages/color)
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/static/card.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/docs/static/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions packages/global/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# @theme-ui/global

Wrapper around the Emotion `Global` component, made Theme UI theme-aware.

**Note:** _This package is included in the main `theme-ui` package and a
separate installation is not required unless you’re using `@theme-ui/core`._

```sh
npm i @theme-ui/global @theme-ui/core @emotion/react
```

```jsx
import Global from '@theme-ui/global'

export default (props) => (
<Global
styles={{
button: {
m: 0,
bg: 'primary',
color: 'background',
border: 0,
},
}}
/>
)
```
27 changes: 27 additions & 0 deletions packages/global/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "@theme-ui/global",
"version": "0.15.4",
"repository": "system-ui/theme-ui",
"main": "dist/theme-ui-global.cjs.js",
"module": "dist/theme-ui-global.esm.js",
"source": "src/index.tsx",
"author": "Lachlan Campbell",
"license": "MIT",
"sideEffects": false,
"publishConfig": {
"access": "public"
},
"dependencies": {
"@theme-ui/core": "workspace:^",
"@theme-ui/css": "workspace:^"
},
"peerDependencies": {
"@emotion/react": "^11",
"react": ">=18"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@types/react": "^18",
"@theme-ui/test-utils": "workspace:^"
}
}
16 changes: 16 additions & 0 deletions packages/global/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { jsx, type ThemeUIStyleObject } from '@theme-ui/core'
import { css, type Theme } from '@theme-ui/css'
import { Global as EmotionGlobal } from '@emotion/react'

export interface GlobalProps {
styles: ThemeUIStyleObject
}
const Global = ({ styles }: GlobalProps): JSX.Element =>
jsx(EmotionGlobal, {
styles: (emotionTheme: unknown) => {
const theme = emotionTheme as Theme
return css(styles)(theme)
},
})

export default Global
77 changes: 77 additions & 0 deletions packages/global/test/__snapshots__/index.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders global and component styles 1`] = `
.emotion-0 {
color: pink;
}

<html>
<head>
<style
data-emotion="css"
data-s=""
>

.css-2cx43c{}
</style>
<style
data-emotion="css"
data-s=""
>

.css-2cx43c html{background-color:hotpink;}
</style>
<style
data-emotion="css"
data-s=""
>

.emotion-0{color:pink;}
</style>
</head>
<body>
<div>
<header>
<div
class="emotion-0"
/>
</header>
</div>
</body>
</html>
`;

exports[`renders global styles 1`] = `
<html>
<head>
<style
data-emotion="css-global"
data-s=""
>

@font-face{font-family:some-name;}
</style>
<style
data-emotion="css-global"
data-s=""
>

body{font-family:Georgia,serif;margin:0;}
</style>
<style
data-emotion="css-global"
data-s=""
>

h1{color:salmon;}
</style>
</head>
<body>
<div>
<h1>
Hello
</h1>
</div>
</body>
</html>
`;
82 changes: 82 additions & 0 deletions packages/global/test/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* @jest-environment jsdom
* @jsx jsx
*/

import { jsx } from '@theme-ui/core'
import { cleanup } from '@testing-library/react'
import { render } from '@theme-ui/test-utils'
import { matchers } from '@emotion/jest'

import { ThemeProvider } from '@theme-ui/core'
import Global from '../src'

expect.extend(matchers)

beforeEach(() => {
document.head.innerHTML = ''
jest.resetAllMocks()
})

afterEach(cleanup)

test.only('renders global styles', async () => {
const root = (
<ThemeProvider
theme={{
config: {
useRootStyles: false,
},
fonts: {
body: 'Georgia,serif',
},
colors: {
primary: 'salmon',
},
}}
>
<Global
styles={{
'@font-face': {
fontFamily: 'some-name',
},
body: {
fontFamily: 'body',
margin: 0,
},
h1: {
color: 'primary',
},
}}
/>
<h1>Hello</h1>
</ThemeProvider>
)

const document = render(root)
expect(document.baseElement.parentElement).toMatchSnapshot()

const bodyStyle = global.getComputedStyle(document.baseElement)
expect(bodyStyle.fontFamily).toBe('Georgia,serif')
expect(bodyStyle.margin).toBe('0px')

const h1 = document.baseElement.querySelector('h1')!
expect(global.getComputedStyle(h1).color).toBe('salmon')
})

test('renders global and component styles', () => {
const root = (
<header>
<Global
styles={{
html: {
backgroundColor: 'hotpink',
},
}}
/>
<div sx={{ color: 'pink' }} />
</header>
)
const { baseElement } = render(root)
expect(baseElement.parentElement).toMatchSnapshot()
})
3 changes: 1 addition & 2 deletions packages/sidenav/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @jsx jsx */
import { jsx, ThemeProvider, Theme, ThemeStyles } from 'theme-ui'
import { jsx, ThemeProvider, Theme, ThemeStyles, Global } from 'theme-ui'
import { MDXProvider, MDXProviderComponents } from '@mdx-js/react'
import React, {
useState,
Expand All @@ -11,7 +11,6 @@ import React, {
ReactComponentElement,
ReactElement,
} from 'react'
import { Global } from '@emotion/react'
import merge from 'deepmerge'

const createNestedLinks = (
Expand Down
1 change: 1 addition & 0 deletions packages/theme-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@theme-ui/components": "workspace:^",
"@theme-ui/core": "workspace:^",
"@theme-ui/css": "workspace:^",
"@theme-ui/global": "workspace:^",
"@theme-ui/theme-provider": "workspace:^"
},
"peerDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/theme-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type {
} from '@theme-ui/core'
export { useColorMode, InitializeColorMode } from '@theme-ui/color-modes'
export { ThemeProvider } from '@theme-ui/theme-provider'
export { default as Global } from '@theme-ui/global'
export * from '@theme-ui/components'
export { css, get } from '@theme-ui/css'

Expand Down
Loading