Skip to content

Commit

Permalink
feat(components/alert): 与 Tag 组件统一初始状态
Browse files Browse the repository at this point in the history
1. 默认从无边框改为有边框
2. 默认从 default 类型为 primary,
3. onClose 可手动中断关闭
  • Loading branch information
mengxinssfd committed Aug 24, 2023
1 parent 6c91d66 commit 6953a86
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 55 deletions.
22 changes: 11 additions & 11 deletions packages/components/src/alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ const cls = getClasses(
['bordered', 'centered'],
);
const defaultProps = {
type: 'default',
bordered: false,
type: 'primary',
bordered: true,
closable: false,
} satisfies Partial<AlertProps>;

const Icons: Record<Required<AlertProps>['type'], React.FC> = {
default: CircleInfo,
primary: CircleInfo,
info: CircleInfoFill,
warning: CircleWarningFill,
error: CircleCloseFill,
Expand All @@ -42,23 +42,16 @@ export const Alert: React.FC<AlertProps> = React.forwardRef<
props as RequiredPart<AlertProps, keyof typeof defaultProps>;

const [visible, setVisible] = useState(true);

const DefaultIcon = Icons[type];

const close = () => {
if (!closable) return;
setVisible(false);
onClose?.();
};

const Body = (
<div
{...attrs}
ref={ref}
className={getClassNames(cls.root, attrs?.className, {
[cls['--'].bordered]: bordered,
[cls['--'].centered]: title && !children,
[`${cls.root}--${type}`]: type !== 'default',
[`${cls.root}--${type}`]: type !== 'primary',
})}>
{icon !== null && (
<Icon className={cls.__.icon}>{icon || <DefaultIcon />}</Icon>
Expand All @@ -83,6 +76,13 @@ export const Alert: React.FC<AlertProps> = React.forwardRef<

if (!closable) return Body;
return <CollapseTransition>{visible && Body}</CollapseTransition>;

function close(e: React.MouseEvent<HTMLButtonElement>) {
if (!closable) return;
onClose?.(e);
if (e.isDefaultPrevented()) return;
setVisible(false);
}
});

Alert.defaultProps = defaultProps;
Expand Down
50 changes: 40 additions & 10 deletions packages/components/src/alert/__tests__/Alert.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, fireEvent } from '@testing-library/react';
import { render, fireEvent, act } from '@testing-library/react';
import { Alert } from '..';
import { Left } from '@pkg/icons';
import { testAttrs } from '~/testAttrs';
Expand All @@ -15,6 +15,13 @@ describe('Alert', () => {
test('bordered', () => {
expect(
render(<Alert title="Tips">foo bar</Alert>).container.firstChild,
).toHaveClass('t-alert--bordered');
expect(
render(
<Alert title="Tips" bordered={false}>
foo bar
</Alert>,
).container.firstChild,
).not.toHaveClass('t-alert--bordered');
expect(
render(
Expand Down Expand Up @@ -52,15 +59,38 @@ describe('Alert', () => {
).toMatchSnapshot();
});

test('onClose', () => {
const onClose = jest.fn();
const { container } = render(
<Alert title="Tips" closable onClose={onClose}>
foo bar
</Alert>,
);
fireEvent.click(container.querySelector('.t-alert__close-btn')!);
expect(onClose).toBeCalled();
describe('onClose', () => {
test('basic', () => {
jest.useFakeTimers();
const onClose = jest.fn();
const { container } = render(
<Alert title="Tips" closable onClose={onClose}>
foo bar
</Alert>,
);
expect(onClose).not.toBeCalled();
fireEvent.click(container.querySelector('.t-alert__close-btn')!);
expect(onClose).toBeCalled();
expect(container.firstChild).not.toBeNull();
act(() => jest.advanceTimersByTime(300));
expect(container.firstChild).toBeNull();
});

test('preventDefault', () => {
jest.useFakeTimers();
const onClose = jest.fn((e) => e.preventDefault());
const { container } = render(
<Alert title="Tips" closable onClose={onClose}>
foo bar
</Alert>,
);
expect(onClose).not.toBeCalled();
fireEvent.click(container.querySelector('.t-alert__close-btn')!);
expect(onClose).toBeCalled();
expect(container.firstChild).not.toBeNull();
act(() => jest.advanceTimersByTime(300));
expect(container.firstChild).not.toBeNull();
});
});

test('partial', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`Alert basic 1`] = `
<div
class="t-alert"
class="t-alert t-alert--bordered"
>
<i
class="t-icon t-alert__icon"
Expand Down Expand Up @@ -36,7 +36,7 @@ exports[`Alert basic 1`] = `

exports[`Alert closable 1`] = `
<div
class="t-collapse-transition t-alert t-collapse-transition--h"
class="t-collapse-transition t-alert t-alert--bordered t-collapse-transition--h"
>
<i
class="t-icon t-alert__icon"
Expand Down Expand Up @@ -89,7 +89,7 @@ exports[`Alert closable 1`] = `

exports[`Alert icon 1`] = `
<div
class="t-alert"
class="t-alert t-alert--bordered"
>
<i
class="t-icon t-alert__icon"
Expand Down Expand Up @@ -123,7 +123,7 @@ exports[`Alert icon 1`] = `

exports[`Alert icon 2`] = `
<div
class="t-alert"
class="t-alert t-alert--bordered"
>
<div
class="t-alert__content"
Expand All @@ -144,7 +144,7 @@ exports[`Alert icon 2`] = `

exports[`Alert partial 1`] = `
<div
class="t-alert t-alert--centered"
class="t-alert t-alert--bordered t-alert--centered"
>
<i
class="t-icon t-alert__icon"
Expand Down Expand Up @@ -173,7 +173,7 @@ exports[`Alert partial 1`] = `

exports[`Alert partial 2`] = `
<div
class="t-alert"
class="t-alert t-alert--bordered"
>
<i
class="t-icon t-alert__icon"
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/alert/alert.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React from 'react';
import { PropsBase } from '@pkg/shared';

export interface AlertProps extends PropsBase<HTMLDivElement> {
type?: 'default' | 'success' | 'info' | 'warning' | 'error';
type?: 'primary' | 'success' | 'info' | 'warning' | 'error';
bordered?: boolean;
closable?: boolean;
icon?: React.ReactNode;
title?: React.ReactNode;
onClose?: () => void;
onClose?: (e: React.MouseEvent<HTMLButtonElement>) => void;
}
19 changes: 7 additions & 12 deletions packages/components/src/alert/demo/bordered.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
/**
* title: 边框
* description: 可以添加边框
* description: 可以添加或移除边框
*/

import React, { useState } from 'react';
import { Alert, AlertProps, Space } from '@tool-pack/react-ui';
import { Alert, AlertProps, Space, Switch } from '@tool-pack/react-ui';

const Types: Required<AlertProps>['type'][] = [
'default',
'primary',
'info',
'success',
'warning',
'error',
];
const App: React.FC = () => {
const [bordered, setBordered] = useState(true);
const [bordered, setBordered] = useState(false);

return (
<Space vertical fill>
<label>
边框:
<input
type="checkbox"
checked={bordered}
onChange={(e) => setBordered(e.target.checked)}
/>
</label>
<div>
<Switch checked={bordered} onChange={setBordered} />
</div>
{Types.map((t) => (
<Alert key={t} bordered={bordered} type={t} title={`${t} tips`}>
foo bar
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/alert/demo/closable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React from 'react';
import { Alert, AlertProps } from '@tool-pack/react-ui';

const Types: Required<AlertProps>['type'][] = [
'default',
'primary',
'info',
'success',
'warning',
Expand Down
15 changes: 10 additions & 5 deletions packages/components/src/alert/demo/on-close.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ import { Alert, useMessageHolder } from '@tool-pack/react-ui';

const App: React.FC = () => {
const [message, holder] = useMessageHolder();
const onClose = () => {
message.success('已关闭');
console.log('已关闭');
};
return (
<>
{holder}
<Alert title="提示" onClose={onClose} closable>
<Alert
title="提示"
onClose={(e) => {
if (window.confirm('是否关闭提示?')) {
message.success('已关闭');
} else {
e.preventDefault();
}
}}
closable>
点击关闭按钮
</Alert>
</>
Expand Down
17 changes: 12 additions & 5 deletions packages/components/src/alert/demo/partial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ const App: React.FC = () => {
<Alert title="完全状态" bordered closable>
完全状态包含:边框、图标、标题、描述、关闭按钮
</Alert>
<Alert icon={null} title="移除部分">
<Alert icon={null} bordered={false} title="移除部分">
移除边框、图标、关闭按钮
</Alert>
<Alert title="移除描述" closable />
<Alert title="只留下标题和关闭按钮" icon={null} closable />
<Alert title="移除描述" bordered={false} closable />
<Alert
title="只留下标题和关闭按钮"
bordered={false}
icon={null}
closable
/>

<Alert closable>移除title</Alert>
<Alert icon={null} />
<Alert closable bordered={false}>
移除title
</Alert>
<Alert icon={null} bordered={false} />
</Space>
);
};
Expand Down
6 changes: 3 additions & 3 deletions packages/components/src/alert/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ Alert 的属性说明如下:

| 属性 | 说明 | 类型 | 默认值 | 版本 |
| -------- | ------------------------------------- | -------------------------------------------------------- | --------- | ---- |
| type | 提示类型 | 'default' \| 'success' \| 'info' \| 'warning' \| 'error' | 'default' | -- |
| bordered | 是否显示边框 | boolean | false | -- |
| type | 提示类型 | 'primary' \| 'success' \| 'info' \| 'warning' \| 'error' | 'primary' | -- |
| bordered | 是否显示边框 | boolean | true | -- |
| closable | 是否显示关闭按钮 | boolean | false | -- |
| icon | 提示图标,为 null 时不显示图标 | React.ReactNode | 预设图标 | -- |
| title | 提示标题,为空时不显示标题 | React.ReactNode | -- | -- |
| onClose | 提示关闭时的回调 | () => void | -- | -- |
| onClose | 提示关闭时的回调 | (e: React.MouseEvent\<HTMLButtonElement\>) | -- | -- |
| attrs | html 标签属性,如 className、style 等 | React.HTMLAttributes\<HTMLElement> | -- | -- |

0 comments on commit 6953a86

Please sign in to comment.