Skip to content

Commit

Permalink
Merge pull request #2385 from system-ui/2207-global-component
Browse files Browse the repository at this point in the history
Add theme-aware Global component
  • Loading branch information
hasparus committed Jan 22, 2023
2 parents 9fbd1fc + ac36c53 commit f9c7f93
Show file tree
Hide file tree
Showing 18 changed files with 346 additions and 64 deletions.
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
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
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

0 comments on commit f9c7f93

Please sign in to comment.