Skip to content

Commit

Permalink
feat(notification): move inner content to toast
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitrsavk committed Jan 18, 2021
1 parent 09de8b0 commit 8b7a4e9
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 332 deletions.
1 change: 1 addition & 0 deletions packages/notification/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"dependencies": {
"@alfalab/core-components-button": "^1.10.0",
"@alfalab/core-components-portal": "^1.4.0",
"@alfalab/core-components-toast": "^1.0.0",
"classnames": "^2.2.6",
"react-merge-refs": "^1.1.0",
"react-swipeable": "^6.0.0"
Expand Down
50 changes: 0 additions & 50 deletions packages/notification/src/Component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,6 @@ describe('Notification', () => {

expect(baseElement).toMatchSnapshot();
});

it('should match snapshot with leftAddons', () => {
const { baseElement } = render(
<Notification leftAddons={<div>leftAddons</div>} onClose={onClose} />,
);

expect(baseElement).toMatchSnapshot();
});

it('should match snapshot without icon', () => {
const { baseElement } = render(
<Notification title='title' onClose={onClose}>
text
</Notification>,
);

expect(baseElement).toMatchSnapshot();
});
});

it('should set `data-test-id` attribute', () => {
Expand Down Expand Up @@ -67,17 +49,6 @@ describe('Notification', () => {
expect(el).toHaveClass(className);
});

it('should set `hasCloser` class', () => {
const dataTestId = 'test-id';
const { getByTestId } = render(
<Notification hasCloser={true} dataTestId={dataTestId} />,
);

const el = getByTestId(dataTestId);

expect(el).toHaveClass('hasCloser');
});

it('should set `visible` class', () => {
const dataTestId = 'test-id';
const { getByTestId } = render(<Notification visible={true} dataTestId={dataTestId} />);
Expand All @@ -86,27 +57,6 @@ describe('Notification', () => {

expect(el).toHaveClass('isVisible');
});

it('should set `positive` class if `icon` prop is `positive`', () => {
const icon = 'positive';
const { baseElement } = render(<Notification icon={icon} />);

expect(baseElement.querySelector('.icon')).toHaveClass(icon);
});

it('should set `negative` class if `icon` prop is `negative`', () => {
const icon = 'negative';
const { baseElement } = render(<Notification icon={icon} />);

expect(baseElement.querySelector('.icon')).toHaveClass(icon);
});

it('should set `warning` class if `icon` prop is `warning`', () => {
const icon = 'warning';
const { baseElement } = render(<Notification icon={icon} />);

expect(baseElement.querySelector('.icon')).toHaveClass(icon);
});
});

describe('Callbacks tests', () => {
Expand Down
103 changes: 9 additions & 94 deletions packages/notification/src/Component.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,15 @@
import React, {
forwardRef,
useCallback,
ReactNode,
MouseEvent,
useRef,
HTMLAttributes,
useEffect,
useState,
} from 'react';
import React, { forwardRef, useCallback, MouseEvent, useRef, useEffect, useState } from 'react';
import cn from 'classnames';
import mergeRefs from 'react-merge-refs';
import { useSwipeable, LEFT, RIGHT, UP } from 'react-swipeable';
import { CloseSWhiteIcon } from '@alfalab/icons-classic/CloseSWhiteIcon';
import { CheckmarkMIcon } from '@alfalab/icons-glyph/CheckmarkMIcon';
import { CrossMIcon } from '@alfalab/icons-glyph/CrossMIcon';
import { ExclamationMIcon } from '@alfalab/icons-glyph/ExclamationMIcon';
import { Portal } from '@alfalab/core-components-portal';
import { Button } from '@alfalab/core-components-button';
import { Toast, ToastProps } from '@alfalab/core-components-toast';

import { useClickOutside } from './utils';

import styles from './index.module.css';

export type NotificationProps = HTMLAttributes<HTMLDivElement> & {
/**
* Дополнительный класс
*/
className?: string;

/**
* Дочерние элементы
*/
children?: ReactNode;

export type NotificationProps = ToastProps & {
/**
* Управление видимостью компонента
*/
Expand All @@ -42,36 +20,11 @@ export type NotificationProps = HTMLAttributes<HTMLDivElement> & {
*/
offset?: number;

/**
* Управляет отображением кнопки закрытия уведомления
*/
hasCloser?: boolean;

/**
* Заголовок компонента
*/
title?: ReactNode;

/**
* Вид иконки
*/
icon?: 'negative' | 'positive' | 'warning';

/**
* Слот слева, заменяет стандартную иконку
*/
leftAddons?: ReactNode;

/**
* Время до закрытия компонента
*/
autoCloseDelay?: number;

/**
* Обработчик клика по крестику
*/
onClose?: (event?: MouseEvent<HTMLButtonElement>) => void;

/**
* Обработчик события истечения времени до закрытия компонента
*/
Expand All @@ -91,21 +44,10 @@ export type NotificationProps = HTMLAttributes<HTMLDivElement> & {
* Обработчик клика вне компонента
*/
onClickOutside?: (event?: MouseEvent<any>) => void;

/**
* Идентификатор для систем автоматизированного тестирования
*/
dataTestId?: string;
};

const notificationClassNameSelector = `.${styles.notificationComponent}`;

const iconComponent = {
negative: <CrossMIcon className={styles.iconSvg} />,
positive: <CheckmarkMIcon className={styles.iconSvg} />,
warning: <ExclamationMIcon className={styles.iconSvg} />,
};

export const Notification = forwardRef<HTMLDivElement, NotificationProps>(
(
{
Expand All @@ -114,16 +56,12 @@ export const Notification = forwardRef<HTMLDivElement, NotificationProps>(
visible,
offset = 108,
hasCloser = true,
title,
icon,
leftAddons,
autoCloseDelay = 5000,
onClose,
onCloseTimeout,
onMouseEnter,
onMouseLeave,
onClickOutside,
dataTestId,
style,
...restProps
},
Expand Down Expand Up @@ -222,12 +160,11 @@ export const Notification = forwardRef<HTMLDivElement, NotificationProps>(
return (
<Portal>
<div {...swipeableHandlers}>
<div
<Toast
className={cn(
styles.notificationComponent,
{
[styles.isVisible]: visible,
[styles.hasCloser]: hasCloser,
[styles.isClosing]: isClosing,
},
className,
Expand All @@ -240,34 +177,12 @@ export const Notification = forwardRef<HTMLDivElement, NotificationProps>(
onMouseLeave={handleMouseLeave}
ref={mergeRefs([ref, notificationRef])}
role={visible ? 'alert' : undefined}
data-test-id={dataTestId}
hasCloser={hasCloser}
onClose={onClose}
{...restProps}
>
{(leftAddons || icon) && (
<div className={styles.leftAddons}>
{leftAddons ||
(icon && (
<div className={cn(styles.icon, styles[icon])}>
{iconComponent[icon]}
</div>
))}
</div>
)}
<div className={styles.contentContainer}>
{title && <div className={styles.title}>{title}</div>}
{children && <div className={styles.content}>{children}</div>}
</div>
{hasCloser && onClose && (
<Button
className={styles.closer}
view='ghost'
onClick={onClose}
aria-label='закрыть'
>
<CloseSWhiteIcon />
</Button>
)}
</div>
{children}
</Toast>
</div>
</Portal>
);
Expand Down
102 changes: 1 addition & 101 deletions packages/notification/src/__snapshots__/Component.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ exports[`Notification Snapshots tests should match snapshot 1`] = `
>
<div>
<div
class="notificationComponent hasCloser"
class="component hasCloser notificationComponent"
style="top: 108px;"
>
<div
Expand Down Expand Up @@ -73,103 +73,3 @@ exports[`Notification Snapshots tests should match snapshot 1`] = `
</div>
</body>
`;

exports[`Notification Snapshots tests should match snapshot with leftAddons 1`] = `
<body>
<div
alfa-portal-container=""
>
<div>
<div
class="notificationComponent hasCloser"
style="top: 108px;"
>
<div
class="leftAddons"
>
<div>
leftAddons
</div>
</div>
<div
class="contentContainer"
/>
<button
aria-label="закрыть"
class="component ghost m closer"
>
<span
class="text stretchText"
>
<svg
focusable="false"
height="18"
version="1"
viewBox="0 0 18 18"
width="18"
>
<path
d="M14.646 2.646L9 8.293 3.354 2.646l-.708.708L8.293 9l-5.647 5.646.708.708L9 9.707l5.646 5.647.708-.708L9.707 9l5.647-5.646z"
fill="#FFF"
/>
</svg>
</span>
</button>
</div>
</div>
</div>
<div />
</body>
`;

exports[`Notification Snapshots tests should match snapshot without icon 1`] = `
<body>
<div
alfa-portal-container=""
>
<div>
<div
class="notificationComponent hasCloser"
style="top: 108px;"
>
<div
class="contentContainer"
>
<div
class="title"
>
title
</div>
<div
class="content"
>
text
</div>
</div>
<button
aria-label="закрыть"
class="component ghost m closer"
>
<span
class="text stretchText"
>
<svg
focusable="false"
height="18"
version="1"
viewBox="0 0 18 18"
width="18"
>
<path
d="M14.646 2.646L9 8.293 3.354 2.646l-.708.708L8.293 9l-5.647 5.646.708.708L9 9.707l5.646 5.647.708-.708L9.707 9l5.647-5.646z"
fill="#FFF"
/>
</svg>
</span>
</button>
</div>
</div>
</div>
<div />
</body>
`;

0 comments on commit 8b7a4e9

Please sign in to comment.