Skip to content

Commit

Permalink
docs: show advantage usage for mini cart
Browse files Browse the repository at this point in the history
  • Loading branch information
gciotola committed Nov 6, 2023
1 parent 8b7c5bb commit 2db0fd7
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 48 deletions.
2 changes: 1 addition & 1 deletion packages/docs/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const parameters: Parameters = {
'Orders',
['OrderStorage', 'OrderContainer'],
'Cart',
['AddToCartButton', 'HostedCart', 'CartLink']
['AddToCartButton', 'HostedCart', 'CartLink', 'MiniCart']
],
'Examples',
['Listing Page', 'Cart Page']
Expand Down
47 changes: 0 additions & 47 deletions packages/docs/stories/cart/CartLink.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import type { Meta, StoryFn } from '@storybook/react'
import CommerceLayer from '../_internals/CommerceLayer'
import OrderContainer from '#components/orders/OrderContainer'
import CartLink from '#components/orders/CartLink'
import { HostedCart } from '#components/orders/HostedCart'
import { OrderStorage } from '../_internals/OrderStorage'

const setup: Meta<typeof CartLink> = {
title: 'Components/Cart/CartLink',
Expand All @@ -29,48 +27,3 @@ Default.args = {
onClick: () => {},
className: 'underline hover:text-blue-500'
}

/**
* <span title='Mini cart' type='info'>
* You can use this component to open the mini cart, by setting the `type` prop to `mini`.
* It requires the `<HostedCart type='mini' />` component to be on the same page.
* </span>
*/
export const MiniCart: StoryFn<typeof CartLink> = (arg) => {
return (
<OrderContainer>
<HostedCart
type='mini'
openAdd
style={{
container: {
backgroundColor: 'white'
}
}}
/>
<CartLink
label='Open mini cart'
type='mini'
className='underline hover:text-blue-500'
/>
</OrderContainer>
)
}

MiniCart.decorators = [
(Story) => {
return (
<CommerceLayer
accessToken='my-access-token'
endpoint='https://demo-store.commercelayer.io'
>
<OrderStorage persistKey='cl-examples1-cartId'>
<div className='min-h-[600px]'>
{/* we need more space on the canvas to open the mini cart */}
<Story />
</div>
</OrderStorage>
</CommerceLayer>
)
}
]
56 changes: 56 additions & 0 deletions packages/docs/stories/cart/MiniCart.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Meta, Source, Canvas } from '@storybook/addon-docs';
import * as Stories from './MiniCart.stories.tsx'

<Meta of={Stories} />


# Mini Cart
We can combine the two components just described (`<HostedCart>` and `<CartLink>`) to create a mini cart
that will open as a modal on top of the page.

To do so, we need to set the prop `type='mini'` to both components. Try to click the link below to open the mini cart.
<Canvas of={Stories.Basic} />


### Advanced usage
In the previous example we used as `label` prop a simple string, but it can accept any React component (`ReactNode`).

This means we can be creative and mix other components to create a more complex label, like a shopping bag icon
that previews the number of items in the cart.

This icon component can be built using `<LineItemsContainer>` and `<LineItemsCount>` and a custom svg icon.

<Source dark code={`
const MyCartIcon = () => (
<div className='relative inline-block cursor-pointer text-xs font-bold'>
<LineItemsContainer>
{/* static icon */}
<svg
xmlns='http://www.w3.org/2000/svg'
width='36'
height='36'
fill='currentColor'
viewBox='0 0 256 256'
>
<path d='M216,64H176a48,48,0,0,0-96,0H40A16,16,0,0,0,24,80V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V80A16,16,0,0,0,216,64ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm88,168H40V80H80V96a8,8,0,0,0,16,0V80h64V96a8,8,0,0,0,16,0V80h40Z' />
</svg>
{/* total number of cart items */}
<LineItemsCount className='absolute bottom-2 left-1/2 transform -translate-x-1/2' />
</LineItemsContainer>
</div>
)
`} language='jsx' />

Now we can use our custom component as `label` prop of `<CartLink>` to create a mini cart that can be
placed in the top navigation of your site.

