feat(ui-toolkit,trading): allow toast box configuration (#3811)

This commit is contained in:
Maciek 2023-05-18 13:53:36 +02:00 committed by GitHub
parent 2904975fd3
commit f7aab5a78a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 191 additions and 3 deletions

View File

@ -5,6 +5,7 @@ import {
RoundedWrapper,
Switch,
ThemeSwitcher,
ToastPositionSetter,
} from '@vegaprotocol/ui-toolkit';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
@ -41,6 +42,8 @@ export const Settings = () => {
'Help identify bugs and improve the service by sharing anonymous usage data.'
)}
/>
<Divider />
<ToastPositionSetter />
</RoundedWrapper>
</div>
</div>

View File

@ -1,3 +1,4 @@
export * from './toast';
export * from './toasts-container';
export * from './use-toasts';
export * from './toast-position-setter';

View File

@ -0,0 +1,145 @@
import classNames from 'classnames';
import { t } from '@vegaprotocol/i18n';
import { IconNames } from '@blueprintjs/icons';
import { Icon } from '../icon';
import { Button } from '../button';
import { ToastPosition, useToastsConfiguration, useToasts } from './use-toasts';
import { useCallback } from 'react';
import { Intent } from '../../utils/intent';
const testToast = {
id: 'test-toast',
intent: Intent.Primary,
content: <>{t('This is an example of a toast notification')}</>,
};
export const ToastPositionSetter = () => {
const setPostion = useToastsConfiguration((store) => store.setPosition);
const position = useToastsConfiguration((store) => store.position);
const setToast = useToasts((store) => store.setToast);
const handleChange = useCallback(
(position: ToastPosition) => {
setPostion(position);
setToast(testToast);
},
[setToast, setPostion]
);
const iconCssClasses = 'absolute top-[4px] left-[4px]';
const buttonCssClasses =
'relative border-none bg-neutral-500/20 dark:bg-neutral-500/40';
const activeButton = 'bg-neutral-800/80 dark:bg-neutral-200/40';
const activeIcon = 'fill-white dark:fill-black';
return (
<div className="flex justify-between py-3 items-center">
<span>{t('Toast location')}</span>
<div
className={classNames(
'grid grid-cols-3 grid-rows-2 w-[64px] h-[42px] gap-[2px]'
)}
>
<Button
className={classNames(
buttonCssClasses,
position === ToastPosition.TopLeft && activeButton
)}
onClick={() => handleChange(ToastPosition.TopLeft)}
size="xs"
>
<Icon
className={classNames(
iconCssClasses,
position === ToastPosition.TopLeft && activeIcon
)}
size={3}
name={IconNames.ARROW_TOP_LEFT}
/>{' '}
</Button>
<Button
className={classNames(
buttonCssClasses,
position === ToastPosition.TopCenter && activeButton
)}
onClick={() => handleChange(ToastPosition.TopCenter)}
size="xs"
>
<Icon
className={classNames(
iconCssClasses,
position === ToastPosition.TopCenter && activeIcon
)}
size={3}
name={IconNames.ARROW_UP}
/>
</Button>
<Button
className={classNames(
buttonCssClasses,
position === ToastPosition.TopRight && activeButton
)}
onClick={() => handleChange(ToastPosition.TopRight)}
size="xs"
>
<Icon
className={classNames(
iconCssClasses,
position === ToastPosition.TopRight && activeIcon
)}
size={3}
name={IconNames.ARROW_TOP_RIGHT}
/>
</Button>
<Button
className={classNames(
buttonCssClasses,
position === ToastPosition.BottomLeft && activeButton
)}
onClick={() => handleChange(ToastPosition.BottomLeft)}
size="xs"
>
<Icon
className={classNames(
iconCssClasses,
position === ToastPosition.BottomLeft && activeIcon
)}
size={3}
name={IconNames.ARROW_BOTTOM_LEFT}
/>
</Button>
<Button
className={classNames(
buttonCssClasses,
position === ToastPosition.BottomCenter && activeButton
)}
onClick={() => handleChange(ToastPosition.BottomCenter)}
size="xs"
>
<Icon
className={classNames(
iconCssClasses,
position === ToastPosition.BottomCenter && activeIcon
)}
size={3}
name={IconNames.ARROW_DOWN}
/>
</Button>
<Button
className={classNames(
buttonCssClasses,
position === ToastPosition.BottomRight && activeButton
)}
onClick={() => handleChange(ToastPosition.BottomRight)}
size="xs"
>
<Icon
className={classNames(
iconCssClasses,
position === ToastPosition.BottomRight && activeIcon
)}
size={3}
name={IconNames.ARROW_BOTTOM_RIGHT}
/>
</Button>
</div>
</div>
);
};

View File

@ -6,7 +6,7 @@ import { useLayoutEffect, useRef } from 'react';
import { Button } from '../button';
import { Toast } from './toast';
import type { Toasts } from './use-toasts';
import { useToasts } from './use-toasts';
import { ToastPosition, useToasts, useToastsConfiguration } from './use-toasts';
import { Portal } from '@radix-ui/react-portal';
@ -21,7 +21,7 @@ export const ToastsContainer = ({
}: ToastsContainerProps) => {
const ref = useRef<HTMLDivElement>();
const closeAll = useToasts((store) => store.closeAll);
const position = useToastsConfiguration((store) => store.position);
// Scroll to top for desc, bottom for asc when a toast is added.
const count = usePrevious(Object.keys(toasts).length) || 0;
useLayoutEffect(() => {
@ -46,7 +46,19 @@ export const ToastsContainer = ({
ref={ref as Ref<HTMLDivElement>}
className={classNames(
'group',
'absolute bottom-0 right-0 z-20 ',
'absolute z-20',
{ 'bottom-0 right-0': position === ToastPosition.BottomRight },
{ 'bottom-0 left-0': position === ToastPosition.BottomLeft },
{ 'top-0 left-0': position === ToastPosition.TopLeft },
{ 'top-0 right-0': position === ToastPosition.TopRight },
{
'top-0 left-[50%] translate-x-[-50%]':
position === ToastPosition.TopCenter,
},
{
'bottom-0 left-[50%] translate-x-[-50%]':
position === ToastPosition.BottomCenter,
},
'p-[8px_16px_16px_16px]',
'max-w-full max-h-full overflow-x-hidden overflow-y-auto',
{

View File

@ -1,9 +1,12 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
import type { Toast } from './toast';
import omit from 'lodash/omit';
import isEqual from 'lodash/isEqual';
const STORAGE_KEY = 'vega_toast_store';
export type Toasts = Record<string, Toast>;
const isUpdateable = (a: Toast, b: Toast) =>
@ -96,3 +99,27 @@ export const useToasts = create<ToastsStore>()(
removeAll: () => set({ toasts: {}, count: 0 }),
}))
);
export enum ToastPosition {
BottomRight,
BottomLeft,
TopLeft,
TopRight,
TopCenter,
BottomCenter,
}
type ToastConfiguration = {
position: ToastPosition;
setPosition: (position: ToastPosition) => void;
};
export const useToastsConfiguration = create<ToastConfiguration>()(
persist(
immer((set) => ({
position: ToastPosition.BottomRight,
setPosition: (position: ToastPosition) => set({ position }),
})),
{ name: STORAGE_KEY }
)
);