Skip to content

Commit

Permalink
feat(snackbar): add snackbar component
Browse files Browse the repository at this point in the history
  • Loading branch information
pingviki authored and apust committed Oct 6, 2020
1 parent c7919a7 commit 80effb8
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 2 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
}
},
"dependencies": {
"@elephas/core": "^1.0.0",
"@elephas/layout": "^1.0.0",
"@elephas/core": "^1.1.0",
"@elephas/layout": "^1.1.0",
"mime": "^2.4.6",
"react": "^16.11.0",
"react-dom": "^16.11.0"
Expand Down
14 changes: 14 additions & 0 deletions src/packages/core/src/snackbar/Snackbar.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Meta, Description, Props, Preview, Story } from '@storybook/addon-docs/blocks';

import { Snackbar } from '.';
import { SnackbarExample } from './SnackbarExample';

<Meta title="Core/Snackbar" component={Snackbar} />

# Snackbar

<Props of={Snackbar} />

<Preview>
<SnackbarExample />
</Preview>
34 changes: 34 additions & 0 deletions src/packages/core/src/snackbar/Snackbar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { MouseEvent } from 'react';
import { render, fireEvent } from '@testing-library/react';

import { Snackbar } from '.';

describe('<Snackbar />', () => {
const getButton = (el: HTMLElement): HTMLButtonElement | null => el.querySelector('button');

let onClose: (event?: MouseEvent<HTMLButtonElement>) => void;
let btnText: string;
let message: string;

beforeEach(() => {
onClose = jest.fn();
btnText = 'Click me';
message = 'I am Snackbar';
});

it('method onClose has been called after click button', () => {
const { container } = render(
<Snackbar
buttonText={btnText}
message={message}
isOpen={false}
onClose={onClose}
/>,
);
const button = getButton(container);

button && fireEvent.click(button);

expect(onClose).toHaveBeenCalledTimes(1);
});
});
55 changes: 55 additions & 0 deletions src/packages/core/src/snackbar/Snackbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useState, useEffect } from 'react';
import classNames from 'classnames';
import { SnackbarProps } from './types';
import { Button } from '..';

export function Snackbar(props: SnackbarProps) {
const {
buttonText,
className,
duration = 10,
isOpen,
message,
onClose,
} = props;

const [autoHideDuration, setAutoHideDuration] = useState(duration);
let time = autoHideDuration;

const snackbarClassNames = classNames({
[`${className}`]: className,
_e_snackbar: true,
_e_snackbar_open: isOpen,
_e_snackbar_hidden: !isOpen,
});

useEffect(() => {
let interval: number;
if (isOpen) {
time = duration;
setAutoHideDuration(time);
interval = window.setInterval(() => {
if (time !== 0) {
time -= 1;
setAutoHideDuration(time);
} else {
onClose && onClose(undefined);
}
}, 1000);
}
return () => clearInterval(interval);
}, [isOpen]);

return (
<div className={snackbarClassNames}>
<div className="_e_snackbar__text">
{message}
<span className="_e_snackbar__timer">
:
{autoHideDuration}
</span>
</div>
<Button onClick={onClose} className="_e_snackbar__button _e_button">{buttonText}</Button>
</div>
);
}
29 changes: 29 additions & 0 deletions src/packages/core/src/snackbar/SnackbarExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { useState } from 'react';
import { Snackbar } from '.';
import { Button } from '../button';

export function SnackbarExample() {
const [isOpen, setOpen] = useState(false);

const handleClick = () => {
setOpen(!isOpen);
};

const handleClose = () => {
setOpen(false);
};

return (
<>
<Button onClick={handleClick}>
Snackbar
</Button>
<Snackbar
onClose={handleClose}
isOpen={isOpen}
buttonText="Отменить"
message="Сохранить изменения"
/>
</>
);
}
1 change: 1 addition & 0 deletions src/packages/core/src/snackbar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Snackbar } from './Snackbar';
37 changes: 37 additions & 0 deletions src/packages/core/src/snackbar/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { MouseEvent } from 'react';

export interface SnackbarProps {
/**
* Text on the button.
*/
buttonText: string,

/**
* Additional CSS class.
*/
className?: string,

/**
* Number of seconds to wait before automatically calling the
* `onClose` function.
* @default 10
*/
duration?: number,

/**
* Controls Snackbar open state.
*/
isOpen: boolean,

/**
* Message to display.
*/
message: string,

/**
* Callback fired when the component requests to be closed.
* @param {object} event The event source of the callback.
* If event `undefined`, `Snackbar` closed by timeout (`duration` expired).
*/
onClose?: (event?: MouseEvent<HTMLButtonElement>) => void,
}

0 comments on commit 80effb8

Please sign in to comment.