diff --git a/apps/storybook/.gitignore b/apps/storybook/.gitignore index 8c444bd2f4..5689902ae1 100644 --- a/apps/storybook/.gitignore +++ b/apps/storybook/.gitignore @@ -8,7 +8,9 @@ pnpm-debug.log* lerna-debug.log* node_modules -storybook-static +storybook-static/* +!storybook-static/favicon.ico +!storybook-static/sb-cover.jpg dist dist-ssr *.local diff --git a/apps/storybook/.storybook/main.js b/apps/storybook/.storybook/main.ts similarity index 66% rename from apps/storybook/.storybook/main.js rename to apps/storybook/.storybook/main.ts index 5fa1ab07ce..bc68cb15c0 100644 --- a/apps/storybook/.storybook/main.js +++ b/apps/storybook/.storybook/main.ts @@ -1,14 +1,16 @@ -import { dirname, join } from "path"; +import type { StorybookConfig } from "@storybook/nextjs"; +import path, { dirname, join } from "path"; -const path = require("path"); - -module.exports = { +const config: StorybookConfig = { stories: [ "../intro.stories.mdx", - "../../../packages/ui/components/**/*.stories.mdx", - "../../../packages/atoms/**/*.stories.mdx", - "../../../packages/features/**/*.stories.mdx", + "../../../packages/ui/components/**/*.stories.mdx", // legacy SB6 stories "../../../packages/ui/components/**/*.stories.@(js|jsx|ts|tsx)", + "../../../packages/ui/components/**/*.docs.mdx", + "../../../packages/features/**/*.stories.@(js|jsx|ts|tsx)", + "../../../packages/features/**/*.docs.mdx", + "../../../packages/atoms/**/*.stories.@(js|jsx|ts|tsx)", + "../../../packages/atoms/**/*.docs.mdx", ], addons: [ @@ -17,23 +19,23 @@ module.exports = { getAbsolutePath("@storybook/addon-interactions"), getAbsolutePath("storybook-addon-rtl-direction"), getAbsolutePath("storybook-react-i18next"), - getAbsolutePath("@storybook/addon-mdx-gfm"), ], framework: { - name: getAbsolutePath("@storybook/nextjs"), + name: getAbsolutePath("@storybook/nextjs") as "@storybook/nextjs", options: { - builder: { - fsCache: true, - lazyCompilation: true, - }, + // builder: { + // fsCache: true, + // lazyCompilation: true, + // }, }, }, staticDirs: ["../public"], webpackFinal: async (config, { configType }) => { + config.resolve = config.resolve || {}; config.resolve.fallback = { fs: false, assert: false, @@ -61,6 +63,8 @@ module.exports = { zlib: false, }; + config.module = config.module || {}; + config.module.rules = config.module.rules || []; config.module.rules.push({ test: /\.css$/, use: [ @@ -85,6 +89,8 @@ module.exports = { }, }; +export default config; + function getAbsolutePath(value) { return dirname(require.resolve(join(value, "package.json"))); } diff --git a/apps/storybook/.storybook/preview.jsx b/apps/storybook/.storybook/preview.jsx deleted file mode 100644 index 0ff662d639..0000000000 --- a/apps/storybook/.storybook/preview.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import { I18nextProvider } from "react-i18next"; - -import "../styles/globals.css"; -import "../styles/storybook-styles.css"; -import i18n from "./i18next"; - -export const parameters = { - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, - }, - }, - - globals: { - locale: "en", - locales: { - en: "English", - fr: "Français", - }, - }, - i18n, -}; - -const withI18next = (Story) => ( - -
- -
-
-); - -export const decorators = [withI18next]; - -window.getEmbedNamespace = () => { - const url = new URL(document.URL); - const namespace = url.searchParams.get("embed"); - return namespace; -}; - -window.getEmbedTheme = () => { - return "auto"; -}; diff --git a/apps/storybook/.storybook/preview.tsx b/apps/storybook/.storybook/preview.tsx new file mode 100644 index 0000000000..620f7a9ff6 --- /dev/null +++ b/apps/storybook/.storybook/preview.tsx @@ -0,0 +1,73 @@ +// adds tooltip context to all stories +import { TooltipProvider } from "@radix-ui/react-tooltip"; +import type { Preview } from "@storybook/react"; +import React from "react"; +import { I18nextProvider } from "react-i18next"; + +import type { EmbedThemeConfig } from "@calcom/embed-core/src/types"; +// adds trpc context to all stories (esp. booker) +import { StorybookTrpcProvider } from "@calcom/ui"; + +import "../styles/globals.css"; +import "../styles/storybook-styles.css"; +import i18n from "./i18next"; + +const preview: Preview = { + parameters: { + actions: { argTypesRegex: "^on[A-Z].*" }, + + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + + globals: { + locale: "en", + locales: { + en: "English", + fr: "Français", + }, + }, + + i18n, + + nextjs: { + appDirectory: true, + }, + }, + + decorators: [ + (Story) => ( + + + +
+ +
+
+
+
+ ), + ], +}; + +export default preview; + +declare global { + interface Window { + getEmbedNamespace: () => string | null; + getEmbedTheme: () => EmbedThemeConfig | null; + } +} + +window.getEmbedNamespace = () => { + const url = new URL(document.URL); + const namespace = url.searchParams.get("embed"); + return namespace; +}; + +window.getEmbedTheme = () => { + return "auto"; +}; diff --git a/apps/storybook/components/CustomArgsTable.tsx b/apps/storybook/components/CustomArgsTable.tsx index e8feabf577..1bb51bbdd9 100644 --- a/apps/storybook/components/CustomArgsTable.tsx +++ b/apps/storybook/components/CustomArgsTable.tsx @@ -1,6 +1,6 @@ import { ArgsTable } from "@storybook/addon-docs"; -import { SortType } from "@storybook/components"; -import { PropDescriptor } from "@storybook/store"; +import type { SortType } from "@storybook/blocks"; +import type { PropDescriptor } from "@storybook/preview-api"; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ignore storybook addon types component as any so we have to do type Component = any; diff --git a/apps/storybook/package.json b/apps/storybook/package.json index 1b16a80ca3..0cc7d6cb30 100644 --- a/apps/storybook/package.json +++ b/apps/storybook/package.json @@ -20,7 +20,10 @@ "@radix-ui/react-slider": "^1.0.0", "@radix-ui/react-switch": "^1.0.0", "@radix-ui/react-tooltip": "^1.0.0", + "@storybook/addon-docs": "^7.6.3", + "@storybook/blocks": "^7.6.3", "@storybook/nextjs": "^7.6.3", + "@storybook/preview-api": "^7.6.3", "next": "^13.4.6", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -33,7 +36,6 @@ "@storybook/addon-essentials": "^7.6.3", "@storybook/addon-interactions": "^7.6.3", "@storybook/addon-links": "^7.6.3", - "@storybook/addon-mdx-gfm": "^7.6.3", "@storybook/nextjs": "^7.6.3", "@storybook/react": "^7.6.3", "@storybook/testing-library": "^0.2.2", diff --git a/packages/atoms/booker/Booker.docs.mdx b/packages/atoms/booker/Booker.docs.mdx new file mode 100644 index 0000000000..f92c09c954 --- /dev/null +++ b/packages/atoms/booker/Booker.docs.mdx @@ -0,0 +1,12 @@ +import { Meta, Canvas, ArgsTable } from "@storybook/blocks"; +import { Title } from "@calcom/storybook/components"; +import { Booker } from "./Booker"; +import * as BookerStories from "./Booker.stories"; + + + + + +<ArgsTable of={Booker} /> + +<Canvas of={BookerStories.Default}/> diff --git a/packages/atoms/booker/Booker.stories.tsx b/packages/atoms/booker/Booker.stories.tsx new file mode 100644 index 0000000000..ab485daa3f --- /dev/null +++ b/packages/atoms/booker/Booker.stories.tsx @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { Booker } from "./Booker"; + +const meta: Meta<typeof Booker> = { + component: Booker, + title: "Atoms/Booker", +}; + +export default meta; +type Story = StoryObj<typeof Booker>; + +export const Default: Story = { + name: "Booker", + render: () => <Booker username="pro" eventSlug="" entity={{}} />, +}; diff --git a/packages/atoms/booker/booker.stories.mdx b/packages/atoms/booker/booker.stories.mdx deleted file mode 100644 index 1a9021ec8e..0000000000 --- a/packages/atoms/booker/booker.stories.mdx +++ /dev/null @@ -1,16 +0,0 @@ -import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs"; - -import { Title } from "@calcom/storybook/components"; -import { Icon } from "@calcom/ui"; - -import { Booker } from "./Booker"; - -<Meta title="Atoms/Booker" component={Booker} /> - -<Title title="Booker" /> - -<Canvas> - <Story name="Booker"> - <Booker username="pro" /> - </Story> -</Canvas> diff --git a/packages/features/bookings/components/VerifyCodeDialog.docs.mdx b/packages/features/bookings/components/VerifyCodeDialog.docs.mdx new file mode 100644 index 0000000000..ab7d72009d --- /dev/null +++ b/packages/features/bookings/components/VerifyCodeDialog.docs.mdx @@ -0,0 +1,24 @@ +import { Canvas, Meta } from "@storybook/blocks"; + +import { Title, CustomArgsTable } from "@calcom/storybook/components"; + +import { VerifyCodeDialog } from "./VerifyCodeDialog"; +import * as VerifyCodeDialogStories from "./VerifyCodeDialog.stories"; + +<Meta of={VerifyCodeDialogStories} /> + +<Title title="VerifyCodeDialog" suffix="Brief" subtitle="Version 1.0 — Last Update: 11 Sep 2023" /> + +## Definition + +The `VerifyCodeDialog` component allows users to enter a verification code sent to their email. The component provides feedback in case of an error and can handle different verification processes depending on whether the user session is required. + +## Structure + +This component contains an input form to capture a 6-digit verification code, error handling UI, and action buttons. + +<CustomArgsTable of={VerifyCodeDialog} /> + +{/* ## VerifyCodeDialog Story + +<Canvas of={VerifyCodeDialogStories.Default} /> */} diff --git a/packages/features/bookings/components/VerifyCodeDialog.stories.tsx b/packages/features/bookings/components/VerifyCodeDialog.stories.tsx new file mode 100644 index 0000000000..d58e7604ae --- /dev/null +++ b/packages/features/bookings/components/VerifyCodeDialog.stories.tsx @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import type { ComponentProps } from "react"; + +import { StorybookTrpcProvider } from "@calcom/ui"; + +import { VerifyCodeDialog } from "./VerifyCodeDialog"; + +type StoryArgs = ComponentProps<typeof VerifyCodeDialog>; + +const meta: Meta<StoryArgs> = { + component: VerifyCodeDialog, + title: "Features/VerifyCodeDialog", + argTypes: { + isOpenDialog: { control: "boolean", description: "Indicates whether the dialog is open or not." }, + setIsOpenDialog: { action: "setIsOpenDialog", description: "Function to set the dialog state." }, + email: { control: "text", description: "Email to which the verification code was sent." }, + onSuccess: { action: "onSuccess", description: "Callback function when verification succeeds." }, + // onError: { action: "onError", description: "Callback function when verification fails." }, + isUserSessionRequiredToVerify: { + control: "boolean", + description: "Indicates if user session is required for verification.", + }, + }, + decorators: [ + (Story) => ( + <StorybookTrpcProvider> + <Story /> + </StorybookTrpcProvider> + ), + ], + render: (args) => <VerifyCodeDialog {...args} />, +}; + +export default meta; +type Story = StoryObj<StoryArgs>; + +export const Default: Story = { + name: "Dialog", + args: { + isOpenDialog: true, + email: "example@email.com", + // onError: (err) => { + // if (err.message === "invalid_code") { + // alert("Code provided is invalid"); + // } + // }, + }, +}; diff --git a/packages/features/bookings/components/event-meta/EventMeta.docs.mdx b/packages/features/bookings/components/event-meta/EventMeta.docs.mdx new file mode 100644 index 0000000000..7740319317 --- /dev/null +++ b/packages/features/bookings/components/event-meta/EventMeta.docs.mdx @@ -0,0 +1,13 @@ +import { Canvas, Meta } from "@storybook/blocks"; + +import { Title } from "@calcom/storybook/components"; + +import * as EventMetaStories from "./EventMeta.stories"; + +<Meta of={EventMetaStories} /> + +<Title title="Event Meta" suffix="Brief" subtitle="Version 2.0 — Last Update: 12 Dec 2022" /> + +<Canvas of={EventMetaStories.ExampleStory} /> + +<Canvas of={EventMetaStories.AllVariants} /> diff --git a/packages/features/bookings/components/event-meta/EventMeta.stories.mdx b/packages/features/bookings/components/event-meta/EventMeta.stories.mdx deleted file mode 100644 index 58c169224f..0000000000 --- a/packages/features/bookings/components/event-meta/EventMeta.stories.mdx +++ /dev/null @@ -1,59 +0,0 @@ -import { TooltipProvider } from "@radix-ui/react-tooltip"; -import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs"; - -import { - Examples, - Example, - Note, - Title, - VariantsTable, - VariantColumn, - RowTitles, - CustomArgsTable, - VariantRow, -} from "@calcom/storybook/components"; -import { Icon } from "@calcom/ui"; - -import { EventDetails } from "./Details"; -import { EventMembers } from "./Members"; -import { EventTitle } from "./Title"; -import { mockEvent } from "./event.mock.ts"; - -<Meta title="Features/Events/Meta" component={EventDetails} /> - -<Title title="Event Meta" suffix="Brief" subtitle="Version 2.0 — Last Update: 12 Dec 2022" /> -<TooltipProvider> - <Examples title="Combined event meta block"> - <div style={{ maxWidth: 300 }}> - <Example title="Event Title"> - <EventTitle event={mockEvent} /> - </Example> - <Example title="Event Details"> - <EventDetails event={mockEvent} /> - </Example> - </div> - </Examples> -</TooltipProvider> - -<Canvas> - <Story name="All variants"> - <VariantsTable titles={["Event Meta Components"]} columnMinWidth={150}> - <VariantRow variant=""> - <div style={{ maxWidth: 300 }}> - <TooltipProvider> - <EventMembers - entity={{ name: "entityName" }} - profile={{ name: "profileName" }} - users={[ - { name: "Pro example", username: "pro" }, - { name: "Team example", username: "team" }, - ]} - /> - <EventTitle>Quick catch-up</EventTitle> - <EventDetails event={mockEvent} /> - </TooltipProvider> - </div> - </VariantRow> - </VariantsTable> - </Story> -</Canvas> diff --git a/packages/features/bookings/components/event-meta/EventMeta.stories.tsx b/packages/features/bookings/components/event-meta/EventMeta.stories.tsx new file mode 100644 index 0000000000..9bb5d2c284 --- /dev/null +++ b/packages/features/bookings/components/event-meta/EventMeta.stories.tsx @@ -0,0 +1,62 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import type { PublicEvent } from "bookings/types"; +import type { ComponentProps } from "react"; + +import { Examples, Example, VariantsTable, VariantRow } from "@calcom/storybook/components"; + +import { EventDetails } from "./Details"; +import { EventMembers } from "./Members"; +import { EventTitle } from "./Title"; +import { mockEvent } from "./event.mock"; + +type StoryArgs = ComponentProps<typeof EventDetails>; + +const meta: Meta<StoryArgs> = { + component: EventDetails, + parameters: { + nextjs: { + appDirectory: true, + }, + }, + title: "Features/Events/Meta", +}; + +export default meta; +type Story = StoryObj<StoryArgs>; + +export const ExampleStory: Story = { + name: "Examples", + render: () => ( + <Examples title="Combined event meta block"> + <div style={{ maxWidth: 300 }}> + <Example title="Event Title"> + <EventTitle>{mockEvent.title}</EventTitle> + </Example> + <Example title="Event Details"> + <EventDetails event={mockEvent} /> + </Example> + </div> + </Examples> + ), +}; + +export const AllVariants: Story = { + name: "All variants", + render: () => ( + <VariantsTable titles={["Event Meta Components"]} columnMinWidth={150}> + <VariantRow variant=""> + <div style={{ maxWidth: 300 }}> + <EventMembers + users={mockEvent.users} + schedulingType="COLLECTIVE" + entity={{ isUnpublished: false, name: "Example", orgSlug: null }} + // TODO remove type assertion + profile={{ weekStart: "Sunday" } as PublicEvent["profile"]} + /> + <EventTitle>Quick catch-up</EventTitle> + <EventDetails event={mockEvent} /> + </div> + </VariantRow> + </VariantsTable> + ), +}; diff --git a/packages/features/bookings/components/event-meta/event.mock.ts b/packages/features/bookings/components/event-meta/event.mock.ts index 1bbff1ff57..100e1b0fe0 100644 --- a/packages/features/bookings/components/event-meta/event.mock.ts +++ b/packages/features/bookings/components/event-meta/event.mock.ts @@ -1,14 +1,17 @@ -import type { RouterOutputs } from "@calcom/trpc/react"; +import type { PublicEvent } from "bookings/types"; -export const mockEvent: RouterOutputs["viewer"]["public"]["event"] = { +export const mockEvent: PublicEvent = { id: 1, title: "Quick check-in", slug: "quick-check-in", eventName: "Quick check-in", description: "Use this event for a quick 15 minute catchup. Visit this long url to test the component https://cal.com/averylongurlwithoutspacesthatshouldntbreaklayout", - users: [{ name: "Pro Example", username: "pro" }], + users: [ + { name: "Pro example", username: "pro", weekStart: "Sunday", organizationId: null }, + { name: "Team example", username: "team", weekStart: "Sunday", organizationId: 1 }, + ], schedulingType: null, length: 30, locations: [{ type: "integrations:google:meet" }, { type: "integrations:zoom" }], -}; +} as PublicEvent; // TODO: complete mock and remove type assertion diff --git a/packages/features/bookings/components/verifyCodeDialog.stories.mdx b/packages/features/bookings/components/verifyCodeDialog.stories.mdx deleted file mode 100644 index 6083512999..0000000000 --- a/packages/features/bookings/components/verifyCodeDialog.stories.mdx +++ /dev/null @@ -1,60 +0,0 @@ -import { Canvas, Meta, Story } from "@storybook/addon-docs"; - -import { Title, CustomArgsTable } from "@calcom/storybook/components"; - -import { StorybookTrpcProvider } from "../../../ui/components/mocks/trpc.tsx"; -import { VerifyCodeDialog } from "./VerifyCodeDialog"; - -<Meta title="Features/VerifyCodeDialog" component={VerifyCodeDialog} /> - -<Title title="VerifyCodeDialog" suffix="Brief" subtitle="Version 1.0 — Last Update: 11 Sep 2023" /> - -## Definition - -The `VerifyCodeDialog` component allows users to enter a verification code sent to their email. The component provides feedback in case of an error and can handle different verification processes depending on whether the user session is required. - -## Structure - -This component contains an input form to capture a 6-digit verification code, error handling UI, and action buttons. - -<CustomArgsTable of={VerifyCodeDialog} /> - -## VerifyCodeDialog Story - -<Canvas> - <Story - name="VerifyCodeDialog" - parameters={{ - nextjs: { - appDirectory: true, - }, - }} - args={{ - isOpenDialog: true, - setIsOpenDialog: () => {}, - email: "example@email.com", - onSuccess: () => {}, - onError: (err) => { - if (err.message === "invalid_code") { - alert("Code provided is invalid"); - } - }, - }} - argTypes={{ - isOpenDialog: { control: "boolean", description: "Indicates whether the dialog is open or not." }, - setIsOpenDialog: { action: "setIsOpenDialog", description: "Function to set the dialog state." }, - email: { control: "text", description: "Email to which the verification code was sent." }, - onSuccess: { action: "onSuccess", description: "Callback function when verification succeeds." }, - onError: { action: "onError", description: "Callback function when verification fails." }, - isUserSessionRequiredToVerify: { - control: "boolean", - description: "Indicates if user session is required for verification.", - }, - }}> - {(args) => ( - <StorybookTrpcProvider> - <VerifyCodeDialog {...args} /> - </StorybookTrpcProvider> - )} - </Story> -</Canvas> diff --git a/packages/ui/components/badge/badge.stories.mdx b/packages/ui/components/badge/badge.stories.mdx index f456c3cb97..03268a037e 100644 --- a/packages/ui/components/badge/badge.stories.mdx +++ b/packages/ui/components/badge/badge.stories.mdx @@ -15,7 +15,7 @@ import { Badge } from "./Badge"; <Meta title="UI/Badge" component={Badge} /> -<Title title="Bages" suffix="Brief" subtitle="Version 2.0 — Last Update: 22 Aug 2022" /> +<Title title="Badge" suffix="Brief" subtitle="Version 2.0 — Last Update: 22 Aug 2022" /> ## Definition diff --git a/packages/ui/components/breadcrumb/breadcrumb.stories.mdx b/packages/ui/components/breadcrumb/breadcrumb.stories.mdx index 8fbd56164d..25fddfa8d1 100644 --- a/packages/ui/components/breadcrumb/breadcrumb.stories.mdx +++ b/packages/ui/components/breadcrumb/breadcrumb.stories.mdx @@ -2,7 +2,7 @@ import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs"; import { Examples, Example, Note, Title, CustomArgsTable } from "@calcom/storybook/components"; -import { Breadcrumb } from "./Breadcrumb"; +import { Breadcrumb, BreadcrumbItem } from "./Breadcrumb"; <Meta title="UI/Breadcrumbs" component={Breadcrumb} /> diff --git a/packages/ui/components/dialog/Dialog.docs.mdx b/packages/ui/components/dialog/Dialog.docs.mdx new file mode 100644 index 0000000000..eef8469f8a --- /dev/null +++ b/packages/ui/components/dialog/Dialog.docs.mdx @@ -0,0 +1,52 @@ +import { Meta } from "@storybook/blocks"; +import { Title, CustomArgsTable } from "@calcom/storybook/components"; +import { Dialog, DialogContent, DialogFooter, DialogClose, DialogHeader } from "./Dialog"; +import * as DialogStories from "./Dialog.stories"; + +<Meta of={DialogStories} /> + +<Title title="Dialog" suffix="Brief" subtitle="Version 1.0 — Last Update: 18 Aug 2023" /> + +## Definition + +The `Dialog` component provides a flexible way to create dialogs in your application. + +## Structure + +The `Dialog` component is composed of the following components: + +- `Dialog`: The main component that wraps the entire dialog. It manages the dialog's open and close states. + +- `DialogContent`: Represents the content of the dialog. It can have different sizes, types, and an optional icon. + +- `DialogHeader`: Renders the header of the dialog, including the title and subtitle. + +- `DialogFooter`: Renders the footer of the dialog, which can contain action buttons. + +- `DialogClose`: Renders a close button for the dialog. + +## Components Arguments + +### Dialog + +<CustomArgsTable of={Dialog} /> + +### DialogContent + +<CustomArgsTable of={DialogContent} /> + +### DialogHeader + +<CustomArgsTable of={DialogHeader} /> + +### DialogFooter + +<CustomArgsTable of={DialogFooter} /> + +### DialogClose + +<CustomArgsTable of={DialogClose} /> + +{/* ## Dialog Story + +<Canvas of={DialogStories.Default}/> */} diff --git a/packages/ui/components/dialog/Dialog.stories.tsx b/packages/ui/components/dialog/Dialog.stories.tsx new file mode 100644 index 0000000000..71abf446ab --- /dev/null +++ b/packages/ui/components/dialog/Dialog.stories.tsx @@ -0,0 +1,87 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import type { ComponentProps } from "react"; + +import { Dialog, DialogContent, DialogFooter, DialogClose, DialogHeader } from "./Dialog"; + +type StoryArgs = ComponentProps<typeof Dialog> & + ComponentProps<typeof DialogContent> & + ComponentProps<typeof DialogHeader> & + ComponentProps<typeof DialogFooter> & + ComponentProps<typeof DialogClose> & { + onClick: (...args: unknown[]) => void; + }; + +const meta: Meta<StoryArgs> = { + component: Dialog, + parameters: { + nextjs: { + appDirectory: true, + }, + }, + title: "UI/Dialog", + argTypes: { + title: { + control: "text", + }, + description: { + control: "text", + }, + type: { + options: ["creation", "confirmation"], + control: { + type: "select", + }, + }, + open: { + control: "boolean", + }, + showDivider: { + control: "boolean", + }, + disabled: { + control: "boolean", + }, + color: { + options: ["minimal", "primary", "secondary", "emphasis"], + control: { + type: "select", + }, + }, + onClick: { action: "clicked" }, // this is a storybook action addons action + }, + render: ({ title, description, type, open, showDivider, disabled, color, onClick }) => ( + <Dialog open={open}> + <DialogContent type={type}> + <DialogHeader title={title} subtitle={description} /> + <DialogFooter showDivider={showDivider}> + <DialogClose + disabled={disabled} + color={color} + onClick={() => { + const currentUrl = new URL(window.location.href); + currentUrl.searchParams.set("args", "open:false"); + window.open(currentUrl.toString(), "_self"); + onClick(); + }} + /> + </DialogFooter> + </DialogContent> + </Dialog> + ), +}; + +export default meta; +type Story = StoryObj<StoryArgs>; + +export const Default: Story = { + name: "Dialog", + args: { + title: "Example Dialog", + description: "Example Dialog Description", + type: "creation", + open: true, + showDivider: false, + disabled: false, + color: "minimal", + }, +}; diff --git a/packages/ui/components/dialog/dialog.stories.mdx b/packages/ui/components/dialog/dialog.stories.mdx deleted file mode 100644 index a3ab15df0f..0000000000 --- a/packages/ui/components/dialog/dialog.stories.mdx +++ /dev/null @@ -1,119 +0,0 @@ -import { Canvas, Meta, Story } from "@storybook/addon-docs"; - -import { Title, CustomArgsTable } from "@calcom/storybook/components"; - -import { Dialog, DialogContent, DialogFooter, DialogClose, DialogHeader } from "./Dialog"; - -<Meta title="UI/Dialog" component={Dialog} /> - -<Title title="Dialog" suffix="Brief" subtitle="Version 1.0 — Last Update: 18 Aug 2023" /> - -## Definition - -The `Dialog` component provides a flexible way to create dialogs in your application. - -## Structure - -The `Dialog` component is composed of the following components: - -- `Dialog`: The main component that wraps the entire dialog. It manages the dialog's open and close states. - -- `DialogContent`: Represents the content of the dialog. It can have different sizes, types, and an optional icon. - -- `DialogHeader`: Renders the header of the dialog, including the title and subtitle. - -- `DialogFooter`: Renders the footer of the dialog, which can contain action buttons. - -- `DialogClose`: Renders a close button for the dialog. - -## Components Arguments - -### Dialog - -<CustomArgsTable of={Dialog} /> - -### DialogContent - -<CustomArgsTable of={DialogContent} /> - -### DialogHeader - -<CustomArgsTable of={DialogHeader} /> - -### DialogFooter - -<CustomArgsTable of={DialogFooter} /> - -### DialogClose - -<CustomArgsTable of={DialogClose} /> - -## Dialog Story - -<Canvas> - <Story - name="Dialog" - parameters={{ - nextjs: { - appDirectory: true, - }, - }} - args={{ - title: "Example Dialog", - description: "Example Dialog Description", - type: "creation", - open: true, - showDivider: false, - disabled: false, - color: "minimal", - }} - argTypes={{ - title: { - control: "text", - }, - description: { - control: "text", - }, - type: { - control: { - type: "select", - options: ["creation", "confirmation"], - }, - }, - open: { - control: "boolean", - }, - showDivider: { - control: "boolean", - }, - disabled: { - control: "boolean", - }, - color: { - control: { - type: "select", - options: ["minimal", "primary", "secondary", "emphasis"], - }, - }, - onClick: { action: "clicked" }, - }}> - {({ title, description, type, open, showDivider, disabled, color, onClick }) => ( - <Dialog title="Default" open={open}> - <DialogContent type={type}> - <DialogHeader title={title} subtitle={description} /> - <DialogFooter showDivider={showDivider}> - <DialogClose - disabled={disabled} - color={color} - onClick={() => { - const newPath = "?path=/story/ui-dialog--dialog&args=open:false"; - window.open(newPath, "_self"); - onClick(); - }} - /> - </DialogFooter> - </DialogContent> - </Dialog> - )} - </Story> -</Canvas> diff --git a/packages/ui/components/form/color-picker/colorpicker.stories.mdx b/packages/ui/components/form/color-picker/colorpicker.stories.mdx index 797c4c3f86..a3b7213c1e 100644 --- a/packages/ui/components/form/color-picker/colorpicker.stories.mdx +++ b/packages/ui/components/form/color-picker/colorpicker.stories.mdx @@ -1,7 +1,4 @@ -import { TooltipProvider } from "@radix-ui/react-tooltip"; -import { - Tooltip, -} from "@calcom/ui"; +import { Tooltip } from "@radix-ui/react-tooltip"; import { Canvas, Meta, Story } from "@storybook/addon-docs"; import { @@ -69,17 +66,15 @@ The `Color Picker` takes in several props {({ defaultValue, onChange, resetDefaultValue, className, popoverAlign }) => ( <VariantsTable titles={["Default"]} columnMinWidth={150}> <VariantRow> - <TooltipProvider> - <Tooltip content="color picker"> - <ColorPicker - defaultValue={defaultValue} - onChange={onChange} - resetDefaultValue={resetDefaultValue} - className={className} - popoverAlign={popoverAlign} - /> - </Tooltip> - </TooltipProvider> + <Tooltip content="color picker"> + <ColorPicker + defaultValue={defaultValue} + onChange={onChange} + resetDefaultValue={resetDefaultValue} + className={className} + popoverAlign={popoverAlign} + /> + </Tooltip> </VariantRow> </VariantsTable> )} diff --git a/packages/ui/components/form/color-picker/colorpicker.test.tsx b/packages/ui/components/form/color-picker/colorpicker.test.tsx index 700c79ef1a..20a2411dab 100644 --- a/packages/ui/components/form/color-picker/colorpicker.test.tsx +++ b/packages/ui/components/form/color-picker/colorpicker.test.tsx @@ -48,7 +48,7 @@ describe("Tests for ColorPicker component", () => { const colorInput = screen.getByRole("textbox"); await act(async () => userEvent.clear(colorInput)); const newColorValue = "#00FF00"; - await act(async () => userEvent.type(colorInput, newColorValue)); + await act(async () => await userEvent.type(colorInput, newColorValue)); expect(screen.getByRole("button", { name: "pick colors" })).toHaveStyle( `background-color: ${newColorValue}` ); diff --git a/packages/ui/components/form/wizard/wizard.stories.mdx b/packages/ui/components/form/wizard/wizard.stories.mdx index feeee3f2dc..e31277b354 100644 --- a/packages/ui/components/form/wizard/wizard.stories.mdx +++ b/packages/ui/components/form/wizard/wizard.stories.mdx @@ -1,5 +1,4 @@ import { Canvas, Meta, Story } from "@storybook/addon-docs"; -import { useRouter } from "next/router"; import { CustomArgsTable, Title, VariantsTable, VariantRow } from "@calcom/storybook/components"; diff --git a/packages/ui/components/navigation/tabs/__stories__/verticalTabs.stories.mdx b/packages/ui/components/navigation/tabs/__stories__/verticalTabs.stories.mdx index 6b7b3ea2c6..bfc8ea9c5a 100644 --- a/packages/ui/components/navigation/tabs/__stories__/verticalTabs.stories.mdx +++ b/packages/ui/components/navigation/tabs/__stories__/verticalTabs.stories.mdx @@ -1,4 +1,4 @@ -import { Meta, Story } from "@storybook/addon-docs/blocks"; +import { Meta, Story, Canvas } from "@storybook/addon-docs/blocks"; import { Title, @@ -6,7 +6,7 @@ import { Examples, Example, VariantsTable, - VariantsRow, + VariantRow, } from "@calcom/storybook/components"; import { Plus } from "@calcom/ui/components/icon"; diff --git a/packages/ui/components/tooltip/Tooltip.docs.mdx b/packages/ui/components/tooltip/Tooltip.docs.mdx new file mode 100644 index 0000000000..fd7fe7d344 --- /dev/null +++ b/packages/ui/components/tooltip/Tooltip.docs.mdx @@ -0,0 +1,20 @@ +import { Canvas, Meta } from "@storybook/blocks"; +import { Title, CustomArgsTable } from "@calcom/storybook/components"; +import { TooltipProvider } from "@radix-ui/react-tooltip"; +import { Tooltip } from "./Tooltip"; + +import * as TooltipStories from "./Tooltip.stories"; + +<Meta of={TooltipStories} /> + +<Title title="Tooltip" suffix="Brief" subtitle="Version 2.0 — Last Update: 06 Jan 2023" /> + +## Definition + +Tooltip components can be used to provide additional information about an element when the user hovers over or focuses on the element. + +<TooltipProvider> + <CustomArgsTable of={Tooltip} /> +</TooltipProvider> + +<Canvas of={TooltipStories.Default}/> diff --git a/packages/ui/components/tooltip/Tooltip.stories.tsx b/packages/ui/components/tooltip/Tooltip.stories.tsx new file mode 100644 index 0000000000..f7d79d1f47 --- /dev/null +++ b/packages/ui/components/tooltip/Tooltip.stories.tsx @@ -0,0 +1,37 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { VariantRow, VariantsTable } from "@calcom/storybook/components"; + +import { Tooltip } from "./Tooltip"; + +const meta: Meta<typeof Tooltip> = { + component: Tooltip, + title: "UI/Tooltip", +}; + +export default meta; +type Story = StoryObj<typeof Tooltip>; + +export const Default: Story = { + name: "Tooltip", + parameters: { + hoverMsg: "Click to copy", + alertMsg: "Copied!", + content: "Copy me!", + }, + render: (_, { parameters: { content, hoverMsg, alertMsg } }) => ( + <VariantsTable titles={[]}> + <VariantRow variant="Default"> + <Tooltip content={`${hoverMsg}`}> + <span + className="dark:text-darkgray-50 bg-brand-default dark:bg-darkgray-900 rounded-md p-2 text-gray-100 hover:cursor-pointer" + onClick={() => { + alert(`${alertMsg}`); + }}> + {content} + </span> + </Tooltip> + </VariantRow> + </VariantsTable> + ), +}; diff --git a/packages/ui/components/tooltip/tooltip.stories.mdx b/packages/ui/components/tooltip/tooltip.stories.mdx deleted file mode 100644 index a70c518c39..0000000000 --- a/packages/ui/components/tooltip/tooltip.stories.mdx +++ /dev/null @@ -1,69 +0,0 @@ -import { TooltipProvider } from "@radix-ui/react-tooltip"; -import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs"; - -import { - Examples, - Example, - Note, - Title, - CustomArgsTable, - VariantsTable, - VariantRow, -} from "@calcom/storybook/components"; - -import Tooltip from "./Tooltip"; - -<Meta title="UI/Tooltip" component={Tooltip} /> - -<Title title="Tooltip" suffix="Brief" subtitle="Version 2.0 — Last Update: 06 Jan 2023" /> - -## Definition - -Tooltip components can be used to provide additional information about an element when the user hovers over or focuses on the element. - -<CustomArgsTable of={Tooltip} /> - -<Canvas> - <Story - name="Tooltip" - args={{ - alertMsg: "Copied!", - hoverMsg: "Copy to clipboard", - content: "Hover Me", - }} - argTypes={{ - alertMsg: { - control: { - type: "text", - }, - }, - hoverMsg: { - control: { - type: "text", - }, - }, - content: { - control: { - type: "text", - }, - }, - }}> - {({ alertMsg, hoverMsg, content }) => ( - <TooltipProvider> - <VariantsTable titles={[""]} columnMinWidth={150}> - <VariantRow variant="Default"> - <Tooltip content={`${hoverMsg}`}> - <span - className="dark:text-darkgray-50 bg-brand-default dark:bg-darkgray-900 rounded-md p-2 text-gray-100 hover:cursor-pointer" - onClick={() => { - alert(`${alertMsg}`); - }}> - {content} - </span> - </Tooltip> - </VariantRow> - </VariantsTable> - </TooltipProvider> - )} - </Story> -</Canvas> diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index c0922cb2aa..c7f60603cd 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -164,3 +164,5 @@ export { } from "./components/command"; export { Popover, PopoverContent, PopoverTrigger } from "./components/popover"; + +export { StorybookTrpcProvider } from "./components/mocks/trpc"; diff --git a/packages/ui/package.json b/packages/ui/package.json index 7e44b2f922..ef421807d4 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -31,6 +31,8 @@ "@radix-ui/react-portal": "^1.0.0", "@radix-ui/react-select": "^0.1.1", "@react-icons/all-files": "^4.1.0", + "@storybook/blocks": "^7.6.3", + "@storybook/react": "^7.6.3", "@tanstack/react-query": "^4.3.9", "@tanstack/react-table": "^8.9.3", "@wojtekmaj/react-daterange-picker": "^3.3.1",