-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(snackbar): add snackbar component
- Loading branch information
Showing
7 changed files
with
172 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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="Сохранить изменения" | ||
/> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { Snackbar } from './Snackbar'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} |