diff --git a/govtool/frontend/.storybook/preview.tsx b/govtool/frontend/.storybook/preview.tsx index f3deaefc6..406ac7970 100644 --- a/govtool/frontend/.storybook/preview.tsx +++ b/govtool/frontend/.storybook/preview.tsx @@ -1,8 +1,12 @@ +import React from "react"; import type { Preview } from "@storybook/react"; import { ThemeProvider } from "@emotion/react"; import { theme } from "../src/theme"; import { MemoryRouter, Routes, Route } from "react-router-dom"; import { QueryClient, QueryClientProvider } from "react-query"; +import { I18nextProvider } from "react-i18next"; +import i18n from "../src/i18n"; +import { ModalProvider } from "../src/context/modal"; const queryClient = new QueryClient(); @@ -19,26 +23,30 @@ const preview: Preview = { decorators: [ (Story) => ( - - - - - - - } - /> - - - + + + + + + + + + } + /> + + + + + ), ], diff --git a/govtool/frontend/src/stories/DashboardCard.stories.ts b/govtool/frontend/src/stories/DashboardCard.stories.ts index 21bac97e4..fc47278eb 100644 --- a/govtool/frontend/src/stories/DashboardCard.stories.ts +++ b/govtool/frontend/src/stories/DashboardCard.stories.ts @@ -21,9 +21,7 @@ export const DashboardCardComponent: Story = { args: { description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit.", firstButtonLabel: "first button", - imageHeight: 80, imageURL: IMAGES.govActionDelegateImage, - imageWidth: 115, secondButtonLabel: "second button", title: "Action card", }, @@ -38,13 +36,22 @@ export const DashboardCardComponent: Story = { }, }; +export const WithDRepIdDashboardCardComponent: Story = { + args: { + description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit.", + firstButtonLabel: "first button", + imageURL: IMAGES.govActionDelegateImage, + secondButtonLabel: "second button", + title: "Action card", + cardId: "drep1gwsw9ckkhuwscj9savt5f7u9xsrudw209hne7pggcktzuw5sv32", + }, +}; + export const isLoadingDashboardCard: Story = { args: { description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit.", firstButtonLabel: "first button", - imageHeight: 80, imageURL: IMAGES.govActionDelegateImage, - imageWidth: 115, secondButtonLabel: "second button", title: "Action card", isLoading: true, @@ -62,9 +69,7 @@ export const isProgressDashboardCard: Story = { args: { description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit.", firstButtonLabel: "first button", - imageHeight: 80, imageURL: IMAGES.govActionDelegateImage, - imageWidth: 115, secondButtonLabel: "second button", title: "Action card", inProgress: true, diff --git a/govtool/frontend/src/stories/DashboardTopNav.stories.ts b/govtool/frontend/src/stories/DashboardTopNav.stories.ts index 06508f3aa..3ecbb15b7 100644 --- a/govtool/frontend/src/stories/DashboardTopNav.stories.ts +++ b/govtool/frontend/src/stories/DashboardTopNav.stories.ts @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import { DashboardTopNav } from "@organisms"; -import { IMAGES } from "@/consts"; import { within, userEvent, waitFor, screen } from "@storybook/testing-library"; import { expect } from "@storybook/jest"; @@ -15,7 +14,7 @@ export default meta; type Story = StoryObj; export const DashboardTopNavComponent: Story = { - args: { title: "Example title", isDrawer: true }, + args: { title: "Example title" }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText("Example title")).toBeInTheDocument(); @@ -31,16 +30,3 @@ export const DashboardTopNavComponent: Story = { }); }, }; - -export const DashboardTopNavWithIcon: Story = { - args: { - title: "Example title", - isDrawer: true, - imageSRC: IMAGES.appLogoWithoutText, - imageHeight: 24, - }, - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - expect(canvas.getByRole("img")).toBeInTheDocument(); - }, -}; diff --git a/govtool/frontend/src/stories/DelegateActionRadio.stories.ts b/govtool/frontend/src/stories/DelegateActionRadio.stories.ts index a05563d28..49c24295c 100644 --- a/govtool/frontend/src/stories/DelegateActionRadio.stories.ts +++ b/govtool/frontend/src/stories/DelegateActionRadio.stories.ts @@ -68,3 +68,19 @@ export const ActionRadioActive: Story = { ); }, }; + +export const ActionRadioOnlyTitle: Story = { + args: { + title: "Title", + value: "", + isChecked: false, + }, +}; + +export const ActionRadioOnlyTitleChecked: Story = { + args: { + title: "Title", + value: "", + isChecked: true, + }, +}; diff --git a/govtool/frontend/src/stories/Input.stories.tsx b/govtool/frontend/src/stories/Input.stories.tsx index cbe95a400..95a134c60 100644 --- a/govtool/frontend/src/stories/Input.stories.tsx +++ b/govtool/frontend/src/stories/Input.stories.tsx @@ -60,3 +60,8 @@ ErrorAndLabel.play = async ({ canvasElement }) => { expect(canvas.getByText("Label")).toBeInTheDocument(); expect(canvas.getByTestId("error-message-error")).toBeInTheDocument(); }; + +export const WithHelpfulText = Template.bind({}); +WithHelpfulText.args = { + helpfulText: "Helpful text", +}; diff --git a/govtool/frontend/src/stories/LinkWithIcon.stories.tsx b/govtool/frontend/src/stories/LinkWithIcon.stories.tsx new file mode 100644 index 000000000..83e533f25 --- /dev/null +++ b/govtool/frontend/src/stories/LinkWithIcon.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { LinkWithIcon } from "@molecules"; +import { ICONS } from "@consts"; + +const meta: Meta = { + title: "Example/LinkWithIcon", + component: LinkWithIcon, + parameters: { + layout: "centered", + }, +}; + +export default meta; + +export const Default: StoryObj = { + args: { + label: "Default Link", + }, +}; + +export const WithCustomIcon: StoryObj = { + args: { + label: "Custom Icon Link", + icon: , + }, +}; diff --git a/govtool/frontend/src/stories/LoadingButton.stories.tsx b/govtool/frontend/src/stories/LoadingButton.stories.tsx new file mode 100644 index 000000000..935014cd1 --- /dev/null +++ b/govtool/frontend/src/stories/LoadingButton.stories.tsx @@ -0,0 +1,31 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { LoadingButton } from "@atoms"; + +const meta = { + title: "Example/LoadingButton", + component: LoadingButton, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + children: "Button", + variant: "contained", + isLoading: false, + }, +}; + +export const Loading: Story = { + args: { + children: "Button", + variant: "contained", + isLoading: true, + }, +}; diff --git a/govtool/frontend/src/stories/Step.stories.tsx b/govtool/frontend/src/stories/Step.stories.tsx new file mode 100644 index 000000000..aecebae56 --- /dev/null +++ b/govtool/frontend/src/stories/Step.stories.tsx @@ -0,0 +1,62 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { Button } from "@atoms"; +import OpenInNewIcon from "@mui/icons-material/OpenInNew"; + +import { Field, Step } from "@molecules"; + +const meta: Meta = { + title: "Example/Step", + component: Step, + parameters: { + layout: "centered", + }, +}; + +export default meta; + +export const WithButton: StoryObj = { + args: { + label: "Download this file", + stepNumber: 1, + component: ( + + ), + }, +}; + +export const WithIconButton: StoryObj = { + args: { + label: + "Save this file in a location that provides a public URL (ex. github)", + stepNumber: 2, + component: ( + + ), + }, +}; + +export const WithInput: StoryObj = { + args: { + label: + "Save this file in a location that provides a public URL (ex. github)", + stepNumber: 2, + component: , + }, +}; diff --git a/govtool/frontend/src/stories/TextArea.stories.tsx b/govtool/frontend/src/stories/TextArea.stories.tsx new file mode 100644 index 000000000..8f6cc178b --- /dev/null +++ b/govtool/frontend/src/stories/TextArea.stories.tsx @@ -0,0 +1,42 @@ +import type { Meta, StoryFn } from "@storybook/react"; + +import { Field } from "@molecules"; +import { ComponentProps } from "react"; + +const meta: Meta = { + title: "Example/TextArea", + component: Field.TextArea, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], +}; + +export default meta; + +const Template: StoryFn> = (args) => { + return ; +}; + +export const Default = Template.bind({}); + +export const WithLabel = Template.bind({}); +WithLabel.args = { + label: "Label", +}; + +export const WithHelpfulText = Template.bind({}); +WithHelpfulText.args = { + helpfulText: "Helpful text here", +}; + +export const Error = Template.bind({}); +Error.args = { + errorMessage: "Error message", +}; + +export const ErrorAndLabel = Template.bind({}); +ErrorAndLabel.args = { + errorMessage: "Error message", + label: "Label", +}; diff --git a/govtool/frontend/src/stories/modals/ExternalLinkModal.stories.tsx b/govtool/frontend/src/stories/modals/ExternalLinkModal.stories.tsx index dc2df8b5d..236943ac5 100644 --- a/govtool/frontend/src/stories/modals/ExternalLinkModal.stories.tsx +++ b/govtool/frontend/src/stories/modals/ExternalLinkModal.stories.tsx @@ -1,28 +1,22 @@ -import { ComponentProps, useEffect } from "react"; -import { Story, Meta, StoryFn } from "@storybook/react"; +import { useEffect } from "react"; +import { Meta, StoryFn } from "@storybook/react"; import { Modal } from "@atoms"; import { ExternalLinkModal, ExternalLinkModalState } from "@organisms"; -import { ModalProvider, useModal } from "../../context/modal"; +import { useModal } from "../../context/modal"; import { userEvent, within, screen, waitFor } from "@storybook/testing-library"; import { expect, jest } from "@storybook/jest"; +import { callAll } from "@/utils"; const meta = { title: "Example/Modals/ExternalLinkModal", component: ExternalLinkModal, - decorators: [ - (Story) => ( - - - - ), - ], } satisfies Meta; export default meta; const Template: StoryFn = (args) => { - const { openModal, modal, closeModal } = useModal(); + const { openModal, modal, modals } = useModal(); const open = () => { openModal({ @@ -40,12 +34,18 @@ const Template: StoryFn = (args) => { - {modal?.component && ( + {modals[modal.type]?.component && ( + openModal({ type: "none", state: null }) + ) + : undefined + } > - {modal.component} + {modals[modal.type]?.component ?? <>} )} diff --git a/govtool/frontend/src/stories/modals/StatusModal.stories.tsx b/govtool/frontend/src/stories/modals/StatusModal.stories.tsx index 24bb364b1..d7c0b56ce 100644 --- a/govtool/frontend/src/stories/modals/StatusModal.stories.tsx +++ b/govtool/frontend/src/stories/modals/StatusModal.stories.tsx @@ -1,22 +1,16 @@ import { useEffect } from "react"; -import { Story, Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryFn } from "@storybook/react"; +import { expect } from "@storybook/jest"; +import { within, waitFor, screen, userEvent } from "@storybook/testing-library"; import { Modal } from "@atoms"; import { StatusModal, StatusModalState } from "@organisms"; -import { ModalProvider, useModal } from "../../context/modal"; -import { within, waitFor, screen, userEvent } from "@storybook/testing-library"; -import { expect } from "@storybook/jest"; +import { useModal } from "../../context/modal"; +import { callAll } from "@utils"; const meta = { title: "Example/Modals/StatusModal", component: StatusModal, - decorators: [ - (Story) => ( - - - - ), - ], } satisfies Meta; export default meta; @@ -40,7 +34,7 @@ const performCommonAction = async (canvas: any, args: any) => { }); }; const Template: StoryFn = (args) => { - const { openModal, modal, closeModal } = useModal(); + const { openModal, modal, modals, closeModal } = useModal(); const open = () => { openModal({ @@ -67,12 +61,18 @@ const Template: StoryFn = (args) => { - {modal?.component && ( + {modals[modal.type]?.component && ( + openModal({ type: "none", state: null }) + ) + : undefined + } > - {modal.component} + {modals[modal.type]?.component ?? <>} )} diff --git a/govtool/frontend/src/stories/modals/StatusWithLink.stories.tsx b/govtool/frontend/src/stories/modals/StatusWithLink.stories.tsx index e331a14bb..1181fb143 100644 --- a/govtool/frontend/src/stories/modals/StatusWithLink.stories.tsx +++ b/govtool/frontend/src/stories/modals/StatusWithLink.stories.tsx @@ -1,28 +1,22 @@ import { useEffect } from "react"; -import { Story, Meta, StoryFn } from "@storybook/react"; +import { Meta, StoryFn } from "@storybook/react"; +import { expect, jest } from "@storybook/jest"; +import { userEvent, waitFor, within, screen } from "@storybook/testing-library"; import { Modal } from "@atoms"; import { StatusModal, StatusModalState } from "@organisms"; -import { ModalProvider, useModal } from "../../context/modal"; -import { userEvent, waitFor, within, screen } from "@storybook/testing-library"; -import { expect, jest } from "@storybook/jest"; +import { useModal } from "../../context/modal"; +import { callAll } from "@utils"; const meta = { title: "Example/Modals/StatusModalWithLink", component: StatusModal, - decorators: [ - (Story) => ( - - - - ), - ], } satisfies Meta; export default meta; const Template: StoryFn = (args) => { - const { openModal, modal, closeModal } = useModal(); + const { openModal, modal, modals, closeModal } = useModal(); const open = () => { openModal({ @@ -48,12 +42,18 @@ const Template: StoryFn = (args) => { - {modal?.component && ( + {modals[modal.type]?.component && ( + openModal({ type: "none", state: null }) + ) + : undefined + } > - {modal.component} + {modals[modal.type]?.component ?? <>} )} diff --git a/govtool/frontend/src/stories/modals/VotingPowerModal.stories.tsx b/govtool/frontend/src/stories/modals/VotingPowerModal.stories.tsx new file mode 100644 index 000000000..5820c9bb3 --- /dev/null +++ b/govtool/frontend/src/stories/modals/VotingPowerModal.stories.tsx @@ -0,0 +1,56 @@ +import { Meta, StoryFn } from "@storybook/react"; + +import { Modal } from "@atoms"; +import { StatusModal, VotingPowerModalState } from "@organisms"; +import { useModal } from "@context"; +import { callAll } from "@utils"; + +const meta = { + title: "Example/Modals/VotingPowerModal", + component: StatusModal, +} satisfies Meta; + +export default meta; + +const Template: StoryFn = (args) => { + const { openModal, modal, modals } = useModal(); + + const open = () => { + openModal({ + type: "votingPower", + state: { + ...args, + }, + }); + }; + + return ( + <> + + {modals[modal.type]?.component && ( + + openModal({ type: "none", state: null }) + ) + : undefined + } + > + {modals[modal.type]?.component ?? <>} + + )} + + ); +}; + +export const Default = Template.bind({}); +Default.args = { + yesVotes: 1000000000000, + noVotes: 10000000000, + abstainVotes: 324000000, + vote: "yes", +};