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
26 changes: 26 additions & 0 deletions .storybook/dark-theme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import '@doist/product-libraries-tokens/css/td-dark.css'

import * as React from 'react'

const THEME_CLASS = 'theme_dark'

function DarkTheme({ children }: { children: React.ReactNode }) {
React.useEffect(function applyDarkTheme() {
const root = document.documentElement
root.classList.add(THEME_CLASS)
return () => root.classList.remove(THEME_CLASS)
}, [])

return <>{children}</>
}

/**
* Renders a story under the product library's dark theme.
*/
export function withDarkTheme(Story: React.ComponentType) {
return (
<DarkTheme>
<Story />
</DarkTheme>
)
}
1 change: 1 addition & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '@doist/product-libraries-tokens/css/td-light.css'
import '../src/styles/design-tokens.css'
import '../stories/components/styles/story.css'

Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,39 @@ If you prefer to include static files grab the [minified build from the dist fol
<link rel="stylesheet" type="text/css" href="./node_modules/@doist/reactist/styles/reactist.css" />
```

## Theming

Reactist bakes a light palette (`@doist/product-libraries-tokens`) into `reactist.css`. To use a dark or accent theme, load one of the theme files Reactist re-exports and toggle its class on the root element:

```html
<link rel="stylesheet" href="./node_modules/@doist/reactist/styles/tokens/<theme_name>.css" />
```

```js
import '@doist/reactist/styles/tokens/<theme_name>.css'
```

Then set the matching class on `:root`. Each theme file sets its own `color-scheme`, so you do not need to declare it yourself — the column below is what you get, not what you set.

| Theme / file name | color-scheme | class |
| ------------------- | ------------ | ---------------------- |
| `td-light` | `light` | none |
| `td-dark` | `dark` | `theme_dark` |
| `td-blueberry` | `light` | `theme_blueberry` |
| `td-blueberry-dark` | `dark` | `theme_blueberry_dark` |
| `td-gold` | `light` | `theme_gold` |
| `td-gold-dark` | `dark` | `theme_gold_dark` |
| `td-kale` | `light` | `theme_kale` |
| `td-kale-dark` | `dark` | `theme_kale_dark` |
| `td-lavender` | `light` | `theme_lavender` |
| `td-lavender-dark` | `dark` | `theme_lavender_dark` |
| `td-moonstone` | `light` | `theme_moonstone` |
| `td-moonstone-dark` | `dark` | `theme_moonstone_dark` |
| `td-raspberry` | `light` | `theme_raspberry` |
| `td-raspberry-dark` | `dark` | `theme_raspberry_dark` |
| `td-tangerine` | `light` | `theme_tangerine` |
| `td-tangerine-dark` | `dark` | `theme_tangerine_dark` |

# Changelog

You can find our changelog [here](./CHANGELOG.md).
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"@babel/register": "7.29.3",
"@doist/eslint-config": "12.0.1",
"@doist/prettier-config": "4.0.1",
"@doist/product-libraries-tokens": "1.0.0",
"@doist/react-compiler-tracker": "2.3.6",
"@doist/tsconfig": "2.0.1",
"@rollup/plugin-babel": "6.1.0",
Expand Down
2 changes: 2 additions & 0 deletions scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ rimraf dist/assets
# We delete duplicate styles in dist/ & lib/
./scripts/organize-styles.sh

# Copy the product-library theme CSS into styles/tokens/
./scripts/copy-token-themes.sh
29 changes: 29 additions & 0 deletions scripts/copy-token-themes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env sh

# Copy the product library's generated theme CSS into styles/tokens/. As it is a devDependency,
# consumers do not install the token package themselves, Each file is stamped with the token
# package version for record.

set -e

SRC="node_modules/@doist/product-libraries-tokens/dist/colors/css"
DEST="styles/tokens"
VERSION=$(node -p "require('@doist/product-libraries-tokens/package.json').version")

if [ ! -d "$SRC" ]; then
echo "❌ $SRC not found — is @doist/product-libraries-tokens installed?" >&2
exit 1
fi

mkdir -p "$DEST"
count=0
for f in "$SRC"/*.css; do
name=$(basename "$f")
{
printf '/* @doist/product-libraries-tokens@%s — generated theme, do not edit. Copied at Reactist build time. */\n' "$VERSION"
cat "$f"
} >"$DEST/$name"
count=$((count + 1))
done

printf "\n🎨 Copied %s token theme file(s) into %s (v%s).\n\n" "$count" "$DEST" "$VERSION"
88 changes: 44 additions & 44 deletions src/avatar/avatar.module.css
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
:root {
--reactist-avatar-initials-color: var(--reactist-actionable-primary-idle-tint);
--reactist-avatar-initials-color: var(--product-library-display-secondary-idle-tint);
--reactist-avatar-border-tint: #0000001a;
--reactist-avatar-empty-fill: var(--reactist-framework-fill-crest);

--reactist-avatar-meta-0-fill: #b8255f;
--reactist-avatar-meta-0-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-1-fill: #dc4c3e;
--reactist-avatar-meta-1-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-2-fill: #f48318;
--reactist-avatar-meta-2-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-3-fill: #fecf05;
--reactist-avatar-meta-3-on-idle-tint: #202020;
--reactist-avatar-meta-4-fill: #aeb83a;
--reactist-avatar-meta-4-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-5-fill: #7ecc48;
--reactist-avatar-meta-5-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-6-fill: #369307;
--reactist-avatar-meta-6-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-7-fill: #52ccb8;
--reactist-avatar-meta-7-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-8-fill: #148fad;
--reactist-avatar-meta-8-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-9-fill: #3ab9e2;
--reactist-avatar-meta-9-on-idle-tint: #202020;
--reactist-avatar-meta-10-fill: #96c3eb;
--reactist-avatar-meta-10-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-11-fill: #2a67e2;
--reactist-avatar-meta-11-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-12-fill: #692ec2;
--reactist-avatar-meta-12-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-13-fill: #ac30cc;
--reactist-avatar-meta-13-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-14-fill: #eb96c8;
--reactist-avatar-meta-14-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-15-fill: #e05095;
--reactist-avatar-meta-15-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-16-fill: #c9766f;
--reactist-avatar-meta-16-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-17-fill: #808080;
--reactist-avatar-meta-17-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-18-fill: #999999;
--reactist-avatar-meta-18-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-meta-19-fill: #ccae96;
--reactist-avatar-meta-19-on-idle-tint: var(--reactist-avatar-initials-color);
--reactist-avatar-empty-fill: var(--product-library-display-quaternary-idle-tint);

--reactist-avatar-meta-0-fill: var(--product-library-meta-berry-fill);
--reactist-avatar-meta-0-on-idle-tint: #fff;
--reactist-avatar-meta-1-fill: var(--product-library-meta-red-fill);
--reactist-avatar-meta-1-on-idle-tint: #fff;
--reactist-avatar-meta-2-fill: var(--product-library-meta-orange-fill);
--reactist-avatar-meta-2-on-idle-tint: #fff;
--reactist-avatar-meta-3-fill: var(--product-library-meta-yellow-fill);
--reactist-avatar-meta-3-on-idle-tint: #1f1f1f;
--reactist-avatar-meta-4-fill: var(--product-library-meta-olive-green-fill);
--reactist-avatar-meta-4-on-idle-tint: #fff;
--reactist-avatar-meta-5-fill: var(--product-library-meta-lime-green-fill);
--reactist-avatar-meta-5-on-idle-tint: #fff;
--reactist-avatar-meta-6-fill: var(--product-library-meta-green-fill);
--reactist-avatar-meta-6-on-idle-tint: #fff;
--reactist-avatar-meta-7-fill: var(--product-library-meta-mint-green-fill);
--reactist-avatar-meta-7-on-idle-tint: #fff;
--reactist-avatar-meta-8-fill: var(--product-library-meta-teal-fill);
--reactist-avatar-meta-8-on-idle-tint: #fff;
--reactist-avatar-meta-9-fill: var(--product-library-meta-sky-blue-fill);
--reactist-avatar-meta-9-on-idle-tint: #1f1f1f;
--reactist-avatar-meta-10-fill: var(--product-library-meta-light-blue-fill);
--reactist-avatar-meta-10-on-idle-tint: #fff;
--reactist-avatar-meta-11-fill: var(--product-library-meta-blue-fill);
--reactist-avatar-meta-11-on-idle-tint: #fff;
--reactist-avatar-meta-12-fill: var(--product-library-meta-grape-fill);
--reactist-avatar-meta-12-on-idle-tint: #fff;
--reactist-avatar-meta-13-fill: var(--product-library-meta-violet-fill);
--reactist-avatar-meta-13-on-idle-tint: #fff;
--reactist-avatar-meta-14-fill: var(--product-library-meta-lavender-fill);
--reactist-avatar-meta-14-on-idle-tint: #fff;
--reactist-avatar-meta-15-fill: var(--product-library-meta-magenta-fill);
--reactist-avatar-meta-15-on-idle-tint: #fff;
--reactist-avatar-meta-16-fill: var(--product-library-meta-salmon-fill);
--reactist-avatar-meta-16-on-idle-tint: #fff;
--reactist-avatar-meta-17-fill: var(--product-library-meta-charcoal-fill);
--reactist-avatar-meta-17-on-idle-tint: #fff;
--reactist-avatar-meta-18-fill: var(--product-library-meta-grey-fill);
--reactist-avatar-meta-18-on-idle-tint: #fff;
--reactist-avatar-meta-19-fill: var(--product-library-meta-taupe-fill);
--reactist-avatar-meta-19-on-idle-tint: #fff;
}

.avatar {
--reactist-avatar-size: 36px;
--reactist-avatar-rounded-radius: 5px;
--reactist-avatar-outline-width: 1px;
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-0-fill);
--reactist-avatar-meta-fill: var(--product-library-meta-grey-fill);

background-color: var(--reactist-avatar-empty-fill);
width: var(--reactist-avatar-size);
Expand Down
4 changes: 1 addition & 3 deletions src/badge/badge.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ The following CSS custom properties are available to customize the badge compone

### Dark mode

Even though Reactist does not yet owns the concept of dark mode, and leaves it for apps to set it
up, here's a demo on how easily you can prepare badges for dark mode by setting CSS custom
properties.
Dark mode colors are applied when the `.theme_dark` class is set on the root element.

<Canvas of={BadgeStories.DarkMode} />
16 changes: 8 additions & 8 deletions src/badge/badge.module.css
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
:root {
--reactist-badge-font-size: 10px;

--reactist-badge-info-tint: #666666;
--reactist-badge-info-fill: #eeeeee;
--reactist-badge-info-tint: var(--product-library-info-neutral-tertiary-on-idle-tint);
--reactist-badge-info-fill: var(--product-library-info-neutral-tertiary-idle-fill);

--reactist-badge-positive-tint: #058527;
--reactist-badge-positive-fill: #e0f0e3;
--reactist-badge-positive-tint: var(--product-library-info-positive-secondary-on-idle-tint);
--reactist-badge-positive-fill: var(--product-library-info-positive-secondary-idle-fill);

--reactist-badge-promote-tint: #8f4700;
--reactist-badge-promote-fill: #faead1;
--reactist-badge-promote-tint: var(--product-library-info-promote-tertiary-on-idle-tint);
--reactist-badge-promote-fill: var(--product-library-info-promote-tertiary-idle-fill);

--reactist-badge-attention-tint: #cf473a;
--reactist-badge-attention-fill: #f9e3e2;
--reactist-badge-attention-tint: var(--product-library-info-attention-secondary-on-idle-tint);
--reactist-badge-attention-fill: var(--product-library-info-attention-secondary-idle-fill);
}

.badge {
Expand Down
27 changes: 8 additions & 19 deletions src/badge/badge.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react'

import { withDarkTheme } from '../../.storybook/dark-theme'
import { Box } from '../box'
import { Button } from '../button'
import { Column, Columns } from '../columns'
Expand Down Expand Up @@ -62,25 +63,7 @@ function BadgeExamples() {

function DarkModeTemplate() {
return (
<Box
padding="xlarge"
style={{
backgroundColor: '#202020',
'--reactist-content-primary': 'rgba(255, 255, 255, 0.88)',
// tone="info"
'--reactist-badge-info-tint': '#B3B3B3',
'--reactist-badge-info-fill': '#363636',
// tone="positive"
'--reactist-badge-positive-tint': '#08A531',
'--reactist-badge-positive-fill': '#19231B',
// tone="promote"
'--reactist-badge-promote-tint': '#FF8C1A',
'--reactist-badge-promote-fill': '#412A06',
// tone="attention"
'--reactist-badge-attention-tint': '#CF473A',
'--reactist-badge-attention-fill': '#351E1C',
}}
>
<Box padding="xlarge" background="default">
<BadgeExamples />
</Box>
)
Expand Down Expand Up @@ -188,13 +171,19 @@ export const InsideOtherElements = {

export const DarkMode = {
render: DarkModeTemplate.bind({}),
decorators: [withDarkTheme],
name: 'Dark mode',

parameters: {
docs: {
source: {
type: 'dynamic',
},
// Render as an iframe to scope `theme_dark` to the story
story: {
inline: false,
height: '260px',
},
},
},
}
4 changes: 1 addition & 3 deletions src/banner/banner.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ The following CSS custom properties are available to customize the banner compon

### Dark mode

Even though Reactist does not yet owns the concept of dark mode, and leaves it for apps to set it
up, here's a demo on how easily you can prepare banners for dark mode by setting CSS custom
properties.
Dark mode colors are applied when the `.theme_dark` class is set on the root element.

<Canvas of={BannerStories.DarkMode} />
10 changes: 5 additions & 5 deletions src/banner/banner.module.css
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
:root {
--reactist-banner-background-color: #fcfaf8;
--reactist-banner-border-color: #e6e6e6;
--reactist-banner-divider-color: var(--reactist-divider-secondary);
--reactist-banner-background-color: var(--product-library-background-base-secondary);
--reactist-banner-border-color: var(--product-library-border-idle-tint);
--reactist-banner-divider-color: var(--product-library-divider-secondary);

--reactist-banner-main-copy-font-size: 14px;
--reactist-banner-main-copy-line-height: 21px;
--reactist-banner-main-copy-spacing: -0.15px;
--reactist-banner-main-copy-color: #202020;
--reactist-banner-main-copy-color: var(--product-library-display-primary-idle-tint);

--reactist-banner-secondary-copy-font-size: 12px;
--reactist-banner-secondary-copy-line-height: 20px;
--reactist-banner-secondary-copy-color: #666666;
--reactist-banner-secondary-copy-color: var(--product-library-display-secondary-idle-tint);

--reactist-banner-min-width: 0;
}
Expand Down
Loading
Loading