Skip to content

Commit 76cd121

Browse files
authored
Merge pull request #52 from fortanix/mkrause/241209-sass-refactoring
Refactor top-level Sass code
2 parents d683455 + 8b112eb commit 76cd121

32 files changed

+689
-476
lines changed

.storybook/preview.scss

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,7 @@
22
|* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
33
|* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
@use '../src/styling/defs.scss' as bk;
6-
7-
/* Cascade layer ordering */
8-
/*
9-
Note: this ordering must be injected before any other CSS rules.
10-
*/
11-
@layer normalize, reset, baklava, app, accessibility, storybook;
12-
@layer baklava.base, baklava.body-text, baklava.theming, baklava.components;
13-
14-
@import '../src/styling/lib/normalize.css' layer(normalize);
15-
@import '../src/styling/lib/reset.css' layer(reset);
16-
@import '../src/styling/lib/reset-custom.css' layer(reset);
17-
18-
@import '../src/styling/variables.css';
19-
@import '../src/styling/fonts.css';
20-
@import '../src/styling/context/theming.scss';
21-
@import '../src/styling/global.scss' layer(baklava.base);
22-
@import '../src/typography/BodyText/BodyText.module.scss';
23-
24-
@import '../src/styling/accessibility.css' layer(accessibility);
5+
@use '../src/styling/main.scss';
256

267

278
/* Storybook-specific style overrides */

.storybook/preview.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from 'storybook-dar
1414
import { DocsContainer, Title, Subtitle, Description, Primary, Controls, Stories } from '@storybook/blocks';
1515

1616

