Skip to content

Commit

Permalink
Merge branch 'main' into 3543-remove-global-styles
Browse files Browse the repository at this point in the history
  • Loading branch information
bashirkarimi authored Sep 18, 2024
2 parents 0fbe279 + 2b44242 commit c9f21d2
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 38 deletions.
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.
39 changes: 39 additions & 0 deletions packages/documentation/.storybook/addons/addons.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@use '@swisspost/design-system-styles/core' as post;

.addon-dropdown {
min-width: 12rem;
display: flex;
flex-flow: column nowrap;
gap: post.$size-line;
position: absolute;
top: -5px;
right: 0;
padding: post.$size-mini;
background-color: var(--post-light);
border: post.$border-width solid post.$border-color;
border-radius: post.$border-radius;
font-size: post.$font-size-sm;

.addon-dropdown__item {
display: block;
padding: post.$size-mini post.$size-small-regular;
border-radius: post.$border-radius-sm;
text-decoration: none;
color: post.$body-color !important;

&:hover {
background-color: post.$gray-10;
}

&.active {
background-color: post.$yellow;
}
}
}

.addon-button {
post-icon {
font-size: post.$font-size-20;
margin-inline-end: post.$size-line;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import React, { useEffect, useState } from 'react';
import { IconButton, WithTooltip } from '@storybook/components';

const STYLESHEET_ID = 'preview-stylesheet';
const STORAGE_KEY_PREFIX = 'swisspost-documentation';
const THEMES = ['Post'];
const CHANNELS = ['External', 'Internal'];
const MODES = ['Light', 'Dark'];

function StylesSwitcher() {
const [currentTheme, setCurrentTheme] = useState<string>(
localStorage.getItem(`${STORAGE_KEY_PREFIX}-theme`) || THEMES[0],
);
const [currentChannel, setCurrentChannel] = useState<string>(
localStorage.getItem(`${STORAGE_KEY_PREFIX}-channel`) || CHANNELS[0],
);
const [currentMode, setCurrentMode] = useState<string>(
localStorage.getItem(`${STORAGE_KEY_PREFIX}-mode`) || MODES[0],
);

/**
* Sets the 'data-color-mode' attribute and preview stylesheet when the addon initializes
*/
useEffect(() => {
setPreviewStylesheet();
setDataColorModeAttribute();
});

/**
* Sets the stylesheet matching the selected theme and channel in the preview document head
*/
const setPreviewStylesheet = () => {
const preview = getPreviewDocument();
const previewHead = preview && preview.querySelector('head');

if (!previewHead) return;

let stylesheetLink = previewHead.querySelector(`#${STYLESHEET_ID}`);

if (!stylesheetLink) {
stylesheetLink = document.createElement('link');
stylesheetLink.setAttribute('rel', 'stylesheet');
stylesheetLink.setAttribute('id', STYLESHEET_ID);
previewHead.appendChild(stylesheetLink);
}

stylesheetLink.setAttribute(
'href',
`/styles/${currentTheme.toLowerCase()}-${currentChannel.toLowerCase()}.css`,
);
};

/**
* Sets the 'data-color-mode' attribute of the preview body to match the selected mode
*/
const setDataColorModeAttribute = () => {
const preview = getPreviewDocument();
if (!preview) return;

const mode = currentMode.toLowerCase();
const storyContainers = preview.querySelectorAll('.sbdocs-preview, .sb-main-padded');
storyContainers.forEach(storyContainer => {
storyContainer.classList.remove('bg-light', 'bg-dark');
storyContainer.classList.add(`bg-${mode}`);
storyContainer.setAttribute('data-color-mode', mode);
});
};

/**
* Returns the Document contained in the preview iframe
*/
const getPreviewDocument = (): Document | undefined => {
const preview = document.querySelector('#storybook-preview-iframe');
return preview && (preview as HTMLIFrameElement).contentWindow.document;
};

/**
* Applies selected theme and registers it to the local storage
*/
const applyTheme = (theme: string) => {
setCurrentTheme(theme);
localStorage.setItem(`${STORAGE_KEY_PREFIX}-theme`, theme);
};

/**
* Applies selected channel and registers it to the local storage
*/
const applyChannel = (channel: string) => {
setCurrentChannel(channel);
localStorage.setItem(`${STORAGE_KEY_PREFIX}-channel`, channel);
};

/**
* Applies selected mode and registers it to the local storage
*/
const applyMode = (mode: string) => {
setCurrentMode(mode);
localStorage.setItem(`${STORAGE_KEY_PREFIX}-mode`, mode);
};

return (
<>
{/* Theme dropdown */}
<WithTooltip
placement="bottom-end"
trigger="click"
closeOnOutsideClick
tooltip={
<div className="addon-dropdown">
{THEMES.map(theme => (
<IconButton
className={'addon-dropdown__item' + (theme === currentTheme ? ' active' : '')}
key={theme}
onClick={() => applyTheme(theme)}
>
{theme}
</IconButton>
))}
</div>
}
>
<IconButton size="medium">Theme: {currentTheme}</IconButton>
</WithTooltip>

{/* Channel dropdown */}
<WithTooltip
placement="bottom-end"
trigger="click"
closeOnOutsideClick
tooltip={
<div className="addon-dropdown">
{CHANNELS.map(channel => (
<IconButton
className={'addon-dropdown__item' + (channel === currentChannel ? ' active' : '')}
key={channel}
onClick={() => applyChannel(channel)}
>
{channel}
</IconButton>
))}
</div>
}
>
<IconButton size="medium">Chanel: {currentChannel}</IconButton>
</WithTooltip>

{/* Mode dropdown */}
<WithTooltip
placement="bottom-end"
trigger="click"
closeOnOutsideClick
tooltip={
<div className="addon-dropdown">
{MODES.map(mode => (
<IconButton
className={'addon-dropdown__item' + (mode === currentMode ? ' active' : '')}
key={mode}
onClick={() => applyMode(mode)}
>
{mode}
</IconButton>
))}
</div>
}
>
<IconButton size="medium">Mode: {currentMode}</IconButton>
</WithTooltip>
</>
);
}

export default StylesSwitcher;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

import { addons, types } from '@storybook/manager-api';
import StylesSwitcher from './StylesSwitcher';

const ADDON_ID = 'postStylesSwitcher';

addons.register(ADDON_ID, () => {
addons.add(ADDON_ID, {
title: 'Switch the documentation styles',
type: types.TOOL,
render: () => {
return <StylesSwitcher />;
},
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function VersionSwitcher() {
closeOnOutsideClick
tooltip={() => (
<>
<div className="version-switcher__dropdown">
<div className="addon-dropdown version-switcher__dropdown">
{versions.map(version => {
const isActive =
getVersion(version.version ?? '', 'major') === CURRENT_MAJOR_VERSION
Expand All @@ -66,7 +66,7 @@ function VersionSwitcher() {

return (
<a
className={['dropdown__item', isActive].filter(c => c).join(' ')}
className={['addon-dropdown__item', isActive].filter(c => c).join(' ')}
key={version.title}
href={version.url}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ addons.register(ADDON_ID, () => {
addons.add(ADDON_ID, {
title: 'Switch to another version',
type: types.TOOLEXTRA,
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(docs)$/)),
render: () => {
return <VersionSwitcher />;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,6 @@
}

.version-switcher__dropdown {
display: flex;
flex-flow: column nowrap;
gap: post.$size-line;
position: absolute;
top: -5px;
right: 0;
padding: post.$size-mini;
background-color: var(--post-light);
border: post.$border-width solid post.$border-color;
border-radius: post.$border-radius;
font-size: post.$font-size-sm;

.dropdown__item {
display: block;
padding: post.$size-mini post.$size-small-regular;
border-radius: post.$border-radius-sm;
text-decoration: none;
color: inherit;

&:hover {
background-color: post.$gray-10;
}

&.active {
background-color: post.$yellow;
}
}

.item__title {
display: block;
}
Expand Down
34 changes: 30 additions & 4 deletions packages/documentation/.storybook/helpers/open-full-screen-demo.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
import { StoryContext, StoryFn } from '@storybook/web-components';
import { html } from 'lit';

export const fullScreenUrlDecorator = (story: StoryFn, context: StoryContext) => {
const { allArgs, initialArgs, id } = context;

const args = Object.entries(allArgs)
.map(([argKey, argValue]) => {
const initialValue = initialArgs[argKey];
if (argValue === initialValue) return null;

const separator = typeof argValue === 'string' || typeof argValue === 'number' ? ':' : ':!';
const value = typeof argValue === 'string' ? encodeURI(argValue) : argValue;
return `${argKey}${separator}${value}`;
})
.filter(arg => !!arg)
.join(';');

let storyURL = `/?path=/story/${id}&full=true`;
if (args.length) storyURL += `&args=${args}`;

return html`
<p class="storyURL" hidden>${storyURL}</p>
${story(context.args, context)}
`;
};

export const openFullScreenDemo = (e: Event) => {
const target = e.target as HTMLButtonElement;
const canvas = target.closest('.docs-story');
const story = canvas?.querySelector('.sb-story');
const iframeId = story?.id?.replace('story--', '');
const storyURL = canvas && canvas.querySelector('.storyURL');

if (iframeId) {
window.open(`/iframe.html?id=${iframeId}`, '_blank');
if (storyURL) {
window.open(storyURL.textContent, '_blank');
} else {
alert('The full screen demo is not available.');
}
Expand Down
7 changes: 7 additions & 0 deletions packages/documentation/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const config: StorybookConfig = {
highlight: false,
outline: false,
docs: false,
measure: false,
viewport: false,
},
},
{
Expand Down Expand Up @@ -52,12 +54,17 @@ const config: StorybookConfig = {
'@storybook/addon-links',
'@kurbar/storybook-addon-docs-stencil',
'./addons/version-switcher/register',
'./addons/styles-switcher/register',
],
staticDirs: [
{
from: '../public/assets',
to: '/assets',
},
{
from: '../node_modules/@swisspost/design-system-styles',
to: '/styles',
},
'../public',
'../node_modules/@swisspost/design-system-icons/public',
],
Expand Down
12 changes: 11 additions & 1 deletion packages/documentation/.storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addons } from '@storybook/manager-api';
import themes from './styles/themes';
import { defineCustomElement as definePostIcon } from '@swisspost/design-system-components/dist/components/post-icon.js';
import themes from './styles/themes';

definePostIcon();

Expand All @@ -12,4 +12,14 @@ addons.setConfig({
sidebar: {
collapsedRoots: [],
},

// the toolbar is only visible in the fill screen view after clicking "View full screen" on a story
toolbar: {
remount: { hidden: true }, // controls the visibility of the "Remount component" button
zoom: { hidden: true }, // controls the visibility of the "Zoom in", "Zoom out", and "Reset zoom" buttons
addons: { hidden: true }, // controls the visibility of the "Show addons" button
fullscreen: { hidden: true }, // controls the visibility of the "Go full screen" button
eject: { hidden: true }, // controls the visibility of the "Open canvas in new tab" button
copy: { hidden: true }, // controls the visibility of the "Copy canvas link" button
},
});
Loading

0 comments on commit c9f21d2

Please sign in to comment.