Skip to content

Commit 9e6d5ce

Browse files
refactor: replace @chakra-ui/addon with local setup
1 parent ffdbd8a commit 9e6d5ce

File tree

8 files changed

+162
-16
lines changed

8 files changed

+162
-16
lines changed

.storybook/ChakraDecorator.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
ChakraBaseProvider,
3+
extendBaseTheme,
4+
useColorMode,
5+
} from "@chakra-ui/react"
6+
import type { Decorator } from "@storybook/react"
7+
8+
import theme from "../src/@chakra-ui/theme"
9+
import { useEffect, useMemo, useState } from "react"
10+
import i18n from "./i18next"
11+
12+
type DecoratorProps = Parameters<Decorator>
13+
14+
const ColorModeSync = ({ context }: { context: DecoratorProps[1] }) => {
15+
const { setColorMode } = useColorMode()
16+
17+
useEffect(() => {
18+
const isDarkMode = localStorage.getItem("chakra-ui-color-mode") === "dark"
19+
20+
context.globals.colorMode = isDarkMode ? "dark" : "light"
21+
}, [])
22+
23+
useEffect(() => {
24+
setColorMode(context.globals.colorMode)
25+
}, [setColorMode, context])
26+
27+
return null
28+
}
29+
30+
/**
31+
* This is a custom local setup of the official Chakra UI Storybook addon.
32+
*
33+
* A local version was created in response to provide a better sync between
34+
* updated local direction to the Chakra theme.
35+
*
36+
* (This would most likely not be updated in the addon due to ongoing creation of Chakra v3 at the time this
37+
* setup was created.)
38+
*
39+
* Will be deprecated and removed when Chakra v3 is available for migration.
40+
*
41+
*/
42+
export const ChakraDecorator: Decorator = (getStory, context) => {
43+
const [dir, updateDir] = useState<"ltr" | "rtl">()
44+
45+
i18n.on("languageChanged", (locale) => {
46+
const direction = i18n.dir(locale)
47+
document.documentElement.dir = direction
48+
updateDir(direction)
49+
})
50+
51+
const themeWithDirectionOverride = useMemo(() => {
52+
return extendBaseTheme({ direction: dir }, theme)
53+
}, [dir])
54+
55+
return (
56+
<ChakraBaseProvider theme={themeWithDirectionOverride}>
57+
<>
58+
<ColorModeSync context={context} />
59+
{getStory(context)}
60+
</>
61+
</ChakraBaseProvider>
62+
)
63+
}

.storybook/i18next.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const baseLocales = {
66
zh: { title: "中国人", left: "Zh" },
77
ru: { title: "Русский", left: "Ru" },
88
uk: { title: "українська", left: "Uk" },
9+
fa: { title: "فارسی", left: "Fa" },
910
}
1011

1112
// Only i18n files named in this array are being exposed to Storybook. Add filenames as necessary.

.storybook/main.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const config: StorybookConfig = {
2121
"@storybook/addon-links",
2222
"@storybook/addon-essentials",
2323
"@storybook/addon-interactions",
24-
"@chakra-ui/storybook-addon",
2524
"storybook-react-i18next",
2625
],
2726
staticDirs: ["../public"],

.storybook/preview.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
import { extendBaseTheme } from "@chakra-ui/react"
21
import type { Preview } from "@storybook/react"
32

43
import theme from "../src/@chakra-ui/theme"
54

5+
import { ChakraDecorator } from "./ChakraDecorator"
66
import i18n, { baseLocales } from "./i18next"
77

88
import "../src/styles/global.css"
99

10-
const extendedTheme = extendBaseTheme(theme)
11-
12-
const chakraBreakpointArray = Object.entries(extendedTheme.breakpoints) as [
10+
const chakraBreakpointArray = Object.entries(theme.breakpoints) as [
1311
string,
1412
string
1513
][]
@@ -19,6 +17,20 @@ const preview: Preview = {
1917
locale: "en",
2018
locales: baseLocales,
2119
},
20+
globalTypes: {
21+
colorMode: {
22+
name: "Color Mode",
23+
description: "Change the color mode",
24+
toolbar: {
25+
icon: "circlehollow",
26+
items: [
27+
{ value: "light", icon: "circlehollow", title: "Light Mode" },
28+
{ value: "dark", icon: "circle", title: "Dark Mode" },
29+
],
30+
},
31+
},
32+
},
33+
decorators: [ChakraDecorator],
2234
parameters: {
2335
i18n,
2436
actions: { argTypesRegex: "^on[A-Z].*" },
@@ -36,9 +48,6 @@ const preview: Preview = {
3648
order: ["Atoms", "Molecules", "Organisms", "Templates", "Pages"],
3749
},
3850
},
39-
chakra: {
40-
theme: extendedTheme,
41-
},
4251
layout: "centered",
4352
// Modify viewport selection to match Chakra breakpoints (or custom breakpoints)
4453
viewport: {

.storybook/types.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import type { ArgTypes } from "@storybook/react"
2+
import type { ThemingProps } from "@chakra-ui/react"
3+
4+
// Type declarations below pulled directly from `@chakra-ui/storybook-addon`
5+
// with some alteration
6+
// (Subject to deprecation and removal upon release of Chakra v3)
7+
8+
/**
9+
* `keyof` alternative which omits non-string keys
10+
*/
11+
type KeyOf<T> = [T] extends [never]
12+
? never
13+
: T extends object
14+
? Extract<keyof T, string>
15+
: never
16+
17+
export type ThemingArgTypeKey = "variant" | "size"
18+
19+
/**
20+
* Create Storybook controls based on a Chakra UI theme component.
21+
*
22+
* @example
23+
* export default {
24+
* title: "Components / Forms / Button",
25+
* argTypes: getThemingArgTypes(theme, "Button"),
26+
* }
27+
*
28+
* @example full example
29+
* import { Meta, StoryFn } from "@storybook/react"
30+
* import { getThemingArgTypes } from "@chakra-ui/storybook-addon"
31+
* import { theme } from "<your-theme>"
32+
*
33+
* export default {
34+
* title: "Components / Forms / Button",
35+
* argTypes: {
36+
* ...getThemingArgTypes(theme, "Button"),
37+
* children: "string"
38+
* },
39+
* args: { children: "Button" },
40+
* } as Meta
41+
*
42+
* interface StoryProps extends ThemingProps<"Button"> {
43+
* children?: React.ReactNode
44+
* }
45+
*
46+
* export const Basic: StoryFn<StoryProps> = (props) => <Button {...props} />
47+
*
48+
* @param theme same Chakra UI theme used in .storybook/preview.tsx
49+
* @param componentName component name to create the ArgTypes for
50+
*/
51+
export function getThemingArgTypes<
52+
Theme extends Record<string, any>,
53+
ComponentName extends KeyOf<Theme["components"]>
54+
>(theme: Theme, componentName: ComponentName) {
55+
const component = theme.components[componentName]
56+
if (!component) {
57+
return undefined
58+
}
59+
60+
const argTypes: ArgTypes<
61+
Partial<Pick<ThemingProps<ComponentName>, ThemingArgTypeKey>>
62+
> = {}
63+
64+
const variantOptions = Object.keys(component.variants || {})
65+
if (variantOptions.length) {
66+
argTypes.variant = {
67+
type: { name: "enum", value: variantOptions },
68+
defaultValue: component.defaultProps?.variant,
69+
}
70+
}
71+
72+
const sizeOptions = Object.keys(component.sizes || {})
73+
if (sizeOptions.length) {
74+
argTypes.size = {
75+
type: { name: "enum", value: sizeOptions },
76+
defaultValue: component.defaultProps?.size,
77+
}
78+
}
79+
80+
return argTypes
81+
}

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
},
6262
"devDependencies": {
6363
"@chakra-ui/cli": "^2.4.1",
64-
"@chakra-ui/storybook-addon": "5.1.0",
6564
"@netlify/plugin-nextjs": "^4.41.3",
6665
"@storybook/addon-essentials": "7.6.6",
6766
"@storybook/addon-interactions": "7.6.6",

src/components/Buttons/Button.stories.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as React from "react"
22
import { MdChevronRight, MdExpandMore, MdNightlight } from "react-icons/md"
33
import { HStack, Text, ThemingProps, VStack } from "@chakra-ui/react"
4-
import { getThemingArgTypes } from "@chakra-ui/storybook-addon"
54
import { Meta, StoryObj } from "@storybook/react"
65

6+
import { getThemingArgTypes } from "../../../.storybook/types"
77
import theme from "../../@chakra-ui/theme"
88
import Translation from "../Translation"
99

@@ -41,7 +41,6 @@ const variants: ThemingProps<"Button">["variant"][] = [
4141
export const StyleVariants: Story = {
4242
argTypes: {
4343
size: {
44-
// @ts-expect-error looking for a more specific type, but this is still valid
4544
...getThemingArgTypes(theme, "Button")?.size,
4645
defaultValue: "md",
4746
},

yarn.lock

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,11 +1945,6 @@
19451945
"@chakra-ui/react-context" "2.1.0"
19461946
"@chakra-ui/shared-utils" "2.0.5"
19471947

1948-
"@chakra-ui/[email protected]":
1949-
version "5.1.0"
1950-
resolved "https://registry.yarnpkg.com/@chakra-ui/storybook-addon/-/storybook-addon-5.1.0.tgz#b95ec65ad4b79383939f0951918287f4dc66a232"
1951-
integrity sha512-l9DIdTAw+FLbDrMVpoLCn9EdOygJDRV2SYobuoR0dDmuXlHq/u/RvE51Yq8XgUTn9Fkqv0g8ellMZEGytZEVYw==
1952-
19531948
"@chakra-ui/[email protected]":
19541949
version "2.9.2"
19551950
resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.9.2.tgz#898ab63da560a4a014f7b05fa7767e8c76da6d2f"

0 commit comments

Comments
 (0)