17-
1817
const channel = addons.getChannel();
1918
const preview = {
2019
parameters: {

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ Additionally, you will need to add the following import in your main entry file:
5555
import 'virtual:svg-icons-register';
5656
```
5757

58+
Please make sure that Baklava is the first CSS that gets loaded in to your bundle. Baklava relies on CSS
59+
[cascade layers](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) for its specificity
60+
management. If your application emits any code that uses an `@layer` name that is also used by Baklava
61+
(like `baklava.components`), and Baklava's layer ordering is not emitted first, then the ordering of the layers will
62+
get messed up (since browsers order layers by source order). If you want, you can also just emit the layers ordering
63+
from Baklava explicitly (rather than the whole bundle):
64+
65+
```
66+
@use '@fortanix/baklava/styling/layers.scss';
67+
@include layers.styles;
68+
```
69+
5870

5971
## Contributing
6072

package-lock.json

Lines changed: 84 additions & 84 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
},
2929
"./styling/variables.scss": {
3030
"default": "./src/styling/variables.scss"
31+
},
32+
"./styling/defs.scss": {
33+
"default": "./src/styling/defs.scss"
34+
},
35+
"./styling/layers.scss": {
36+
"default": "./src/styling/layers.scss"
3137
}
3238
},
3339
"scripts": {
@@ -38,8 +44,9 @@
3844
"plop": "NODE_OPTIONS=\"--import tsx\" plop",
3945
"import": "tsx scripts/import.ts",
4046
"automate": "tsx scripts/automate.ts",
47+
"verify": "tsx scripts/verify.ts",
4148
"serve:dev": "vite --config=./vite.config.ts serve",
42-
"build": "tsc -b && vite --config=./vite.config.ts build",
49+
"build": "tsc -b && vite --config=./vite.config.ts build && npm run verify verify:build",
4350
"storybook:serve": "storybook dev -p 6006",
4451
"storybook:build": "storybook build --docs",
4552
"chromatic": "npx chromatic",
@@ -87,7 +94,7 @@
8794
"@percy/storybook": "^6.0.3",
8895
"vite-css-modules": "^1.6.0",
8996
"typescript-plugin-css-modules": "^5.0.1",
90-
"sass-embedded": "^1.82.0",
97+
"sass-embedded": "^1.83.0",
9198
"lightningcss": "^1.28.2",
9299
"@types/react": "^19.0.1",
93100
"@types/react-dom": "^19.0.1"

package.json.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,18 @@ const packageConfig = {
3030
//'require': './dist/baklava.cjs',
3131
'default': './dist/baklava.js',
3232
},
33+
// Expose variables for use in consumer components
3334
'./styling/variables.scss': {
3435
'default': './src/styling/variables.scss',
3536
},
37+
// Expose mixins for use in consumer components
38+
'./styling/defs.scss': {
39+
'default': './src/styling/defs.scss',
40+
},
41+
// Expose layer ordering, since consumers may want to explicitly emit these first (see note in README.md)
42+
'./styling/layers.scss': {
43+
'default': './src/styling/layers.scss',
44+
},
3645
},
3746

3847
scripts: {
@@ -46,14 +55,15 @@ const packageConfig = {
4655
'plop': 'NODE_OPTIONS="--import tsx" plop',
4756
'import': 'tsx scripts/import.ts',
4857
'automate': 'tsx scripts/automate.ts',
58+
'verify': 'tsx scripts/verify.ts',
4959

5060
// Library
5161
//'lib:build': '',
5262

5363
// App
5464
'serve:dev': 'vite --config=./vite.config.ts serve',
5565
//'build': 'vite --config=./vite.config.ts --emptyOutDir build && cp src/types/vite-env.d.ts dist && echo \'{"name": "@fortanix/baklava","main": "./baklava.js"}\' > dist/package.json',
56-
'build': 'tsc -b && vite --config=./vite.config.ts build',
66+
'build': 'tsc -b && vite --config=./vite.config.ts build && npm run verify verify:build',
5767

5868
// Storybook
5969
'storybook:serve': 'storybook dev -p 6006',
@@ -127,7 +137,7 @@ const packageConfig = {
127137
// Styling
128138
'vite-css-modules': '^1.6.0',
129139
'typescript-plugin-css-modules': '^5.0.1',
130-
'sass-embedded': '^1.82.0',
140+
'sass-embedded': '^1.83.0',
131141
'lightningcss': '^1.28.2',
132142

133143
// React
File renamed without changes.

scripts/verify.ts

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
2+
import { dedent } from 'ts-dedent';
3+
import { parseArgs } from 'node:util';
4+
import { fileURLToPath } from 'node:url';
5+
import * as fs from 'node:fs/promises';
6+
import { exec } from 'node:child_process';
7+
import { AsyncLocalStorage } from 'node:async_hooks';
8+
9+
10+
//
11+
// Setup
12+
//
13+
14+
type Logger = Pick<Console, 'info' | 'error' | 'log'>;
15+
type Services = { logger: Logger };
16+
const servicesStorage = new AsyncLocalStorage<Services>();
17+
const getServices = () => {
18+
const services = servicesStorage.getStore();
19+
if (typeof services === 'undefined') { throw new Error(`Missing services`); }
20+
return services;
21+
};
22+
23+
type ScriptArgs = {
24+
values: {
25+
help?: undefined | boolean,
26+
silent?: undefined | boolean,
27+
},
28+
positionals: Array<string>,
29+
};
30+
31+
32+
//
33+
// Common
34+
//
35+
36+
const getCurrentGitBranch = () => new Promise<string>((resolve, reject) => {
37+
return exec('git rev-parse --abbrev-ref HEAD', (err, stdout, stderr) => {
38+
if (err) {
39+
reject(`Failed to determine current git branch: ${err}`);
40+
} else if (typeof stdout === 'string') {
41+
resolve(stdout.trim());
42+
}
43+
});
44+
});
45+
46+
const readDistCss = async () => {
47+
const path = fileURLToPath(new URL('../dist/lib.css', import.meta.url));
48+
return (await fs.readFile(path)).toString(); // May throw
49+
};
50+
51+
52+
//
53+
// Commands
54+
//
55+
56+
export const runVerifyBuild = async (args: ScriptArgs) => {
57+
const { logger } = getServices();
58+
59+
const cssContent = await readDistCss();
60+
const cssContentStripped = cssContent.replaceAll(`@charset "UTF-8";`, '').trim();
61+
62+
// We need to make sure that an `@layer` ordering is at the beginning of the CSS build file.
63+
if (!cssContentStripped.match(/^@layer [^{]+?;/)) {
64+
throw new Error(`Missing @layer ordering at the start of the CSS build file`);
65+
}
66+
67+
logger.log('verify:build – No issues found');
68+
};
69+
70+
71+
//
72+
// Run
73+
//
74+
75+
const printUsage = () => {
76+
const { logger } = getServices();
77+
78+
logger.info(dedent`
79+
Usage: verify.ts <cmd> <...args>
80+
81+
Commands:
82+
- verify:build
83+
`);
84+
};
85+
86+
// Run the script with the given CLI arguments
87+
export const run = async (argsRaw: Array<string>): Promise<void> => {
88+
// Ref: https://exploringjs.com/nodejs-shell-scripting/ch_node-util-parseargs.html
89+
const args = parseArgs({
90+
args: argsRaw,
91+
allowPositionals: true,
92+
options: {
93+
help: { type: 'boolean', short: 'h' },
94+
silent: { type: 'boolean' },
95+
},
96+
});
97+
98+
// Services
99+
const logger: Logger = {
100+
info: args.values.silent ? () => {} : console.info,
101+
error: console.error,
102+
log: console.log,
103+
};
104+
105+
await servicesStorage.run({ logger }, async () => {
106+
const command: null | string = args.positionals[0] ?? null;
107+
if (command === null || args.values.help) {
108+
printUsage();
109+
return;
110+
}
111+
112+
const argsForCommand: ScriptArgs = { ...args, positionals: args.positionals.slice(1) };
113+
switch (command) {
114+
case 'verify:build': await runVerifyBuild(argsForCommand); break;
115+
default:
116+
logger.error(`Unknown command '${command}'\n`);
117+
printUsage();
118+
break;
119+
}
120+
});
121+
};
122+
123+
// Detect if this module is being run directly from the command line
124+
const [_argExec, argScript, ...args] = process.argv; // First two arguments should be the executable + script
125+
if (argScript && await fs.realpath(argScript) === fileURLToPath(import.meta.url)) {
126+
try {
127+
await run(args);
128+
process.exit(0);
129+
} catch (error: unknown) {
130+
console.error(error);
131+
process.exit(1);
132+
}
133+
}

src/components/forms/controls/Select/Select.module.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
/* Make sure the content does not have any extra space (e.g. under the line) due to baseline alignment */
1414
display: flex;
1515

16-
> input {
16+
.bk-select__input {
1717
min-width: $bk-select-min-width;
1818
caret-color: transparent; /* FIXME: find better way to manage the input state */
1919
}

src/components/forms/controls/Select/Select.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ export const Select = Object.assign(
140140
ref={mergeRefs(selectedRef, refs.setReference as any)}
141141
>
142142
<Input
143+
className={cl['bk-select__input']}
143144
tabIndex={-1}
144145
placeholder="Select an option"
145146
value={selected === null ? '' : selected.label}

0 commit comments

Comments
 (0)