Skip to content

Commit

Permalink
refactor: add changes after review
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyrylo Hudym-Levkovych authored and Kyrylo Hudym-Levkovych committed Jan 2, 2024
1 parent 4276858 commit 4bf88cf
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 242 deletions.
104 changes: 104 additions & 0 deletions src/Toast/BaseToast.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* eslint-disable react/prop-types */
import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import classNames from 'classnames';

import Icon from '../Icon';
import IconButton from '../IconButton';
import Button from '../Button';
import { Close } from '../../icons';

function Toast({
id, message, onDismiss, actions, className, duration, ...rest
}) {
const intl = useIntl();
const intlCloseLabel = intl.formatMessage({
id: 'pgn.Toast.closeLabel',
defaultMessage: 'Close',
description: 'Close label for Toast component',
});

const timerRef = useRef();

useEffect(() => {
timerRef.current = setTimeout(() => onDismiss(id), duration);

return () => clearTimeout(timerRef.current);
}, [id, onDismiss, duration]);

const clearTimer = () => {
clearTimeout(timerRef.current);
};

const startTimer = () => {
clearTimer();
timerRef.current = setTimeout(() => onDismiss(id), duration);
};

return (
<div
className={classNames('pgn__toast', className)}
onMouseOver={clearTimer}
onMouseOut={startTimer}
onFocus={clearTimer}
onBlur={startTimer}
{...rest}
>
<div className="pgn__toast__header small">
<p className="pgn__toast__message">{message}</p>

<IconButton
iconAs={Icon}
alt={intlCloseLabel}
className="pgn__toast__close-btn align-self-start"
src={Close}
onClick={() => onDismiss(id)}
variant="primary"
invertColors
/>
</div>
{actions
? (
<div className="pgn__toast__optional-actions">
{actions.map((action) => (
<Button
as={action.href ? 'a' : 'button'}
href={action.href}
onClick={action.onClick}
size="sm"
variant="inverse-outline-primary"
>
{action.label}
</Button>
))}
</div>
)
: null}
</div>
);
}

export default Toast;

Toast.propTypes = {
id: PropTypes.number.isRequired,
message: PropTypes.string.isRequired,
onDismiss: PropTypes.func,
actions: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
onClick: PropTypes.func,
href: PropTypes.string,
}),
),
className: PropTypes.string,
duration: PropTypes.number,
};

Toast.defaultProps = {
onDismiss: () => {},
actions: null,
className: '',
duration: 5000,
};
78 changes: 26 additions & 52 deletions src/Toast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ title: 'Toast'
type: 'component'
components:
- ToastContainer
- toast
categories:
- Overlays
status: 'New'
Expand All @@ -14,18 +13,12 @@ notes: ''

`Toast` is a pop-up style message that shows the user a brief, fleeting, dismissible message about a successful app process.

## Features

- **Customizable Appearance**: Choose the window position for toast.
- **Interactive**: Includes a close button for manual dismissal.
- **Auto-dismiss**: Disappears automatically after a set duration.
- **Hover Interactivity**: Auto-dismiss timer pauses on hover or focus, allowing users to interact with the content.

## Behaviors

- Auto-dismiss: Toast automatically dismisses after a default duration of 5 seconds.
- Disable timer: Pause the auto-dismiss timer on hover or focus of the Toast or the dismiss icon.
- Re-enable timer: Resume the auto-dismiss timer on mouse leave or blur of the Toast component.
- **Customizable Appearance**: Choose the window position for toast.
- **Auto-dismiss**: Toast automatically dismisses after a default duration of 5 seconds.
- **Disable timer**: Pause the auto-dismiss timer on hover or focus of the Toast or the dismiss icon.
- **Re-enable timer**: Resume the auto-dismiss timer on mouse leave or blur of the Toast component.

## Basic Usage

Expand All @@ -34,7 +27,7 @@ notes: ''
const [position, setPosition] = useState('bottom-left');
const [timer, setTimer] = useState(5000);
const [message, setMessage] = useState('Example of a basic Toast.');
const [actions, setActions] = useState([]);
const [withActions, setWithActions] = useState('false');

const testAction = {
label: "Optional Button",
Expand All @@ -43,7 +36,26 @@ notes: ''

return (
<>
<div className="mt-3">

{/* start example form block */}
<ExamplePropsForm
inputs={[
{ value: position, setValue: (value) => setPosition(value), name: 'Position', options: [
{ value: "top-left", name: "top-left" },
{ value: "top-right", name: "top-right" },
{ value: "bottom-left", name: "bottom-left" },
{ value: "bottom-right", name: "bottom-right" }]
},
{ value: timer, setValue: (value) => setTimer(value), name: 'Duration (ms)', range: { min: 1000 , max: 10000, step: 1000 } },
{ value: withActions, setValue: (value) => setWithActions(value), name: 'With actions', options: [
{ value: 'true', name: "True" },
{ value: 'false', name: "False" },
]},
]}
/>
{/* end example form block */}

<div className="mt-3 mb-3">
Message:
<Form.Control
className="mt-1"
Expand All @@ -52,48 +64,10 @@ notes: ''
onChange={(e) => setMessage(e.target.value)}
/>
</div>

<div className="mt-3">
Duration (ms):
<Form.Control className="mt-1" type="number" value={timer} onChange={(e) => setTimer(Number(e.target.value))} />
</div>

<div className="mt-3 mb-4">
Position:
<Form.Control
as="select"
className="mt-1"
value={position}
onChange={(e) => setPosition(e.target.value)}
>
<option value="top-left">Top Left</option>
<option value="top-right">Top Right</option>
<option value="bottom-left">Bottom Left</option>
<option value="bottom-right">Bottom Right</option>
</Form.Control>
</div>

<div className="mt-3 mb-4">
Add and remove actions:

<p>Total added: {actions.length}</p>

<Stack className="mt-2" direction="horizontal" gap="2">
<Button onClick={() => setActions(prevState => [...prevState, testAction])} variant="tertiary">
Add action
</Button>
<Button onClick={() => setActions([])} variant="tertiary">
Clear actions
</Button>
</Stack>
</div>


<Button onClick={() => toast({ message, duration: timer, actions})}>
<Button onClick={() => toast({ message, duration: timer, actions: withActions === 'true' ? [testAction] : [], position })}>
Show Toast
</Button>

<ToastContainer position={position} />
</>
);
}
Expand Down
82 changes: 0 additions & 82 deletions src/Toast/ToastContainer.jsx

This file was deleted.

16 changes: 16 additions & 0 deletions src/Toast/constants/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const TOAST_POSITIONS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];

export const positionStyles = {
'top-left': {
top: '0', left: '0', right: 'auto', bottom: 'auto',
},
'top-right': {
top: '0', right: '0', left: 'auto', bottom: 'auto',
},
'bottom-left': {
bottom: '0', left: '0', right: 'auto', top: 'auto',
},
'bottom-right': {
bottom: '0', right: '0', left: 'auto', top: 'auto',
},
};
Loading

0 comments on commit 4bf88cf

Please sign in to comment.