Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions docs/components/color-scheme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: 'ColorScheme'
description: A JSX email component which provides meta and style foundations for color scheme support
slug: color-scheme
type: component
---

<!--@include: @/include/header.md-->

::: tip
Please be sure to read our FAQ about Dark Mode in the context of email templates: https://jsx.email/docs/faq#dark-and-light-mode
:::

<!--@include: @/include/install.md-->

## Usage

Add the component to your email template.

```jsx
import { Body, ColorScheme, Head, Html } from 'jsx-email';

const Email = () => {
return (
<Html>
<Head>
<ColorScheme mode="light only" />
</Head>
<Body></Body>
</Html>
);
};
```

## Component Props

```ts
export interface ColorSchemeProps {
mode?: Mode;
}
```

### Individual Props

```ts
mode?: ColorSchemeMode;
```

Default: `'normal'`<br/>

Selects the color scheme mode that informs the email client which mode to render.

Supported Values:

- `'dark'`
- `'dark only'` The email client will only ever render the content in the dark color scheme and forbids the email client from overriding the color scheme.
- `'light'`
- `'light dark'` The email client will choose the light or dark theme to match the user’s preference. If the user’s preference does not match something in the list, the email client will choose which mode to display.
- `'light dark only'` The email client will choose the first of the listed schemes that it supports taking user preference into account and forbids the email client from overriding the color scheme.
- `'light only'` The email client will only ever render the content in the light color scheme and forbids the email client from overriding the color scheme.
- `'normal'` Indicates that the email supports the page's supported color schemes, if they are set, or that it supports no color schemes at all otherwise.
2 changes: 1 addition & 1 deletion docs/components/html.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ Identify the direction of text content on the email

