From e0b05cd68afa687a528a87cf8369c0c563978801 Mon Sep 17 00:00:00 2001 From: Rafael Youakeem Date: Fri, 13 Sep 2024 19:45:13 +0200 Subject: [PATCH] Create Default ProductCard story --- .../src/components/ProductCard/Divider.tsx | 14 ++ .../ProductCard/ProductCard.stories.tsx | 123 ++++++++++++++++++ .../ProductCard/ProductCardDetails.tsx | 86 ++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 apps/store/src/components/ProductCard/Divider.tsx create mode 100644 apps/store/src/components/ProductCard/ProductCard.stories.tsx create mode 100644 apps/store/src/components/ProductCard/ProductCardDetails.tsx diff --git a/apps/store/src/components/ProductCard/Divider.tsx b/apps/store/src/components/ProductCard/Divider.tsx new file mode 100644 index 0000000000..5ea69f7afe --- /dev/null +++ b/apps/store/src/components/ProductCard/Divider.tsx @@ -0,0 +1,14 @@ +import { tokens } from 'ui' + +export const Divider = () => { + return ( +
+ ) +} diff --git a/apps/store/src/components/ProductCard/ProductCard.stories.tsx b/apps/store/src/components/ProductCard/ProductCard.stories.tsx new file mode 100644 index 0000000000..93e690b6e7 --- /dev/null +++ b/apps/store/src/components/ProductCard/ProductCard.stories.tsx @@ -0,0 +1,123 @@ + +import type { Meta, StoryObj } from '@storybook/react' +import { type ComponentProps } from 'react' +import { Badge, BasePillow, Button, Card, CrossIcon, IconButton, sprinkles, Text, tokens } from 'ui' +import { CurrencyCode } from '@/services/graphql/graphql' +import { InputStartDay } from '../InputDay/InputStartDay' +import { Price } from '../Price' +import { DetailsList } from './DetailsList/DetailsList' +import { Divider } from './Divider' +import { ProductCardDetails } from './ProductCardDetails' + +type Controls = ComponentProps + +const meta: Meta = { + title: 'Components / ProductCard', + component: Card.Root, + argTypes: { + variant: { + options: ['primary', 'secondary'], + control: { type: 'select' }, + }, + }, + parameters: { + design: { + allowFullscreen: true, + type: 'figma', + url: 'https://www.figma.com/file/5kmmDdh6StpXzbEfr7WevV/Hedvig-UI-Kit?type=design&node-id=18673-5100', + }, + }, +} +export default meta + +type Story = StoryObj + +export const Default: Story = { + render: (args: Controls) => ( +
+ + + + + + + + + + + + Homeowner Insurance + Bellmansgatan 19A + + + + + + Show details + Hide details + + + + Details + + + Home type + Homeowner + + + + Address + Bellmansgatan 19A + + + + Zip code + 118 47 + + + + + + + + + + + + Homeowner Insurance{' '} + + Max + + + 379 kr/mo + + + + Extended travel 60 days + 79 kr/mo + + + + + + + + Total + + + + + + +
+ ), + args: { + variant: 'primary', + }, +} diff --git a/apps/store/src/components/ProductCard/ProductCardDetails.tsx b/apps/store/src/components/ProductCard/ProductCardDetails.tsx new file mode 100644 index 0000000000..b30b10954a --- /dev/null +++ b/apps/store/src/components/ProductCard/ProductCardDetails.tsx @@ -0,0 +1,86 @@ +import { type ComponentProps, createContext, type PropsWithChildren, useContext, useState } from 'react' +import { Button } from 'ui' +import Collapsible from '@/components/Collapsible/Collapsible' + +type ContextValue = { + isOpen: boolean + toggle: () => void +} + +const Context = createContext(null) + +const useProductDetails = () => { + const context = useContext(Context) + + if (!context) { + throw new Error('useProductDetails must be used inside ProductCardDetails') + } + + return context +} + +type RootProps = ComponentProps +const Root = ({ children, ...props }: RootProps) => { + const [isOpen, setIsOpen] = useState(false) + + const toggle = () => { + setIsOpen((isOpen) => !isOpen) + } + + return ( + + {children} + + ) +} + +type TriggerProps = ComponentProps +const Trigger = ({ children, ...props }: TriggerProps) => { + const { toggle } = useProductDetails() + + return ( + + + + ) +} + +type ContentProps = ComponentProps<'div'> +const Content = ({ children, ...props }: ContentProps) => { + return ( + + {/* This `div` wraps all content not to conflict with `Collapsible.Content` animation */} +
{children}
+
+ ) +} + +const ExpandedLabel = ({ children }: PropsWithChildren) => { + const { isOpen } = useProductDetails() + + if (!isOpen) { + return null + } + + return children +} + +const CollapsedLabel = ({ children }: PropsWithChildren) => { + const { isOpen } = useProductDetails() + + if (isOpen) { + return null + } + + return children +} + +export const ProductCardDetails = { + Root, + Trigger, + Content, + ExpandedLabel, + CollapsedLabel, +}