title |
---|
How it Works |
Theme UI combines several libraries together to form a mini-framework for styling applications.
Theme UI is built with:
- Emotion: used to generate isolated CSS with theming context
- MDX: used to provide custom Emotion styled components to MDX documents, without polluting the global CSS scope
- Typography.js: optionally used for creating rich typographic styles with a simple, high-level API
The Theme UI ThemeProvider
component is a wrapper around MDX's MDXProvider
,
which adds custom React components to context, and Emotion's ThemeProvider
,
which adds the theme
object to context for use with Emotion.
The Theme UI ThemeProvider
includes a default components
object with styled
components that pick up values from the theme.styles
object. For example,
theme.styles.h1
will be used in its components.h1
component and rendered in
MDX documents.
For illustrative purposes, the ThemeProvider
renders something like the
following:
// for demonstration only – this does not reflect the actual source code
import { MDXProvider } from '@mdx-js/react'
import { ThemeProvider } from 'emotion-theming'
import styled from '@emotion/styled'
const themeUIComponents = {
h1: styled('h1')((props) => props.theme.styles.h1),
h2: styled('h2')((props) => props.theme.styles.h2),
// other MDX components
}
export default ({ components, theme, children }) => (
<ThemeProvider theme={theme}>
<MDXProvider components={merge(themeUIComponents, components)}>
{children}
</MDXProvider>
</ThemeProvider>
)
When using the components
prop to add custom MDX components, each component is
wrapped with the sx
prop to allow the component to pick up values from the
theme.styles
object.
The Theme UI JSX function wraps the Emotion JSX function, converting the sx
prop to a call to @theme-ui/css
. The two examples below yield the same
results:
// with Emotion's JSX function
// this is typically handled with the Emotion Babel preset
/** @jsxImportSource @emotion/react */
import { css } from 'theme-ui'
export default (props) => (
<div
{...props}
css={css({
color: 'white',
bg: 'primary',
fontSize: 4,
})}
/>
)
// with Theme UI's JSX function
/** @jsxImportSource theme-ui */
export default (props) => (
<div
{...props}
sx={{
color: 'white',
bg: 'primary',
fontSize: 4,
}}
/>
)
Confused about this @jsxImportSource
comment? Read more about
JSX Pragma.