<span title='One context' type='info'>
This works because `LineItemsContainer` and `HostedCart` are both using the same order context:
they are both inside the same `<OrderContainer>` component.
</span>

Click on the icon to show the side cart modal.
<Canvas of={Stories.WithCartIcon} />
138 changes: 138 additions & 0 deletions packages/docs/stories/cart/MiniCart.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import type { Meta, StoryFn, Decorator } from '@storybook/react'
import CommerceLayer from '../_internals/CommerceLayer'
import OrderContainer from '#components/orders/OrderContainer'
import CartLink from '#components/orders/CartLink'
import { HostedCart } from '#components/orders/HostedCart'
import { OrderStorage } from '../_internals/OrderStorage'
import LineItemsContainer from '#components/line_items/LineItemsContainer'
import LineItemsCount from '#components/line_items/LineItemsCount'

const setup: Meta = {
title: 'Components/Cart/Mini Cart'
}

export default setup

const CartDecorator: Decorator = (Story) => {
return (
<CommerceLayer
accessToken='my-access-token'
endpoint='https://demo-store.commercelayer.io'
>
<OrderStorage persistKey='cl-examples1-cartId'>
<div
style={{
minHeight: 600
}}
>
{/* we need more space on the canvas to open the mini cart */}
<Story />
</div>
</OrderStorage>
</CommerceLayer>
)
}

export const Basic: StoryFn = (arg) => {
return (
<OrderContainer>
<HostedCart
type='mini'
openAdd
style={{
container: {
backgroundColor: 'white'
}
}}
/>
<CartLink
label='Open mini cart'
type='mini'
className='underline hover:text-blue-500'
/>
</OrderContainer>
)
}

Basic.decorators = [CartDecorator]

export const CartIcon: StoryFn = (args) => {
return (
<div className='relative inline-block cursor-pointer text-xs font-bold'>
<LineItemsContainer>
<svg
xmlns='http://www.w3.org/2000/svg'
width='36'
height='36'
fill='currentColor'
viewBox='0 0 256 256'
>
<path d='M216,64H176a48,48,0,0,0-96,0H40A16,16,0,0,0,24,80V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V80A16,16,0,0,0,216,64ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm88,168H40V80H80V96a8,8,0,0,0,16,0V80h64V96a8,8,0,0,0,16,0V80h40Z' />
</svg>
<LineItemsCount className='absolute bottom-2 left-1/2 transform -translate-x-1/2' />
</LineItemsContainer>
</div>
)
}
CartIcon.parameters = {}
CartIcon.decorators = [
(Story) => (
<CommerceLayer
accessToken='my-access-token'
endpoint='https://demo-store.commercelayer.io'
>
<OrderStorage persistKey='cl-examples1-cartId'>
<OrderContainer>
<Story />
</OrderContainer>
</OrderStorage>
</CommerceLayer>
)
]

export const WithCartIcon: StoryFn = (args) => {
const MyCartIcon = (): JSX.Element => (
<div className='relative inline-block cursor-pointer text-xs font-bold'>
<LineItemsContainer>
<svg
xmlns='http://www.w3.org/2000/svg'
width='36'
height='36'
fill='currentColor'
viewBox='0 0 256 256'
>
<path d='M216,64H176a48,48,0,0,0-96,0H40A16,16,0,0,0,24,80V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V80A16,16,0,0,0,216,64ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm88,168H40V80H80V96a8,8,0,0,0,16,0V80h64V96a8,8,0,0,0,16,0V80h40Z' />
</svg>
<LineItemsCount className='absolute bottom-2 left-1/2 transform -translate-x-1/2' />
</LineItemsContainer>
</div>
)

return (
<OrderContainer>
<HostedCart
type='mini'
openAdd
style={{
container: {
backgroundColor: 'white'
}
}}
/>
<CartLink
label={<MyCartIcon />}
type='mini'
className='underline hover:text-blue-500'
/>
</OrderContainer>
)
}

WithCartIcon.decorators = [CartDecorator]
WithCartIcon.parameters = {
docs: {
canvas: {
sourceState: 'shown'
}
}
}

0 comments on commit 2db0fd7

Please sign in to comment.