Skip to content

Commit

Permalink
Simplify theme next storybook toolbar (#3393)
Browse files Browse the repository at this point in the history
  • Loading branch information
origami-z authored Jun 20, 2024
1 parent 0da6bf8 commit 0e3f091
Show file tree
Hide file tree
Showing 6 changed files with 719 additions and 280 deletions.
12 changes: 11 additions & 1 deletion .storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { addons } from "@storybook/manager-api";
import { addons, types } from "@storybook/manager-api";
import saltTheme from "./SaltTheme";
import { ThemeNextToolbar } from "./toolbar/ThemeNextToolbar";

addons.setConfig({
theme: saltTheme,
});

addons.register("theme-next-addon", () => {
addons.add("theme-next-addon/toolbar", {
title: "Theme next toolbar",
//👇 Sets the type of UI element in Storybook
type: types.TOOL,
render: ThemeNextToolbar,
});
});
54 changes: 3 additions & 51 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import { SaltProvider } from "@salt-ds/core";
import { DocsContainer } from "@storybook/addon-docs";
import { initialize, mswLoader } from "msw-storybook-addon";

import { globalOptions as themeNextGlobals } from "./toolbar/ThemeNextToolbar";

const densities = ["touch", "low", "medium", "high"];
const DEFAULT_DENSITY = "medium";
const DEFAULT_MODE = "light";
Expand Down Expand Up @@ -107,57 +109,7 @@ export const globalTypes: GlobalTypes = {
title: "Component Style Injection",
},
},
themeNext: {
name: "Experimental theme next",
description: "Turn on/off theme next",
defaultValue: "disable",
toolbar: {
icon: "beaker",
items: ["disable", "enable"],
title: "Theme Next",
},
},
corner: {
name: "Experimental corner",
description: "Switch corner to sharp / rounded",
defaultValue: "sharp",
// if: { global: "themeNext", eq: "enable" }, // todo: why if doesn't work?
toolbar: {
icon: "beaker",
items: ["sharp", "rounded"],
title: "Corner",
},
},
headingFont: {
name: "Experimental heading font",
description: "Switch heading font to open sans / amplitude",
defaultValue: "Open Sans",
toolbar: {
icon: "beaker",
items: ["Open Sans", "Amplitude"],
title: "Heading font",
},
},
accent: {
name: "Experimental accent",
description: "Switch accent to blue / teal",
defaultValue: "blue",
toolbar: {
icon: "beaker",
items: ["blue", "teal"],
title: "Accent",
},
},
actionFont: {
name: "Experimental action font",
description: "Switch action font to open sans / amplitude",
defaultValue: "Open Sans",
toolbar: {
icon: "beaker",
items: ["Open Sans", "Amplitude"],
title: "Action font",
},
},
...themeNextGlobals,
};

