Skip to content

Commit 5dac45c

Browse files
authored
Extract CSS vars from RAC docs into reusable package (#5419)
1 parent 3688f07 commit 5dac45c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+694
-1465
lines changed

.parcelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"bundle-text:*.svg": ["@parcel/transformer-svg", "@parcel/transformer-inline-string"],
1010
"*.{md,mdx}": ["parcel-transformer-mdx-docs"],
1111
"*.svg": ["@parcel/transformer-svg-react"],
12-
"*.global.css": ["parcel-transformer-css-global", "..."],
12+
"packages/@react-aria/example-theme/**/*.css": ["@parcel/transformer-css"],
1313
"*.css": ["...", "parcel-transformer-css-env"],
1414
"*.{js,mjs,jsm,jsx,es6,cjs,ts,tsx}": [
1515
"@parcel/transformer-js",

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,10 @@
187187
"browserslist": "4.20.3"
188188
},
189189
"@parcel/transformer-css": {
190-
"cssModules": true,
190+
"cssModules": {
191+
"global": true,
192+
"exclude": ["**/*.global.css", "packages/@react-aria/example-theme/**"]
193+
},
191194
"drafts": {
192195
"nesting": true
193196
},
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# @react-aria/example-theme
2+
3+
This package is part of [react-spectrum](https://github.com/adobe/react-spectrum). See the repo for more details.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "@react-aria/example-theme",
3+
"version": "1.0.0",
4+
"description": "Spectrum UI components in React",
5+
"license": "Apache-2.0",
6+
"source": "src/index.css",
7+
"dist": "dist/index.css",
8+
"main": "dist/index.css",
9+
"targets": {
10+
"main": false,
11+
"dist": {
12+
"optimize": false
13+
}
14+
},
15+
"repository": {
16+
"type": "git",
17+
"url": "https://github.com/adobe/react-spectrum"
18+
},
19+
"publishConfig": {
20+
"access": "public"
21+
}
22+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* color themes for dark and light modes, generated with Leonardo.
2+
* Light: https://leonardocolor.io/theme.html?name=Light&config=%7B%22baseScale%22%3A%22Gray%22%2C%22colorScales%22%3A%5B%7B%22name%22%3A%22Gray%22%2C%22colorKeys%22%3A%5B%22%23000000%22%5D%2C%22colorspace%22%3A%22RGB%22%2C%22ratios%22%3A%5B%22-1.12%22%2C%221.45%22%2C%222.05%22%2C%223.02%22%2C%224.54%22%2C%227%22%2C%2210.86%22%5D%2C%22smooth%22%3Afalse%7D%2C%7B%22name%22%3A%22Purple%22%2C%22colorKeys%22%3A%5B%22%235e30eb%22%5D%2C%22colorspace%22%3A%22RGB%22%2C%22ratios%22%3A%5B%22-1.12%22%2C%221.45%22%2C%222.05%22%2C%223.02%22%2C%224.54%22%2C%227%22%2C%2210.86%22%5D%2C%22smooth%22%3Afalse%7D%2C%7B%22name%22%3A%22Red%22%2C%22colorKeys%22%3A%5B%22%23e32400%22%5D%2C%22colorspace%22%3A%22RGB%22%2C%22ratios%22%3A%5B%22-1.12%22%2C%221.45%22%2C%222.05%22%2C%223.02%22%2C%224.54%22%2C%227%22%2C%2210.86%22%5D%2C%22smooth%22%3Afalse%7D%5D%2C%22lightness%22%3A98%2C%22contrast%22%3A1%2C%22saturation%22%3A100%2C%22formula%22%3A%22wcag2%22%7D */
3+
:root {
4+
--background-color: #f8f8f8;
5+
--gray-50: #ffffff;
6+
--gray-100: #d0d0d0;
7+
--gray-200: #afafaf;
8+
--gray-300: #8f8f8f;
9+
--gray-400: #717171;
10+
--gray-500: #555555;
11+
--gray-600: #393939;
12+
--purple-100: #d5c9fa;
13+
--purple-200: #b8a3f6;
14+
--purple-300: #997cf2;
15+
--purple-400: #7a54ef;
16+
--purple-500: #582ddc;
17+
--purple-600: #3c1e95;
18+
--red-100: #f7c4ba;
19+
--red-200: #f29887;
20+
--red-300: #eb664d;
21+
--red-400: #de2300;
22+
--red-500: #a81b00;
23+
--red-600: #731200;
24+
--highlight-hover: rgb(0 0 0 / 0.07);
25+
--highlight-pressed: rgb(0 0 0 / 0.15);
26+
}
27+
28+
/* Dark: https://leonardocolor.io/theme.html?name=Dark&config=%7B%22baseScale%22%3A%22Gray%22%2C%22colorScales%22%3A%5B%7B%22name%22%3A%22Gray%22%2C%22colorKeys%22%3A%5B%22%23000000%22%5D%2C%22colorspace%22%3A%22RGB%22%2C%22ratios%22%3A%5B%22-1.12%22%2C%221.45%22%2C%222.05%22%2C%223.02%22%2C%224.54%22%2C%227%22%2C%2210.86%22%5D%2C%22smooth%22%3Afalse%7D%2C%7B%22name%22%3A%22Purple%22%2C%22colorKeys%22%3A%5B%22%235e30eb%22%5D%2C%22colorspace%22%3A%22RGB%22%2C%22ratios%22%3A%5B%22-1.12%22%2C%221.45%22%2C%222.05%22%2C%223.02%22%2C%224.54%22%2C%227%22%2C%2210.86%22%5D%2C%22smooth%22%3Afalse%7D%2C%7B%22name%22%3A%22Red%22%2C%22colorKeys%22%3A%5B%22%23e32400%22%5D%2C%22colorspace%22%3A%22RGB%22%2C%22ratios%22%3A%5B%22-1.12%22%2C%221.45%22%2C%222.05%22%2C%223.02%22%2C%224.54%22%2C%227%22%2C%2210.86%22%5D%2C%22smooth%22%3Afalse%7D%5D%2C%22lightness%22%3A11%2C%22contrast%22%3A1%2C%22saturation%22%3A100%2C%22formula%22%3A%22wcag2%22%7D */
29+
@media (prefers-color-scheme: dark) {
30+
:root {
31+
--background-color: #1d1d1d;
32+
--gray-50: #101010;
33+
--gray-100: #393939;
34+
--gray-200: #4f4f4f;
35+
--gray-300: #686868;
36+
--gray-400: #848484;
37+
--gray-500: #a7a7a7;
38+
--gray-600: #cfcfcf;
39+
--purple-100: #3c1e95;
40+
--purple-200: #522acd;
41+
--purple-300: #6f46ed;
42+
--purple-400: #8e6ef1;
43+
--purple-500: #b099f5;
44+
--purple-600: #d5c8fa;
45+
--red-100: #721200;
46+
--red-200: #9c1900;
47+
--red-300: #cc2000;
48+
--red-400: #e95034;
49+
--red-500: #f08c79;
50+
--red-600: #f7c3ba;
51+
--highlight-hover: rgb(255 255 255 / 0.1);
52+
--highlight-pressed: rgb(255 255 255 / 0.2);
53+
}
54+
}
55+
56+
/* Semantic colors */
57+
:root {
58+
--focus-ring-color: var(--purple-400);
59+
--text-color: var(--gray-600);
60+
--text-color-base: var(--gray-500);
61+
--text-color-hover: var(--gray-600);
62+
--text-color-disabled: var(--gray-200);
63+
--text-color-placeholder: var(--gray-400);
64+
--link-color: var(--purple-500);
65+
--link-color-secondary: var(--gray-500);
66+
--link-color-pressed: var(--purple-600);
67+
--border-color: var(--gray-300);
68+
--border-color-hover: var(--gray-400);
69+
--border-color-pressed: var(--gray-400);
70+
--border-color-disabled: var(--gray-100);
71+
--field-background: var(--gray-50);
72+
--field-text-color: var(--gray-600);
73+
--overlay-background: var(--gray-50);
74+
--button-background: var(--gray-50);
75+
--button-background-pressed: var(--background-color);
76+
/* these colors are the same between light and dark themes
77+
* to ensure contrast with the foreground color */
78+
--highlight-background: #6f46ed; /* purple-300 from dark theme, 3.03:1 against background-color */
79+
--highlight-background-pressed: #522acd; /* purple-200 from dark theme */
80+
--highlight-background-invalid: #cc2000; /* red-300 from dark theme */
81+
--highlight-foreground: white; /* 5.56:1 against highlight-background */
82+
--highlight-foreground-pressed: #ddd;
83+
--highlight-overlay: rgb(from #6f46ed r g b / 15%);
84+
--invalid-color: var(--red-400);
85+
--invalid-color-pressed: var(--red-500);
86+
}
87+
88+
/* Windows high contrast mode overrides */
89+
@media (forced-colors: active) {
90+
:root {
91+
--background-color: Canvas;
92+
--focus-ring-color: Highlight;
93+
--text-color: ButtonText;
94+
--text-color-base: ButtonText;
95+
--text-color-hover: ButtonText;
96+
--text-color-disabled: GrayText;
97+
--text-color-placeholder: ButtonText;
98+
--link-color: LinkText;
99+
--link-color-secondary: LinkText;
100+
--link-color-pressed: LinkText;
101+
--border-color: ButtonBorder;
102+
--border-color-hover: ButtonBorder;
103+
--border-color-pressed: ButtonBorder;
104+
--border-color-disabled: GrayText;
105+
--field-background: Field;
106+
--field-text-color: FieldText;
107+
--overlay-background: Canvas;
108+
--button-background: ButtonFace;
109+
--button-background-pressed: ButtonFace;
110+
--highlight-background: Highlight;
111+
--highlight-background-pressed: Highlight;
112+
--highlight-background-invalid: LinkText;
113+
--highlight-foreground: HighlightText;
114+
--highlight-foreground-pressed: HighlightText;
115+
--invalid-color: LinkText;
116+
--invalid-color-pressed: LinkText;
117+
}
118+
}

packages/dev/parcel-transformer-css-global/CSSGlobalTransformer.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

packages/dev/parcel-transformer-css-global/package.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

packages/dev/parcel-transformer-mdx-docs/MDXTransformer.js

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ const {fragmentUnWrap, fragmentWrap} = require('./MDXFragments');
1717
const yaml = require('js-yaml');
1818
const dprint = require('dprint-node');
1919
const t = require('@babel/types');
20-
const lightningcss = require('lightningcss');
21-
const fs = require('fs');
22-
const path = require('path');
20+
const processCSS = require('./processCSS');
2321

2422
const IMPORT_MAPPINGS = {
2523
'@react-spectrum/theme-default': {
@@ -44,9 +42,6 @@ module.exports = new Transformer({
4442
let preRelease = preReleaseParts ? preReleaseParts[0] : '';
4543

4644
let visit = (await import('unist-util-visit')).visit;
47-
let unified = (await import('unified')).unified;
48-
let remarkParse = (await import('remark-parse')).default;
49-
let remarkMdx = (await import('remark-mdx')).default;
5045
const extractExamples = () => (tree, file) => (
5146
flatMap(tree, node => {
5247
if (node.type === 'code') {
@@ -169,50 +164,7 @@ module.exports = new Transformer({
169164
);
170165

171166
let appendCSS = () => async (tree) => {
172-
let transformed = await lightningcss.bundleAsync({
173-
filename: `${asset.filePath}.lightning`,
174-
minify: true,
175-
drafts: {
176-
nesting: true
177-
},
178-
targets: {
179-
chrome: 95 << 16,
180-
safari: 15 << 16
181-
},
182-
resolver: {
183-
resolve(specifier, parent) {
184-
if (specifier.startsWith('.')) {
185-
return path.resolve(path.dirname(parent), specifier);
186-
}
187-
188-
let baseDir = process.env.DOCS_ENV === 'production' ? 'docs' : 'packages';
189-
return path.resolve(options.projectRoot, baseDir, specifier);
190-
},
191-
read(filePath) {
192-
if (filePath === `${asset.filePath}.lightning`) {
193-
return cssCode.join('\n');
194-
}
195-
let result = '';
196-
try {
197-
let contents = fs.readFileSync(filePath, 'utf8');
198-
// get all css blocks and concat
199-
let ast = unified().use(remarkParse).use(remarkMdx).parse(contents);
200-
visit(ast, 'code', node => {
201-
if (node.lang !== 'css' || node?.meta?.includes('render=false') || node?.meta?.includes('hidden')) {
202-
return;
203-
}
204-
let code = node.value;
205-
code = code.replace(/@import.*/g, '');
206-
result += code;
207-
});
208-
} catch (e) {
209-
console.log(e);
210-
}
211-
return result;
212-
}
213-
}
214-
});
215-
let css = transformed.code.toString();
167+
let css = await processCSS(cssCode, asset, options);
216168

217169
tree.children.push(
218170
{
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
const lightningcss = require('lightningcss');
14+
const fs = require('fs');
15+
const path = require('path');
16+
17+
module.exports = async function processCSS(cssCode, asset, options) {
18+
let visit = (await import('unist-util-visit')).visit;
19+
let unified = (await import('unified')).unified;
20+
let remarkParse = (await import('remark-parse')).default;
21+
let remarkMdx = (await import('remark-mdx')).default;
22+
let transformed = await lightningcss.bundleAsync({
23+
filename: `${asset.filePath}.lightning`,
24+
minify: true,
25+
drafts: {
26+
nesting: true
27+
},
28+
targets: {
29+
chrome: 95 << 16,
30+
safari: 15 << 16
31+
},
32+
resolver: {
33+
resolve(specifier, parent) {
34+
if (specifier.startsWith('.')) {
35+
return path.resolve(path.dirname(parent), specifier);
36+
}
37+
38+
if (path.extname(specifier) === '') {
39+
// Assume this is a package.
40+
specifier += '/src/index.css';
41+
}
42+
43+
let baseDir = process.env.DOCS_ENV === 'production' ? 'docs' : 'packages';
44+
return path.resolve(options.projectRoot, baseDir, specifier);
45+
},
46+
read(filePath) {
47+
if (filePath === `${asset.filePath}.lightning`) {
48+
return cssCode.join('\n');
49+
}
50+
asset.invalidateOnFileChange(filePath);
51+
52+
let result = '';
53+
try {
54+
let contents = fs.readFileSync(filePath, 'utf8');
55+
if (path.extname(filePath) === '.css') {
56+
return contents;
57+
}
58+
// get all css blocks and concat
59+
let ast = unified().use(remarkParse).use(remarkMdx).parse(contents);
60+
visit(ast, 'code', node => {
61+
if (node.lang !== 'css' || node?.meta?.includes('render=false') || node?.meta?.includes('hidden')) {
62+
return;
63+
}
64+
let code = node.value;
65+
code = code.replace(/@import.*/g, '');
66+
result += code;
67+
});
68+
} catch (e) {
69+
console.log(e);
70+
}
71+
return result;
72+
}
73+
},
74+
visitor: {
75+
Rule: {
76+
media(m) {
77+
// Convert dark mode media query to use docs color scheme.
78+
let mediaQueries = m.value.query.mediaQueries;
79+
let condition = mediaQueries[0].condition;
80+
let isDarkMode = mediaQueries.length === 1
81+
&& condition.type === 'feature'
82+
&& condition.value.type === 'plain'
83+
&& condition.value.name === 'prefers-color-scheme'
84+
&& condition.value.value.value === 'dark';
85+
if (isDarkMode) {
86+
return {
87+
type: 'style',
88+
value: {
89+
// Generates this selector: `:root[style*="color-scheme: dark"]`
90+
selectors: [[
91+
{type: 'pseudo-class', kind: 'root'},
92+
{type: 'attribute', name: 'style', operation: {operator: 'substring', value: 'color-scheme: dark'}}
93+
]],
94+
loc: m.value.loc,
95+
declarations: m.value.rules[0].value.declarations
96+
}
97+
};
98+
}
99+
}
100+
}
101+
}
102+
});
103+
104+
return transformed.code.toString();
105+
};

0 commit comments

Comments
 (0)