From 4458fc7e4d264b72d73a3e9ded0c5d698d605d64 Mon Sep 17 00:00:00 2001 From: hasparus Date: Sun, 10 May 2020 18:29:20 +0200 Subject: [PATCH 01/12] Turn ColorMode into an interface and update comment - Interfaces support declaration merging, and thus are superior in this case. An user can add his own color names. The index signature might be removed some day for "strict mode". - The comment is outdated. - Smaller types in tooltips lead to more readable type errors. --- packages/css/src/types.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/css/src/types.ts b/packages/css/src/types.ts index 9e0cf59d7..0e2f9c8b4 100644 --- a/packages/css/src/types.ts +++ b/packages/css/src/types.ts @@ -489,18 +489,10 @@ type ObjectOrArray = T[] | { [K: string]: T | ObjectOrArray } export type TLengthStyledSystem = string | 0 | number /** - * To use Theme UI color modes, color scales should include at least a text - * and background color. These values are used in the ColorMode component to - * set body foreground and background colors. Color modes should be defined as - * nested objects within a theme.colors.modes object. Each key in this object - * should correspond to a color mode name, where the name can be anything, but - * typically light and dark are used for applications with a dark mode. The - * initialColorModeName key is required to enable color modes and will be used as - * the name for the root color palette. + * Color modes can be used to create a user-configurable dark mode + * or any number of other color modes. */ -export type ColorMode = { - [k: string]: CSS.ColorProperty | ObjectOrArray -} & { +export interface ColorMode { /** * Body background color */ @@ -531,6 +523,8 @@ export type ColorMode = { * A contrast color for emphasizing UI */ accent?: CSS.ColorProperty + + [k: string]: CSS.ColorProperty | ObjectOrArray } export interface Theme { From 0c4ad6714f0aacecf6be82540028581799a31659 Mon Sep 17 00:00:00 2001 From: hasparus Date: Sun, 10 May 2020 18:57:14 +0200 Subject: [PATCH 02/12] Move colors scale to separate interface --- packages/css/src/types.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/css/src/types.ts b/packages/css/src/types.ts index 0e2f9c8b4..f53b48a3b 100644 --- a/packages/css/src/types.ts +++ b/packages/css/src/types.ts @@ -527,6 +527,16 @@ export interface ColorMode { [k: string]: CSS.ColorProperty | ObjectOrArray } +interface ColorModesScale extends ColorMode { + /** + * Nested color modes can provide overrides when used in conjunction with + * `Theme.initialColorModeName and `useColorMode()` + */ + modes?: { + [k: string]: ColorMode + } +} + export interface Theme { breakpoints?: Array mediaQueries?: { [size: string]: string } @@ -584,15 +594,7 @@ export interface Theme { /** * Define the colors that are available through this theme */ - colors?: ColorMode & { - /** - * Nested color modes can provide overrides when used in conjunction with - * `Theme.initialColorModeName and `useColorMode()` - */ - modes?: { - [k: string]: ColorMode - } - } + colors?: ColorModesScale /** * Styles for elements rendered in MDX can be added to the theme.styles From e38b48bd2676900e0d6c60b86c16e949de2fda0e Mon Sep 17 00:00:00 2001 From: hasparus Date: Sun, 24 May 2020 12:35:23 +0200 Subject: [PATCH 03/12] Fix ThemeProvider components prop type --- packages/theme-provider/src/index.ts | 13 +- packages/theme-ui/test/color-modes.tsx | 502 +++++++++++++++++++++++++ packages/theme-ui/test/index.tsx | 209 ++++++++++ 3 files changed, 721 insertions(+), 3 deletions(-) create mode 100644 packages/theme-ui/test/color-modes.tsx create mode 100644 packages/theme-ui/test/index.tsx diff --git a/packages/theme-provider/src/index.ts b/packages/theme-provider/src/index.ts index 920d16093..2ed13f9ae 100644 --- a/packages/theme-provider/src/index.ts +++ b/packages/theme-provider/src/index.ts @@ -2,6 +2,7 @@ import { jsx, useThemeUI, ThemeProvider as CoreProvider, + ThemeProviderProps as CoreThemeProviderProps, IntrinsicSxElements, } from '@theme-ui/core' import { css, Theme } from '@theme-ui/css' @@ -33,10 +34,16 @@ const BodyStyles = () => }, }) -interface ThemeProviderProps { - theme: Theme +type ProvidedComponentsKnownKeys = { + [key in keyof IntrinsicSxElements]?: React.ComponentType | string +} +export interface ProvidedComponents extends ProvidedComponentsKnownKeys { + [key: string]: React.ComponentType | string | undefined +} + +interface ThemeProviderProps extends Pick { children?: React.ReactNode - components?: { [key in keyof IntrinsicSxElements]?: React.ReactNode } + components?: ProvidedComponents } export const ThemeProvider: React.FC = ({ diff --git a/packages/theme-ui/test/color-modes.tsx b/packages/theme-ui/test/color-modes.tsx new file mode 100644 index 000000000..006235810 --- /dev/null +++ b/packages/theme-ui/test/color-modes.tsx @@ -0,0 +1,502 @@ +/** @jsx jsx */ +import React from 'react' +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 { version as emotionVersion } from '@emotion/core/package.json' +import { jsx, ThemeProvider, useColorMode, useThemeUI } from '../src/index' + +const STORAGE_KEY = 'theme-ui-color-mode' + +afterEach(cleanup) +beforeEach(() => { + localStorage.removeItem(STORAGE_KEY) +}) +expect.extend(matchers) + +test('renders with color modes', () => { + let json + let mode + const Mode = (props) => { + const [colorMode] = useColorMode() + mode = colorMode + return
Mode
+ } + renderer.act(() => { + renderer.create( + + + + ) + }) + expect(mode).toBe('default') +}) + +test('renders with initial color mode name', () => { + let json + let mode + const Mode = (props) => { + const [colorMode] = useColorMode() + mode = colorMode + return
Mode
+ } + renderer.act(() => { + renderer.create( + + + + ) + }) + expect(mode).toBe('light') +}) + +test('useColorMode updates color mode state', () => { + let mode + const Button = (props) => { + const [colorMode, setMode] = useColorMode() + mode = colorMode + return ( +