export const argTypes: ArgTypes = {
Expand Down
9 changes: 9 additions & 0 deletions .storybook/toolbar/ThemeNextToolbar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* Custom Toolbar */
.theme-next-toolbar-group-wrapper {
cursor: not-allowed;
}

.theme-next-toolbar-group-wrapper > span > span {
font-weight: bold;
color: darkgray;
}
120 changes: 120 additions & 0 deletions .storybook/toolbar/ThemeNextToolbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import type { TooltipLinkListLink } from "@storybook/components";
import {
IconButton,
Separator,
TooltipLinkList,
WithTooltip,
} from "@storybook/components";
import { BeakerIcon, CheckIcon } from "@storybook/icons";
import { useGlobals } from "@storybook/manager-api";
import { clsx } from "clsx";
import React, { AnchorHTMLAttributes } from "react";

import "./ThemeNextToolbar.css";

const description = "Theme next controls";

const camelCaseToWords = (s: string) => {
const result = s.replace(/([A-Z])/g, " $1");
return result.charAt(0).toUpperCase() + result.slice(1);
};

export const globalOptions: Record<
string,
{ name: string; description: string; defaultValue: string; items: string[] }
> = {
themeNext: {
name: "Experimental theme next",
description: "Turn on/off theme next",
defaultValue: "disable",
items: ["enable", "disable"],
},
corner: {
name: "Experimental corner",
description: "Switch corner to sharp / rounded",
defaultValue: "sharp",
items: ["sharp", "rounded"],
},
headingFont: {
name: "Experimental heading font",
description: "Switch heading font to open sans / amplitude",
defaultValue: "Open Sans",
items: ["Open Sans", "Amplitude"],
},
accent: {
name: "Experimental accent",
description: "Switch accent to blue / teal",
defaultValue: "blue",
items: ["blue", "teal"],
},
actionFont: {
name: "Experimental action font",
description: "Switch action font to open sans / amplitude",
defaultValue: "Open Sans",
items: ["Open Sans", "Amplitude"],
},
};

const GroupWrapper = ({
className,
children,
}: AnchorHTMLAttributes<HTMLAnchorElement>) => {
return (
<div
className={clsx(className, "theme-next-toolbar-group-wrapper")}
children={children}
/>
);
};

export const ThemeNextToolbar = ({ active }: { active?: boolean }) => {
const [globals, updateGlobals] = useGlobals();

const items: TooltipLinkListLink[] = Object.keys(globalOptions).flatMap(
(globalKey) => {
return [
{
id: `theme-next-${globalKey}-header`,
title: camelCaseToWords(globalKey),
LinkWrapper: GroupWrapper, // Custom wrapper to render group
href: "#", // Without href, `LinkWrapper` will not work
},
...globalOptions[globalKey].items.map((value) => {
const disabled =
globalKey === "themeNext"
? false
: globals["themeNext"] !== "enable";
const active = globals[globalKey] === value;

return {
id: `theme-next-${globalKey}-${value}`,
right: active ? (
<CheckIcon style={{ fill: "inherit" }} />
) : undefined,
active,
title: camelCaseToWords(value),
onClick: () => {
!disabled && updateGlobals({ [globalKey]: value });
},
disabled,
};
}),
];
}
);

return (
<>
<Separator />
<WithTooltip
tooltip={() => <TooltipLinkList links={items} />}
trigger="click"
closeOnOutsideClick
>
<IconButton title={description} active={active}>
<BeakerIcon /> Theme Next
</IconButton>
</WithTooltip>
</>
);
};
32 changes: 17 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,22 @@
"@fontsource/open-sans": "^4.5.13",
"@fontsource/pt-mono": "^5.0.12",
"@mswjs/data": "^0.14.0",
"@storybook/addon-a11y": "^8.1.8",
"@storybook/addon-actions": "^8.1.8",
"@storybook/addon-docs": "^8.1.8",
"@storybook/addon-essentials": "^8.1.8",
"@storybook/addon-interactions": "^8.1.8",
"@storybook/addon-links": "^8.1.8",
"@storybook/addon-mdx-gfm": "^8.1.8",
"@storybook/addon-storysource": "^8.1.8",
"@storybook/blocks": "^8.1.8",
"@storybook/manager-api": "^8.1.8",
"@storybook/react": "^8.1.8",
"@storybook/react-vite": "^8.1.8",
"@storybook/test": "^8.1.8",
"@storybook/theming": "^8.1.8",
"@storybook/addon-a11y": "^8.1.10",
"@storybook/addon-actions": "^8.1.10",
"@storybook/addon-docs": "^8.1.10",
"@storybook/addon-essentials": "^8.1.10",
"@storybook/addon-interactions": "^8.1.10",
"@storybook/addon-links": "^8.1.10",
"@storybook/addon-mdx-gfm": "^8.1.10",
"@storybook/addon-storysource": "^8.1.10",
"@storybook/blocks": "^8.1.10",
"@storybook/components": "^8.1.10",
"@storybook/icons": "^1.2.9",
"@storybook/manager-api": "^8.1.10",
"@storybook/react": "^8.1.10",
"@storybook/react-vite": "^8.1.10",
"@storybook/test": "^8.1.10",
"@storybook/theming": "^8.1.10",
"@tanstack/react-query": "^4.28.0",
"@testing-library/cypress": "^10.0.0",
"@testing-library/dom": "^10.0.0",
Expand Down Expand Up @@ -113,7 +115,7 @@
"react-dom": "^18.0.0",
"rifm": "^0.12.0",
"sass": "^1.52.3",
"storybook": "^8.1.8",
"storybook": "^8.1.10",
"stylelint": "^16.0.0",
"typescript": "4.6.4",
"vite": "^4.4.9",
Expand Down
Loading

0 comments on commit 0e3f091

Please sign in to comment.