Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
831d0d4
feat(headless-docsite): embed code panel in canvas, Bebop magenta the…
tudorpopams Apr 28, 2026
12ace04
chore(headless-docsite): rename bebop -> theme and add styling discla…
tudorpopams Apr 28, 2026
01fd2c2
refactor(headless-docsite): colocate CSS modules with their stories
tudorpopams Apr 28, 2026
aa9ac09
refactor(headless-docsite): move theme/ into public-docsite-v9-headless
tudorpopams Apr 28, 2026
3dc45fa
refactor(headless-docsite): move theme/ into the stories package
tudorpopams Apr 28, 2026
70325a3
docs(headless-docsite): rephrase styling disclaimer
tudorpopams Apr 28, 2026
d5e2759
fix(headless-docsite): correct tokens.css path in stories storybook p…
tudorpopams Apr 28, 2026
c4e0ac2
fix(headless-docsite): exclude stories from test-ssr and fix RIT type…
tudorpopams Apr 28, 2026
f3f4ee8
fix(headless-docsite): bigger disclaimer + preview note + magenta but…
tudorpopams Apr 29, 2026
94e8c37
fix(headless-docsite): enlarge disclaimer text, match preview note size
tudorpopams Apr 29, 2026
694e404
fix(headless-docsite): annotate stories storybook main.js for type-check
tudorpopams Apr 29, 2026
8d36053
fix(headless-stories): repair mangled CSS module class names
tudorpopams Apr 29, 2026
6f982cf
fix(headless-stories): match deployed Skeleton story layout
tudorpopams Apr 29, 2026
941f3dc
fix(headless-stories): re-enable SSR tests, teach esbuild ?raw + modu…
tudorpopams Apr 30, 2026
12a3e1b
fix(headless-stories): scope ?raw module declaration to this package
tudorpopams Apr 30, 2026
a754d28
fix(babel-preset-storybook-full-source): drop relative-import allowlist
tudorpopams Apr 30, 2026
2f859dd
refactor(headless-stories): extract shared CSS-modules webpack rule
tudorpopams Apr 30, 2026
47151ab
refactor(headless-docsite): move docs page + source panel into docsit…
tudorpopams Apr 30, 2026
dc11b17
fix(headless-docsite): load Segoe UI from c.s-microsoft.com
tudorpopams Apr 30, 2026
d624206
feat(babel-preset-storybook-full-source): auto-inject docs source params
tudorpopams Apr 30, 2026
0cc060f
fix(headless-stories): convert Card to CSS modules + design tokens
tudorpopams Apr 30, 2026
d74e592
docs: refresh READMEs after PR #36073 review changes
tudorpopams Apr 30, 2026
78c296a
fix(headless-docsite): override SB chrome painting code panel black
tudorpopams Apr 30, 2026
825da93
fix(headless-stories): clip Card children to its rounded corners
tudorpopams May 4, 2026
94b1716
fix(headless-stories): convert Drawer + Popover to CSS modules
tudorpopams May 4, 2026
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
156 changes: 156 additions & 0 deletions apps/public-docsite-v9-headless/.storybook/HeadlessDocsPage.tsx
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this to be a part of headless components stories package? Maybe we should move it to headless docsite instead?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, we dont need this for stories package sb boot, thus should live in app domain. in general this should follow our sb addon pattern later on if proved valid

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved in 7c949d1HeadlessDocsPage and HeadlessSourcePanel now live in apps/public-docsite-v9-headless/.storybook/. The stories package keeps only the runtime helper (withCssModuleSource).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into the docsite app in 7c949d1. The longer-term SB-addon repackaging is tracked in the PR description's Follow-ups list.

Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/**
* `HeadlessDocsPage` — replaces Storybook's autodocs page so we can render a
* **tabbed** "Show code" panel under each story (TSX + each CSS Module the
* story uses). The deployed Fluent docs page (`FluentDocsPage`) hard-wires
* `<Primary>` / `<Stories>` blocks whose Source can't be made multi-language,
* so we re-implement the same layout (Title / Subtitle / Description /
* primary canvas + source / ArgTypes / Stories heading / each story canvas +
* source) and swap the source block for our own `<HeadlessSourcePanel>`. The order
* mirrors `packages/react-components/react-storybook-addon/src/docs/FluentDocsPage.tsx`
* so the page matches what's deployed at storybooks.fluentui.dev/headless.
*
* Wired in by `.storybook/preview.js` via `parameters.docs.page`. Lives in the
* docsite app (not the stories package) — see PR #36073 review thread.
*/
import * as React from 'react';

