Skip to content

Commit 70a3e37

Browse files
HotelltudorpopamsCopilotclaude
authored
feat(storybook): modularize CSS module support as pluggable preset config (#36088)
Co-authored-by: Tudor Popa <popatudor@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f00737e commit 70a3e37

162 files changed

Lines changed: 5797 additions & 1316 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
const rootMain = require('../../../.storybook/main');
1+
const headlessMain = require('../../../packages/react-components/react-headless-components-preview/stories/.storybook/main');
22

33
module.exports = /** @type {Omit<import('../../../.storybook/main'), 'typescript'|'babel'>} */ ({
4-
...rootMain,
4+
...headlessMain,
55
stories: [
6-
...rootMain.stories,
7-
// docsite stories
8-
'../src/**/*.mdx',
9-
'../src/**/index.stories.@(ts|tsx)',
6+
...headlessMain.stories,
107
// headless package stories
118
'../../../packages/react-components/react-headless-components-preview/stories/src/**/index.stories.@(ts|tsx)',
129
],
1310
staticDirs: ['../public'],
14-
addons: [...rootMain.addons],
1511
build: {
1612
previewUrl: process.env.DEPLOY_PATH,
1713
},
18-
webpackFinal: (config, options) => {
19-
const localConfig = /** @type config */ ({ ...rootMain.webpackFinal(config, options) });
20-
21-
return localConfig;
22-
},
2314
});

apps/public-docsite-v9-headless/.storybook/manager-head.html

Lines changed: 53 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,33 @@
55
<link href="/shell.css" rel="stylesheet" />
66

77
<!--
8-
Override the default styles used in the Storybook svg icons for the left tree panel.
9-
10-
@see https://storybook.js.org/docs/react/configure/theming#css-escape-hatches
11-
12-
> 💡 NOTE:
13-
>
14-
> This is brittle way for providing custom non thenable styles for manager UI
15-
>
16-
> Those selectors might change on any storybook version bump.
8+
Segoe UI from Microsoft's static font CDN. The fallbacks in `font-family`
9+
below cover users on networks blocking the CDN, but on a healthy connection
10+
the docsite renders Segoe UI on every platform — not just Windows.
1711
-->
12+
<link rel="preconnect" href="https://c.s-microsoft.com" crossorigin />
13+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.css" />
14+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.css" />
15+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.css" />
16+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.css" />
1817

19-
<style>
20-
@font-face {
21-
font-family: 'Segoe UI';
22-
src: local('Segoe UI Light'),
23-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.woff2) format('woff2'),
24-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.woff) format('woff'),
25-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.ttf) format('truetype');
26-
font-weight: 100;
27-
}
28-
29-
@font-face {
30-
font-family: 'Segoe UI';
31-
src: local('Segoe UI Semilight'),
32-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.woff2) format('woff2'),
33-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.woff) format('woff'),
34-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.ttf) format('truetype');
35-
font-weight: 200;
36-
}
18+
<!--
19+
Headless docsite chrome overrides for the Storybook manager UI.
3720
38-
@font-face {
39-
font-family: 'Segoe UI';
40-
src: local('Segoe UI'),
41-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.woff2) format('woff2'),
42-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.woff) format('woff'),
43-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.ttf) format('truetype');
44-
font-weight: 400;
45-
}
21+
The sidebar selectors are brittle — they depend on Storybook's manager DOM
22+
structure and may need updating on Storybook version bumps. Color values
23+
mirror {@link ../../../packages/react-components/react-headless-components-preview/stories/.storybook/tokens.css} (light mode).
4624
47-
@font-face {
48-
font-family: 'Segoe UI';
49-
src: local('Segoe UI Semibold'),
50-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.woff2) format('woff2'),
51-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.woff) format('woff'),
52-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.ttf) format('truetype');
53-
font-weight: 600;
54-
}
25+
@see https://storybook.js.org/docs/react/configure/theming#css-escape-hatches
26+
-->
5527

56-
@font-face {
57-
font-family: 'Segoe UI';
58-
src: local('Segoe UI Bold'),
59-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.woff2) format('woff2'),
60-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.woff) format('woff'),
61-
url(https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.ttf) format('truetype');
62-
font-weight: 700;
28+
<style>
29+
:root {
30+
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
31+
--hl-text: #0a0a0a;
32+
--hl-text-muted: #52525b;
33+
--hl-accent: #9b1f5a;
34+
--hl-accent-contrast: #ffffff;
6335
}
6436

6537
#storybook-preview-iframe {
@@ -75,12 +47,12 @@
7547

7648
.sidebar-item svg,
7749
.sidebar-svg-icon {
78-
color: #11100f !important;
50+
color: var(--hl-text) !important;
7951
}
8052

