Skip to content

Commit

Permalink
fix(toast): restore the timer after remove the element from the stack…
Browse files Browse the repository at this point in the history
… top
  • Loading branch information
unix committed Feb 3, 2022
1 parent e7ce959 commit 13047cb
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
12 changes: 10 additions & 2 deletions components/geist-provider/geist-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { PropsWithChildren, useMemo } from 'react'
import React, { PropsWithChildren, useMemo, useState } from 'react'
import {
GeistUIContent,
GeistUIContextParams,
UpdateToastsFunction,
UpdateToastsIDFunction,
UpdateToastsLayoutFunction,
} from '../utils/use-geist-ui-context'
import ThemeProvider from './theme-provider'
Expand All @@ -21,6 +22,8 @@ const GeistProvider: React.FC<PropsWithChildren<GeistProviderProps>> = ({
themeType,
children,
}) => {
const [lastUpdateToastId, setLastUpdateToastId] =
useState<GeistUIContextParams['lastUpdateToastId']>(null)
const [toasts, setToasts, toastsRef] = useCurrentState<GeistUIContextParams['toasts']>(
[],
)
Expand All @@ -34,15 +37,20 @@ const GeistProvider: React.FC<PropsWithChildren<GeistProviderProps>> = ({
const nextLayout = fn(toastLayoutRef.current)
setToastLayout(nextLayout)
}
const updateLastToastId: UpdateToastsIDFunction = fn => {
setLastUpdateToastId(fn())
}

const initialValue = useMemo<GeistUIContextParams>(
() => ({
toasts,
toastLayout,
updateToasts,
lastUpdateToastId,
updateToastLayout,
updateLastToastId,
}),
[toasts, toastLayout],
[toasts, toastLayout, lastUpdateToastId],
)

return (
Expand Down
21 changes: 17 additions & 4 deletions components/use-toasts/toast-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { useGeistUIContext } from '../utils/use-geist-ui-context'
import ToastItem from './toast-item'
import useClasses from '../use-classes'
import { isLeftPlacement, isTopPlacement } from './helpers'
import useCurrentState from '../utils/use-current-state'

const ToastContainer: React.FC<React.PropsWithChildren<unknown>> = () => {
const theme = useTheme()
const portal = usePortal('toast')
const { toasts, updateToasts, toastLayout } = useGeistUIContext()
const [, setHovering, hoveringRef] = useCurrentState<boolean>(false)
const { toasts, updateToasts, toastLayout, lastUpdateToastId } = useGeistUIContext()
const memoizedLayout = useMemo(() => toastLayout, [toastLayout])
const toastElements = useMemo(
() =>
Expand All @@ -28,7 +30,8 @@ const ToastContainer: React.FC<React.PropsWithChildren<unknown>> = () => {
[memoizedLayout],
)
const hoverHandler = (isHovering: boolean) => {
if (isHovering)
setHovering(isHovering)
if (isHovering) {
return updateToasts(last =>
last.map(toast => {
if (!toast.visible) return toast
Expand All @@ -39,6 +42,7 @@ const ToastContainer: React.FC<React.PropsWithChildren<unknown>> = () => {
}
}),
)
}

updateToasts(last =>
last.map((toast, index) => {
Expand All @@ -58,6 +62,15 @@ const ToastContainer: React.FC<React.PropsWithChildren<unknown>> = () => {
)
}

useEffect(() => {
const index = toasts.findIndex(r => r._internalIdent === lastUpdateToastId)
const toast = toasts[index]
if (!toast || toast.visible || !hoveringRef.current) return
const hasVisible = toasts.find((r, i) => i < index && r.visible)
if (hasVisible || !hoveringRef.current) return
hoverHandler(false)
}, [toasts, lastUpdateToastId])

useEffect(() => {
let timeout: null | number = null
const timer = window.setInterval(() => {
Expand All @@ -80,8 +93,8 @@ const ToastContainer: React.FC<React.PropsWithChildren<unknown>> = () => {
return createPortal(
<div
className={classNames}
onMouseOver={() => hoverHandler(true)}
onMouseOut={() => hoverHandler(false)}>
onMouseEnter={() => hoverHandler(true)}
onMouseLeave={() => hoverHandler(false)}>
{toastElements}
<style jsx>{`
.toasts {
Expand Down
4 changes: 3 additions & 1 deletion components/use-toasts/use-toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export type ToastHooksResult = {
}

const useToasts = (layout?: ToastLayout): ToastHooksResult => {
const { updateToasts, toasts, updateToastLayout } = useGeistUIContext()
const { updateToasts, toasts, updateToastLayout, updateLastToastId } =
useGeistUIContext()

useEffect(() => {
if (!layout) return
Expand All @@ -77,6 +78,7 @@ const useToasts = (layout?: ToastLayout): ToastHooksResult => {
return { ...item, visible: false }
}),
)
updateLastToastId(() => internalId)
}
const removeAll = () => {
updateToasts(last => last.map(toast => ({ ...toast, visible: false })))
Expand Down
5 changes: 5 additions & 0 deletions components/utils/use-geist-ui-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@ export type UpdateToastsFunction = (fn: (toasts: Array<Toast>) => Array<Toast>)
export type UpdateToastsLayoutFunction = (
fn: (layout: Required<ToastLayout>) => Required<ToastLayout>,
) => any
export type UpdateToastsIDFunction = (fn: () => string | null) => any

export interface GeistUIContextParams {
toasts: Array<Toast>
updateToasts: UpdateToastsFunction
toastLayout: Required<ToastLayout>
updateToastLayout: UpdateToastsLayoutFunction
lastUpdateToastId: string | null
updateLastToastId: UpdateToastsIDFunction
}

const defaultParams: GeistUIContextParams = {
toasts: [],
toastLayout: defaultToastLayout,
updateToastLayout: t => t,
updateToasts: t => t,
lastUpdateToastId: null,
updateLastToastId: () => null,
}

export const GeistUIContent: React.Context<GeistUIContextParams> =
Expand Down

0 comments on commit 13047cb

Please sign in to comment.