Skip to content

Commit

Permalink
feat(docs): add toolbar to switch theme, channel, and mode (#3441)
Browse files Browse the repository at this point in the history
Co-authored-by: Oliver Schürch <[email protected]>
  • Loading branch information
alizedebray and oliverschuerch authored Sep 3, 2024
1 parent 42ce5c2 commit 712185a
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/empty-islands-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-documentation': minor
---

Added a toolbar for switching the theme, channel, and mode of all stories.
5 changes: 4 additions & 1 deletion packages/documentation/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Preview } from '@storybook/web-components';
import type { Args, Preview } from '@storybook/web-components';
import { extractArgTypes, extractComponentDescription } from '@kurbar/storybook-addon-docs-stencil';
import { format } from 'prettier';
import DocsLayout from './blocks/layout/layout';
Expand All @@ -10,12 +10,15 @@ import './styles/preview.scss';

import { SyntaxHighlighter } from '@storybook/components';
import scss from 'react-syntax-highlighter/dist/esm/languages/prism/scss';
import { toolbarConfig, applyToolbarSelection } from './toolbar';

SyntaxHighlighter.registerLanguage('scss', scss);

export const SourceDarkMode = true;

const preview: Preview = {
globalTypes: toolbarConfig,
decorators: [applyToolbarSelection],
parameters: {
options: {
storySort: {
Expand Down
10 changes: 10 additions & 0 deletions packages/documentation/.storybook/styles/manager.scss
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,13 @@
}
}
}

.sb-bar {
> * > * > :first-child {
display: none;
}

button::after {
content: ' ';
}
}
6 changes: 6 additions & 0 deletions packages/documentation/.storybook/styles/preview.scss
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,9 @@
right: 0;
}
}

story-container {
display: block;
margin: -40px -30px -39px;
padding: 40px 30px;
}
70 changes: 70 additions & 0 deletions packages/documentation/.storybook/toolbar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { html } from 'lit/static-html.js';

import './story-container';
import { StoryFn } from '@storybook/web-components';

/**
* Configuration of the buttons displayed in the Storybook toolbar
*/
export const toolbarConfig = {
// Theme: Post, Cargo, etc.
theme: {
description: 'Switch component themes between different branding colors.',
defaultValue: 'post',
toolbar: {
items: [
{
title: 'Post Theme', // label of the option in the dropdown list
value: 'post', // value of the option in the decorator (see `applyToolbarSelection` bellow)
},
],
dynamicTitle: true, // dynamic title so that the option label replaces the button label when selected
},
},

// Channel: External, Internal
channel: {
description: 'Toggle component appearance between internal and external application styles.',
defaultValue: 'external',
toolbar: {
items: [
{ value: 'external', title: 'External' },
{ value: 'internal', title: 'Internal' },
],
dynamicTitle: true,
},
},

// Mode: Light, Dark
mode: {
description: 'Switch component color schemes between light and dark modes.',
defaultValue: 'light',
toolbar: {
items: [
{ value: 'light', title: 'Light' },
{ value: 'dark', title: 'Dark' },
],
dynamicTitle: true,
},
},
};

/**
* Decorator to apply the toolbar selection to all stories.
* Stories are then rendered in a shadow dom were the expected styles are applied
*/
export const applyToolbarSelection = (story: StoryFn, context: object) => {
// mode is added through the `data-color-mode` attribute, we also set a dark background color when necessary
const mode = context.globals.mode || 'light';

return html`
<story-container
class=${mode === 'dark' ? 'bg-dark' : ''}
data-color-mode=${mode}
theme=${context.globals.theme}
channel=${context.globals.channel}
.story=${story}
.context=${context}
/>
`;
};
53 changes: 53 additions & 0 deletions packages/documentation/.storybook/toolbar/story-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Args, StoryContext, StoryFn } from '@storybook/web-components';
import { html, LitElement, unsafeCSS } from 'lit';
import { customElement, property } from 'lit/decorators.js';

import postExternalStyles from '@swisspost/design-system-styles/post-external.css?inline';
import postInternalStyles from '@swisspost/design-system-styles/post-internal.css?inline';

/**
* Transforms a style input into a CSSResult output adapted to web components
*/
export function useStyles(styles: any) {
if (typeof styles !== 'string') return unsafeCSS('');
return unsafeCSS(styles.replace(/:root/g, ':host'));
}

/**
* Web component that renders a story inside a shadow DOM importing the styles expected from the toolbar selection.
*/
@customElement('story-container')
export class StoryContainer extends LitElement {
styles = {
post: {
internal: useStyles(postInternalStyles),
external: useStyles(postExternalStyles),
},
};

@property()
theme?: string;

@property()
channel?: string;

@property({ attribute: true })
story!: StoryFn;

@property({ attribute: true })
context!: { args: StoryContext<Args> };

render() {
const style = this.styles[this.theme]?.[this.channel];
const template = this.story(this.context, this.context.args);

if (!style) return template;

return html`
<style>
${style}
</style>
${template}
`;
}
}

0 comments on commit 712185a

Please sign in to comment.