8153
.sidebar-item[data-selected='true'] svg,
8254
.sidebar-item[data-selected='true'] .sidebar-svg-icon {
83-
color: #ffffff !important;
55+
color: var(--hl-accent-contrast) !important;
8456
}
8557

8658
/**
@@ -91,11 +63,11 @@
9163
.sidebar-subheading,
9264
button[data-action='collapse-ref'] {
9365
font-weight: 600 !important;
94-
font-size: 16px !important;
95-
letter-spacing: 0px !important;
96-
line-height: 24px !important;
66+
font-size: 13px !important;
67+
letter-spacing: -0.01em !important;
68+
line-height: 20px !important;
9769
text-transform: none !important;
98-
color: #11100f !important;
70+
color: var(--hl-text) !important;
9971
}
10072

10173
.sidebar-subheading button,
@@ -107,10 +79,30 @@
10779
.sidebar-item {
10880
align-items: center !important;
10981
font-weight: 400 !important;
110-
font-size: 14px !important;
82+
font-size: 13px !important;
11183
letter-spacing: -0.01em !important;
11284
line-height: 24px !important;
113-
color: #11100f !important;
85+
color: var(--hl-text) !important;
86+
border-radius: 999px !important;
87+
}
88+
89+
/*
90+
Override Storybook's default hover (a saturated pink derived from
91+
`colorSecondary`) with a subtle neutral surface tone. Matches the
92+
`--surface-muted` token from {@link ../../../packages/react-components/react-headless-components-preview/stories/.storybook/tokens.css}.
93+
*/
94+
.sidebar-item:hover,
95+
.sidebar-item:hover svg,
96+
.sidebar-item:hover .sidebar-svg-icon {
97+
background: #f2f2f4 !important;
98+
color: var(--hl-text) !important;
99+
}
100+
101+
.sidebar-item[data-selected='true']:hover,
102+
.sidebar-item[data-selected='true']:hover svg,
103+
.sidebar-item[data-selected='true']:hover .sidebar-svg-icon {
104+
background: var(--hl-accent) !important;
105+
color: var(--hl-accent-contrast) !important;
114106
}
115107

