Add Notices Documentation to Storybook and upgrade to Storybook 7 (https://github.com/woocommerce/woocommerce-blocks/pull/11524)
* Rename stories * MDX guidelines * dedupe and fix dependencies * Notice Banner Docs * Fix root elements and icon library docs * Fix ProductPrice stories * Organise storybook structure * Fix error placeholder story * Snackbar docs * Missing dotenv dependency * Update storybook/main.js Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/snackbar-list/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/notice-banner/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/snackbar-list/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/snackbar-list/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/snackbar-list/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/snackbar-list/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/snackbar-list/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update assets/js/base/components/snackbar-list/docs/docs.mdx Co-authored-by: Alex Florisca <alex.florisca@automattic.com> * Update package lock * update snaps * fix json error check --------- Co-authored-by: Alex Florisca <alex.florisca@automattic.com>
This commit is contained in:
parent
abdfe69b38
commit
ba09750661
|
@ -124,6 +124,7 @@ module.exports = {
|
||||||
extends: [
|
extends: [
|
||||||
'plugin:@woocommerce/eslint-plugin/recommended',
|
'plugin:@woocommerce/eslint-plugin/recommended',
|
||||||
'plugin:you-dont-need-lodash-underscore/compatible',
|
'plugin:you-dont-need-lodash-underscore/compatible',
|
||||||
|
'plugin:storybook/recommended',
|
||||||
],
|
],
|
||||||
globals: {
|
globals: {
|
||||||
wcBlocksMiddlewareConfig: 'readonly',
|
wcBlocksMiddlewareConfig: 'readonly',
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Button, { ButtonProps } from '..';
|
||||||
const availableTypes = [ 'button', 'input', 'submit' ];
|
const availableTypes = [ 'button', 'input', 'submit' ];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/Button',
|
title: 'Base Components/Button',
|
||||||
argTypes: {
|
argTypes: {
|
||||||
children: {
|
children: {
|
||||||
control: 'text',
|
control: 'text',
|
|
@ -13,7 +13,7 @@ import { VALIDATION_STORE_KEY } from '@woocommerce/block-data';
|
||||||
import { TotalsCoupon, TotalsCouponProps } from '..';
|
import { TotalsCoupon, TotalsCouponProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/cart-checkout/totals/Coupon',
|
title: 'Base Components/Totals/Coupon',
|
||||||
component: TotalsCoupon,
|
component: TotalsCoupon,
|
||||||
args: {
|
args: {
|
||||||
initialOpen: true,
|
initialOpen: true,
|
|
@ -67,7 +67,7 @@ function extractValuesFromCoupons(
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/cart-checkout/totals/Discount',
|
title: 'Base Components/Totals/Discount',
|
||||||
component: Discount,
|
component: Discount,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
currency: currencyControl,
|
currency: currencyControl,
|
|
@ -21,7 +21,7 @@ const NZD: Currency = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/cart-checkout/totals/FooterItem',
|
title: 'Base Components/Totals/FooterItem',
|
||||||
component: FooterItem,
|
component: FooterItem,
|
||||||
args: {
|
args: {
|
||||||
currency: NZD,
|
currency: NZD,
|
|
@ -15,7 +15,7 @@ import { countries } from './countries-filler';
|
||||||
type CountryCode = keyof typeof countries;
|
type CountryCode = keyof typeof countries;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/CountryInput',
|
title: 'Base Components/CountryInput',
|
||||||
component: CountryInput,
|
component: CountryInput,
|
||||||
args: {
|
args: {
|
||||||
countries,
|
countries,
|
|
@ -10,7 +10,7 @@ import { useState } from '@wordpress/element';
|
||||||
import FormTokenField, { Props } from '..';
|
import FormTokenField, { Props } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/FormTokenField',
|
title: 'Base Components/FormTokenField',
|
||||||
argTypes: {},
|
argTypes: {},
|
||||||
component: FormTokenField,
|
component: FormTokenField,
|
||||||
} as Meta< Props >;
|
} as Meta< Props >;
|
|
@ -1,138 +0,0 @@
|
||||||
# NoticeBanner Component <!-- omit in toc -->
|
|
||||||
|
|
||||||
An informational UI displayed near the top of the store pages.
|
|
||||||
|
|
||||||
## Table of contents <!-- omit in toc -->
|
|
||||||
|
|
||||||
- [Design Guidelines](#design-guidelines)
|
|
||||||
- [Development Guidelines](#development-guidelines)
|
|
||||||
- [Usage](#usage)
|
|
||||||
- [Props](#props)
|
|
||||||
- [`children`: `React.ReactNode`](#children-reactreactnode)
|
|
||||||
- [`className`: `string`](#classname-string)
|
|
||||||
- [`isDismissible`: `boolean`](#isdismissible-boolean)
|
|
||||||
- [`onRemove`: `() => void`](#onremove---void)
|
|
||||||
- [`politeness`: `'polite' | 'assertive'`](#politeness-polite--assertive)
|
|
||||||
- [`spokenMessage`: `string`](#spokenmessage-string)
|
|
||||||
- [`status`: `'success' | 'error' | 'info' | 'warning' | 'default'`](#status-success--error--info--warning--default)
|
|
||||||
- [`summary`: `string`](#summary-string)
|
|
||||||
- [Example](#example)
|
|
||||||
|
|
||||||
## Design Guidelines
|
|
||||||
|
|
||||||
Notices are informational UI displayed near the top of store pages. Notices are used to indicate the result of an action, or to draw the user’s attention to necessary information.
|
|
||||||
|
|
||||||
Notices are color-coded to indicate the type of message being communicated, and also show an icon to reinforce the meaning of the message. The color and icon used for a notice are determined by the `status` prop.
|
|
||||||
|
|
||||||
### Informational
|
|
||||||
|
|
||||||
Blue notices used for general information for buyers that are not blocking and do not require action.
|
|
||||||
|
|
||||||
![Informational notice](./screenshots/info.png)
|
|
||||||
|
|
||||||
### Error
|
|
||||||
|
|
||||||
Red notices to show that an error has occurred and that the user needs to take action.
|
|
||||||
|
|
||||||
![Error notice](./screenshots/error.png)
|
|
||||||
|
|
||||||
### Success
|
|
||||||
|
|
||||||
Green notices that show an action was successful.
|
|
||||||
|
|
||||||
![Success notice](./screenshots/success.png)
|
|
||||||
|
|
||||||
### Warning
|
|
||||||
|
|
||||||
Yellow notices that show that the user may need to take action, or needs to be aware of something important.
|
|
||||||
|
|
||||||
![Warning notice](./screenshots/warning.png)
|
|
||||||
|
|
||||||
### Default
|
|
||||||
|
|
||||||
Gray notice, similar to info, but used for less important messaging.
|
|
||||||
|
|
||||||
![Default notice](./screenshots/default.png)
|
|
||||||
|
|
||||||
## Development Guidelines
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
To display a plain notice, pass the notice message as a string:
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
import { NoticeBanner } from '@woocommerce/base-components';
|
|
||||||
|
|
||||||
<NoticeBanner status="info">Your message here</NoticeBanner>;
|
|
||||||
```
|
|
||||||
|
|
||||||
For more complex markup, you can pass any JSX element:
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
import { NoticeBanner } from '@woocommerce/base-components';
|
|
||||||
|
|
||||||
<NoticeBanner status="error">
|
|
||||||
<p>
|
|
||||||
An error occurred: <code>{ errorDetails }</code>.
|
|
||||||
</p>
|
|
||||||
</NoticeBanner>;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Props
|
|
||||||
|
|
||||||
#### `children`: `React.ReactNode`
|
|
||||||
|
|
||||||
The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.
|
|
||||||
|
|
||||||
#### `className`: `string`
|
|
||||||
|
|
||||||
Additional class name to give to the notice.
|
|
||||||
|
|
||||||
#### `isDismissible`: `boolean`
|
|
||||||
|
|
||||||
Determines whether the notice can be dismissed by the user. When set to true, a close icon will be displayed on the banner.
|
|
||||||
|
|
||||||
#### `onRemove`: `() => void`
|
|
||||||
|
|
||||||
Function called when dismissing the notice. When the close icon is clicked or the Escape key is pressed, this function will be called.
|
|
||||||
|
|
||||||
#### `politeness`: `'polite' | 'assertive'`
|
|
||||||
|
|
||||||
Determines the level of politeness for the notice for assistive technology. Acceptable values are 'polite' and 'assertive'. Default is 'polite'.
|
|
||||||
|
|
||||||
#### `spokenMessage`: `string`
|
|
||||||
|
|
||||||
Optionally provided to change the spoken message for assistive technology. If not provided, the `children` prop will be used as the spoken message.
|
|
||||||
|
|
||||||
#### `status`: `'success' | 'error' | 'info' | 'warning' | 'default'`
|
|
||||||
|
|
||||||
Status determines the color of the notice and the icon. Acceptable values are `success`, `error`, `info`, `warning`, and `default`.
|
|
||||||
|
|
||||||
#### `summary`: `string`
|
|
||||||
|
|
||||||
Optional summary text shown above notice content, used when several notices are listed together.
|
|
||||||
|
|
||||||
##### Example
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { NoticeBanner } from '@woocommerce/base-components';
|
|
||||||
|
|
||||||
const errorMessages = [
|
|
||||||
'First error message',
|
|
||||||
'Second error message',
|
|
||||||
'Third error message',
|
|
||||||
];
|
|
||||||
|
|
||||||
<NoticeBanner
|
|
||||||
status="error"
|
|
||||||
summary="There are errors in your form submission:"
|
|
||||||
>
|
|
||||||
<ul>
|
|
||||||
{ errorMessages.map( ( message ) => (
|
|
||||||
<li key={ message }>{ message }</li>
|
|
||||||
) ) }
|
|
||||||
</ul>
|
|
||||||
</NoticeBanner>;
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, the summary prop is used to indicate to the user that there are errors in the form submission. The list of error messages is rendered within the NoticeBanner component using an unordered list (`<ul>`) and list items (`<li>`). The `status` prop is set to `error` to indicate that the notice represents an error message.
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
import { Canvas, Meta, ArgTypes, Primary, Source } from '@storybook/blocks';
|
||||||
|
|
||||||
|
import * as NoticeBannerStories from '../stories/index.stories.tsx';
|
||||||
|
|
||||||
|
<Meta name="Docs" of={ NoticeBannerStories } />
|
||||||
|
|
||||||
|
# NoticeBanner
|
||||||
|
|
||||||
|
An informational UI displayed near the top of the store pages.
|
||||||
|
|
||||||
|
<Primary />
|
||||||
|
|
||||||
|
## Design Guidelines
|
||||||
|
|
||||||
|
`NoticeBanner` is an informational UI element displayed near the top of store pages used to indicate the result of an action, or to draw the user's attention to necessary information.
|
||||||
|
|
||||||
|
Notices are color-coded to indicate the type of message being communicated, and also show an icon to reinforce the meaning of the message. The color and icon used for a notice are determined by the `status` prop.
|
||||||
|
|
||||||
|
### Default Notices
|
||||||
|
|
||||||
|
By default, noices are grey and used for less important messaging.
|
||||||
|
|
||||||
|
<Canvas of={ NoticeBannerStories.Default } />
|
||||||
|
|
||||||
|
### Informational Notices
|
||||||
|
|
||||||
|
Blue notices with an info icon are used for general information for buyers, but do not require them to take an action.
|
||||||
|
|
||||||
|
<Canvas of={ NoticeBannerStories.Info } />
|
||||||
|
|
||||||
|
### Error Notices
|
||||||
|
|
||||||
|
Red notices with an alert icon are used to show that an error has occurred and that the user needs to take action.
|
||||||
|
|
||||||
|
<Canvas of={ NoticeBannerStories.Error } />
|
||||||
|
|
||||||
|
### Success Notices
|
||||||
|
|
||||||
|
Green notices with a success icon are used to show an action was successful.
|
||||||
|
|
||||||
|
<Canvas of={ NoticeBannerStories.Success } />
|
||||||
|
|
||||||
|
### Warning Notices
|
||||||
|
|
||||||
|
Yellow notices with an alert icon are used to show that the user may need to take action, or needs to be aware of something important.
|
||||||
|
|
||||||
|
<Canvas of={ NoticeBannerStories.Warning } />
|
||||||
|
|
||||||
|
### Error Summary
|
||||||
|
|
||||||
|
If you provide a `summary` it will be displayed above the notice content. This can be useful for displaying a summary of errors in a list format.
|
||||||
|
|
||||||
|
<Canvas of={ NoticeBannerStories.ErrorSummary } />
|
||||||
|
|
||||||
|
## Development Guidelines
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
<ArgTypes />
|
||||||
|
|
||||||
|
### Usage examples
|
||||||
|
|
||||||
|
#### Example: string based notices
|
||||||
|
|
||||||
|
To display a basic notice, pass the notice message as a string:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { NoticeBanner } from '@woocommerce/base-components';
|
||||||
|
|
||||||
|
<NoticeBanner status="info">Your message here</NoticeBanner>;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example: components within notices
|
||||||
|
|
||||||
|
For more complex markup, you can wrap any JSX element:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { NoticeBanner } from '@woocommerce/base-components';
|
||||||
|
|
||||||
|
<NoticeBanner status="error">
|
||||||
|
<p>
|
||||||
|
An error occurred: <code>{ errorDetails }</code>.
|
||||||
|
</p>
|
||||||
|
</NoticeBanner>;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example: list of notices
|
||||||
|
|
||||||
|
In this example, the summary prop is used to indicate to the user that there are errors in the form submission.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { NoticeBanner } from '@woocommerce/base-components';
|
||||||
|
|
||||||
|
const errorMessages = [
|
||||||
|
'First error message',
|
||||||
|
'Second error message',
|
||||||
|
'Third error message',
|
||||||
|
];
|
||||||
|
|
||||||
|
<NoticeBanner
|
||||||
|
status="error"
|
||||||
|
summary="There are errors in your form submission:"
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
{ errorMessages.map( ( message ) => (
|
||||||
|
<li key={ message }>{ message }</li>
|
||||||
|
) ) }
|
||||||
|
</ul>
|
||||||
|
</NoticeBanner>;
|
||||||
|
```
|
||||||
|
|
||||||
|
The list of error messages is rendered within the NoticeBanner component using an unordered list (`<ul>`) and list items (`<li>`). The `status` prop is set to `error` to indicate that the notice represents an error message.
|
|
@ -14,29 +14,20 @@ import Button from '../button';
|
||||||
import { useSpokenMessage } from '../../hooks';
|
import { useSpokenMessage } from '../../hooks';
|
||||||
|
|
||||||
export interface NoticeBannerProps {
|
export interface NoticeBannerProps {
|
||||||
// The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.
|
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
// Additional class name to give to the notice.
|
className?: string;
|
||||||
className?: string | undefined;
|
isDismissible?: boolean;
|
||||||
// Determines whether the notice can be dismissed by the user.
|
onRemove?: () => void;
|
||||||
isDismissible?: boolean | undefined;
|
politeness?: 'polite' | 'assertive';
|
||||||
// Function called when dismissing the notice.
|
spokenMessage?: string | React.ReactNode;
|
||||||
onRemove?: ( () => void ) | undefined;
|
|
||||||
// Determines the level of politeness for the notice for assistive technology.
|
|
||||||
politeness?: 'polite' | 'assertive' | undefined;
|
|
||||||
// Optionally provided to change the spoken message for assistive technology.
|
|
||||||
spokenMessage?: string | React.ReactNode | undefined;
|
|
||||||
// Status determines the color of the notice and the icon.
|
|
||||||
status: 'success' | 'error' | 'info' | 'warning' | 'default';
|
status: 'success' | 'error' | 'info' | 'warning' | 'default';
|
||||||
// Optional summary text shown above notice content, used when several notices are listed together.
|
summary?: string;
|
||||||
summary?: string | undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NoticeBanner: An informational UI displayed near the top of the store pages.
|
* NoticeBanner component.
|
||||||
*
|
*
|
||||||
* Notices are informational UI displayed near the top of store pages. WooCommerce blocks, themes, and plugins all use
|
* An informational UI displayed near the top of the store pages.
|
||||||
* notices to indicate the result of an action, or to draw the user’s attention to necessary information.
|
|
||||||
*/
|
*/
|
||||||
const NoticeBanner = ( {
|
const NoticeBanner = ( {
|
||||||
className,
|
className,
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.6 KiB |
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import type { Story, Meta } from '@storybook/react';
|
import type { StoryFn, Meta } from '@storybook/react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -10,7 +10,7 @@ import NoticeBanner, { NoticeBannerProps } from '../';
|
||||||
const availableStatus = [ 'default', 'success', 'error', 'warning', 'info' ];
|
const availableStatus = [ 'default', 'success', 'error', 'warning', 'info' ];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/NoticeBanner',
|
title: 'Base Components/NoticeBanner',
|
||||||
argTypes: {
|
argTypes: {
|
||||||
status: {
|
status: {
|
||||||
control: 'radio',
|
control: 'radio',
|
||||||
|
@ -20,7 +20,8 @@ export default {
|
||||||
},
|
},
|
||||||
isDismissible: {
|
isDismissible: {
|
||||||
control: 'boolean',
|
control: 'boolean',
|
||||||
description: 'Determines whether the notice can be dismissed.',
|
description:
|
||||||
|
'Determines whether the notice can be dismissed by the user. When set to true, a close icon will be displayed on the banner.',
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
description:
|
description:
|
||||||
|
@ -33,7 +34,7 @@ export default {
|
||||||
},
|
},
|
||||||
spokenMessage: {
|
spokenMessage: {
|
||||||
description:
|
description:
|
||||||
'Optionally provided to change the spoken message for assistive technology.',
|
'Optionally provided to change the spoken message for assistive technology. If not provided, the `children` prop will be used as the spoken message.',
|
||||||
control: 'text',
|
control: 'text',
|
||||||
},
|
},
|
||||||
politeness: {
|
politeness: {
|
||||||
|
@ -44,18 +45,19 @@ export default {
|
||||||
},
|
},
|
||||||
children: {
|
children: {
|
||||||
description:
|
description:
|
||||||
'The content of the notice; either text or a React node such as a list of errors.',
|
'The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.',
|
||||||
disable: true,
|
disable: true,
|
||||||
},
|
},
|
||||||
onRemove: {
|
onRemove: {
|
||||||
description: 'Function called when dismissing the notice.',
|
description:
|
||||||
|
'Function called when dismissing the notice. When the close icon is clicked or the Escape key is pressed, this function will be called.',
|
||||||
disable: true,
|
disable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
component: NoticeBanner,
|
component: NoticeBanner,
|
||||||
} as Meta< NoticeBannerProps >;
|
} as Meta< NoticeBannerProps >;
|
||||||
|
|
||||||
const Template: Story< NoticeBannerProps > = ( args ) => {
|
const Template: StoryFn< NoticeBannerProps > = ( args ) => {
|
||||||
return <NoticeBanner { ...args } />;
|
return <NoticeBanner { ...args } />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,7 +86,7 @@ Warning.args = {
|
||||||
|
|
||||||
export const Info = Template.bind( {} );
|
export const Info = Template.bind( {} );
|
||||||
Info.args = {
|
Info.args = {
|
||||||
children: 'This is an info notice',
|
children: 'This is an informational notice',
|
||||||
status: 'info',
|
status: 'info',
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { currencies, currencyControl } from '@woocommerce/storybook-controls';
|
||||||
import PriceSlider, { PriceSliderProps } from '..';
|
import PriceSlider, { PriceSliderProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/PriceSlider',
|
title: 'Base Components/PriceSlider',
|
||||||
component: PriceSlider,
|
component: PriceSlider,
|
||||||
args: {
|
args: {
|
||||||
currency: currencies.USD,
|
currency: currencies.USD,
|
|
@ -9,7 +9,7 @@ import type { Story, Meta } from '@storybook/react';
|
||||||
import ProductName, { ProductNameProps } from '..';
|
import ProductName, { ProductNameProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/cart-checkout/ProductName',
|
title: 'Base Components/ProductName',
|
||||||
component: ProductName,
|
component: ProductName,
|
||||||
args: {
|
args: {
|
||||||
name: 'Test product',
|
name: 'Test product',
|
|
@ -12,7 +12,7 @@ import ProductPrice, { ProductPriceProps } from '..';
|
||||||
const ALLOWED_ALIGN_VALUES = [ 'left', 'center', 'right' ];
|
const ALLOWED_ALIGN_VALUES = [ 'left', 'center', 'right' ];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/ProductPrice',
|
title: 'Base Components/ProductPrice',
|
||||||
component: ProductPrice,
|
component: ProductPrice,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
align: {
|
align: {
|
||||||
|
@ -25,6 +25,15 @@ export default {
|
||||||
align: 'left',
|
align: 'left',
|
||||||
format: '<price/>',
|
format: '<price/>',
|
||||||
price: 3000,
|
price: 3000,
|
||||||
|
currency: {
|
||||||
|
code: 'USD',
|
||||||
|
symbol: '$',
|
||||||
|
thousandSeparator: ' ',
|
||||||
|
decimalSeparator: '.',
|
||||||
|
minorUnit: 2,
|
||||||
|
prefix: '$',
|
||||||
|
suffix: '',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as Meta< ProductPriceProps >;
|
} as Meta< ProductPriceProps >;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import type { Story, Meta } from '@storybook/react';
|
||||||
import QuantitySelector, { QuantitySelectorProps } from '..';
|
import QuantitySelector, { QuantitySelectorProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/QuantitySelector',
|
title: 'Base Components/QuantitySelector',
|
||||||
component: QuantitySelector,
|
component: QuantitySelector,
|
||||||
args: {
|
args: {
|
||||||
itemName: 'widgets',
|
itemName: 'widgets',
|
|
@ -9,7 +9,7 @@ import type { Story, Meta } from '@storybook/react';
|
||||||
import ReadMore, { defaultProps, ReadMoreProps } from '..';
|
import ReadMore, { defaultProps, ReadMoreProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/ReadMore',
|
title: 'Base Components/ReadMore',
|
||||||
component: ReadMore,
|
component: ReadMore,
|
||||||
args: defaultProps,
|
args: defaultProps,
|
||||||
argTypes: {
|
argTypes: {
|
|
@ -1,62 +0,0 @@
|
||||||
# SnackbarList Component <!-- omit in toc -->
|
|
||||||
|
|
||||||
A temporary informational UI displayed at the bottom of store pages.
|
|
||||||
|
|
||||||
## Table of contents <!-- omit in toc -->
|
|
||||||
|
|
||||||
- [Design Guidelines](#design-guidelines)
|
|
||||||
- [Development Guidelines](#development-guidelines)
|
|
||||||
- [Usage](#usage)
|
|
||||||
- [Props](#props)
|
|
||||||
- [`className`: `string`](#classname-string)
|
|
||||||
- [`onRemove`: `( noticeId ) => void`](#onremove--noticeid---void)
|
|
||||||
- [`notices`: `NoticeType[]`](#notices-noticetype)
|
|
||||||
|
|
||||||
## Design Guidelines
|
|
||||||
|
|
||||||
The buyer notice snackbar is temporary informational UI displayed at the bottom of store pages. WooCommerce blocks, themes, and plugins all use snackbar notices to indicate the result of a successful action.
|
|
||||||
|
|
||||||
Snackbar notices work in the same way as the NoticeBanner component, and support the same statuses and styles.
|
|
||||||
|
|
||||||
## Development Guidelines
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
To display snackbar notices, pass an array of `notices` to the `SnackbarList` component:
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
import { SnackbarList } from '@woocommerce/base-components';
|
|
||||||
|
|
||||||
const notices = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
content: 'This is a snackbar notice.',
|
|
||||||
status: 'default',
|
|
||||||
isDismissible: true,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
<SnackbarList notices={ notices }>;
|
|
||||||
```
|
|
||||||
|
|
||||||
The component consuming `SnackbarList` is responsible for managing the notices state. The `SnackbarList` component will automatically remove notices from the list when they are dismissed by the user using the provided `onRemove` callback, and also when the notice times out after 10000ms.
|
|
||||||
|
|
||||||
### Props
|
|
||||||
|
|
||||||
#### `className`: `string`
|
|
||||||
|
|
||||||
Additional class name to give to the notice.
|
|
||||||
|
|
||||||
#### `onRemove`: `( noticeId ) => void`
|
|
||||||
|
|
||||||
Function called when dismissing the notice. When the close icon is clicked or the Escape key is pressed, this function will be called. This is also called when the notice times out after 10000ms.
|
|
||||||
|
|
||||||
#### `notices`: `NoticeType[]`
|
|
||||||
|
|
||||||
A list of notices to display as snackbars. Each notice must have an `id` and `content` prop.
|
|
||||||
|
|
||||||
- The `id` prop is used to identify the notice and should be unique.
|
|
||||||
- The `content` prop is the content to display in the notice.
|
|
||||||
- The `status` prop is used to determine the color of the notice and the icon. Acceptable values are 'success', 'error', 'info', 'warning', and 'default'.
|
|
||||||
- The `isDismissible` prop determines whether the notice can be dismissed by the user.
|
|
||||||
- The `spokenMessage` prop is used to change the spoken message for assistive technology. If not provided, the `content` prop will be used as the spoken message.
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { Canvas, Meta, ArgTypes } from '@storybook/blocks';
|
||||||
|
|
||||||
|
import * as SnackbarListStories from '../stories/index.stories.tsx';
|
||||||
|
import * as SnackbarStories from '../stories/snackbar.stories.tsx';
|
||||||
|
|
||||||
|
<Meta name="Docs" of={ SnackbarListStories } />
|
||||||
|
|
||||||
|
# SnackbarList
|
||||||
|
|
||||||
|
A temporary informational UI element displayed at the bottom of store pages.
|
||||||
|
|
||||||
|
<Canvas
|
||||||
|
of={ SnackbarListStories.Default }
|
||||||
|
layout="padded"
|
||||||
|
className={ 'force-canvas-height' }
|
||||||
|
/>
|
||||||
|
|
||||||
|
## Design Guidelines
|
||||||
|
|
||||||
|
The Snackbar is a temporary informational UI element displayed at the bottom of store pages. WooCommerce blocks, themes, and plugins all use snackbar notices to indicate the result of a successful action. For example, adding something to the cart.
|
||||||
|
|
||||||
|
Snackbar notices work in the same way as the NoticeBanner component, and support the same statuses and styles.
|
||||||
|
|
||||||
|
### Default Snackbars
|
||||||
|
|
||||||
|
By default, notices are grey and used for less important messaging.
|
||||||
|
|
||||||
|
<Canvas of={ SnackbarStories.Default } />
|
||||||
|
|
||||||
|
### Informational Snackbars
|
||||||
|
|
||||||
|
Blue notices with an info icon are used for general information for buyers, but do not require action.
|
||||||
|
|
||||||
|
<Canvas of={ SnackbarStories.Info } />
|
||||||
|
|
||||||
|
### Error Snackbars
|
||||||
|
|
||||||
|
Red notices with an alert icon are used to show that an error has occurred and that the user needs to take action.
|
||||||
|
|
||||||
|
<Canvas of={ SnackbarStories.Error } />
|
||||||
|
|
||||||
|
### Success Snackbars
|
||||||
|
|
||||||
|
Green notices with a success icon are used to show an action was successful.
|
||||||
|
|
||||||
|
<Canvas of={ SnackbarStories.Success } />
|
||||||
|
|
||||||
|
### Warning Snackbars
|
||||||
|
|
||||||
|
Yellow notices with an alert icon are used to show that the user may need to take action, or needs to be aware of something important.
|
||||||
|
|
||||||
|
<Canvas of={ SnackbarStories.Warning } />
|
||||||
|
|
||||||
|
## Development Guidelines
|
||||||
|
|
||||||
|
The component consuming `SnackbarList` is responsible for managing the notices state. The `SnackbarList` component will automatically remove notices from the list when they are dismissed by the user using the provided `onRemove` callback, and also when the notice times out after 10000ms.
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
<ArgTypes />
|
||||||
|
|
||||||
|
### NoticeType
|
||||||
|
|
||||||
|
Each notice can be provided with the following args.
|
||||||
|
|
||||||
|
- The `id` (required) prop is used to identify the notice and should be unique.
|
||||||
|
- The `content` (required) prop is the content to display in the notice.
|
||||||
|
- The `status` prop is used to determine the color of the notice and the icon. Acceptable values are 'success', 'error', 'info', 'warning', and 'default'.
|
||||||
|
- The `isDismissible` prop determines whether the notice can be dismissed by the user.
|
||||||
|
- The `spokenMessage` prop is used to change the spoken message for assistive technology. If not provided, the `content` prop will be used as the spoken message.
|
||||||
|
|
||||||
|
### Usage example
|
||||||
|
|
||||||
|
To display snackbar notices, pass an array of `notices` to the `SnackbarList` component:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { SnackbarList } from '@woocommerce/base-components';
|
||||||
|
|
||||||
|
const notices = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
content: 'This is a snackbar notice.',
|
||||||
|
status: 'default',
|
||||||
|
isDismissible: true,
|
||||||
|
spokenMessage: "Hello snackbar!"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
<SnackbarList notices={ notices }>;
|
||||||
|
```
|
|
@ -2,6 +2,7 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { useEffect } from '@wordpress/element';
|
import { useEffect } from '@wordpress/element';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -9,15 +10,18 @@ import { useEffect } from '@wordpress/element';
|
||||||
import NoticeBanner, { NoticeBannerProps } from '../notice-banner';
|
import NoticeBanner, { NoticeBannerProps } from '../notice-banner';
|
||||||
import { SNACKBAR_TIMEOUT } from './constants';
|
import { SNACKBAR_TIMEOUT } from './constants';
|
||||||
|
|
||||||
const Snackbar = ( {
|
export interface SnackbarProps extends NoticeBannerProps {
|
||||||
|
// A ref to the list that contains the snackbar.
|
||||||
|
listRef?: React.MutableRefObject< HTMLDivElement | null >;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Snackbar = ( {
|
||||||
onRemove = () => void 0,
|
onRemove = () => void 0,
|
||||||
children,
|
children,
|
||||||
listRef,
|
listRef,
|
||||||
|
className,
|
||||||
...notice
|
...notice
|
||||||
}: {
|
}: SnackbarProps ) => {
|
||||||
// A ref to the list that contains the snackbar.
|
|
||||||
listRef?: React.MutableRefObject< HTMLDivElement | null >;
|
|
||||||
} & NoticeBannerProps ) => {
|
|
||||||
// Only set up the timeout dismiss if we're not explicitly dismissing.
|
// Only set up the timeout dismiss if we're not explicitly dismissing.
|
||||||
useEffect( () => {
|
useEffect( () => {
|
||||||
const timeoutHandle = setTimeout( () => {
|
const timeoutHandle = setTimeout( () => {
|
||||||
|
@ -29,6 +33,10 @@ const Snackbar = ( {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NoticeBanner
|
<NoticeBanner
|
||||||
|
className={ classNames(
|
||||||
|
className,
|
||||||
|
'wc-block-components-notice-snackbar'
|
||||||
|
) }
|
||||||
{ ...notice }
|
{ ...notice }
|
||||||
onRemove={ () => {
|
onRemove={ () => {
|
||||||
// Prevent focus loss by moving it to the list element.
|
// Prevent focus loss by moving it to the list element.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import type { Story, Meta } from '@storybook/react';
|
import type { StoryFn, Meta } from '@storybook/react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -9,7 +9,7 @@ import type { Story, Meta } from '@storybook/react';
|
||||||
import SnackbarList, { SnackbarListProps } from '../';
|
import SnackbarList, { SnackbarListProps } from '../';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/SnackbarList',
|
title: 'Base Components/SnackbarList',
|
||||||
args: {
|
args: {
|
||||||
notices: [
|
notices: [
|
||||||
{
|
{
|
||||||
|
@ -28,18 +28,20 @@ export default {
|
||||||
control: 'text',
|
control: 'text',
|
||||||
},
|
},
|
||||||
notices: {
|
notices: {
|
||||||
description: 'List of notice objects to show as snackbar notices.',
|
description:
|
||||||
|
'A list of notices to display as snackbars. Each notice must have an `id` and `content` prop.',
|
||||||
disable: true,
|
disable: true,
|
||||||
},
|
},
|
||||||
onRemove: {
|
onRemove: {
|
||||||
description: 'Function called when dismissing the notice(s).',
|
description:
|
||||||
|
'Function called when dismissing the notice. When the close icon is clicked or the Escape key is pressed, this function will be called. This is also called when the notice times out after 10000ms.',
|
||||||
disable: true,
|
disable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
component: SnackbarList,
|
component: SnackbarList,
|
||||||
} as Meta< SnackbarListProps >;
|
} as Meta< SnackbarListProps >;
|
||||||
|
|
||||||
const Template: Story< SnackbarListProps > = ( args ) => {
|
const Template: StoryFn< SnackbarListProps > = ( args ) => {
|
||||||
return <SnackbarList { ...args } />;
|
return <SnackbarList { ...args } />;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import type { StoryFn, Meta } from '@storybook/react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import Snackbar, { SnackbarProps } from '../snackbar';
|
||||||
|
const availableStatus = [ 'default', 'success', 'error', 'warning', 'info' ];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Base Components/SnackbarList/Snackbar',
|
||||||
|
argTypes: {
|
||||||
|
status: {
|
||||||
|
control: 'radio',
|
||||||
|
options: availableStatus,
|
||||||
|
description:
|
||||||
|
'Status determines the color of the notice and the icon.',
|
||||||
|
},
|
||||||
|
isDismissible: {
|
||||||
|
control: 'boolean',
|
||||||
|
description:
|
||||||
|
'Determines whether the notice can be dismissed by the user. When set to true, a close icon will be displayed on the banner.',
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
description:
|
||||||
|
'Optional summary text shown above notice content, used when several notices are listed together.',
|
||||||
|
control: 'text',
|
||||||
|
},
|
||||||
|
className: {
|
||||||
|
description: 'Additional class name to give to the notice.',
|
||||||
|
control: 'text',
|
||||||
|
},
|
||||||
|
spokenMessage: {
|
||||||
|
description:
|
||||||
|
'Optionally provided to change the spoken message for assistive technology. If not provided, the `children` prop will be used as the spoken message.',
|
||||||
|
control: 'text',
|
||||||
|
},
|
||||||
|
politeness: {
|
||||||
|
control: 'radio',
|
||||||
|
options: [ 'polite', 'assertive' ],
|
||||||
|
description:
|
||||||
|
'Determines the level of politeness for the notice for assistive technology.',
|
||||||
|
},
|
||||||
|
children: {
|
||||||
|
description:
|
||||||
|
'The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.',
|
||||||
|
disable: true,
|
||||||
|
},
|
||||||
|
onRemove: {
|
||||||
|
description:
|
||||||
|
'Function called when dismissing the notice. When the close icon is clicked or the Escape key is pressed, this function will be called.',
|
||||||
|
disable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
component: Snackbar,
|
||||||
|
} as Meta< SnackbarProps >;
|
||||||
|
|
||||||
|
const Template: StoryFn< SnackbarProps > = ( args ) => {
|
||||||
|
return <Snackbar { ...args } />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = Template.bind( {} );
|
||||||
|
Default.args = {
|
||||||
|
children: 'This is a default snackbar notice',
|
||||||
|
status: 'default',
|
||||||
|
isDismissible: true,
|
||||||
|
summary: undefined,
|
||||||
|
className: undefined,
|
||||||
|
spokenMessage: undefined,
|
||||||
|
politeness: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Error = Template.bind( {} );
|
||||||
|
Error.args = {
|
||||||
|
children: 'This is an error snackbar notice',
|
||||||
|
status: 'error',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Warning = Template.bind( {} );
|
||||||
|
Warning.args = {
|
||||||
|
children: 'This is a warning snackbar notice',
|
||||||
|
status: 'warning',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Info = Template.bind( {} );
|
||||||
|
Info.args = {
|
||||||
|
children: 'This is an informational snackbar notice',
|
||||||
|
status: 'info',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Success = Template.bind( {} );
|
||||||
|
Success.args = {
|
||||||
|
children: 'This is a success snackbar notice',
|
||||||
|
status: 'success',
|
||||||
|
};
|
|
@ -9,8 +9,10 @@
|
||||||
bottom: $gap-large;
|
bottom: $gap-large;
|
||||||
left: $gap-large;
|
left: $gap-large;
|
||||||
right: $gap-large;
|
right: $gap-large;
|
||||||
|
}
|
||||||
|
|
||||||
.wc-block-components-notice-banner {
|
.wc-block-components-notice-snackbar-list .wc-block-components-notice-banner,
|
||||||
|
.wc-block-components-notice-banner.wc-block-components-notice-snackbar {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
width: auto;
|
width: auto;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
|
@ -18,7 +20,13 @@
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: $gap-large 0 0;
|
margin: $gap-large $gap 0 0;
|
||||||
|
|
||||||
|
&.is-error,
|
||||||
|
&.is-info,
|
||||||
|
&.is-success {
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
&.is-default {
|
&.is-default {
|
||||||
border-color: $gray-800;
|
border-color: $gray-800;
|
||||||
|
@ -28,7 +36,6 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice-transition-enter {
|
.notice-transition-enter {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { useState } from '@wordpress/element';
|
||||||
import { __TabsWithoutInstanceId as Tabs, TabsProps } from '..';
|
import { __TabsWithoutInstanceId as Tabs, TabsProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/Tabs',
|
title: 'Base Components/Tabs',
|
||||||
component: Tabs,
|
component: Tabs,
|
||||||
args: {
|
args: {
|
||||||
tabs: [
|
tabs: [
|
|
@ -35,12 +35,10 @@ describe( 'formatError', () => {
|
||||||
const mockResponse = new Response( mockMalformedJson, { status: 400 } );
|
const mockResponse = new Response( mockMalformedJson, { status: 400 } );
|
||||||
|
|
||||||
const error = await formatError( mockResponse );
|
const error = await formatError( mockResponse );
|
||||||
const expectedError = {
|
|
||||||
message:
|
|
||||||
'invalid json response body at reason: Unexpected end of JSON input',
|
|
||||||
type: 'general',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect( error ).toEqual( expectedError );
|
expect( error.message ).toContain(
|
||||||
|
'invalid json response body at reason:'
|
||||||
|
);
|
||||||
|
expect( error.type ).toEqual( 'general' );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -40,11 +40,11 @@ export interface ErrorPlaceholderProps {
|
||||||
/**
|
/**
|
||||||
* Callback to retry an action.
|
* Callback to retry an action.
|
||||||
*/
|
*/
|
||||||
onRetry?: () => void;
|
onRetry?: ( () => void ) | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ErrorPlaceholder = ( {
|
const ErrorPlaceholder = ( {
|
||||||
className,
|
className = '',
|
||||||
error,
|
error,
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
onRetry,
|
onRetry,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type { Story, Meta } from '@storybook/react';
|
||||||
import ErrorMessage, { ErrorMessageProps } from '../error-message';
|
import ErrorMessage, { ErrorMessageProps } from '../error-message';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/editor-components/Errors/Base Error Atom',
|
title: 'Editor Components/Errors/Base Error Atom',
|
||||||
component: ErrorMessage,
|
component: ErrorMessage,
|
||||||
} as Meta< ErrorMessageProps >;
|
} as Meta< ErrorMessageProps >;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import type { Story, Meta } from '@storybook/react';
|
import type { StoryFn, Meta } from '@storybook/react';
|
||||||
import { useArgs } from '@storybook/client-api';
|
import { useArgs } from '@storybook/client-api';
|
||||||
import { INTERACTION_TIMEOUT } from '@woocommerce/storybook-controls';
|
import { INTERACTION_TIMEOUT } from '@woocommerce/storybook-controls';
|
||||||
|
|
||||||
|
@ -11,11 +11,11 @@ import { INTERACTION_TIMEOUT } from '@woocommerce/storybook-controls';
|
||||||
import ErrorPlaceholder, { ErrorPlaceholderProps } from '..';
|
import ErrorPlaceholder, { ErrorPlaceholderProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/editor-components/Errors',
|
title: 'Editor Components/Errors/Error Placeholder',
|
||||||
component: ErrorPlaceholder,
|
component: ErrorPlaceholder,
|
||||||
} as Meta< ErrorPlaceholderProps >;
|
} as Meta< ErrorPlaceholderProps >;
|
||||||
|
|
||||||
const Template: Story< ErrorPlaceholderProps > = ( args ) => {
|
const Template: StoryFn< ErrorPlaceholderProps > = ( args ) => {
|
||||||
const [ { isLoading }, setArgs ] = useArgs();
|
const [ { isLoading }, setArgs ] = useArgs();
|
||||||
|
|
||||||
const onRetry = args.onRetry
|
const onRetry = args.onRetry
|
||||||
|
@ -63,7 +63,7 @@ UnknownError.args = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NoRetry: Story< ErrorPlaceholderProps > = ( args ) => {
|
export const NoRetry: StoryFn< ErrorPlaceholderProps > = ( args ) => {
|
||||||
return <ErrorPlaceholder { ...args } onRetry={ undefined } />;
|
return <ErrorPlaceholder { ...args } onRetry={ undefined } />;
|
||||||
};
|
};
|
||||||
NoRetry.args = {
|
NoRetry.args = {
|
|
@ -9,7 +9,7 @@ import type { Story, Meta } from '@storybook/react';
|
||||||
import ExternalLinkCard, { ExternalLinkCardProps } from '..';
|
import ExternalLinkCard, { ExternalLinkCardProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/editor-components/ExternalLinkCard',
|
title: 'Editor Components/ExternalLinkCard',
|
||||||
component: ExternalLinkCard,
|
component: ExternalLinkCard,
|
||||||
} as Meta< ExternalLinkCardProps >;
|
} as Meta< ExternalLinkCardProps >;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
||||||
|
import { Meta, Title, IconGallery, IconItem } from '@storybook/blocks';
|
||||||
|
import * as icons from '../index';
|
||||||
|
|
||||||
|
<Meta title="Icons/Icon Library" />
|
||||||
|
|
||||||
|
# Icon Library
|
||||||
|
|
||||||
|
<IconGallery>
|
||||||
|
{ Object.entries( icons ).map( ( [ name, icon ] ) => {
|
||||||
|
return (
|
||||||
|
<IconItem key={ name } name={ name }>
|
||||||
|
{ typeof icon === 'function' ? icon( {} ) : icon }
|
||||||
|
</IconItem>
|
||||||
|
);
|
||||||
|
} ) }
|
||||||
|
</IconGallery>
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { bagAlt } from '@woocommerce/icons';
|
||||||
|
import { Icon } from '@wordpress/icons';
|
||||||
|
|
||||||
|
const IconExample = () => <Icon icon={ bagAlt } />;
|
||||||
|
```
|
|
@ -1,97 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import type { Story } from '@storybook/react';
|
|
||||||
import { useState } from '@wordpress/element';
|
|
||||||
import { Icon } from '@wordpress/icons';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dependencies
|
|
||||||
*/
|
|
||||||
import * as icons from '../index';
|
|
||||||
const { ...availableIcons } = icons;
|
|
||||||
|
|
||||||
export const Library: Story = ( args ) => {
|
|
||||||
const [ filter, setFilter ] = useState( '' );
|
|
||||||
|
|
||||||
const filteredIcons = Object.entries( availableIcons ).reduce(
|
|
||||||
( acc: Record< string, unknown >, [ name, icon ] ) => {
|
|
||||||
if ( name.includes( filter ) ) {
|
|
||||||
acc[ name ] = icon;
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Partial< typeof availableIcons >
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={ { padding: '20px' } }>
|
|
||||||
<label htmlFor="filter-icons" style={ { paddingRight: '30px' } }>
|
|
||||||
Filter Icons
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="filter-icons"
|
|
||||||
type="search"
|
|
||||||
value={ filter }
|
|
||||||
placeholder="Icon name"
|
|
||||||
onChange={ ( event ) => setFilter( event.target.value ) }
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
style={ {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'bottom',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
} }
|
|
||||||
>
|
|
||||||
{ Object.entries( filteredIcons ).map( ( [ name, icon ] ) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={ name }
|
|
||||||
style={ {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
width: '25%',
|
|
||||||
padding: '25px 0 25px 0',
|
|
||||||
} }
|
|
||||||
>
|
|
||||||
<strong
|
|
||||||
style={ {
|
|
||||||
width: '200px',
|
|
||||||
} }
|
|
||||||
>
|
|
||||||
{ name }
|
|
||||||
</strong>
|
|
||||||
<div
|
|
||||||
style={ {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
} }
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className={ args.className }
|
|
||||||
icon={ icon }
|
|
||||||
/>
|
|
||||||
<Icon
|
|
||||||
className={ args.className }
|
|
||||||
style={ { paddingLeft: '10px' } }
|
|
||||||
icon={ icon }
|
|
||||||
size={ 36 }
|
|
||||||
/>
|
|
||||||
<Icon
|
|
||||||
className={ args.className }
|
|
||||||
style={ { paddingLeft: '10px' } }
|
|
||||||
icon={ icon }
|
|
||||||
size={ 48 }
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} ) }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
Library.parameters = {
|
|
||||||
controls: { include: [], hideNoControlsWarning: true },
|
|
||||||
};
|
|
||||||
Library.storyName = 'Icon Library';
|
|
File diff suppressed because it is too large
Load Diff
|
@ -77,8 +77,8 @@
|
||||||
"release": "sh ./bin/wordpress-deploy.sh",
|
"release": "sh ./bin/wordpress-deploy.sh",
|
||||||
"rimraf": "./node_modules/rimraf/bin.js",
|
"rimraf": "./node_modules/rimraf/bin.js",
|
||||||
"start": "rimraf build/* && cross-env BABEL_ENV=default CHECK_CIRCULAR_DEPS=true webpack --watch",
|
"start": "rimraf build/* && cross-env BABEL_ENV=default CHECK_CIRCULAR_DEPS=true webpack --watch",
|
||||||
"storybook": "start-storybook -c ./storybook -p 6006 --ci",
|
"storybook": "storybook dev -c ./storybook -p 6006 --ci",
|
||||||
"storybook:build": "BABEL_ENV=development build-storybook -c ./storybook -o ./storybook/dist",
|
"storybook:build": "BABEL_ENV=development storybook build -c ./storybook -o ./storybook/dist",
|
||||||
"storybook:deploy": "rimraf ./storybook/dist/* && npm run storybook:build && gh-pages -d ./storybook/dist",
|
"storybook:deploy": "rimraf ./storybook/dist/* && npm run storybook:build && gh-pages -d ./storybook/dist",
|
||||||
"test": "wp-scripts test-unit-js --config tests/js/jest.config.json",
|
"test": "wp-scripts test-unit-js --config tests/js/jest.config.json",
|
||||||
"test:debug": "ndb .",
|
"test:debug": "ndb .",
|
||||||
|
@ -110,26 +110,26 @@
|
||||||
"@actions/github": "5.1.1",
|
"@actions/github": "5.1.1",
|
||||||
"@automattic/color-studio": "2.5.0",
|
"@automattic/color-studio": "2.5.0",
|
||||||
"@babel/cli": "7.23.0",
|
"@babel/cli": "7.23.0",
|
||||||
"@babel/core": "7.22.9",
|
"@babel/core": "7.23.2",
|
||||||
"@babel/plugin-proposal-class-properties": "7.18.6",
|
"@babel/plugin-proposal-class-properties": "7.18.6",
|
||||||
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
||||||
"@babel/plugin-syntax-jsx": "7.22.5",
|
"@babel/plugin-syntax-jsx": "7.22.5",
|
||||||
"@babel/polyfill": "7.12.1",
|
"@babel/polyfill": "7.12.1",
|
||||||
"@babel/preset-typescript": "7.22.5",
|
"@babel/preset-typescript": "7.23.2",
|
||||||
"@bartekbp/typescript-checkstyle": "5.0.0",
|
"@bartekbp/typescript-checkstyle": "5.0.0",
|
||||||
"@octokit/action": "5.0.2",
|
"@octokit/action": "5.0.2",
|
||||||
"@octokit/graphql": "5.0.5",
|
"@octokit/graphql": "5.0.5",
|
||||||
"@playwright/test": "1.38.1",
|
"@playwright/test": "1.38.1",
|
||||||
"@storybook/addon-a11y": "6.5.16",
|
"@storybook/addon-a11y": "7.5.2",
|
||||||
"@storybook/addon-essentials": "6.5.15",
|
"@storybook/addon-docs": "^7.5.2",
|
||||||
"@storybook/addon-links": "6.5.15",
|
"@storybook/addon-essentials": "7.5.2",
|
||||||
"@storybook/addon-postcss": "^2.0.0",
|
"@storybook/addon-links": "7.5.2",
|
||||||
"@storybook/addon-storysource": "6.5.15",
|
"@storybook/addon-storysource": "7.5.2",
|
||||||
"@storybook/addons": "6.5.15",
|
"@storybook/addon-styling-webpack": "^0.0.5",
|
||||||
"@storybook/builder-webpack5": "^6.5.15",
|
"@storybook/addons": "7.5.2",
|
||||||
"@storybook/client-api": "7.1.1",
|
"@storybook/client-api": "7.5.2",
|
||||||
"@storybook/manager-webpack5": "^6.5.15",
|
"@storybook/react": "7.5.2",
|
||||||
"@storybook/react": "6.5.15",
|
"@storybook/react-webpack5": "^7.5.2",
|
||||||
"@testing-library/dom": "9.3.3",
|
"@testing-library/dom": "9.3.3",
|
||||||
"@testing-library/jest-dom": "5.16.5",
|
"@testing-library/jest-dom": "5.16.5",
|
||||||
"@testing-library/react": "12.1.5",
|
"@testing-library/react": "12.1.5",
|
||||||
|
@ -164,12 +164,12 @@
|
||||||
"@woocommerce/eslint-plugin": "2.2.0",
|
"@woocommerce/eslint-plugin": "2.2.0",
|
||||||
"@woocommerce/woocommerce-rest-api": "1.0.1",
|
"@woocommerce/woocommerce-rest-api": "1.0.1",
|
||||||
"@wordpress/api-fetch": "6.21.0",
|
"@wordpress/api-fetch": "6.21.0",
|
||||||
"@wordpress/babel-preset-default": "7.22.0",
|
"@wordpress/babel-preset-default": "7.28.0",
|
||||||
"@wordpress/base-styles": "4.35.0",
|
"@wordpress/base-styles": "4.35.0",
|
||||||
"@wordpress/block-editor": "8.2.0",
|
"@wordpress/block-editor": "8.2.0",
|
||||||
"@wordpress/blocks": "11.1.5",
|
"@wordpress/blocks": "11.1.5",
|
||||||
"@wordpress/browserslist-config": "5.21.0",
|
"@wordpress/browserslist-config": "5.21.0",
|
||||||
"@wordpress/components": "19.1.5",
|
"@wordpress/components": "19.17.0",
|
||||||
"@wordpress/data-controls": "2.2.7",
|
"@wordpress/data-controls": "2.2.7",
|
||||||
"@wordpress/dependency-extraction-webpack-plugin": "4.6.0",
|
"@wordpress/dependency-extraction-webpack-plugin": "4.6.0",
|
||||||
"@wordpress/dom": "3.27.0",
|
"@wordpress/dom": "3.27.0",
|
||||||
|
@ -196,13 +196,16 @@
|
||||||
"core-js": "3.25.0",
|
"core-js": "3.25.0",
|
||||||
"create-file-webpack": "1.0.2",
|
"create-file-webpack": "1.0.2",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
|
"css-loader": "^6.8.1",
|
||||||
"cssnano": "5.1.12",
|
"cssnano": "5.1.12",
|
||||||
"deep-freeze": "0.0.1",
|
"deep-freeze": "0.0.1",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
"eslint-import-resolver-typescript": "3.2.4",
|
"eslint-import-resolver-typescript": "3.2.4",
|
||||||
"eslint-import-resolver-webpack": "0.13.2",
|
"eslint-import-resolver-webpack": "0.13.2",
|
||||||
"eslint-plugin-import": "2.28.1",
|
"eslint-plugin-import": "2.28.1",
|
||||||
"eslint-plugin-playwright": "0.15.3",
|
"eslint-plugin-playwright": "0.15.3",
|
||||||
"eslint-plugin-rulesdir": "^0.2.2",
|
"eslint-plugin-rulesdir": "^0.2.2",
|
||||||
|
"eslint-plugin-storybook": "^0.6.15",
|
||||||
"eslint-plugin-woocommerce": "file:bin/eslint-plugin-woocommerce",
|
"eslint-plugin-woocommerce": "file:bin/eslint-plugin-woocommerce",
|
||||||
"eslint-plugin-you-dont-need-lodash-underscore": "6.12.0",
|
"eslint-plugin-you-dont-need-lodash-underscore": "6.12.0",
|
||||||
"expect-puppeteer": "6.1.1",
|
"expect-puppeteer": "6.1.1",
|
||||||
|
@ -240,7 +243,8 @@
|
||||||
"rimraf": "5.0.5",
|
"rimraf": "5.0.5",
|
||||||
"rtlcss": "^4.0.0",
|
"rtlcss": "^4.0.0",
|
||||||
"sass-loader": "10.1.0",
|
"sass-loader": "10.1.0",
|
||||||
"storybook-addon-react-docgen": "1.2.43",
|
"storybook": "^7.5.2",
|
||||||
|
"storybook-addon-react-docgen": "1.2.44",
|
||||||
"terser-webpack-plugin": "5.3.6",
|
"terser-webpack-plugin": "5.3.6",
|
||||||
"typescript": "4.7.4",
|
"typescript": "4.7.4",
|
||||||
"utility-types": "3.10.0",
|
"utility-types": "3.10.0",
|
||||||
|
@ -259,7 +263,7 @@
|
||||||
"@dnd-kit/modifiers": "^6.0.0",
|
"@dnd-kit/modifiers": "^6.0.0",
|
||||||
"@dnd-kit/sortable": "^7.0.1",
|
"@dnd-kit/sortable": "^7.0.1",
|
||||||
"@dnd-kit/utilities": "^3.2.0",
|
"@dnd-kit/utilities": "^3.2.0",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@preact/signals": "^1.1.2",
|
"@preact/signals": "^1.1.2",
|
||||||
"@woocommerce/tracks": "^1.3.0",
|
"@woocommerce/tracks": "^1.3.0",
|
||||||
"@wordpress/autop": "3.16.0",
|
"@wordpress/autop": "3.16.0",
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type { Story, Meta } from '@storybook/react';
|
||||||
import CheckboxControl, { CheckboxControlProps } from '..';
|
import CheckboxControl, { CheckboxControlProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/Checkout Blocks/CheckboxControl',
|
title: 'Checkout Components/CheckboxControl',
|
||||||
component: CheckboxControl,
|
component: CheckboxControl,
|
||||||
args: {
|
args: {
|
||||||
instanceId: 'my-checkbox-id',
|
instanceId: 'my-checkbox-id',
|
|
@ -14,7 +14,7 @@ import {
|
||||||
import Fees, { TotalsFeesProps } from '..';
|
import Fees, { TotalsFeesProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/Checkout Blocks/totals/Fees',
|
title: 'Checkout Components/Totals/Fees',
|
||||||
component: Fees,
|
component: Fees,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
currency: currencyControl,
|
currency: currencyControl,
|
|
@ -10,7 +10,7 @@ import { currencies, currencyControl } from '@woocommerce/storybook-controls';
|
||||||
import Item, { TotalsItemProps } from '..';
|
import Item, { TotalsItemProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/Checkout Blocks/totals/Item',
|
title: 'Checkout Components/Totals/Item',
|
||||||
component: Item,
|
component: Item,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
currency: currencyControl,
|
currency: currencyControl,
|
|
@ -10,7 +10,7 @@ import { currencies, currencyControl } from '@woocommerce/storybook-controls';
|
||||||
import Subtotal, { SubtotalProps } from '..';
|
import Subtotal, { SubtotalProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/Checkout Blocks/totals/Subtotal',
|
title: 'Checkout Components/Totals/Subtotal',
|
||||||
component: Subtotal,
|
component: Subtotal,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
currency: currencyControl,
|
currency: currencyControl,
|
|
@ -10,7 +10,7 @@ import { currencies, currencyControl } from '@woocommerce/storybook-controls';
|
||||||
import Taxes, { TotalsTaxesProps } from '..';
|
import Taxes, { TotalsTaxesProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/Checkout Blocks/totals/Taxes',
|
title: 'Checkout Components/Totals/Taxes',
|
||||||
component: Taxes,
|
component: Taxes,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
currency: currencyControl,
|
currency: currencyControl,
|
|
@ -40,7 +40,6 @@ export interface ChipProps {
|
||||||
*
|
*
|
||||||
* Each chip defaults to a list element but this can be customized by providing
|
* Each chip defaults to a list element but this can be customized by providing
|
||||||
* a wrapperElement.
|
* a wrapperElement.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
const Chip: React.FC< ChipProps > = ( {
|
const Chip: React.FC< ChipProps > = ( {
|
||||||
text,
|
text,
|
||||||
|
|
|
@ -36,16 +36,6 @@ export interface RemovableChipProps extends ChipProps {
|
||||||
/**
|
/**
|
||||||
* Component used to render a "chip" -- an item containing some text with
|
* Component used to render a "chip" -- an item containing some text with
|
||||||
* an X button to remove/dismiss each chip.
|
* an X button to remove/dismiss each chip.
|
||||||
*
|
|
||||||
* @param {Object} props Incoming props for the component.
|
|
||||||
* @param {string} props.ariaLabel Aria label content.
|
|
||||||
* @param {string} props.className CSS class used.
|
|
||||||
* @param {boolean} props.disabled Whether action is disabled or not.
|
|
||||||
* @param {function():any} props.onRemove Function to call when remove event is fired.
|
|
||||||
* @param {boolean} props.removeOnAnyClick Whether to expand click area for remove event.
|
|
||||||
* @param {string} props.text The text for the chip.
|
|
||||||
* @param {string} props.screenReaderText The screen reader text for the chip.
|
|
||||||
* @param {Object} props.props Rest of props passed into component.
|
|
||||||
*/
|
*/
|
||||||
export const RemovableChip = ( {
|
export const RemovableChip = ( {
|
||||||
ariaLabel = '',
|
ariaLabel = '',
|
||||||
|
|
|
@ -11,7 +11,7 @@ const availableElements = [ 'li', 'div', 'span' ];
|
||||||
const availableRadii = [ 'none', 'small', 'medium', 'large' ];
|
const availableRadii = [ 'none', 'small', 'medium', 'large' ];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/Chip',
|
title: 'Block Components/Chip',
|
||||||
component: Chip,
|
component: Chip,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
element: {
|
element: {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { RemovableChip, RemovableChipProps } from '../removable-chip';
|
||||||
const availableElements = [ 'li', 'div', 'span' ];
|
const availableElements = [ 'li', 'div', 'span' ];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@base-components/Chip/RemovableChip',
|
title: 'Block Components/RemovableChip',
|
||||||
component: RemovableChip,
|
component: RemovableChip,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
element: {
|
element: {
|
||||||
|
|
|
@ -10,8 +10,12 @@ import { useArgs } from '@storybook/client-api';
|
||||||
import FormattedMonetaryAmount, { type FormattedMonetaryAmountProps } from '..';
|
import FormattedMonetaryAmount, { type FormattedMonetaryAmountProps } from '..';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'WooCommerce Blocks/@woocommerce-blocks-components/FormattedMonetaryAmount',
|
title: 'Block Components/FormattedMonetaryAmount',
|
||||||
component: FormattedMonetaryAmount,
|
component: FormattedMonetaryAmount,
|
||||||
|
args: {
|
||||||
|
displayType: 'text',
|
||||||
|
value: 1234,
|
||||||
|
},
|
||||||
argTypes: {
|
argTypes: {
|
||||||
className: {
|
className: {
|
||||||
control: 'text',
|
control: 'text',
|
||||||
|
@ -39,7 +43,6 @@ export default {
|
||||||
},
|
},
|
||||||
control: 'select',
|
control: 'select',
|
||||||
options: [ 'input', 'text' ],
|
options: [ 'input', 'text' ],
|
||||||
defaultValue: 'text',
|
|
||||||
description:
|
description:
|
||||||
'Whether this should be an input or just a text display.',
|
'Whether this should be an input or just a text display.',
|
||||||
},
|
},
|
||||||
|
@ -50,7 +53,6 @@ export default {
|
||||||
summary: 'number',
|
summary: 'number',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultValue: 1234,
|
|
||||||
description:
|
description:
|
||||||
'The raw value of the currency, it will be formatted depending on the props of this component.',
|
'The raw value of the currency, it will be formatted depending on the props of this component.',
|
||||||
},
|
},
|
|
@ -1,16 +1,30 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
const path = require( 'path' );
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
stories: [
|
stories: [
|
||||||
// WooCommerce Blocks stuff (anywhere in repo!)
|
// WooCommerce Blocks stuff (anywhere in repo!)
|
||||||
'../assets/js/**/stories/*.@(js|jsx|ts|tsx)',
|
'../assets/js/**/stories/*.stories.@(js|jsx|ts|tsx)',
|
||||||
'../packages/**/stories/*.@(js|jsx|ts|tsx)',
|
'../packages/**/stories/*.stories.@(js|jsx|ts|tsx)',
|
||||||
|
'../assets/js/**/*.mdx',
|
||||||
],
|
],
|
||||||
addons: [
|
addons: [
|
||||||
'@storybook/addon-essentials',
|
'@storybook/addon-essentials',
|
||||||
|
'@storybook/addon-docs',
|
||||||
'@storybook/addon-a11y',
|
'@storybook/addon-a11y',
|
||||||
'@storybook/addon-links',
|
'@storybook/addon-links',
|
||||||
'storybook-addon-react-docgen',
|
'storybook-addon-react-docgen',
|
||||||
'@storybook/addon-postcss',
|
'@storybook/addon-styling-webpack',
|
||||||
],
|
],
|
||||||
|
typescript: {
|
||||||
|
reactDocgen: 'react-docgen-typescript-plugin',
|
||||||
|
},
|
||||||
|
docs: {
|
||||||
|
autodocs: true,
|
||||||
|
defaultName: 'Docs',
|
||||||
|
},
|
||||||
features: {
|
features: {
|
||||||
babelModeV7: true,
|
babelModeV7: true,
|
||||||
emotionAlias: false,
|
emotionAlias: false,
|
||||||
|
@ -18,9 +32,6 @@ module.exports = {
|
||||||
core: {
|
core: {
|
||||||
builder: 'webpack5',
|
builder: 'webpack5',
|
||||||
},
|
},
|
||||||
typescript: {
|
|
||||||
reactDocgen: 'react-docgen-typescript-plugin',
|
|
||||||
},
|
|
||||||
// webpackFinal field was added in following PR: https://github.com/woocommerce/woocommerce-blocks/pull/7514
|
// webpackFinal field was added in following PR: https://github.com/woocommerce/woocommerce-blocks/pull/7514
|
||||||
// This fixes "storybook build issue" related to framer-motion library.
|
// This fixes "storybook build issue" related to framer-motion library.
|
||||||
// Solution is from this commment: https://github.com/storybookjs/storybook/issues/16690#issuecomment-971579785
|
// Solution is from this commment: https://github.com/storybookjs/storybook/issues/16690#issuecomment-971579785
|
||||||
|
@ -31,6 +42,16 @@ module.exports = {
|
||||||
type: 'javascript/auto',
|
type: 'javascript/auto',
|
||||||
} );
|
} );
|
||||||
config.externals = [ 'react-dom/client' ];
|
config.externals = [ 'react-dom/client' ];
|
||||||
|
// https://github.com/storybookjs/storybook/discussions/22650#discussioncomment-6414161
|
||||||
|
config.resolve.alias = {
|
||||||
|
...config.resolve.alias,
|
||||||
|
react: path.resolve( __dirname, '../node_modules/react' ),
|
||||||
|
'react-dom': path.resolve( __dirname, '../node_modules/react-dom' ),
|
||||||
|
};
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
|
framework: {
|
||||||
|
name: '@storybook/react-webpack5',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,10 +12,18 @@ export const parameters = {
|
||||||
date: /Date$/,
|
date: /Date$/,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
layout: 'centered',
|
||||||
a11y: {
|
a11y: {
|
||||||
element: '#storybook-root',
|
element: '#storybook-root',
|
||||||
config: {},
|
config: {},
|
||||||
options: {},
|
options: {},
|
||||||
manual: true,
|
manual: true,
|
||||||
},
|
},
|
||||||
|
docs: {
|
||||||
|
toc: {
|
||||||
|
headingSelector: 'h2, h3',
|
||||||
|
title: 'Table of Contents',
|
||||||
|
disable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,3 +30,7 @@ body {
|
||||||
.button .screen-reader-text {
|
.button .screen-reader-text {
|
||||||
height: auto; /* Fixes a Safari+VoiceOver bug, see ticket #42006 */
|
height: auto; /* Fixes a Safari+VoiceOver bug, see ticket #42006 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.force-canvas-height .innerZoomElementWrapper {
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue