Skip to content

Commit

Permalink
Lift position wrapper to Toaster
Browse files Browse the repository at this point in the history
  • Loading branch information
timolins committed Dec 24, 2020
1 parent e76370d commit aa3c0c6
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 64 deletions.
66 changes: 13 additions & 53 deletions src/components/toast-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { useCallback } from 'react';
import { styled, keyframes, CSSAttribute } from 'goober';
import { styled, keyframes } from 'goober';

import { Toast, ToastPosition, resolveValueOrFunction } from '../core/types';
import { Indicator } from './indicator';
Expand Down Expand Up @@ -41,42 +41,11 @@ const Message = styled('div')`

interface ToastBarProps {
toast: Toast;
offset: number;
onHeight: (height: number) => void;

position: ToastPosition;
}

const getPositionStyle = (
position: ToastPosition,
offset: number
): React.CSSProperties => {
const top = position.includes('top');
const verticalStyle = top ? { top: 0 } : { bottom: 0 };

const horizontalStyle: CSSAttribute = position.includes('left')
? {
left: 0,
}
: position.includes('right')
? {
right: 0,
}
: {
left: 0,
pointerEvents: 'none',
right: 0,
justifyContent: 'center',
};
return {
position: 'fixed',
transition: 'all 230ms cubic-bezier(.21,1.02,.73,1)',
transform: `translateY(${offset * (top ? 1 : -1)}px)`,
...verticalStyle,
...horizontalStyle,
};
};

const getAnimationStyle = (
position: ToastPosition,
visible: boolean
Expand All @@ -98,15 +67,14 @@ const getAnimationStyle = (
};

export const ToastBar: React.FC<ToastBarProps> = React.memo(
({ toast, position, ...props }) => {
({ toast, position, onHeight }) => {
const ref = useCallback((el: HTMLElement | null) => {
if (el) {
const boundingRect = el.getBoundingClientRect();
props.onHeight(boundingRect.height);
onHeight(boundingRect.height);
}
}, []);

const positionStyle = getPositionStyle(position, props.offset);
const animationStyle = toast?.height
? getAnimationStyle(position, toast.visible)
: { opacity: 0 };
Expand All @@ -125,27 +93,19 @@ export const ToastBar: React.FC<ToastBarProps> = React.memo(
};

return (
<div
<ToastBarBase
ref={ref}
className={toast.className}
style={{
display: 'flex',
zIndex: toast.visible ? 9999 : undefined,
...positionStyle,
...animationStyle,
...toast.style,
}}
>
<ToastBarBase
ref={ref}
className={toast.className}
style={{
...animationStyle,
...toast.style,
}}
>
{renderIcon()}
<Message role={toast.role} aria-live={toast.ariaLive}>
{resolveValueOrFunction(toast.message, toast)}
</Message>
</ToastBarBase>
</div>
{renderIcon()}
<Message role={toast.role} aria-live={toast.ariaLive}>
{resolveValueOrFunction(toast.message, toast)}
</Message>
</ToastBarBase>
);
}
);
59 changes: 48 additions & 11 deletions src/components/toaster.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import * as React from 'react';
import { setup } from 'goober';
import { CSSAttribute } from 'goober';
import CSS from 'csstype';

import { useToaster } from '../core/use-toaster';
import { ToastBar } from './toast-bar';
import { ToastPosition, DefaultToastOptions } from '../core/types';

setup(React.createElement);

interface ToasterProps {
position?: ToastPosition;
reverseOrder?: boolean;
Expand All @@ -16,6 +14,36 @@ interface ToasterProps {
toastOptions?: DefaultToastOptions;
}

const getPositionStyle = (
position: ToastPosition,
offset: number
): React.CSSProperties => {
const top = position.includes('top');
const verticalStyle: CSSAttribute = top ? { top: 0 } : { bottom: 0 };
const horizontalStyle: CSSAttribute = position.includes('left')
? {
left: 0,
}
: position.includes('right')
? {
right: 0,
}
: {
left: 0,
pointerEvents: 'none',
right: 0,
justifyContent: 'center',
};
return {
display: 'flex',
position: 'fixed',
transition: 'all 230ms cubic-bezier(.21,1.02,.73,1)',
transform: `translateY(${offset * (top ? 1 : -1)}px)`,
...verticalStyle,
...horizontalStyle,
};
};

export const Toaster: React.FC<ToasterProps> = ({
reverseOrder,
position = 'top-center',
Expand All @@ -35,16 +63,25 @@ export const Toaster: React.FC<ToasterProps> = ({
onMouseLeave={handlers.endPause}
>
{toasts.map((t) => {
const offset = handlers.calculateOffset(t.id, {
reverseOrder,
});
const positionStyle = getPositionStyle(position, offset);

return (
<ToastBar
<div
key={t.id}
onHeight={(height) => handlers.updateHeight(t.id, height)}
toast={t}
offset={handlers.calculateOffset(t.id, {
reverseOrder,
})}
position={position}
/>
style={{
zIndex: t.visible ? 9999 : undefined,
...positionStyle,
}}
>
<ToastBar
onHeight={(height) => handlers.updateHeight(t.id, height)}
toast={t}
position={position}
/>
</div>
);
})}
</div>
Expand Down

0 comments on commit aa3c0c6

Please sign in to comment.