Skip to content

Commit f603e16

Browse files
lazdpfulton
authored andcommitted
feat: add core tokens
1 parent dc00e17 commit f603e16

File tree

14 files changed

+546
-10
lines changed

14 files changed

+546
-10
lines changed

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ If you're targeting modern browsers, start by including the base set of variable
6060
<link rel="stylesheet" href="node_modules/@spectrum-css/vars/dist/spectrum-dark.css">
6161
<link rel="stylesheet" href="node_modules/@spectrum-css/vars/dist/spectrum-darkest.css">
6262

63+
<!-- Include tokens -->
64+
<link rel="stylesheet" href="node_modules/@spectrum-css/tokens/dist/index.css">
65+
6366
<!-- Include index-vars.css for all components you need -->
6467
<link rel="stylesheet" href="node_modules/@spectrum-css/page/dist/index-vars.css">
6568
<link rel="stylesheet" href="node_modules/@spectrum-css/typography/dist/index-vars.css">
@@ -72,13 +75,28 @@ Then, make sure you've included the relevant classes to choose which scale and c
7275
<html class="spectrum spectrum--medium spectrum--light">
7376
```
7477

75-
**Note:** If you are importing SVG icon sprite sheets, the `.spectrum--medium`/`.spectrum--large` classes should be added to the `<html>` element so UI icons render in the correct size in IE 11. For browsers that support custom properties, or if you're not using SVG sprite sheets for UI icons and are manually managing icon sizing in your implementation, `.spectrum--medium`/`.spectrum--large` can be added to the `<body>` or other element.
78+
To switch to Express, load vars from `@spectrum-css/expressvars` instead of `@spectrum-css/vars` and add the `.spectrum--express` class to the `<html>` element:
79+
80+
```html
81+
<html class="spectrum spectrum--medium spectrum--light spectrum--express">
82+
<head>
83+
<!-- Include only the scales your application needs -->
84+
<link rel="stylesheet" href="node_modules/@spectrum-css/expressvars/dist/spectrum-medium.css">
85+
<link rel="stylesheet" href="node_modules/@spectrum-css/expressvars/dist/spectrum-large.css">
86+
87+
<!-- Include only the colorstops your application needs -->
88+
<link rel="stylesheet" href="node_modules/@spectrum-css/expressvars/dist/spectrum-light.css">
89+
<link rel="stylesheet" href="node_modules/@spectrum-css/expressvars/dist/spectrum-dark.css">
90+
</head>
91+
```
7692

7793
Then you can use components by copy/pasting their code from [the documentation](http://opensource.adobe.com/spectrum-css/).
7894

7995
With the magic of CSS custom properties, you can infinitely nest different color stops and themes, [as illustrated here](https://codepen.io/lazd/pen/axXMRL).
8096

81-
Additionally, you can override variables and customize Spectrum CSS' look and feel by re-defining the custom properties in context, [like so](https://codepen.io/lazd/pen/ROvOPO). See the source in `components/*/index-vars.css` to determine which custom properties you can override.
97+
### Customizing components
98+
99+
You can override variables and customize Spectrum CSS' look and feel by re-defining the custom properties in context. Look for the **Custom Property API** section in each component to determine which custom properties you can override. See [ActionButton for a complete example](https://opensource.adobe.com/spectrum-css/actionbutton.html#customized).
82100

83101
### Importing UI icons
84102

components/tokens/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# @spectrum-css/tokens
2+
> Core tokens builder for Spectrum CSS
3+
4+
This package uses StyleDictionary to build Spectrum core tokens for CSS.
5+
6+
## Output
7+
8+
The output is concatenated into a single `dist/index.css` for use in Spectrum CSS. This entire file should be imported, and the relevant classes should be toggled to swap out core tokens.
9+
10+
On the `<html>` element, start with `.spectrum`, add in `.spectrum--light`, then `.spectrum--medium`. To switch to Express, add `.spectrum--express`.
11+
12+
## Overrides and additions
13+
14+
Custom overrides and additions to core tokens can be added to `custom.css`.
15+
16+
Ensure that you correctly scope any added tokens:
17+
18+
* `.spectrum` - Global, unchanging tokens or tokens specific to the Spectrum flavor
19+
* `.spectrum--express` - Tokens specific to the Express flavor
20+
* `.spectrum--lightest` - Tokens specific to the light color stop (soon to be deprecated)
21+
* `.spectrum--light` - Tokens specific to the light color stop
22+
* `.spectrum--dark` - Tokens specific to the dark color stop
23+
* `.spectrum--darkest` - Tokens specific to the darkest color stop
24+
* `.spectrum--medium` - Tokens specific to the medium (desktop) scale
25+
* `.spectrum--large` - Tokens specific to the large (mobile) scale
26+
* `.spectrum--express.spectrum--*` - Tokens specific to the Express flavor for any of the above color stops and scales

components/tokens/config.js

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
Copyright 2022 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 path = require('path');
14+
const StyleDictionary = require('style-dictionary');
15+
const CSSSetsFormatter = require('style-dictionary-sets').CSSSetsFormatter;
16+
const NameKebabTransfom = require('style-dictionary-sets').NameKebabTransfom;
17+
const AttributeSetsTransform = require('style-dictionary-sets').AttributeSetsTransform;
18+
19+
StyleDictionary.registerTransform(NameKebabTransfom);
20+
StyleDictionary.registerTransform(AttributeSetsTransform);
21+
StyleDictionary.registerFormat(CSSSetsFormatter);
22+
23+
const systemNames = ['express', 'spectrum', 'wireframe'];
24+
25+
const getSets = (token) => {
26+
return token.path.filter(
27+
(part, index, array) => array[index - 1] == "sets"
28+
);
29+
}
30+
31+
const tokenHasSets = (token) => {
32+
return token.path.includes('sets');
33+
}
34+
35+
const generateFileConfig = (setName, subSystemName) => {
36+
const sets = [setName, subSystemName];
37+
38+
const selectorMap = {
39+
'desktop': 'medium',
40+
'mobile': 'large'
41+
};
42+
43+
const fileName = selectorMap[setName] ?? setName;
44+
45+
let selector = `.spectrum--${fileName}`;
46+
if (subSystemName !== 'spectrum') {
47+
selector = `.spectrum--${subSystemName}${selector}`;
48+
}
49+
50+
return {
51+
destination: `${subSystemName}/${fileName}-vars.css`,
52+
format: CSSSetsFormatter.name,
53+
filter: (token) => {
54+
return (
55+
tokenHasSets(token) &&
56+
getSets(token).includes(subSystemName) &&
57+
getSets(token).includes(setName)
58+
);
59+
},
60+
options: {
61+
selector,
62+
showFileHeader: false,
63+
outputReferences: true,
64+
sets
65+
},
66+
}
67+
};
68+
69+
const generateGlobalConfig = (subSystemName) => {
70+
const sets = [subSystemName];
71+
72+
const selector = subSystemName === 'spectrum' ? '.spectrum' : `.spectrum--${subSystemName}`;
73+
74+
return {
75+
destination: `${subSystemName}/global-vars.css`,
76+
format: CSSSetsFormatter.name,
77+
filter: (token) => {
78+
return (
79+
tokenHasSets(token) &&
80+
getSets(token).length === 1 &&
81+
getSets(token)[0] === subSystemName
82+
);
83+
},
84+
options: {
85+
selector,
86+
showFileHeader: false,
87+
outputReferences: true,
88+
sets
89+
},
90+
}
91+
}
92+
93+
const generateGlobalSetConfig = (setName) => {
94+
const sets = [setName];
95+
96+
const selectorMap = {
97+
'desktop': 'medium',
98+
'mobile': 'large'
99+
};
100+
101+
const fileName = selectorMap[setName] ?? setName;
102+
103+
let selectors = [`.spectrum--${fileName}`];
104+
105+
// Apply all light colors as lightest for backwards compat
106+
if (setName === 'light') {
107+
selectors.push('.spectrum--lightest');
108+
}
109+
110+
return {
111+
destination: `${fileName}-vars.css`,
112+
format: CSSSetsFormatter.name,
113+
filter: (token) => {
114+
return (
115+
tokenHasSets(token) &&
116+
getSets(token).every(set => !systemNames.includes(set)) &&
117+
getSets(token).includes(setName)
118+
);
119+
},
120+
options: {
121+
selector: selectors.join(', '),
122+
showFileHeader: false,
123+
outputReferences: true,
124+
sets
125+
},
126+
}
127+
}
128+
129+
const tokenGlob = path.dirname(require.resolve('@adobe/spectrum-tokens')) + '/src/**/*.json';
130+
module.exports = {
131+
source: [tokenGlob],
132+
platforms: {
133+
CSS: {
134+
buildPath: 'dist/css/',
135+
transforms: [AttributeSetsTransform.name, NameKebabTransfom.name],
136+
prefix: 'spectrum',
137+
files: [
138+
{
139+
destination: 'global-vars.css',
140+
format: CSSSetsFormatter.name,
141+
filter: (token) => !tokenHasSets(token),
142+
options: {
143+
showFileHeader: false,
144+
outputReferences: true,
145+
selector: '.spectrum'
146+
},
147+
},
148+
generateGlobalSetConfig('desktop'),
149+
generateGlobalSetConfig('mobile'),
150+
generateGlobalSetConfig('light'),
151+
generateGlobalSetConfig('dark'),
152+
generateGlobalSetConfig('darkest'),
153+
154+
generateGlobalConfig('spectrum'),
155+
generateFileConfig('desktop', 'spectrum'),
156+
generateFileConfig('mobile', 'spectrum'),
157+
generateFileConfig('light', 'spectrum'),
158+
generateFileConfig('dark', 'spectrum'),
159+
generateFileConfig('darkest', 'spectrum'),
160+
161+
generateGlobalConfig('express'),
162+
generateFileConfig('desktop', 'express'),
163+
generateFileConfig('mobile', 'express'),
164+
generateFileConfig('light', 'express'),
165+
generateFileConfig('dark', 'express'),
166+
generateFileConfig('darkest', 'express'),
167+
],
168+
},
169+
},
170+
};

