feat(ui-toolkit,trading): allow toast box configuration (#3811)
This commit is contained in:
parent
2904975fd3
commit
f7aab5a78a
@ -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>
|
||||
|
@ -1,3 +1,4 @@
|
||||
export * from './toast';
|
||||
export * from './toasts-container';
|
||||
export * from './use-toasts';
|
||||
export * from './toast-position-setter';
|
||||
|
145
libs/ui-toolkit/src/components/toast/toast-position-setter.tsx
Normal file
145
libs/ui-toolkit/src/components/toast/toast-position-setter.tsx
Normal 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>
|
||||
);
|
||||
};
|
@ -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',
|
||||
{
|
||||
|
@ -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 }
|
||||
)
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user