Skip to content

Commit

Permalink
Refactor Indicator to ToastIcon component
Browse files Browse the repository at this point in the history
- Also export resolveValue to render custom JSX content
  • Loading branch information
timolins committed Mar 22, 2021
1 parent b7509bd commit 25690e0
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 93 deletions.
22 changes: 0 additions & 22 deletions src/components/icon-wrapper.tsx

This file was deleted.

52 changes: 0 additions & 52 deletions src/components/indicator.tsx

This file was deleted.

20 changes: 5 additions & 15 deletions src/components/toast-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { styled, keyframes } from 'goober';

import { Toast, ToastPosition, resolveValue } from '../core/types';
import { ToastIcon } from './toast-icon';

const enterAnimation = (factor: number) => `
0% {transform: translate3d(0,${factor * -200}%,0) scale(.6); opacity:.5;}
Expand Down Expand Up @@ -38,6 +39,7 @@ const Message = styled('div')`
interface ToastBarProps {
toast: Toast;
position: ToastPosition;
style?: React.CSSProperties;
}

const getAnimationStyle = (
Expand All @@ -61,33 +63,21 @@ const getAnimationStyle = (
};

export const ToastBar: React.FC<ToastBarProps> = React.memo(
({ toast, position }) => {
({ toast, position, style }) => {
const animationStyle = toast?.height
? getAnimationStyle(position, toast.visible)
: { opacity: 0 };

const renderIcon = () => {
const { icon, type, iconTheme } = toast;
if (icon !== undefined) {
if (typeof icon === 'string') {
return <AnimatedIconWrapper>{icon}</AnimatedIconWrapper>;
} else {
return icon;
}
}

return <Indicator theme={iconTheme} type={type} />;
};

return (
<ToastBarBase
className={toast.className}
style={{
...animationStyle,
...style,
...toast.style,
}}
>
{renderIcon()}
<ToastIcon toast={toast} />
<Message role={toast.role} aria-live={toast.ariaLive}>
{resolveValue(toast.message, toast)}
</Message>
Expand Down
79 changes: 79 additions & 0 deletions src/components/toast-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import * as React from 'react';
import { styled, keyframes } from 'goober';

import { Toast } from '../core/types';
import { ErrorIcon, ErrorTheme } from './error';
import { LoaderIcon, LoaderTheme } from './loader';
import { CheckmarkIcon, CheckmarkTheme } from './checkmark';

const StatusWrapper = styled('div')`
position: absolute;
`;

const IndicatorWrapper = styled('div')`
position: relative;
display: flex;
justify-content: center;
align-items: center;
min-width: 20px;
min-height: 20px;
`;

const enter = keyframes`
from {
transform: scale(0.6);
opacity: 0.4;
}
to {
transform: scale(1);
opacity: 1;
}
`;

export const AnimatedIconWrapper = styled('div')`
position: relative;
transform: scale(0.6);
opacity: 0.4;
min-width: 20px;
animation: ${enter} 0.3s 0.12s cubic-bezier(0.175, 0.885, 0.32, 1.275)
forwards;
`;

export type IconThemes = Partial<{
success: CheckmarkTheme;
error: ErrorTheme;
loading: LoaderTheme;
}>;

export const ToastIcon: React.FC<{
toast: Toast;
}> = ({ toast }) => {
const { icon, type, iconTheme } = toast;
if (icon !== undefined) {
if (typeof icon === 'string') {
return <AnimatedIconWrapper>{icon}</AnimatedIconWrapper>;
} else {
return icon;
}
}

if (type === 'blank') {
return null;
}

return (
<IndicatorWrapper>
<LoaderIcon {...iconTheme} />
{type !== 'loading' && (
<StatusWrapper>
{type === 'error' ? (
<ErrorIcon {...iconTheme} />
) : (
<CheckmarkIcon {...iconTheme} />
)}
</StatusWrapper>
)}
</IndicatorWrapper>
);
};
6 changes: 2 additions & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ import {
} from './core/types';
export { useToaster } from './core/use-toaster';
export { ToastBar } from './components/toast-bar';
export { ToastIcon } from './components/toast-icon';
export { Toaster } from './components/toaster';
export { useStore as useToasterStore } from './core/store';

export { CheckmarkIcon } from './components/checkmark';
export { ErrorIcon } from './components/error';
export { LoaderIcon } from './components/loader';

This comment has been minimized.

Copy link
@jlalmes

jlalmes Jun 25, 2021

Contributor

This is a breaking change that wasn't mentioned on the 2.0 docs. Can we bring this back? @timolins

This comment has been minimized.

Copy link
@jlalmes

jlalmes Jun 25, 2021

Contributor

Use case: We are using the LoaderIcon, CheckmarkIcon & ErrorIcon components elsewhere in our app for UI consistency.

This comment has been minimized.

Copy link
@timolins

timolins Jun 25, 2021

Author Owner

Thanks for bringing that up. That slipped through the cracks somehow. I'll add them back in with the next release.

This comment has been minimized.

Copy link
@timolins

timolins Jun 25, 2021

Author Owner

Mind opening an issue so I don't forget?

This comment has been minimized.

Copy link
@jlalmes

jlalmes Jun 25, 2021

Contributor

#94

export { resolveValue } from './core/types';

export type ToastOptions = _ToastOptions;
export type ToastPosition = _ToastPosition;
Expand Down

0 comments on commit 25690e0

Please sign in to comment.