components/tokens/custom.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright 2022 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+
/* This file contains overrides and additions to core tokens */
14+
15+
.spectrum {
16+
--spectrum-animation-duration-100: 130ms;
17+
}
18+
19+
.spectrum--medium {
20+
/* edge-to-visual-only is used for icon-only buttons */
21+
--spectrum-edge-to-visual-only-75: 4px;
22+
--spectrum-edge-to-visual-only-100: 7px;
23+
--spectrum-edge-to-visual-only-200: 10px;
24+
--spectrum-edge-to-visual-only-300: 13px;
25+
}
26+
27+
.spectrum--large {
28+
/* edge-to-visual-only is used for icon-only buttons */
29+
--spectrum-edge-to-visual-only-75: 5px;
30+
--spectrum-edge-to-visual-only-100: 9px;
31+
--spectrum-edge-to-visual-only-200: 13px;
32+
--spectrum-edge-to-visual-only-300: 16px;
33+
}

components/tokens/gulpfile.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright 2022 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 gulp = require('gulp');
14+
const concat = require('gulp-concat');
15+
const del = require('del');
16+
const StyleDictionary = require('style-dictionary').extend('config.js');
17+
18+
function clean() {
19+
return del('dist/*');
20+
}
21+
22+
function concatIndex() {
23+
return gulp.src([
24+
'dist/css/*.css',
25+
'dist/css/spectrum/*.css',
26+
'dist/css/express/*.css',
27+
'custom.css'
28+
])
29+
.pipe(concat('index.css'))
30+
.pipe(gulp.dest('dist/'));
31+
}
32+
33+
function styleDictionary(cb) {
34+
StyleDictionary.buildAllPlatforms();
35+
cb();
36+
}
37+
38+
exports.clean = clean;
39+
exports.build = exports.buildLite = exports.buildMedium = exports.default = gulp.series(
40+
clean,
41+
styleDictionary,
42+
concatIndex
43+
);

