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
3 changes: 3 additions & 0 deletions packages/storybook-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@
"storybook": "10.4.5"
},
"dependencies": {
"@storybook/icons": "2.0.2",
"@surfnet/curve-tokens": "workspace:*"
},
"devDependencies": {
"@surfnet/curve-typescript-config": "workspace:*",
"@types/react": "19.2.17",
"react": "19.2.7",
"storybook": "10.4.5",
"typescript": "6.0.3"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { addons } from 'storybook/manager-api';
import React from 'react';
import { addons, types } from 'storybook/manager-api';
import { create } from 'storybook/theming/create';

import type { Framework } from './frameworks.js';
import { LOGO_SVG } from './logo.js';
import { MODE_TOGGLE_ID, ModeToggle } from './mode-toggle.js';

const FRAMEWORK_TITLES: Record<Framework, string> = {
react: 'React',
Expand Down Expand Up @@ -31,4 +33,13 @@ export function registerManager(framework: Framework): void {
});

addons.setConfig({ theme });

addons.register(MODE_TOGGLE_ID, () => {
addons.add(MODE_TOGGLE_ID, {
type: types.TOOL,
title: 'Mode',
match: () => true,
render: () => <ModeToggle />,
});
});
}
27 changes: 27 additions & 0 deletions packages/storybook-config/src/mode-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Classic JSX runtime: bundling a second react/jsx-runtime crashes the manager,
// so compile against the React that Storybook externalizes.
import React from 'react';
import { MoonIcon, SunIcon } from '@storybook/icons';
import { Button } from 'storybook/internal/components';
import { useGlobals } from 'storybook/manager-api';

export const MODE_TOGGLE_ID = 'curve/mode-toggle';

export function ModeToggle() {
const [{ mode }, updateGlobals] = useGlobals();
const isDark = mode === 'dark';

return (
<Button
key={MODE_TOGGLE_ID}
variant="ghost"
padding="small"
active={isDark}
ariaLabel={isDark ? 'Switch to light mode' : 'Switch to dark mode'}
onClick={() => updateGlobals({ mode: isDark ? 'light' : 'dark' })}
>
{isDark ? <MoonIcon /> : <SunIcon />}
{isDark ? 'Dark' : 'Light'}
</Button>
);
}
15 changes: 2 additions & 13 deletions packages/storybook-config/src/themes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const titleCase = (key: string) =>
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
.join(' ');

// Toolbar selects: one for the theme, one for light/dark mode.
// `mode` has no globalType on purpose: it's driven by the toolbar toggle in
// `mode-toggle.tsx`, not a dropdown.
export const themeGlobalTypes = {
theme: {
description: 'Design system theme',
Expand All @@ -24,18 +25,6 @@ export const themeGlobalTypes = {
dynamicTitle: true,
},
},
mode: {
description: 'Light / dark mode',
toolbar: {
title: 'Mode',
icon: 'mirror',
items: [
{ value: 'light', title: 'Light', icon: 'sun' },
{ value: 'dark', title: 'Dark', icon: 'moon' },
],
dynamicTitle: true,
},
},
};

// Defaults to merge into each preview's `initialGlobals`.
Expand Down
1 change: 1 addition & 0 deletions packages/storybook-config/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"moduleResolution": "bundler",
"target": "ES2022",
"lib": ["ES2022", "DOM"],
"jsx": "react",
"outDir": "dist",
"rootDir": "src",
"types": []
Expand Down
Loading
Loading