Skip to content

Commit

Permalink
Merge pull request #588 from Groww-OSS/fix/ToastDarkModeIssue
Browse files Browse the repository at this point in the history
[BGVW-662] fix clear all buttoon background color issue in dark mode
  • Loading branch information
AkshayNaikGroww authored Dec 27, 2024
2 parents bb8d42a + 1c7db4c commit b82e7cb
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 77 deletions.
2 changes: 1 addition & 1 deletion packages/ui-toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@groww-tech/ui-toolkit",
"version": "0.7.9-alpha.3",
"version": "0.7.9-beta",
"description": "A lightning nature UI",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down
44 changes: 19 additions & 25 deletions packages/ui-toolkit/src/components/atoms/Toaster/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import React, {
useEffect,
useLayoutEffect,
useCallback,
isValidElement,
CSSProperties
} from 'react';

Expand All @@ -17,14 +16,10 @@ import { HeightT, ToastProps } from './types';

import './styles.css';

// Default lifetime of a toasts (in ms)
const TOAST_LIFETIME = 5000;

// Equal to exit animation duration
const TIME_BEFORE_UNMOUNT = 50;

// Default gap between toasts
const GAP = 14;
const TOAST_LIFETIME = 5000; // Default lifetime of a toasts (in ms)
const TIME_BEFORE_UNMOUNT = 50; // Equal to exit animation duration
const GAP = 14; // Default gap between toasts


