Snack: sub-message, close button and duration setting

- Add close button to allow immediate dismissal.

- Add ability to support sub messages. Will be typically used for error codes, etc.

- Add ability to define 'long' auto-dismiss duration (15s) vs. the default of 5s.
    - I didn't add 'off' because there is a comment saying that this scenario should use the Error Modal instead, so respecting that for now.
This commit is contained in:
infinite-persistence 2022-03-18 11:24:58 +08:00 committed by Thomas Zarebczan
parent d1d9b116d4
commit 9482a7f986
3 changed files with 35 additions and 17 deletions

View file

@ -11,10 +11,12 @@ import * as ACTIONS from 'constants/action_types';
*/ */
declare type ToastParams = { declare type ToastParams = {
message: string, message: string,
title?: string, subMessage?: string,
// title?: string,
linkText?: string, linkText?: string,
linkTarget?: string, linkTarget?: string,
isError?: boolean, isError?: boolean,
duration?: 'default' | 'long',
}; };
declare type Toast = { declare type Toast = {

View file

@ -8,24 +8,16 @@ import LbcMessage from 'component/common/lbc-message';
type Props = { type Props = {
removeSnack: (any) => void, removeSnack: (any) => void,
snack: ?{ snack: ?ToastParams,
linkTarget: ?string,
linkText: ?string,
message: string,
isError: boolean,
},
}; };
class SnackBar extends React.PureComponent<Props> { class SnackBar extends React.PureComponent<Props> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
this.displayTime = 5; // in seconds
this.hideTimeout = null; this.hideTimeout = null;
} }
hideTimeout: ?TimeoutID; hideTimeout: ?TimeoutID;
displayTime: number;
render() { render() {
const { snack, removeSnack } = this.props; const { snack, removeSnack } = this.props;
@ -35,13 +27,16 @@ class SnackBar extends React.PureComponent<Props> {
return null; return null;
} }
const { message, linkText, linkTarget, isError } = snack; const { message, subMessage, duration, linkText, linkTarget, isError } = snack;
if (this.hideTimeout === null) { if (this.hideTimeout === null) {
this.hideTimeout = setTimeout(() => { this.hideTimeout = setTimeout(
() => {
this.hideTimeout = null; this.hideTimeout = null;
removeSnack(); removeSnack();
}, this.displayTime * 1000); },
duration === 'long' ? 15000 : 5000
);
} }
return ( return (
@ -52,10 +47,20 @@ class SnackBar extends React.PureComponent<Props> {
> >
<div className="snack-bar__message"> <div className="snack-bar__message">
<Icon icon={isError ? ICONS.ALERT : ICONS.COMPLETED} size={18} /> <Icon icon={isError ? ICONS.ALERT : ICONS.COMPLETED} size={18} />
<p className="snack-bar__messageText"> <p className="snack-bar__messageText">
<LbcMessage>{message}</LbcMessage> <LbcMessage>{message}</LbcMessage>
{subMessage && (
<p className="snack-bar__messageText snack-bar__messageText--sub">
<LbcMessage>{subMessage}</LbcMessage>
</p> </p>
)}
</p>
<Button
className="snack-bar__close"
icon={ICONS.REMOVE}
title={__('Dismiss')}
onClick={() => removeSnack()}
/>
</div> </div>
{linkText && linkTarget && ( {linkText && linkTarget && (
// This is a little weird because of `linkTarget` code in `lbry-redux` // This is a little weird because of `linkTarget` code in `lbry-redux`

View file

@ -5,7 +5,7 @@
background-color: var(--color-primary); background-color: var(--color-primary);
color: var(--color-primary-contrast); color: var(--color-primary-contrast);
border-radius: var(--border-radius); border-radius: var(--border-radius);
padding: var(--spacing-s) var(--spacing-l) var(--spacing-s) var(--spacing-m); padding: var(--spacing-s) var(--spacing-m) var(--spacing-s) var(--spacing-m);
position: fixed; position: fixed;
transition: all var(--transition-duration) var(--transition-type); transition: all var(--transition-duration) var(--transition-type);
z-index: 10000; // hack to get it over react modal z-index: 10000; // hack to get it over react modal
@ -71,8 +71,19 @@
min-width: 1rem; min-width: 1rem;
} }
} }
.snack-bar__messageText { .snack-bar__messageText {
min-width: 0; min-width: 0;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
} }
.snack-bar__messageText--sub {
font-size: var(--font-small);
color: var(--color-text-subtitle);
}
.snack-bar__close {
color: var(--color-primary-contrast);
margin-left: var(--spacing-m);
}