Skip to content

Commit

Permalink
Notice: refactor to TypeScript (#47118)
Browse files Browse the repository at this point in the history
Co-authored-by: Lena Morita <lena@jaguchi.com>
Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com>
  • Loading branch information
3 people committed Jan 30, 2023
1 parent aac398e commit e728b81
Show file tree
Hide file tree
Showing 15 changed files with 480 additions and 260 deletions.
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
([#47384](https://github.com/WordPress/gutenberg/pull/47384)).
- `Button`: Convert to TypeScript ([#46997](https://github.com/WordPress/gutenberg/pull/46997)).
- `QueryControls`: Convert to TypeScript ([#46721](https://github.com/WordPress/gutenberg/pull/46721)).
- `Notice`: refactor to TypeScript ([47118](https://github.com/WordPress/gutenberg/pull/47118)).

### Bug Fix

Expand Down
131 changes: 89 additions & 42 deletions packages/components/src/notice/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,69 +16,59 @@ A Notice displays a succinct message. It can also offer the user options, like v

Use Notices to communicate things that are important but don’t necessarily require action — a user can keep using the product even if they don’t choose to act on a Notice. They are less interruptive than a Modal.

### Anatomy

![Diagram of a Notice component with numbered labels](https://make.wordpress.org/design/files/2019/03/Notice-Anatomy.png)

1. Container (status indicated with color)
2. Icon (optional)
3. Message
4. Dismiss icon (optional)

### Usage

Notices display at the top of the screen, below any toolbars anchored to the top of the page. They’re persistent and non-modal. Since they don’t overlay the content, users can ignore or dismiss them, and choose when to interact with them.

![](https://make.wordpress.org/design/files/2019/03/Notice-States.png)

Notices are color-coded to indicate the type of message being communicated:

- **Default** notices have **no background**.
- **Informational** notices are **blue** by default.
- If there is a parent `Theme` component with an `accent` color prop, informational notices will take on that color instead.
- **Success** notices are **green.**
- **Warning** notices are **yellow\*\***.\*\*
- **Error** notices are **red.**
- **Informational** notices are **blue** by default.
- If there is a parent `Theme` component with an `accent` color prop, informational notices will take on that color instead.
- **Success** notices are **green.**
- **Warning** notices are **yellow\*\***.\*\*
- **Error** notices are **red.**

If an icon is included in the Notice, it should be color-coded to match the Notice state.

### Do's and Don'ts
**Do** use a Notice when you want to communicate a message of medium importance.

![A success Notice for updating a post](https://make.wordpress.org/design/files/2019/03/Notice-Do-1-alt.png)

**Do**
Do use a Notice when you want to communicate a message of medium importance.
---
**Don’t** use a Notice for a message that requires immediate attention and action from the user. Use a Modal for this instead.

![A Notice that requires an immediate action](https://make.wordpress.org/design/files/2019/03/Notice-Dont-1-alt.png)

**Don’t**
Don't use a Notice for a message that requires immediate attention and action from the user. Use a Modal for this instead.
---
**Do** display Notices at the top of the screen, below any toolbars.

![A success Notice for publishing a post](https://make.wordpress.org/design/files/2019/03/Notice-Do-2-alt.png)

**Do**
Do display Notices at the top of the screen, below any toolbars.
---
**Don’t** show Notices on top of toolbars.

![A success Notice on top of the editor toolbar](https://make.wordpress.org/design/files/2019/03/Notice-Dont-2-alt.png)

**Don’t**
Don't show Notices on top of toolbars.
---
**Do** use color to indicate the type of message being communicated.

![An error Notice using red](https://make.wordpress.org/design/files/2019/03/Notice-Do-3-alt.png)

**Do**
Do use color to indicate the type of message being communicated.
---
**Don’t** apply any colors other than those for Warnings, Success, or Errors.

![An error Notice using purple](https://make.wordpress.org/design/files/2019/03/Notice-Dont-3-alt.png)

**Don’t**
Don't apply any colors other than those for Warnings, Success, or Errors.

## Development guidelines

### Usage

To display a plain notice, pass `Notice` a string:

```jsx
import { Notice } from `@wordpress/components`;

const MyNotice = () => (
<Notice status="error">An unknown error occurred.</Notice>
);
Expand All @@ -87,6 +77,8 @@ const MyNotice = () => (
For more complex markup, you can pass any JSX element:

```jsx
import { Notice } from `@wordpress/components`;

const MyNotice = () => (
<Notice status="error">
<p>
Expand All @@ -96,21 +88,76 @@ const MyNotice = () => (
);
```

#### Props
### Props

The following props are used to control the behavior of the component.

- `children`: (string) The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.
- `spokenMessage`: (string) Used to provide a custom spoken message in place of the `children` default.
- `status`: (string) can be `warning` (yellow), `success` (green), `error` (red), or `info`. Defaults to `info`.
- `onRemove`: function called when dismissing the notice
- `politeness`: (string) A politeness level for the notice's spoken message. Should be provided as one of the valid options for [an `aria-live` attribute value](https://www.w3.org/TR/wai-aria-1.1/#aria-live). If not provided, a sensible default is used based on the notice status. Note that this value should be considered a suggestion; assistive technologies may override it based on internal heuristics.
- A value of `'assertive'` is to be used for important, and usually time-sensitive, information. It will interrupt anything else the screen reader is announcing in that moment.
- A value of `'polite'` is to be used for advisory information. It should not interrupt what the screen reader is announcing in that moment (the "speech queue") or interrupt the current task.
- `isDismissible`: (boolean) defaults to true, whether the notice should be dismissible or not
- `onDismiss` : callback function which is executed when the notice is dismissed. It is distinct from onRemove, which _looks_ like a callback but is actually the function to call to remove the notice from the UI.
- `actions`: (array) an array of action objects. Each member object should contain a `label` and either a `url` link string or `onClick` callback function. A `className` property can be used to add custom classes to the button styles. The default appearance of the button is inferred based on whether `url` or `onClick` are provided, rendering the button as a link if appropriate. A `noDefaultClasses` property value of `true` will remove all default styling. You can denote a primary button action for a notice by passing the `variant` property with a value of `primary`.
#### `children`: `ReactNode`

The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.

- Required: Yes

#### `spokenMessage`: `ReactNode`

Used to provide a custom spoken message in place of the `children` default.

- Required: No
- Default: `children`

#### `status`: `'warning' | 'success' | 'error' | 'info'`

Determines the color of the notice: `warning` (yellow), `success` (green), `error` (red), or `'info'`. By default `'info'` will be blue, but if there is a parent Theme component with an accent color prop, the notice will take on that color instead.

- Required: No
- Default: `info`

#### `onRemove`: `() => void`

A function called to dismiss/remove the notice.

- Required: No
- Default: `noop`

#### `politeness`: `'polite' | 'assertive'`

A politeness level for the notice's spoken message. Should be provided as one of the valid options for [an `aria-live` attribute value](https://www.w3.org/TR/wai-aria-1.1/#aria-live).

- A value of `'assertive'` is to be used for important, and usually time-sensitive, information. It will interrupt anything else the screen reader is announcing in that moment.
- A value of `'polite'` is to be used for advisory information. It should not interrupt what the screen reader is announcing in that moment (the "speech queue") or interrupt the current task.

Note that this value should be considered a suggestion; assistive technologies may override it based on internal heuristics.

- Required: No
- Default: `'assertive'` or `'polite'`, based on the notice status.

#### `isDismissible`: `boolean`

Whether the notice should be dismissible or not

- Required: No
- Default: `true`

#### `onDismiss` : `() => void`

A deprecated alternative to `onRemove`. This prop is kept for compatibilty reasons but should be avoided.

- Requiered: No
- Default: `noop`

#### `actions`: `Array<NoticeAction>`.

An array of notice actions. Each member object should contain:

- `label`: `string` containing the text of the button/link
- `url`: `string` OR `onClick`: `( event: SyntheticEvent ) => void` to specify what the action does.
- `className`: `string` (optional) to add custom classes to the button styles.
- `noDefaultClasses`: `boolean` (optional) A value of `true` will remove all default styling.
- `variant`: `'primary' | 'secondary' | 'link'` (optional) You can denote a primary button action for a notice by passing a value of `primary`.

The default appearance of an action button is inferred based on whether `url` or `onClick` are provided, rendering the button as a link if appropriate. If both props are provided, `url` takes precedence, and the action button will render as an anchor tag.

## Related components

- To create a more prominent message that requires action, use a Modal.
- To create a more prominent message that requires action, use a Modal.
- For low priority, non-interruptive messsages, use Snackbar.
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@ import { close } from '@wordpress/icons';
/**
* Internal dependencies
*/
import { Button } from '../';

/** @typedef {import('@wordpress/element').WPElement} WPElement */
import Button from '../button';
import type { NoticeAction, NoticeProps } from './types';
import type { SyntheticEvent } from 'react';
import type { DeprecatedButtonProps } from '../button/types';

const noop = () => {};

/**
* Custom hook which announces the message with the given politeness, if a
* valid message is provided.
*
* @param {string|WPElement} [message] Message to announce.
* @param {'polite'|'assertive'} politeness Politeness to announce.
*/
function useSpokenMessage( message, politeness ) {
function useSpokenMessage(
message: NoticeProps[ 'spokenMessage' ],
politeness: NoticeProps[ 'politeness' ]
) {
const spokenMessage =
typeof message === 'string' ? message : renderToString( message );

Expand All @@ -38,15 +39,7 @@ function useSpokenMessage( message, politeness ) {
}, [ spokenMessage, politeness ] );
}

/**
* Given a notice status, returns an assumed default politeness for the status.
* Defaults to 'assertive'.
*
* @param {string} [status] Notice status.
*
* @return {'polite'|'assertive'} Notice politeness.
*/
function getDefaultPoliteness( status ) {
function getDefaultPoliteness( status: NoticeProps[ 'status' ] ) {
switch ( status ) {
case 'success':
case 'warning':
Expand All @@ -59,6 +52,17 @@ function getDefaultPoliteness( status ) {
}
}

/**
* `Notice` is a component used to communicate feedback to the user.
*
*```jsx
* import { Notice } from `@wordpress/components`;
*
* const MyNotice = () => (
* <Notice status="error">An unknown error occurred.</Notice>
* );
* ```
*/
function Notice( {
className,
status = 'info',
Expand All @@ -73,7 +77,7 @@ function Notice( {
// It is distinct from onRemove, which _looks_ like a callback but is
// actually the function to call to remove the notice from the UI.
onDismiss = noop,
} ) {
}: NoticeProps ) {
useSpokenMessage( spokenMessage, politeness );

const classes = classnames(
Expand All @@ -85,11 +89,11 @@ function Notice( {
}
);

if ( __unstableHTML ) {
if ( __unstableHTML && typeof children === 'string' ) {
children = <RawHTML>{ children }</RawHTML>;
}

const onDismissNotice = ( event ) => {
const onDismissNotice = ( event: SyntheticEvent ) => {
event?.preventDefault?.();
onDismiss();
onRemove();
Expand All @@ -110,7 +114,11 @@ function Notice( {
noDefaultClasses = false,
onClick,
url,
},
}: NoticeAction &
// `isPrimary` is a legacy prop included for
// backcompat, but `variant` should be used
// instead.
Pick< DeprecatedButtonProps, 'isPrimary' >,
index
) => {
let computedVariant = variant;
Expand Down
48 changes: 0 additions & 48 deletions packages/components/src/notice/list.js

This file was deleted.

Loading

0 comments on commit e728b81

Please sign in to comment.