Skip to content

Commit

Permalink
feat: add Storybook utils
Browse files Browse the repository at this point in the history
  • Loading branch information
jtiala committed Jan 25, 2024
1 parent b1eecbe commit 5f0dbf3
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 1 deletion.
27 changes: 27 additions & 0 deletions apps/docs/utils/ExampleGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ReactNode } from "react";

export function ExampleGrid({
columns,
gap = 32,
centered,
children,
}: {
columns: number;
gap?: number;
centered?: boolean;
children: ReactNode;
}) {
return (
<div
style={{
display: "grid",
gridTemplateColumns: `repeat(${columns}, max-content)`,
alignItems: "start",
justifyItems: centered ? "center" : "start",
gap: `${gap}px`,
}}
>
{children}
</div>
);
}
36 changes: 36 additions & 0 deletions apps/docs/utils/ExampleItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ReactNode } from "react";
import { ExampleTitle } from "./ExampleTitle";

export function ExampleItem({
title,
direction = "vertical",
centered,
children,
}: {
title: string;
direction?: "vertical" | "horizontal" | "vertical-reverse";
centered?: boolean;
children: ReactNode;
}) {
return (
<div
style={{
display: "flex",
flexDirection:
direction === "vertical"
? "column"
: direction === "vertical-reverse"
? "column-reverse"
: "row",
alignItems: centered ? "center" : "normal",
gap: "8px",
}}
>
<ExampleTitle>{`${title}${
direction === "horizontal" ? ":" : ""
}`}</ExampleTitle>

{children}
</div>
);
}
37 changes: 37 additions & 0 deletions apps/docs/utils/ExampleStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ReactNode } from "react";
import { SizeElement } from "./SizeElement";

export function ExampleStack({
gap = 32,
children,
}: {
gap?: number;
children?: ReactNode;
}) {
return (
<div
style={{
display: "flex",
flexDirection: "column",
gap: `${gap}px`,
}}
>
{children}
</div>
);
}

function getDefaultElement(elementNumber: number = 0) {
return <SizeElement key={elementNumber} />;
}

export function getStackedElements(
numberOfElements: number,
getElement: (elementNumber: number) => JSX.Element = getDefaultElement,
) {
return (
<ExampleStack>
{[...Array(numberOfElements).keys()].map((n) => getElement(n))}
</ExampleStack>
);
}
13 changes: 13 additions & 0 deletions apps/docs/utils/ExampleTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ReactNode } from "react";

export function ExampleTitle({ children }: { children: ReactNode }) {
return (
<span
style={{
maxWidth: "20ch",
}}
>
<code>{children}</code>
</span>
);
}
43 changes: 43 additions & 0 deletions apps/docs/utils/SizeElement.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CSSProperties, useEffect, useRef, useState } from "react";

export function SizeElement({ styles }: { styles?: CSSProperties }) {
const ref = useRef(null);

const [size, setSize] = useState({
width: 0,
height: 0,
});

useEffect(() => {
const handleResize = () => {
if (ref && "current" in ref && ref.current) {
const { clientWidth: width, clientHeight: height } = ref.current;
setSize({ width, height });
}
};

handleResize();

window.addEventListener("resize", handleResize);

return () => {
window.removeEventListener("resize", handleResize);
};
}, [ref]);

return (
<div
ref={ref}
style={{
backgroundColor: "black",
color: "white",
padding: "8px",
...styles,
}}
>
<code>
{size.width}x{size.height}
</code>
</div>
);
}
84 changes: 84 additions & 0 deletions apps/docs/utils/decorators.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Decorator } from "@storybook/react";
import { useEffect, useState } from "react";

export const marginDecorator: (
margin:
| {
top?: string;
left?: string;
bottom?: string;
right?: string;
}
| string,
) => Decorator = (margin) => {
const decorator: Decorator = (Story) => (
<div
style={
typeof margin === "object"
? {
marginTop: margin.top,
marginLeft: margin.left,
marginBottom: margin.bottom,
marginRight: margin.right,
}
: { margin }
}
>
<Story />
</div>
);

return decorator;
};

export const viewportSizeDecorator: () => Decorator = () => {
const Decorator: Decorator = (Story) => {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});

useEffect(() => {
const handleResize = () => {
setSize({ width: window.innerWidth, height: window.innerHeight });
};

window.addEventListener("resize", handleResize);

return () => {
window.removeEventListener("resize", handleResize);
};
}, []);

// These values should match the ones in `breakpoints.css`
const viewport =
size.width < 640
? "xs"
: size.width < 768
? "sm"
: size.width < 1024
? "md"
: size.width < 1280
? "lg"
: size.width < 1536
? "xl"
: "xxl";

return (
<div
style={{
display: "flex",
flexDirection: "column",
gap: "16px",
}}
>
<code>
viewport: {viewport} ({size.width}x{size.height})
</code>
<Story />
</div>
);
};

return Decorator;
};
6 changes: 6 additions & 0 deletions apps/docs/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from "./ExampleGrid";
export * from "./ExampleItem";
export * from "./ExampleStack";
export * from "./ExampleTitle";
export * from "./SizeElement";
export * from "./decorators";
3 changes: 2 additions & 1 deletion packages/typescript-config/storybook.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"extends": "./base.json",
"compilerOptions": {
"jsx": "react-jsx",
"noEmit": true
"noEmit": true,
"target": "ESNext"
}
}

0 comments on commit 5f0dbf3

Please sign in to comment.