Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ pnpm format # format everything with Prettier

# Storybook (run per package)
pnpm --filter @surfnet/react storybook # http://localhost:6006
pnpm --filter @surfnet/angular storybook # http://localhost:6006
pnpm --filter @surfnet/angular storybook # http://localhost:6007
```

Each component ships a Storybook story covering its full surface (variants, sizes,
states). Start there to see what's available.
states). Start there to see what's available. Both Storybooks are also deployed
to GitHub Pages on every push to `main`:

- **React** — https://surfnet.github.io/DesignSystem/react/
- **Angular** — https://surfnet.github.io/DesignSystem/angular/

## Demo app

Expand Down
2 changes: 1 addition & 1 deletion packages/angular/.storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { registerManager } from '@surfnet/storybook-config/manager';

registerManager();
registerManager('angular');
12 changes: 11 additions & 1 deletion packages/angular/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,15 @@ export default {
initialGlobals: { framework: 'angular', ...themeInitialGlobals },
globalTypes: { ...frameworkGlobalTypes, ...themeGlobalTypes },
decorators: [frameworkSwitcher('angular'), themeSwitcher()],
parameters: sharedParameters,
parameters: {
...sharedParameters,
// Must be a literal (Storybook reads it via static analysis, not
// execution). Keep in sync with packages/react/.storybook/preview.ts.
options: {
storySort: {
method: 'alphabetical',
order: ['Foundations', 'Components'],
},
},
},
};
2 changes: 1 addition & 1 deletion packages/react/.storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { registerManager } from '@surfnet/storybook-config/manager';

registerManager();
registerManager('react');
8 changes: 8 additions & 0 deletions packages/react/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,13 @@ export default {
// `args` param) is treated as a non-args story, so Storybook prints the whole
// story object instead of the JSX. See @storybook/react's `skipJsxRender`.
docs: { source: { type: 'dynamic' } },
// Must be a literal (Storybook reads it via static analysis, not
// execution). Keep in sync with packages/angular/.storybook/preview.ts.
options: {
storySort: {
method: 'alphabetical',
order: ['Foundations', 'Components'],
},
},
},
};
4 changes: 4 additions & 0 deletions packages/storybook-config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export type {

// Shared preview parameters so every framework's Storybook renders stories the
// same way.
//
// `options.storySort` isn't here: Storybook reads it via static analysis of
// each preview.ts, not by executing this module, so it must be a literal in
// every preview.ts instead (see those files for the actual value).
export const sharedParameters = {
layout: 'centered',
controls: {
Expand Down
11 changes: 11 additions & 0 deletions packages/storybook-config/src/logo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Inlined as a string so it works under both the Vite and webpack manager
// builds without extra loader config. Sized down from the 236x168 source.
export const LOGO_SVG = `<svg width="30" height="21" viewBox="0 0 236 168" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="flex-shrink: 0;">
<title>SURF</title>
<g id="Frame-Copy" stroke="none" fill="none" fill-rule="evenodd" stroke-width="1">
<g id="Laag_1" transform="translate(30, 30)">
<path d="M190.344,64.9185444 C198.996,64.9185444 206,72.1546879 206,81.044807 L206,91.3821549 C206,100.272274 198.996,107.508418 190.344,107.508418 L166.654,107.508418 C158.002,107.508418 150.998,100.272274 150.998,91.3821549 L150.998,84.9729992 C150.998,73.8086636 142.14,64.9185444 131.428,64.9185444 L19.57,64.9185444 C8.652,64.9185444 0,56.0284253 0,44.8640896 L0,20.0544548 C0,8.89011914 8.858,0 19.57,0 L131.428,0 C142.346,0 150.998,8.89011914 150.998,20.0544548 L150.998,44.8640896 C150.998,56.0284253 159.856,64.9185444 170.568,64.9185444 L190.344,64.9185444 Z" id="a_1_" fill="#000000"></path>
<path d="M124.836,36.8009583 C126.896,36.8009583 127.926,35.7672235 127.926,33.6997539 C127.926,31.6322844 126.896,30.3918026 124.836,30.3918026 L117.008,30.3918026 L117.008,24.1893939 L129.368,24.1893939 C131.428,24.1893939 132.458,23.1556592 132.458,20.8814426 C132.458,18.8139731 131.428,17.7802383 129.368,17.7802383 L113.712,17.7802383 C111.652,17.7802383 110.416,18.8139731 110.416,21.0881896 L110.416,43.8303548 C110.416,46.1045714 111.446,47.1383061 113.712,47.1383061 C115.772,47.1383061 117.008,46.1045714 117.008,43.8303548 L117.008,36.5942113 C117.008,36.8009583 124.836,36.8009583 124.836,36.8009583 L124.836,36.8009583 Z M99.086,36.1807174 C101.97,34.7334887 103.618,31.8390313 103.618,28.1175861 C103.618,22.1219244 99.292,17.7802383 93.112,17.7802383 L83.842,17.7802383 C81.782,17.7802383 80.546,18.8139731 80.546,21.0881896 L80.546,43.8303548 C80.546,46.1045714 81.576,47.1383061 83.842,47.1383061 C85.902,47.1383061 87.138,46.1045714 87.138,43.8303548 L87.138,37.8346931 L92.7,37.8346931 L95.996,44.8640896 C96.614,46.3113183 97.438,46.9315592 98.674,46.9315592 C100.322,46.9315592 102.382,45.6910774 102.382,43.8303548 C102.382,43.210114 102.176,42.5898731 101.97,41.9696322 L99.086,36.1807174 L99.086,36.1807174 Z M92.288,32.0457783 L86.726,32.0457783 L86.726,24.1893939 L92.288,24.1893939 C94.76,24.1893939 96.82,25.4298757 96.82,28.1175861 C96.82,30.8052966 94.76,32.0457783 92.288,32.0457783 Z M66.126,33.6997539 C66.126,38.248187 63.448,40.9358974 59.74,40.9358974 C56.032,40.9358974 53.354,38.248187 53.354,33.6997539 L53.354,20.8814426 C53.354,18.6072261 52.324,17.5734913 50.058,17.5734913 C47.998,17.5734913 46.762,18.6072261 46.762,20.8814426 L46.762,33.6997539 C46.762,42.1763792 52.324,47.5518001 59.74,47.5518001 C67.156,47.5518001 72.718,42.1763792 72.718,33.6997539 L72.718,20.8814426 C72.718,18.6072261 71.688,17.5734913 69.422,17.5734913 C67.362,17.5734913 66.126,18.6072261 66.126,20.8814426 L66.126,33.6997539 L66.126,33.6997539 Z M29.252,41.3493913 C26.78,41.3493913 24.926,40.7291505 23.69,40.3156566 C22.66,39.9021627 21.836,39.6954157 20.806,39.6954157 C18.952,39.6954157 17.922,40.9358974 17.922,42.79662 C17.922,45.8978244 24.102,47.5518001 29.458,47.5518001 C35.844,47.5518001 40.788,44.0371018 40.788,38.6616809 C40.788,33.6997539 37.492,31.4255374 33.99,30.1850557 L28.634,28.53108 C26.368,27.9108392 25.338,27.2905983 25.338,25.8433696 C25.338,24.3961409 27.604,23.5691531 29.458,23.5691531 C31.724,23.5691531 33.372,24.1893939 34.608,24.6028879 C35.432,24.8096348 36.256,25.2231287 37.286,25.2231287 C38.934,25.2231287 39.964,23.982647 39.964,22.1219244 C39.964,19.02072 34.402,17.3667444 29.458,17.3667444 C23.278,17.3667444 18.746,20.8814426 18.746,26.0501166 C18.746,30.3918026 21.836,32.8727661 25.132,33.9065009 L29.87,35.3537296 C32.342,36.1807174 34.196,36.8009583 34.196,38.248187 C33.784,40.3156566 31.312,41.3493913 29.252,41.3493913 L29.252,41.3493913 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</svg>`;
36 changes: 28 additions & 8 deletions packages/storybook-config/src/manager.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import { addons } from 'storybook/manager-api';
import { create } from 'storybook/theming/create';

import type { Framework } from './frameworks.js';
import { LOGO_SVG } from './logo.js';

const FRAMEWORK_TITLES: Record<Framework, string> = {
react: 'React',
angular: 'Angular',
};

// Leaving brandImage unset makes Storybook render brandTitle as raw HTML
// instead of plain text — the only way to show the logo and text together.
const brandMarkup = (framework: Framework) => `
<span style="display: inline-flex; align-items: center; gap: 8px; line-height: 1; white-space: nowrap;">
${LOGO_SVG}
<span style="font-weight: 600; font-size: 13px;">
Design System
<span style="font-weight: 400; opacity: 0.65;"> - ${FRAMEWORK_TITLES[framework]}</span>
</span>
</span>
`;

// Shared manager (chrome/sidebar) theme so every framework's Storybook is
// branded identically.
const theme = create({
base: 'light',
brandTitle: 'SURF Design System',
brandUrl: 'https://www.surf.nl',
});

export function registerManager(): void {
// branded identically, save for the framework name in the title.
export function registerManager(framework: Framework): void {
const theme = create({
base: 'light',
brandTitle: brandMarkup(framework),
brandUrl: 'https://www.surf.nl',
});

addons.setConfig({ theme });
}
Loading