Skip to content

Commit

Permalink
feat(Message): add support for bordered and centered props on Mes…
Browse files Browse the repository at this point in the history
…sage (#3605)

* feat(Message): add support for `bordered` and `centered` props on Message

* fix: add version
  • Loading branch information
simonguo committed Feb 2, 2024
1 parent 114013f commit 2e0f2ec
Show file tree
Hide file tree
Showing 13 changed files with 245 additions and 41 deletions.
12 changes: 12 additions & 0 deletions docs/pages/components/message/en-US/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ Used to show important tips on a page.

<!--{include:`icons.md`}-->

### Bordered

<!--{include:`bordered.md`}-->

### Centered

<!--{include:`centered.md`}-->

### Closable

<!--{include:`close.md`}-->
Expand Down Expand Up @@ -52,8 +60,12 @@ No keyboard interaction needed.

### `<Message>`

<!-- prettier-sort-markdown-table -->

| Property | Type `(Default)` | Description |
| ----------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| bordered | boolean | Show a border around the message box.<br/>![](https://img.shields.io/badge/min-v5.53.0-blue) |
| centered | boolean | Center the message vertically.<br/>![](https://img.shields.io/badge/min-v5.53.0-blue) |
| children | ReactNode | The description information for the message. |
| classPrefix | string `('message')` | The prefix of the component CSS class. |
| closable | boolean | Whether it is possible to close the message box |
Expand Down
26 changes: 26 additions & 0 deletions docs/pages/components/message/fragments/bordered.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!--start-code-->

```js
import { Message } from 'rsuite';

const App = () => (
<>
<Message type="info" bordered showIcon>
<strong>Info!</strong> You can use the `Message` component to display a info message.
</Message>
<Message type="success" bordered showIcon>
<strong>Success!</strong> You can use the `Message` component to display a success message.
</Message>
<Message type="warning" bordered showIcon>
<strong>Warning!</strong> You can use the `Message` component to display a warning message.
</Message>
<Message type="error" bordered showIcon>
<strong>Error!</strong> You can use the `Message` component to display a error message.
</Message>
</>
);

ReactDOM.render(<App />, document.getElementById('root'));
```

<!--end-code-->
21 changes: 21 additions & 0 deletions docs/pages/components/message/fragments/centered.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!--start-code-->

```js
import { Message } from 'rsuite';

const App = () => (
<Message type="success" centered showIcon header="Application has been accepted !">
<p>
Your application has been successfully submitted, and we will process it within 1-3 working
days.
</p>
<p>
You can check the application status in the <a href="#">application record</a>.
</p>
</Message>
);

ReactDOM.render(<App />, document.getElementById('root'));
```

<!--end-code-->
8 changes: 4 additions & 4 deletions docs/pages/components/message/fragments/header.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { Message, Button, Divider } from 'rsuite';

const App = () => (
<>
<Message showIcon type="warning" header={<strong>Cannot delete the file</strong>}>
<Message showIcon type="warning" header="Cannot delete the file">
We are sorry, the file cannot be deleted. Please try again later.
</Message>

<Message showIcon type="error" header={<strong>A problem occurred</strong>}>
<Message showIcon type="error" header="A problem occurred">
<ol>
<li>Please check your network connection.</li>
<li>Please check the file permissions.</li>
Expand All @@ -18,8 +18,8 @@ const App = () => (
</ol>
</Message>

<Message showIcon type="info" header={<strong>Do you want to allow notifications?</strong>}>
We can let you know when new messages arrive.
<Message showIcon type="info" header="Do you want to allow notifications?">
<p> We can let you know when new messages arrive.</p>
<hr />
<ButtonToolbar>
<Button size="sm">Don't allow</Button>
Expand Down
12 changes: 12 additions & 0 deletions docs/pages/components/message/zh-CN/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@

<!--{include:`icons.md`}-->

### 带边框

<!--{include:`bordered.md`}-->

### 垂直居中

<!--{include:`centered.md`}-->

### 可关闭的

<!--{include:`close.md`}-->
Expand Down Expand Up @@ -52,8 +60,12 @@ Message 的 `role` 为 `alert`。

### `<Message>`

<!-- prettier-sort-markdown-table -->

| 属性名称 | 类型 `(默认值)` | 描述 |
| ----------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| bordered | boolean | 显示消息框边框 <br/>![](https://img.shields.io/badge/min-v5.53.0-blue) |
| centered | boolean | 垂直居中消息框 <br/>![](https://img.shields.io/badge/min-v5.53.0-blue) |
| children | ReactNode | 消息描述信息 |
| classPrefix | string `('message')` | 组件 CSS 类的前缀 |
| closable | boolean | 可以关闭消息框 |
Expand Down
98 changes: 68 additions & 30 deletions src/Message/Message.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
import React, { useState, useCallback, useContext } from 'react';
import React, { useState, useContext } from 'react';
import PropTypes from 'prop-types';
import { useClassNames, useTimeout, MESSAGE_STATUS_ICONS, STATUS, useIsMounted } from '../utils';
import {
useClassNames,
useTimeout,
MESSAGE_STATUS_ICONS,
STATUS,
useIsMounted,
useEventCallback
} from '../utils';
import { WithAsProps, TypeAttributes, RsRefForwardingComponent } from '../@types/common';
import { oneOf } from '../internals/propTypes';
import CloseButton from '../internals/CloseButton';
import ToastContext from '../toaster/ToastContext';

export interface MessageProps extends WithAsProps {
/** The type of the message box. */
/**
* The type of the message box.
*/
type?: TypeAttributes.Status;

/** Whether it is possible to close the message box */
/**
* Show a border around the message box.
* @version 5.53.0
*/
bordered?: boolean;

/**
* Center the message vertically.
* @version 5.53.0
*/
centered?: boolean;

/**
* Whether it is possible to close the message box
*/
closable?: boolean;

/**
Expand All @@ -24,16 +47,24 @@ export interface MessageProps extends WithAsProps {
*/
duration?: number;

/** The title of the message */
/**
* The title of the message
*/
header?: React.ReactNode;

/** Whether to display an icon */
/**
* Whether to display an icon
*/
showIcon?: boolean;

/** Fill the container */
/**
* Fill the container
*/
full?: boolean;

/** Callback after the message is removed */
/**
* Callback after the message is removed
*/
onClose?: (event?: React.MouseEvent<HTMLButtonElement>) => void;
}

Expand All @@ -47,6 +78,8 @@ const Message: RsRefForwardingComponent<'div', MessageProps> = React.forwardRef(
(props: MessageProps, ref) => {
const {
as: Component = 'div',
bordered,
centered,
className,
classPrefix = 'message',
children,
Expand All @@ -68,35 +101,38 @@ const Message: RsRefForwardingComponent<'div', MessageProps> = React.forwardRef(
// Timed close message
const { clear } = useTimeout(onClose, duration, usedToaster && duration > 0);

const handleClose = useCallback(
(event: React.MouseEvent<HTMLButtonElement>) => {
setDisplay('hiding');
onClose?.(event);
clear();

setTimeout(() => {
if (isMounted()) {
setDisplay('hide');
}
}, 1000);
},
[clear, isMounted, onClose]
);
const handleClose = useEventCallback((event: React.MouseEvent<HTMLButtonElement>) => {
setDisplay('hiding');
onClose?.(event);
clear();

setTimeout(() => {
if (isMounted()) {
setDisplay('hide');
}
}, 1000);
});

if (display === 'hide') {
return null;
}

const classes = merge(
className,
withClassPrefix(type, display, { full, ['has-title']: header, ['has-icon']: showIcon })
withClassPrefix(type, display, {
full,
bordered,
centered,
['has-title']: header,
['has-icon']: showIcon
})
);

return (
<Component role="alert" {...rest} ref={ref} className={classes}>
<div className={prefix`container`}>
{closable && <CloseButton onClick={handleClose} />}
{showIcon && <div className={prefix`icon-wrapper`}>{MESSAGE_STATUS_ICONS[type]}</div>}
{showIcon && <div className={prefix`icon`}>{MESSAGE_STATUS_ICONS[type]}</div>}
<div className={prefix`content`}>
{header && <div className={prefix`header`}>{header}</div>}
{children && <div className={prefix`body`}>{children}</div>}
Expand All @@ -109,15 +145,17 @@ const Message: RsRefForwardingComponent<'div', MessageProps> = React.forwardRef(

Message.displayName = 'Message';
Message.propTypes = {
type: oneOf(STATUS),
className: PropTypes.string,
onClose: PropTypes.func,
bordered: PropTypes.bool,
centered: PropTypes.bool,
closable: PropTypes.bool,
title: PropTypes.node,
className: PropTypes.string,
classPrefix: PropTypes.string,
description: PropTypes.node,
showIcon: PropTypes.bool,
full: PropTypes.bool,
classPrefix: PropTypes.string
onClose: PropTypes.func,
showIcon: PropTypes.bool,
title: PropTypes.node,
type: oneOf(STATUS)
};

export default Message;
29 changes: 29 additions & 0 deletions src/Message/stories/Message.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,35 @@ export const Closable: Story = {
}
};

export const Bordered: Story = {
args: {
...defaultArgs,
showIcon: true,
bordered: true
}
};

export const Centered: Story = {
args: {
...defaultArgs,
showIcon: true,
centered: true,
type: 'success',
header: 'Application has been accepted !',
children: (
<>
<p>
Your application has been successfully submitted, and we will process it within 1-3
working days.
</p>
<p>
You can check the application status in the <a href="#">application record</a>.
</p>
</>
)
}
};

export const WithToaster: Story = {
render: props => (
<ButtonToolbar>
Expand Down

0 comments on commit 2e0f2ec

Please sign in to comment.