components/tokens/package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "@spectrum-css/tokens",
3+
"version": "1.0.0-beta.0",
4+
"description": "The Spectrum CSS tokens package",
5+
"license": "Apache-2.0",
6+
"main": "dist/index.css",
7+
"scripts": {
8+
"build": "gulp build"
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "https://github.com/adobe/spectrum-css.git",
13+
"directory": "components/tokens"
14+
},
15+
"bugs": {
16+
"url": "https://github.com/adobe/spectrum-css/issues"
17+
},
18+
"devDependencies": {
19+
"gulp": "^4.0.0",
20+
"gulp-concat": "^2.6.1",
21+
"@adobe/spectrum-tokens": "^12.0.0-beta.21",
22+
"style-dictionary": "^3.7.0",
23+
"style-dictionary-sets": "^1.4.1"
24+
},
25+
"publishConfig": {
26+
"access": "public"
27+
},
28+
"homepage": "https://opensource.adobe.com/spectrum-css/"
29+
}

site/includes/dependencies.pug

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ link(rel='stylesheet', type='text/css', href='../components/vars/spectrum-light.
1414
link(rel='stylesheet', type='text/css', href='../components/vars/spectrum-medium.css')
1515
link(rel='stylesheet', type='text/css', href='../components/vars/spectrum-large.css')
1616

17+
link(rel='stylesheet', type='text/css', href='../components/tokens/index.css')
18+
1719
each dep in dependencyOrder.filter((dep) => dep != 'vars' )
1820
link(rel='stylesheet', type='text/css', href='../components/' + dep + '/index-vars.css', data-dependency=dep )
1921

site/resources/js/SpectrumSwitcher.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ Object.defineProperty(SpectrumSwitcher.prototype, 'varsVersion', {
145145
sheet.setAttribute('href', sheet.href.replaceAll(expressName, defaultName));
146146
}
147147
});
148+
149+
if (varsVersion === 'express') {
150+
document.documentElement.classList.add('spectrum--express');
151+
}
152+
else {
153+
document.documentElement.classList.remove('spectrum--express');
154+
}
155+
148156
this._varsVersion = varsVersion;
149157
},
150158
get: function() {

tools/bundle-builder/lib/depUtils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ async function getFolderDependencyOrder(packagesDir) {
9696
// Nobody relies on it, so it gets clipped, weird
9797
solution.push('@spectrum-css/expressvars');
9898

99+
// Build tokens first
100+
// This is because not every package relies on tokens, but the builder needs tokens to bake vars
101+
solution = solution.filter(p => p !== '@spectrum-css/tokens');
102+
solution.unshift('@spectrum-css/tokens');
103+
99104
return solution;
100105
}
101106

0 commit comments

Comments
 (0)