:::tip
This component also expresses all of the [Common Component Props](https://react.dev/reference/react-dom/components/common) for `ComponentProps<'html'>`.
:::
:::
2 changes: 0 additions & 2 deletions docs/components/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,3 @@ The width of an image in pixels
::: tip
This component also expresses all of the [Common Component Props](https://react.dev/reference/react-dom/components/common) for `ComponentProps<'img'>`.
:::


2 changes: 1 addition & 1 deletion docs/components/link.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ Specify the target attribute for the button link.

::: tip
This component also expresses all of the [Common Component Props](https://react.dev/reference/react-dom/components/common) for `ComponentProps<'a'>`.
:::
:::
2 changes: 1 addition & 1 deletion docs/components/row.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ If `false`, instructs the component not to add default `style` properties to the

::: tip
This component also expresses all of the [Common Component Props](https://react.dev/reference/react-dom/components/common) for `ComponentProps<'table'>`.
:::
:::
2 changes: 1 addition & 1 deletion docs/components/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ If `false`, instructs the component not to add default `style` properties to the

::: tip
This component also expresses all of the [Common Component Props](https://react.dev/reference/react-dom/components/common) for `ComponentProps<'p'>`.
:::
:::
5 changes: 4 additions & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ description: 'You know the drill. Questions that get asked oodles'

## Dark and Light Mode

Handling dark and light mode in emails is tricky, and doesn't work exactly like one would expect with relevant experience handling modes on the web. There's a lot of information (and misinformation) out there about dark and light mode when authoring emails, but we recommend taking a look at the following article, which hits most of the important bits of info for authoring emails: https://www.litmus.com/blog/the-ultimate-guide-to-dark-mode-for-email-marketers
Handling dark and light mode in emails is tricky, and doesn't work exactly like one would expect with relevant experience handling modes on the web. Gmail and Outlook on Windows in particular, have essentially no support for color switching. There's a lot of information (and misinformation) out there about dark and light mode when authoring emails, but we recommend taking a look at the following articles, which hit most of the important bits of info for authoring emails:

- https://www.litmus.com/blog/the-ultimate-guide-to-dark-mode-for-email-marketers
- https://web.dev/articles/color-scheme (crucial web development related dark mode info)

## Monorepo Setup

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"*package.json": [
"prettier --write --plugin=prettier-plugin-package"
],
"((.github/**/*)|(README|CHANGELOG)|(**/(README|CHANGELOG))).md": [
"((.github/**/*)|(docs/**/*)|(web/**/*.md)|(README|CHANGELOG)|(**/(README|CHANGELOG))).md": [
"prettier --write"
]
},
Expand Down
53 changes: 53 additions & 0 deletions packages/jsx-email/src/components/color-scheme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { JsxEmailComponent } from '../types';

export type ColorSchemeMode =
| 'dark'
/**
* The email client will only ever render the content in the dark color scheme and forbids the
* email client from overriding the color scheme.
*/
| 'dark only'
| 'light'
/**
* The email client will choose the light or dark theme to match the user’s preference.
* If the user’s preference does not match something in the list, the email client will choose
* which mode to display.
*/
| 'light dark'
/**
* The email client will choose the first of the listed schemes that it supports taking user
* preference into account and forbids the email client from overriding the color scheme.
*/
| 'light dark only'
/**
* The email client will only ever render the content in the light color scheme and forbids the
* email client from overriding the color scheme.
*/
| 'light only'
/**
* Indicates that the email supports the page’s supported color schemes, if they are set, or
* that it supports no color schemes at all otherwise.
*/
| 'normal';

export interface ColorSchemeProps {
/**
* Selects the color scheme mode that informs the email client which mode to render.
* @default `normal`
*/
mode?: ColorSchemeMode;
}

export const ColorScheme: JsxEmailComponent<ColorSchemeProps> = ({ mode = 'normal' }) => {
const style = `:root { color-scheme: ${mode}; supported-color-schemes: ${mode}; }`;

return (
<>
<meta name="color-scheme" content={mode} />
<meta name="supported-color-schemes" content={mode} />
<style dangerouslySetInnerHTML={{ __html: style }} />;
</>
);
};

ColorScheme.displayName = 'ColorScheme';
1 change: 1 addition & 0 deletions packages/jsx-email/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './components/body';
export * from './components/button/button';
export * from './components/code';
export * from './components/color-scheme';
export * from './components/column';
export * from './components/container';
export * from './components/font';
Expand Down
15 changes: 15 additions & 0 deletions packages/jsx-email/test/.snapshots/color-scheme.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`<ColorScheme> component > renders correctly 1`] = `"<meta name=\\"color-scheme\\" content=\\"normal\\"/><meta name=\\"supported-color-schemes\\" content=\\"normal\\"/><style>:root { color-scheme: normal; supported-color-schemes: normal; }</style>;"`;

exports[`<ColorScheme> component > renders correctly 2`] = `"<meta name=\\"color-scheme\\" content=\\"dark\\"/><meta name=\\"supported-color-schemes\\" content=\\"dark\\"/><style>:root { color-scheme: dark; supported-color-schemes: dark; }</style>;"`;

exports[`<ColorScheme> component > renders correctly 3`] = `"<meta name=\\"color-scheme\\" content=\\"dark only\\"/><meta name=\\"supported-color-schemes\\" content=\\"dark only\\"/><style>:root { color-scheme: dark only; supported-color-schemes: dark only; }</style>;"`;

exports[`<ColorScheme> component > renders correctly 4`] = `"<meta name=\\"color-scheme\\" content=\\"light\\"/><meta name=\\"supported-color-schemes\\" content=\\"light\\"/><style>:root { color-scheme: light; supported-color-schemes: light; }</style>;"`;

exports[`<ColorScheme> component > renders correctly 5`] = `"<meta name=\\"color-scheme\\" content=\\"light dark\\"/><meta name=\\"supported-color-schemes\\" content=\\"light dark\\"/><style>:root { color-scheme: light dark; supported-color-schemes: light dark; }</style>;"`;

exports[`<ColorScheme> component > renders correctly 6`] = `"<meta name=\\"color-scheme\\" content=\\"light dark only\\"/><meta name=\\"supported-color-schemes\\" content=\\"light dark only\\"/><style>:root { color-scheme: light dark only; supported-color-schemes: light dark only; }</style>;"`;

exports[`<ColorScheme> component > renders correctly 7`] = `"<meta name=\\"color-scheme\\" content=\\"light only\\"/><meta name=\\"supported-color-schemes\\" content=\\"light only\\"/><style>:root { color-scheme: light only; supported-color-schemes: light only; }</style>;"`;
32 changes: 32 additions & 0 deletions packages/jsx-email/test/color-scheme.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @ts-ignore
import React from 'react';

import { jsxToString } from '../src/render';
import { ColorScheme, type ColorSchemeMode } from '../src';

describe('<ColorScheme> component', async () => {
beforeEach(() => {
vi.restoreAllMocks();
vi.resetModules();
});

it('renders correctly', async () => {
const html = await jsxToString(<ColorScheme />);
expect(html).toMatchSnapshot();

const modes: ColorSchemeMode[] = [
'dark',
'dark only',
'light',
'light dark',
'light dark only',
'light only'
];

for (const mode of modes) {
// eslint-disable-next-line no-await-in-loop
const html = await jsxToString(<ColorScheme mode={mode} />);
expect(html).toMatchSnapshot();
}
});
});