import {
Anchor,
ArgTypes,
Canvas,
Description,
DocsContext,
HeaderMdx,
Subtitle,
Title,
} from '@storybook/addon-docs/blocks';

import { HeadlessSourcePanel } from './HeadlessSourcePanel';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyStory = Record<string, any>;

const dividerStyle: React.CSSProperties = {
height: 1,
backgroundColor: '#e1dfdd',
border: 0,
margin: '48px 0',
};

const storiesHeadingStyle: React.CSSProperties = {
fontSize: 11,
fontWeight: 700,
lineHeight: '16px',
letterSpacing: '0.35em',
textTransform: 'uppercase',
color: '#666666',
border: 0,
margin: '56px 0 12px',
};

const nameToHash = (name: string) =>
name
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)/g, '');

const disclaimerStyle: React.CSSProperties = {
margin: '20px 0 0',
padding: '18px 22px',
border: '1px solid #e1dfdd',
borderLeft: '4px solid #9b1f5a',
borderRadius: 6,
background: '#fdf6f9',
color: '#3c3c3c',
fontSize: 19,
lineHeight: 1.55,
};

const disclaimerNoteStyle: React.CSSProperties = {
marginTop: 12,
paddingTop: 12,
borderTop: '1px dashed #e1c2d2',
fontSize: 19,
lineHeight: 1.55,
color: '#3c3c3c',
};

export const HeadlessDocsPage: React.FC = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const docsContext = React.useContext(DocsContext) as any;
let stories: AnyStory[] = docsContext.componentStories();

// Mirrors the filtering rules from Storybook's built-in `<Stories>` block:
// honor a project-level `parameters.docs.stories.filter`, and when any
// story is `autodocs`-tagged, restrict to those (skipping `usesMount`
// stories which can't render inline).
const filter = docsContext.projectAnnotations?.parameters?.docs?.stories?.filter as
| ((s: AnyStory, ctx: AnyStory) => boolean)
| undefined;
if (filter) {
stories = stories.filter(story => filter(story, docsContext.getStoryContext(story)));
}
if (stories.some(story => story.tags?.includes('autodocs'))) {
stories = stories.filter(story => story.tags?.includes('autodocs') && !story.usesMount);
}

const primaryStory = stories[0];
const remainingStories = stories.slice(1);

return (
<div className="sb-unstyled headless-docs-page">
{/*
The `@fluentui/react-storybook-addon-export-to-sandbox` decorator looks
for `.docblock-code-toggle` inside `.docs-story` of each story to anchor
its "Open in Stackblitz" button. We keep Canvas's default sourceState
('hidden') so the native "Show code" toggle is rendered there too —
the Stackblitz button sits next to it inside the canvas footer (see
`HeadlessSourcePanel` for how its clicks drive our tabbed panel).
*/}
<Title />
<Subtitle />
<Description />
<aside style={disclaimerStyle} role="note">
<div>
<strong>Heads up:</strong> headless components ship without default styles. The CSS shown in these stories is
provided purely as a demonstration of one possible look.
</div>
<div style={disclaimerNoteStyle}>
<strong>Preview:</strong> these controls are in preview and their APIs are subject to change.
</div>
</aside>

{primaryStory && (
<>
<hr style={dividerStyle} />
<HeaderMdx as="h3" id={nameToHash(primaryStory.name)}>
{primaryStory.name}
</HeaderMdx>
<Anchor storyId={primaryStory.id}>
<Canvas of={primaryStory.moduleExport} />
<HeadlessSourcePanel of={primaryStory.moduleExport} />
</Anchor>
</>
)}

{/* Component-level props table (mirrors what FluentDocsPage renders). */}
<ArgTypes />

{remainingStories.length > 0 && (
<>
<h2 style={storiesHeadingStyle}>Stories</h2>
{remainingStories.map(story => (
<Anchor key={story.id} storyId={story.id}>
<HeaderMdx as="h3" id={nameToHash(story.name)}>
{story.name}
</HeaderMdx>
<Description of={story.moduleExport} />
<Canvas of={story.moduleExport} />
<HeadlessSourcePanel of={story.moduleExport} />
</Anchor>
))}
</>
)}
</div>
);
};
Loading
Loading