From 5bcfa9d488127f3154bf6aa749a479999d1722db Mon Sep 17 00:00:00 2001 From: Zintarh Date: Sat, 30 Nov 2024 08:45:11 +0100 Subject: [PATCH 1/5] feat: story book for Alert, Button, and Carousel --- apps/web/.storybook/main.ts | 22 ++----- apps/web/src/stories/Alert.stories.tsx | 44 +++++++++++++ apps/web/src/stories/Button.stories.ts | 51 --------------- apps/web/src/stories/Button.stories.tsx | 76 +++++++++++++++++++++++ apps/web/src/stories/Carousel.stories.tsx | 65 +++++++++++++++++++ 5 files changed, 190 insertions(+), 68 deletions(-) create mode 100644 apps/web/src/stories/Alert.stories.tsx delete mode 100644 apps/web/src/stories/Button.stories.ts create mode 100644 apps/web/src/stories/Button.stories.tsx create mode 100644 apps/web/src/stories/Carousel.stories.tsx diff --git a/apps/web/.storybook/main.ts b/apps/web/.storybook/main.ts index ed1d7e9..a84f78e 100644 --- a/apps/web/.storybook/main.ts +++ b/apps/web/.storybook/main.ts @@ -1,14 +1,5 @@ import type { StorybookConfig } from "@storybook/nextjs"; -import { dirname, join } from "path"; - -/** - * This function is used to resolve the absolute path of a package. - * It is needed in projects that use Yarn PnP or are set up within a monorepo. - */ -function getAbsolutePath(value: string): string { - return dirname(require.resolve(join(value, "package.json"))); -} const config: StorybookConfig = { stories: [ "../src/**/*.mdx", @@ -16,16 +7,13 @@ const config: StorybookConfig = { "../../../packages/ui/src/**/*.stories.@(js|jsx|mjs|ts|tsx)", ], addons: [ - getAbsolutePath("@storybook/addon-onboarding"), - getAbsolutePath("@storybook/addon-links"), - getAbsolutePath("@storybook/addon-essentials"), - getAbsolutePath("@chromatic-com/storybook"), - getAbsolutePath("@storybook/addon-interactions"), - getAbsolutePath("@storybook/addon-styling-webpack"), - getAbsolutePath("@storybook/addon-themes"), + "@storybook/addon-onboarding", + "@storybook/addon-essentials", + "@chromatic-com/storybook", + "@storybook/addon-interactions", ], framework: { - name: getAbsolutePath("@storybook/nextjs"), + name: "@storybook/nextjs", options: {}, }, staticDirs: ["../public"], diff --git a/apps/web/src/stories/Alert.stories.tsx b/apps/web/src/stories/Alert.stories.tsx new file mode 100644 index 0000000..156d7b9 --- /dev/null +++ b/apps/web/src/stories/Alert.stories.tsx @@ -0,0 +1,44 @@ +import Alert from "@repo/ui/alert"; +import type { Meta, StoryObj } from "@storybook/react"; +import type React from "react"; +import { useState } from "react"; + +const meta: Meta = { + title: "Components/Alert", + tags: ["autofocus"], + component: Alert, + parameters: { + controls: { expanded: true }, + }, + argTypes: { + type: { + control: { type: "select" }, + options: ["success", "error", "info"], + }, + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Template: Story = ( + args: React.JSX.IntrinsicAttributes & { + message: string; + description: string; + type: "success" | "error" | "info"; + onDismiss: () => void; + }, +) => { + const [isVisible, setIsVisible] = useState(true); + + if (!isVisible) return null; + + return setIsVisible(false)} />; +}; + +Template.args = { + message: "This is an alert", + description: "This is an alert description", + type: "success", +}; diff --git a/apps/web/src/stories/Button.stories.ts b/apps/web/src/stories/Button.stories.ts deleted file mode 100644 index e5656a0..0000000 --- a/apps/web/src/stories/Button.stories.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { Button } from "./Button"; - -const meta = { - title: "UI/Button", - component: Button, - parameters: { - layout: "centered", - }, - tags: ["autodocs"], - argTypes: { - variant: { - control: "select", - options: ["default"], - }, - disabled: { - control: "boolean", - }, - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - children: "Button", - }, -}; - -export const Disabled: Story = { - args: { - children: "Disabled Button", - disabled: true, - }, -}; - -export const WithOnClick: Story = { - args: { - children: "Click Me", - onClick: () => alert("Button clicked!"), - }, -}; - -export const SubmitType: Story = { - args: { - children: "Submit", - type: "submit", - }, -}; diff --git a/apps/web/src/stories/Button.stories.tsx b/apps/web/src/stories/Button.stories.tsx new file mode 100644 index 0000000..fe736f9 --- /dev/null +++ b/apps/web/src/stories/Button.stories.tsx @@ -0,0 +1,76 @@ +import type { Meta, StoryFn, StoryObj } from "@storybook/react"; + +import { Button } from "./Button"; + +export default { + title: "Components/Button", + component: Button, + argTypes: { + variant: { + control: "select", + options: ["primary", "secondary", "danger"], + description: "Controls the button style variant", + }, + size: { + control: "select", + options: ["small", "medium", "large"], + description: "Controls the button size", + }, + icon: { + control: false, + description: "Optional icon to display alongside the button text", + }, + disabled: { + control: "boolean", + description: "Disables the button if set to true", + }, + onClick: { + action: "clicked", + description: "Callback function when the button is clicked", + }, + }, +} as Meta; + +const Template: StoryFn = (args) => + + +); + +export const Sizes: StoryFn = () => ( +
+ + + + +
+); diff --git a/apps/web/src/stories/Carousel.stories.tsx b/apps/web/src/stories/Carousel.stories.tsx new file mode 100644 index 0000000..2dbba22 --- /dev/null +++ b/apps/web/src/stories/Carousel.stories.tsx @@ -0,0 +1,65 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import React from "react"; +import CarouselCard, { + type CardProps, +} from "../../../../packages/ui/src/carouselCard"; + +const meta: Meta = { + title: "Components/CarouselCard", + component: CarouselCard, + parameters: { + controls: { expanded: true }, + }, + argTypes: { + tag: { + description: "The tag displayed at the top of the card.", + control: { type: "text" }, + }, + title: { + description: "The title text displayed on the card.", + control: { type: "text" }, + }, + image: { + description: "Background image URL for the card.", + control: { type: "text" }, + }, + }, +}; + +export default meta; + +type Story = StoryObj; + +const defaultArgs: CardProps = { + tag: "Tech", + title: "Latest Innovations in Technology", + id: "1", + image: "https://via.placeholder.com/380x180?text=Card+Image", +}; + +export const Default: Story = { + args: { ...defaultArgs }, +}; + +export const LongTitle: Story = { + args: { + ...defaultArgs, + title: + "Exploring the Intersection of Artificial Intelligence, Blockchain, and Quantum Computing in Modern Technology", + }, +}; + +export const NoImage: Story = { + args: { + ...defaultArgs, + image: "", + title: "A card with no image background", + }, +}; + +export const CustomTag: Story = { + args: { + ...defaultArgs, + tag: "Custom Tag", + }, +}; From 144b900133e353568bd98ab8be343a98f641788c Mon Sep 17 00:00:00 2001 From: Zintarh Date: Sat, 30 Nov 2024 08:55:54 +0100 Subject: [PATCH 2/5] feat: InfoCard story --- apps/web/src/stories/InfoCard.stories.tsx | 55 +++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 apps/web/src/stories/InfoCard.stories.tsx diff --git a/apps/web/src/stories/InfoCard.stories.tsx b/apps/web/src/stories/InfoCard.stories.tsx new file mode 100644 index 0000000..547f1eb --- /dev/null +++ b/apps/web/src/stories/InfoCard.stories.tsx @@ -0,0 +1,55 @@ +import { InfoCard } from "@repo/ui/infoCard"; +import type { Meta, StoryFn } from "@storybook/react"; +import React from "react"; + +export default { + title: "Components/InfoCard", + component: InfoCard, + tags: ["autodocs"], + argTypes: { + title: { control: "text", description: "The title of the InfoCard" }, + options: { + control: false, + description: "Options displayed in the InfoCard", + }, + children: { control: false, description: "Optional child components" }, + }, +} as Meta; + +const options = [ + { + label: "Option 1", + iconSrc: "/images/Avatar.png", + selected: false, + onClick: () => alert("Option 1 clicked"), + }, + { + label: "Option 2", + iconSrc: "/images/Avatar.png", + selected: true, + onClick: () => alert("Option 2 clicked"), + }, + { + label: "Option 3", + iconSrc: "/images/Avatar.png", + selected: false, + onClick: () => alert("Option 3 clicked"), + }, +]; + +const Template: StoryFn = (args) => ( + +); + +export const Default = Template.bind({}); +Default.args = { + title: "Default InfoCard", + options, +}; + +export const NoOptions = Template.bind({}); +NoOptions.args = { + title: "InfoCard with No Options", + options: [], + children:

No options available

, +}; From 60415a54697f2a86dc423fae052daff10bb940d8 Mon Sep 17 00:00:00 2001 From: Zintarh Date: Sat, 30 Nov 2024 09:11:53 +0100 Subject: [PATCH 3/5] chore: Modal story --- apps/web/src/stories/Modal.stories.tsx | 74 ++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 apps/web/src/stories/Modal.stories.tsx diff --git a/apps/web/src/stories/Modal.stories.tsx b/apps/web/src/stories/Modal.stories.tsx new file mode 100644 index 0000000..cc709f3 --- /dev/null +++ b/apps/web/src/stories/Modal.stories.tsx @@ -0,0 +1,74 @@ +import Modal from "@repo/ui/modal"; +import type { Meta, StoryFn } from "@storybook/react"; +import React from "react"; +import TestIcon from "./assets/youtube.svg"; + +export default { + title: "Components/Modal", + tags: ["autodocs"], + component: Modal, + argTypes: { + isOpen: { + control: "boolean", + description: "Controls whether the modal is open or closed", + }, + onClose: { + action: "closed", + description: "Callback function when the modal is closed", + }, + buttons: { + control: "object", + description: "Array of buttons to display inside the modal", + }, + }, +} as Meta; + +const buttons = [ + { + label: "Action 1", + onClick: () => alert("Action 1 clicked"), + }, + { + label: "Action 2", + onClick: () => alert("Action 2 clicked"), + }, +]; + +const Template: StoryFn = (args) => ( + { + throw new Error("Function not implemented."); + }} + buttons={buttons} + {...args} + /> +); + +export const Default = Template.bind({}); +Default.args = { + isOpen: true, + onClose: () => alert("Modal closed"), + buttons, +}; + +export const Icons = Template.bind({}); +Icons.args = { + isOpen: true, + onClose: () => alert("Modal closed"), + buttons: [ + { label: "Accept", onClick: () => alert("Accept clicked") }, + { + label: "Decline", + onClick: () => alert("Decline clicked"), + icon: , + }, + ], +}; + +export const NoButtons = Template.bind({}); +NoButtons.args = { + isOpen: true, + onClose: () => alert("Modal closed"), + buttons: [], +}; From 5e6c831aa8cc473586d071282befa1f11bdb7e9d Mon Sep 17 00:00:00 2001 From: Zintarh Date: Sat, 30 Nov 2024 10:24:43 +0100 Subject: [PATCH 4/5] feat: Badge story --- apps/web/src/stories/Badge.stories.tsx | 45 ++++++++++++++++++++++++ apps/web/src/stories/NftCard.stories.tsx | 41 +++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 apps/web/src/stories/Badge.stories.tsx create mode 100644 apps/web/src/stories/NftCard.stories.tsx diff --git a/apps/web/src/stories/Badge.stories.tsx b/apps/web/src/stories/Badge.stories.tsx new file mode 100644 index 0000000..293ae10 --- /dev/null +++ b/apps/web/src/stories/Badge.stories.tsx @@ -0,0 +1,45 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import React from "react"; +import Badge from "../../../../packages/ui/src/badge"; + +export default { + title: "Components/Badge", + component: Badge, + tags: ["autodocs"], + argTypes: { + variant: { + control: "radio", + options: ["default", "primary", "secondary", "accent", "success"], + }, + size: { + control: "radio", + options: ["sm", "md", "lg"], + }, + }, +} as Meta; + +const Template: StoryFn = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + text: "Default Badge", + variant: "default", + size: "md", +}; + +export const Variants: StoryFn = () => ( +
+ + + + +
+); + +export const Sizes: StoryFn = () => ( +
+ + + +
+); diff --git a/apps/web/src/stories/NftCard.stories.tsx b/apps/web/src/stories/NftCard.stories.tsx new file mode 100644 index 0000000..11ba909 --- /dev/null +++ b/apps/web/src/stories/NftCard.stories.tsx @@ -0,0 +1,41 @@ +import { ArrowRightIcon } from "@heroicons/react/24/solid"; +import NFTCard from "@repo/ui/nftCard"; +import { type Meta, StoryFn, type StoryObj } from "@storybook/react"; +import type React from "react"; + +export default { + title: "Components/NFTCard", + tags: ["autodocs"], + component: NFTCard, + argTypes: { + onDetailsClick: { action: "clicked" }, + nftMetadata: { + control: "object", + defaultValue: { + imageSrc: "https://via.placeholder.com/150", + }, + }, + }, +} as Meta; + +type Story = StoryObj; + +export const Template: Story = ( + args: React.JSX.IntrinsicAttributes & { + title: string; + nftMetadata: { + imageSrc: string; + }; + onDetailsClick: () => void; + }, +) => { + return ; +}; + +Template.args = { + title: "Interactive NFT", + nftMetadata: { + imageSrc: "https://via.placeholder.com/250", + }, + onDetailsClick: () => alert("Details button clicked"), +}; From b01c871f1382da1729fdf697fc5f7c8f6aa2d82f Mon Sep 17 00:00:00 2001 From: Zintarh Date: Sat, 30 Nov 2024 14:22:08 +0100 Subject: [PATCH 5/5] chore: add stories for all component --- apps/web/src/stories/Alert.stories.tsx | 2 +- apps/web/src/stories/Button.stories.tsx | 26 +++--- apps/web/src/stories/Button.tsx | 38 -------- ...l.stories.tsx => CarouselCard.stories.tsx} | 25 +----- .../src/stories/ChatWithSeller.stories.tsx | 44 ++++++++++ apps/web/src/stories/IconButton.stories.tsx | 78 ++++++++++++++++ apps/web/src/stories/NftCard.stories.tsx | 1 - apps/web/src/stories/Particle.stories.tsx | 30 +++++++ apps/web/src/stories/ProductCard.stories.tsx | 88 +++++++++++++++++++ apps/web/src/stories/Skeleton.stories.tsx | 38 ++++++++ apps/web/src/stories/Tooltip.stories.tsx | 53 +++++++++++ apps/web/src/stories/dataCard.stories.tsx | 62 +++++++++++++ apps/web/src/stories/typography.stories.tsx | 44 ++++++++++ 13 files changed, 450 insertions(+), 79 deletions(-) delete mode 100644 apps/web/src/stories/Button.tsx rename apps/web/src/stories/{Carousel.stories.tsx => CarouselCard.stories.tsx} (68%) create mode 100644 apps/web/src/stories/ChatWithSeller.stories.tsx create mode 100644 apps/web/src/stories/IconButton.stories.tsx create mode 100644 apps/web/src/stories/Particle.stories.tsx create mode 100644 apps/web/src/stories/ProductCard.stories.tsx create mode 100644 apps/web/src/stories/Skeleton.stories.tsx create mode 100644 apps/web/src/stories/Tooltip.stories.tsx create mode 100644 apps/web/src/stories/dataCard.stories.tsx create mode 100644 apps/web/src/stories/typography.stories.tsx diff --git a/apps/web/src/stories/Alert.stories.tsx b/apps/web/src/stories/Alert.stories.tsx index 156d7b9..1f67966 100644 --- a/apps/web/src/stories/Alert.stories.tsx +++ b/apps/web/src/stories/Alert.stories.tsx @@ -5,7 +5,7 @@ import { useState } from "react"; const meta: Meta = { title: "Components/Alert", - tags: ["autofocus"], + tags: ["autodocs"], component: Alert, parameters: { controls: { expanded: true }, diff --git a/apps/web/src/stories/Button.stories.tsx b/apps/web/src/stories/Button.stories.tsx index fe736f9..62930a4 100644 --- a/apps/web/src/stories/Button.stories.tsx +++ b/apps/web/src/stories/Button.stories.tsx @@ -1,14 +1,15 @@ -import type { Meta, StoryFn, StoryObj } from "@storybook/react"; - -import { Button } from "./Button"; +import { ArrowRightIcon } from "@heroicons/react/24/solid"; +import Button from "@repo/ui/button"; +import type { Meta, StoryFn } from "@storybook/react"; export default { title: "Components/Button", + tags: ["autodocs"], component: Button, argTypes: { variant: { control: "select", - options: ["primary", "secondary", "danger"], + options: ["primary", "secondary"], description: "Controls the button style variant", }, size: { @@ -33,22 +34,17 @@ export default { const Template: StoryFn = (args) => + + ))} + + ); +}; diff --git a/apps/web/src/stories/dataCard.stories.tsx b/apps/web/src/stories/dataCard.stories.tsx new file mode 100644 index 0000000..2ca14f6 --- /dev/null +++ b/apps/web/src/stories/dataCard.stories.tsx @@ -0,0 +1,62 @@ +import { DataCard } from "@repo/ui/dataCard"; +import type { Meta, StoryFn } from "@storybook/react"; +import React from "react"; + +export default { + title: "Components/DataCard", + tags: ["autodocs"], + component: DataCard, + argTypes: { + label: { + control: "text", + description: "The label displayed on the card.", + defaultValue: "Label", + }, + value: { + control: "text", + description: "The value displayed on the card.", + defaultValue: "Value", + }, + iconSrc: { + control: "text", + description: "The source URL for the icon image.", + defaultValue: "/images/placeholder.svg", + }, + variant: { + control: "select", + options: ["default", "error"], + description: "The visual variant of the card.", + defaultValue: "default", + }, + }, +} as Meta; + +const Template: StoryFn = (args) => ( +
+ +
+); + +export const Default = Template.bind({}); +Default.args = { + label: "Default Label", + value: "Default Value", + iconSrc: "https://via.placeholder.com/250", + variant: "default", +}; + +export const ErrorCard = Template.bind({}); +ErrorCard.args = { + label: "Error Label", + value: "Error Value", + iconSrc: "https://via.placeholder.com/250", + variant: "error", +}; + +export const CustomIcon = Template.bind({}); +CustomIcon.args = { + label: "Custom Icon Label", + value: "Custom Icon Value", + iconSrc: "https://via.placeholder.com/250", + variant: "default", +}; diff --git a/apps/web/src/stories/typography.stories.tsx b/apps/web/src/stories/typography.stories.tsx new file mode 100644 index 0000000..12b95c0 --- /dev/null +++ b/apps/web/src/stories/typography.stories.tsx @@ -0,0 +1,44 @@ +import { + H1, + H2, + H3, + H4, + Text, + TextLegend, + TextSecondary, +} from "@repo/ui/typography"; +import type { Meta } from "@storybook/react"; +import React from "react"; + +export default { + title: "Components/Typography", + tags: ["autodocs"], + argTypes: { + className: { + control: "text", + description: "Additional classes to style the components.", + defaultValue: "", + }, + isSemiBold: { + control: "boolean", + description: + "Sets the font weight to semi-bold (only applicable for Text).", + defaultValue: false, + }, + }, +} as Meta; + +export const TypographyShowcase = ({ className = "", isSemiBold = false }) => ( +
+

This is an H1 Heading

+

This is an H2 Heading

+

This is an H3 Heading

+

This is an H4 Heading

+ + This is a paragraph.{" "} + {isSemiBold ? "It's semi-bold." : "It's normal weight."} + + This is secondary text. + This is legend text. +
+);