116108
.sidebar-item a {
@@ -119,10 +111,11 @@
119111

120112
.sidebar-item[data-selected='true'] {
121113
font-weight: 600 !important;
122-
font-size: 14px !important;
114+
font-size: 13px !important;
123115
letter-spacing: -0.01em !important;
124116
line-height: 24px !important;
125-
color: #ffffff !important;
117+
color: var(--hl-accent-contrast) !important;
118+
background: var(--hl-accent) !important;
126119
}
127120

128121
.sidebar-item > span:first-child,
Lines changed: 18 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,24 @@
1-
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
2-
<style type="text/tailwindcss">
3-
@layer theme, base, utilities;
4-
@import 'tailwindcss/theme' layer(theme);
5-
@import 'tailwindcss/utilities' layer(utilities);
6-
:root {
7-
interpolate-size: allow-keywords;
8-
}
9-
</style>
101
<!--
11-
Tailwind's Preflight is omitted above because it resets h1/h2/p/a in
12-
MDX docs (which rely on typography from react-storybook-addon/src/styles.css).
13-
Re-apply the essential resets here inside `@layer base`, scoped to
14-
`.docs-story` so rendered Canvas examples get border/box-sizing/form-element
15-
normalization without affecting the surrounding MDX page. -->
16-
<style>
17-
@layer base {
18-
@scope (.docs-story) {
19-
*,
20-
::before,
21-
::after,
22-
::backdrop,
23-
::file-selector-button {
24-
box-sizing: border-box;
25-
border: 0 solid currentColor;
26-
}
27-
28-
img,
29-
svg,
30-
video,
31-
canvas,
32-
audio,
33-
iframe,
34-
embed,
35-
object {
36-
display: block;
37-
vertical-align: middle;
38-
}
39-
40-
img,
41-
video {
42-
max-width: 100%;
43-
height: auto;
44-
}
45-
46-
button,
47-
input,
48-
optgroup,
49-
select,
50-
textarea,
51-
::file-selector-button {
52-
font-family: inherit;
53-
font-feature-settings: inherit;
54-
font-variation-settings: inherit;
55-
font-size: 100%;
56-
font-weight: inherit;
57-
line-height: inherit;
58-
letter-spacing: inherit;
59-
color: inherit;
60-
}
2+
Story canvas head.
613
62-
button,
63-
select {
64-
text-transform: none;
65-
}
4+
Design tokens ({@link ../../../packages/react-components/react-headless-components-preview/stories/.storybook/tokens.css}) are imported from `preview.js` so they
5+
reach the iframe via webpack. This file holds raw <link> / <style> tags that
6+
must be present in the iframe document head before any story renders.
7+
-->
668

67-
button,
68-
input:where([type='button'], [type='reset'], [type='submit']),
69-
::file-selector-button {
70-
appearance: button;
71-
background-color: transparent;
72-
background-image: none;
73-
}
74-
75-
:-moz-focusring {
76-
outline: auto;
77-
}
78-
79-
::placeholder {
80-
opacity: 1;
81-
color: color-mix(in oklab, currentColor 50%, transparent);
82-
}
83-
84-
textarea {
85-
resize: vertical;
86-
}
87-
88-
ol,
89-
ul,
90-
menu {
91-
list-style: none;
92-
}
9+
<!--
10+
Segoe UI from Microsoft's static font CDN — same set as `manager-head.html`.
11+
Story canvases declare `font-family: 'Segoe UI', system-ui` via the design
12+
tokens, so loading the webfont here makes them render Segoe on every OS.
13+
-->
14+
<link rel="preconnect" href="https://c.s-microsoft.com" crossorigin />
15+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.css" />
16+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.css" />
17+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.css" />
18+
<link rel="stylesheet" href="https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.css" />
9319

94-
[hidden]:where(:not([hidden='until-found'])) {
95-
display: none !important;
96-
}
97-
}
20+
<style>
21+
:root {
22+
interpolate-size: allow-keywords;
9823
}
9924
</style>

apps/public-docsite-v9-headless/.storybook/preview.js

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,16 @@
1-
import { polyfillBodyAndObserve } from '@microsoft/focusgroup-polyfill/shadowless';
1+
import * as headlessPreview from '../../../packages/react-components/react-headless-components-preview/stories/.storybook/preview';
22

3-
import * as rootPreview from '../../../.storybook/preview';
4-
import { tailwindSandboxTemplate } from './tailwind-sandbox-template';
3+
export const decorators = [...headlessPreview.decorators];
54

6-
polyfillBodyAndObserve();
7-
8-
/** @type {typeof rootPreview.decorators} */
9-
export const decorators = [...rootPreview.decorators];
10-
11-
/** @type {typeof rootPreview.parameters} */
5+
/** @type {typeof headlessPreview.parameters} */
126
export const parameters = {
13-
...rootPreview.parameters,
14-
docs: {
15-
...rootPreview.parameters.docs,
16-
},
7+
...headlessPreview.parameters,
178
options: {
189
storySort: {
1910
method: 'alphabetical',
2011
order: ['Introduction', 'Headless Components'],
2112
},
2213
},
23-
exportToSandbox: {
24-
...rootPreview.parameters.exportToSandbox,
25-
...tailwindSandboxTemplate,
26-
},
2714
reactStorybookAddon: {
2815
docs: {
2916
argTable: {
Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1 @@
1-
import { create } from 'storybook/theming';
2-
3-
/**
4-
* Theming and branding the storybook to fluent. Taken from https://storybook.js.org/docs/react/configure/theming
5-
*/
6-
const theme = create({
7-
base: 'light',
8-
9-
// Storybook-specific color palette
10-
colorPrimary: 'rgba(255, 255, 255, .4)',
11-
colorSecondary: '#0078d4',
12-
13-
// UI
14-
appBg: '#ffffff',
15-
appContentBg: '#ffffff',
16-
appBorderColor: '#e0e0e0', // use msft gray
17-
appBorderRadius: 4,
18-
19-
// Fonts
20-
fontBase:
21-
'"Segoe UI", "Segoe UI Web (West European)", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;',
22-
fontCode: 'monospace',
23-
24-
// Text colors
25-
textColor: '#11100f',
26-
textInverseColor: '#0078d4', // use msft primary blue default
27-
28-
// Toolbar default and active colors
29-
barSelectedColor: '#0078d4', // use msft primary blue default
30-
31-
// Form colors
32-
inputBorderRadius: 4,
33-
34-
// Use the fluent branding for the upper left image
35-
brandTitle: 'Fluent UI Headless Components',
36-
brandUrl:
37-
'https://github.com/microsoft/fluentui/tree/master/packages/react-components/react-headless-components-preview',
38-
});
39-
40-
export default theme;
1+
export { default } from '../../../packages/react-components/react-headless-components-preview/stories/.storybook/theme';

apps/public-docsite-v9-headless/project.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"projects": ["react-storybook-addon", "react-storybook-addon-export-to-sandbox", "storybook-llms-extractor"],
2020
"target": "build"
2121
}
22-
]
22+
],
23+
"inputs": ["default", "{workspaceRoot}/.storybook/**", "{projectRoot}/.storybook/**"]
2324
}
2425
}
2526
}

0 commit comments

Comments
 (0)