const Toast = (props: ToastProps) => {
Expand All @@ -47,22 +42,27 @@ const Toast = (props: ToastProps) => {
const [ removed, setRemoved ] = useState(false);
const [ offsetBeforeRemove, setOffsetBeforeRemove ] = useState(0);
const [ initialHeight, setInitialHeight ] = useState(0);

const toastRef = useRef<HTMLLIElement>(null);
const closeTimerStartTimeRef = useRef(0);
const lastCloseTimerStartTimeRef = useRef(0);
const offset = useRef(0);

const isFront = index === 0;
const isVisible = index + 1 <= visibleToasts;
const toastType = toast.type || 'default';
const dismissible = toast.dismissible !== false;
const showCloseButton = toast.closeButton ?? true; // Default to true
const duration = toast.duration || TOAST_LIFETIME;
const [ y, x ] = position.split('-');
const isDocumentHidden = useIsDocumentHidden();

// Height index is used to calculate the offset as it gets updated before the toast array, which means we can calculate the new layout faster.
const heightIndex = useMemo(
() => heights.findIndex((height) => height.toastId === toast.id) || 0,
[ heights, toast.id ]
);
const showCloseButton = toast.closeButton ?? true; // Default to true
const duration = toast.duration || TOAST_LIFETIME;
const closeTimerStartTimeRef = useRef(0);
const offset = useRef(0);
const lastCloseTimerStartTimeRef = useRef(0);
const [ y, x ] = position.split('-');

const toastsHeightBefore = useMemo(() => {
return heights.reduce((prev, curr, reducerIndex) => {
// Calculate offset up until current toast
Expand All @@ -73,14 +73,12 @@ const Toast = (props: ToastProps) => {
return prev + curr.height;
}, 0);
}, [ heights, heightIndex ]);
const isDocumentHidden = useIsDocumentHidden();

offset.current = useMemo(() => heightIndex * gap + toastsHeightBefore, [ heightIndex, toastsHeightBefore ]);


useEffect(() => {
// Trigger enter animation without using CSS animation
setMounted(true);
setMounted(true); // Trigger enter animation without using CSS animation
}, []);


Expand Down Expand Up @@ -207,7 +205,7 @@ const Toast = (props: ToastProps) => {
tabIndex={0}
ref={toastRef}
className='borderPrimary backgroundPrimary'
data-sonner-toast=""
data-sonner-toast
data-styled={!Boolean(toast.jsx)}
data-mounted={mounted}
data-removed={removed}
Expand Down Expand Up @@ -249,9 +247,7 @@ const Toast = (props: ToastProps) => {
) : null
}
{
toast.jsx || isValidElement(toast.title) ? (
toast.jsx || toast.title
) : (
toast.jsx || (
<>
{
toastType ? (
Expand All @@ -264,11 +260,9 @@ const Toast = (props: ToastProps) => {
) : null
}

<div data-content="">
<div data-content>
{toast.title ? <div className=' bodyLargeHeavy'>{toast.title}</div> : null}
{
toast.description ? <div className='bodyBase'>{toast.description}</div> : null
}
{toast.description ? <div className='bodyBase'>{toast.description}</div> : null}
</div>
</>
)
Expand Down
95 changes: 45 additions & 50 deletions packages/ui-toolkit/src/components/atoms/Toaster/Toaster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import React, {
useRef,
useCallback,
useEffect,
CSSProperties
CSSProperties,
Fragment
} from 'react';
import ReactDOM from 'react-dom';

Expand All @@ -20,17 +21,10 @@ import {

import './styles.css';

// Visible no of toasts at a time in the viewport
const VISIBLE_TOASTS_AMOUNT = 251;

// Viewport padding
const VIEWPORT_OFFSET = '28px';

// Default toast width
const TOAST_WIDTH = 356;

// Default gap between toasts
const GAP = 14;
const VISIBLE_TOASTS_AMOUNT = 251; // Visible no of toasts at a time in the viewport
const VIEWPORT_OFFSET = '28px'; // Viewport padding
const TOAST_WIDTH = 356; // Default toast width
const GAP = 14; // Default gap between toasts


const Toaster = (props: ToasterProps) => {
Expand All @@ -44,21 +38,21 @@ const Toaster = (props: ToasterProps) => {
containerAriaLabel = 'Notifications',
pauseWhenPageIsHidden = true
} = props;
const [ toasts, setToasts ] = useState<ToastT[]>([]);

const possiblePositions: Position[] = useMemo(() => {
const allToastPositions = toasts.filter(toast => toast.position !== undefined).map(toast => toast.position as Position);

return Array.from(new Set([ ...allToastPositions ]));
}, [ toasts, position ]);

const [ toasts, setToasts ] = useState<ToastT[]>([]);
const [ heights, setHeights ] = useState<HeightT[]>([]);
const [ expanded, setExpanded ] = useState(false);
const [ interacting, setInteracting ] = useState(false);

const listRef = useRef<HTMLOListElement>(null);
const hotkeyLabel = hotkey.join('+').replace(/Key/g, '').replace(/Digit/g, '');

const possiblePositions: Position[] = useMemo(() => {
const allToastPositions = toasts.filter(toast => toast.position !== undefined).map(toast => toast.position as Position);

return Array.from(new Set([ ...allToastPositions ]));
}, [ toasts, position ]);


const removeToast = useCallback((toastToRemove: ToastT) => {
setToasts((toasts: ToastT[]) => {
Expand Down Expand Up @@ -103,14 +97,13 @@ const Toaster = (props: ToasterProps) => {

useEffect(() => {
// Ensure expanded is always false when no toasts are present / only one left
if (toasts.length <= 1) {
setExpanded(false);
}
if (toasts.length <= 1) setExpanded(false);
}, [ toasts ]);


useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
const isHotkeyPressed = hotkey.every((key) => (event as any)[key] || event.code === key);
const isHotkeyPressed = hotkey.every((key) => event[key as keyof KeyboardEvent] || event.code === key);

if (isHotkeyPressed) {
setExpanded(true);
Expand All @@ -130,39 +123,47 @@ const Toaster = (props: ToasterProps) => {
return () => document.removeEventListener('keydown', handleKeyDown);
}, [ hotkey ]);

if (!toasts.length) return null;
const calculateTopRightToastsHeight = useCallback(() => {
const topRightToastsHeightArray = heights.filter(toast => toast.position === 'top-right');
//sum of all toast height with position top right
let topRightToastsHeight = topRightToastsHeightArray.reduce((sum, t) => sum + t.height, 0);

const topRightToastsHeightArray = Array.isArray(heights) ? heights.filter(toast => toast.position === 'top-right') : [];
topRightToastsHeight = topRightToastsHeight + (topRightToastsHeightArray.length - 1) * gap;
topRightToastsHeight = typeof topRightToastsHeight === 'number' ? Math.ceil(topRightToastsHeight) : topRightToastsHeight;

//sum of all toast height with position top right + gap
let sumOfTopRightToastsHeight = topRightToastsHeightArray.reduce((a, b) => { return a + b.height; }, 0);
return topRightToastsHeight;
}, [ heights, gap ]);

sumOfTopRightToastsHeight = sumOfTopRightToastsHeight + (topRightToastsHeightArray.length - 1) * gap;
sumOfTopRightToastsHeight = typeof sumOfTopRightToastsHeight === 'number' ? Math.ceil(sumOfTopRightToastsHeight) : sumOfTopRightToastsHeight;

const expandedViewStyle: CSSProperties = expanded ? { height: `${sumOfTopRightToastsHeight}px`, overflow: 'scroll', backdropFilter: 'blur(4px)' } : {};
const expandedViewStyle: CSSProperties = expanded
? {
height: `${calculateTopRightToastsHeight()}px`,
overflow: 'scroll',
backdropFilter: 'blur(4px)'
}
: {};


const removeAllToasts = () => {
ToastState.dismiss();
};


const clearAllButtonUI = (yPosition: string, xPosition: string) => {
//close button handle only for top-right position
const clearAllButtonUI = (position: string) => {
//close all toast button is handled only for top-right position
const topRightToastsArray = toasts.filter(toast => toast.position === 'top-right');

if (yPosition !== 'top' || xPosition !== 'right' || topRightToastsArray.length <= 1) return null;
if (position !== 'top-right' || topRightToastsArray.length <= 1) return null;
const [ y, x ] = position.split('-');

return (
<div
className='backgroundSecondary borderPrimary clear-all'
data-toaster-clear-all
onClick={removeAllToasts}
data-y-position={yPosition}
data-x-position={xPosition}
data-y-position={y}
data-x-position={x}
onMouseEnter={() => setExpanded(true)}
onMouseMove={() => setExpanded(true)}
onMouseLeave={() => setExpanded(false)}
style={
{
Expand All @@ -171,11 +172,14 @@ const Toaster = (props: ToasterProps) => {
zIndex: 99999999
} as CSSProperties
}
>Clear all
>
Clear all
</div>
);
};

if (!toasts.length) return null;

return (
// Remove item from normal navigation flow, only available via hotkey
<section
Expand All @@ -187,10 +191,9 @@ const Toaster = (props: ToasterProps) => {
const [ y, x ] = position.split('-');

return (
<>
{clearAllButtonUI(y, x)}
<Fragment key={position + index}>
{clearAllButtonUI(position)}
<ol
key={position}
tabIndex={-1}
ref={listRef}
data-sonner-toaster
Expand All @@ -208,15 +211,7 @@ const Toaster = (props: ToasterProps) => {
} as CSSProperties
}
onMouseEnter={() => setExpanded(true)}
onMouseMove={() => setExpanded(true)}
onMouseLeave={
() => {
// Avoid setting expanded to false when interacting with a toast, e.g. swiping
if (!interacting) {
setExpanded(false);
}
}
}
onMouseLeave={() => !interacting && setExpanded(false)}
onPointerDown={
(event) => {
const isNotDismissible =
Expand Down Expand Up @@ -251,7 +246,7 @@ const Toaster = (props: ToasterProps) => {
))
}
</ol>
</>
</Fragment>
);
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@

:where([data-toaster-clear-all]):hover {
color: var(--content-primary);
background: var(--background-always-light);
background: var(--background-primary);
}

:where([data-sonner-toast]) :where([data-close-button]) {
Expand Down

0 comments on commit b82e7cb

Please sign in to comment.