Update Toaster position
Change-Id: I474e29f277b3e2638ac758448fe20a56b5b0f3bf
This commit is contained in:
parent
315756790e
commit
931979033b
9 changed files with 217 additions and 119 deletions
|
@ -7,6 +7,7 @@ import MenuIcon from '@prokyon/components/Icons/Menu';
|
|||
import RightToBracketIcon from '@prokyon/components/Icons/RightToBracket';
|
||||
import Modals from '@prokyon/components/Modal/components/Modals';
|
||||
import { Toasters } from '@prokyon/components/Toaster';
|
||||
import { ToastersPosition } from '@prokyon/components/Toaster/components/Toasters';
|
||||
import { SIZES, useMediaQuery } from '@prokyon/hooks/useMediaQuery';
|
||||
import { isNilOrEmpty } from '@prokyon/utils';
|
||||
|
||||
|
@ -24,10 +25,11 @@ export type SkeletonProps = {
|
|||
top?: MenuItem[];
|
||||
user?: MenuItem[];
|
||||
};
|
||||
toasterPosition?: ToastersPosition;
|
||||
};
|
||||
|
||||
export const Skeleton: React.FC<SkeletonProps> = (props) => {
|
||||
const { children, components = {}, items } = props;
|
||||
const { children, components = {}, items, toasterPosition = ToastersPosition.TopRight } = props;
|
||||
const { footer } = components;
|
||||
|
||||
const [, setLocation] = useLocation();
|
||||
|
@ -120,7 +122,7 @@ export const Skeleton: React.FC<SkeletonProps> = (props) => {
|
|||
</div>
|
||||
</div>
|
||||
<Modals />
|
||||
<Toasters />
|
||||
<Toasters position={toasterPosition} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -7,21 +7,21 @@ import Message from '../../Message';
|
|||
import { useToaster } from '../hooks';
|
||||
|
||||
export enum ToastersPosition {
|
||||
topLeft,
|
||||
topCenter,
|
||||
topRight,
|
||||
rightCenter,
|
||||
bottomRight,
|
||||
bottomCenter,
|
||||
bottomLeft,
|
||||
leftCenter,
|
||||
BottomCenter = 'bottomCenter',
|
||||
BottomLeft = 'bottomLeft',
|
||||
BottomRight = 'bottomRight',
|
||||
LeftCenter = 'leftCenter',
|
||||
RightCenter = 'rightCenter',
|
||||
TopCenter = 'topCenter',
|
||||
TopLeft = 'topLeft',
|
||||
TopRight = 'topRight',
|
||||
}
|
||||
|
||||
export type ToastersProps = {
|
||||
position: ToastersPosition;
|
||||
};
|
||||
|
||||
export function Toasters({ position = ToastersPosition.topRight }) {
|
||||
export function Toasters({ position }) {
|
||||
const { toasters } = useToaster();
|
||||
|
||||
if (isNilOrEmpty(toasters)) {
|
||||
|
@ -31,14 +31,14 @@ export function Toasters({ position = ToastersPosition.topRight }) {
|
|||
return (
|
||||
<div
|
||||
className={clsx('toasters', {
|
||||
'toasters--topLeft': ToastersPosition.topLeft === position,
|
||||
'toasters--topCenter': ToastersPosition.topCenter === position,
|
||||
'toasters--topRight': ToastersPosition.topRight === position,
|
||||
'toasters--rightCenter': ToastersPosition.rightCenter === position,
|
||||
'toasters--bottomRight': ToastersPosition.bottomRight === position,
|
||||
'toasters--bottomCenter': ToastersPosition.bottomCenter === position,
|
||||
'toasters--bottomLeft': ToastersPosition.bottomLeft === position,
|
||||
'toasters--leftCenter': ToastersPosition.leftCenter === position,
|
||||
'toasters--topLeft': ToastersPosition.TopLeft === position,
|
||||
'toasters--topCenter': ToastersPosition.TopCenter === position,
|
||||
'toasters--topRight': ToastersPosition.TopRight === position,
|
||||
'toasters--rightCenter': ToastersPosition.RightCenter === position,
|
||||
'toasters--bottomRight': ToastersPosition.BottomRight === position,
|
||||
'toasters--bottomCenter': ToastersPosition.BottomCenter === position,
|
||||
'toasters--bottomLeft': ToastersPosition.BottomLeft === position,
|
||||
'toasters--leftCenter': ToastersPosition.LeftCenter === position,
|
||||
})}>
|
||||
{Object.keys(toasters).map((toasterId) => {
|
||||
const toaster = toasters[toasterId];
|
||||
|
|
|
@ -18,7 +18,7 @@ type ToasterContextType = {
|
|||
toasters: Record<ToasterId, Toaster>;
|
||||
};
|
||||
|
||||
const DefaultTimeout = 6000;
|
||||
const DefaultTimeout = 60000;
|
||||
const timeouts: { [key: ToasterId]: any } = [];
|
||||
|
||||
export const ToasterContext = createContext<ToasterContextType>({
|
||||
|
|
|
@ -8,35 +8,39 @@ const toaster = (theme) => ({
|
|||
zIndex: 10,
|
||||
'&--topLeft': {
|
||||
top: '3rem',
|
||||
right: '3rem',
|
||||
left: '3rem',
|
||||
},
|
||||
'&--topCenter': {
|
||||
top: '3rem',
|
||||
right: '3rem',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, 0%)',
|
||||
},
|
||||
'&--topRight': {
|
||||
top: '3rem',
|
||||
right: '3rem',
|
||||
},
|
||||
'&--rightCenter': {
|
||||
top: '3rem',
|
||||
top: '50%',
|
||||
transform: 'translate(0%, -50%)',
|
||||
right: '3rem',
|
||||
},
|
||||
'&--bottomRight': {
|
||||
top: '3rem',
|
||||
bottom: '3rem',
|
||||
right: '3rem',
|
||||
},
|
||||
'&--bottomCenter': {
|
||||
top: '3rem',
|
||||
right: '3rem',
|
||||
bottom: '3rem',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, 0%)',
|
||||
},
|
||||
'&--bottomLeft': {
|
||||
top: '3rem',
|
||||
right: '3rem',
|
||||
bottom: '3rem',
|
||||
left: '3rem',
|
||||
},
|
||||
'&--leftCenter': {
|
||||
top: '3rem',
|
||||
right: '3rem',
|
||||
top: '50%',
|
||||
transform: 'translate(0%, -50%)',
|
||||
left: '3rem',
|
||||
},
|
||||
[`@media (max-width: ${theme('screens.sm-m.max')})`]: {
|
||||
left: '2rem',
|
||||
|
|
|
@ -42,76 +42,76 @@ All icons are from [reactsvgicons.com](https://reactsvgicons.com/).
|
|||
<IconItem name="AngleLeft">
|
||||
<AngleLeft />
|
||||
</IconItem>
|
||||
<IconItem name="ExclamationCircle">
|
||||
<ExclamationCircle />
|
||||
</IconItem>
|
||||
<IconItem name="RightToBracket">
|
||||
<RightToBracket />
|
||||
</IconItem>
|
||||
<IconItem name="AngleRight">
|
||||
<AngleRight />
|
||||
</IconItem>
|
||||
<IconItem name="ExclamationTriangle">
|
||||
<ExclamationTriangle />
|
||||
</IconItem>
|
||||
<IconItem name="Settings">
|
||||
<Settings />
|
||||
</IconItem>
|
||||
<IconItem name="BuildingStore">
|
||||
<BuildingStore />
|
||||
</IconItem>
|
||||
<IconItem name="External">
|
||||
<External />
|
||||
</IconItem>
|
||||
<IconItem name="Square">
|
||||
<Square />
|
||||
</IconItem>
|
||||
<IconItem name="CheckCircle">
|
||||
<CheckCircle />
|
||||
</IconItem>
|
||||
<IconItem name="File">
|
||||
<File />
|
||||
</IconItem>
|
||||
<IconItem name="Today">
|
||||
<Today />
|
||||
</IconItem>
|
||||
<IconItem name="CheckSquare">
|
||||
<CheckSquare />
|
||||
</IconItem>
|
||||
<IconItem name="Folder">
|
||||
<Folder />
|
||||
</IconItem>
|
||||
<IconItem name="Trash">
|
||||
<Trash />
|
||||
<IconItem name="Circle">
|
||||
<Circle />
|
||||
</IconItem>
|
||||
<IconItem name="CircleFill">
|
||||
<CircleFill />
|
||||
</IconItem>
|
||||
<IconItem name="HappyMessage">
|
||||
<HappyMessage />
|
||||
</IconItem>
|
||||
<IconItem name="UserTie">
|
||||
<UserTie />
|
||||
</IconItem>
|
||||
<IconItem name="Circle">
|
||||
<Circle />
|
||||
</IconItem>
|
||||
<IconItem name="InfoCircle">
|
||||
<InfoCircle />
|
||||
</IconItem>
|
||||
<IconItem name="User">
|
||||
<User />
|
||||
</IconItem>
|
||||
<IconItem name="Cross">
|
||||
<Cross />
|
||||
</IconItem>
|
||||
<IconItem name="Menu">
|
||||
<Menu />
|
||||
</IconItem>
|
||||
<IconItem name="Dashboard">
|
||||
<Dashboard />
|
||||
</IconItem>
|
||||
<IconItem name="ExclamationCircle">
|
||||
<ExclamationCircle />
|
||||
</IconItem>
|
||||
<IconItem name="ExclamationTriangle">
|
||||
<ExclamationTriangle />
|
||||
</IconItem>
|
||||
<IconItem name="External">
|
||||
<External />
|
||||
</IconItem>
|
||||
<IconItem name="File">
|
||||
<File />
|
||||
</IconItem>
|
||||
<IconItem name="Folder">
|
||||
<Folder />
|
||||
</IconItem>
|
||||
<IconItem name="HappyMessage">
|
||||
<HappyMessage />
|
||||
</IconItem>
|
||||
<IconItem name="InfoCircle">
|
||||
<InfoCircle />
|
||||
</IconItem>
|
||||
<IconItem name="Menu">
|
||||
<Menu />
|
||||
</IconItem>
|
||||
<IconItem name="RightFromBracket">
|
||||
<RightFromBracket />
|
||||
</IconItem>
|
||||
<IconItem name="RightToBracket">
|
||||
<RightToBracket />
|
||||
</IconItem>
|
||||
<IconItem name="Settings">
|
||||
<Settings />
|
||||
</IconItem>
|
||||
<IconItem name="Square">
|
||||
<Square />
|
||||
</IconItem>
|
||||
<IconItem name="Today">
|
||||
<Today />
|
||||
</IconItem>
|
||||
<IconItem name="Trash">
|
||||
<Trash />
|
||||
</IconItem>
|
||||
<IconItem name="User">
|
||||
<User />
|
||||
</IconItem>
|
||||
<IconItem name="UserTie">
|
||||
<UserTie />
|
||||
</IconItem>
|
||||
</IconGallery>
|
||||
|
|
|
@ -9,7 +9,7 @@ import { ModalWrapper, openModal as openOutsideReactModal } from '@prokyon/compo
|
|||
import { useModal } from '@prokyon/components/Modal/hooks';
|
||||
import { TextField } from '@prokyon/components/TextField';
|
||||
|
||||
type Story = StoryObj<typeof AddModalButton>;
|
||||
type Story = StoryObj<typeof Modals>;
|
||||
|
||||
export default {
|
||||
component: Modals,
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
import { Title, Unstyled } from '@storybook/blocks';
|
||||
|
||||
import { Button } from '@prokyon/components/Button';
|
||||
import { Toasters } from '@prokyon/components/Toaster';
|
||||
import { showToaster, ToasterWrapper } from '@prokyon/components/Toaster/context';
|
||||
import { StatusEnum } from '@prokyon/types/common';
|
||||
|
||||
<Title>Toaster</Title>
|
||||
|
||||
`import Toaster sfrom '@prokyon/components/Toaster/components/Toasters';`
|
||||
|
||||
```tsx
|
||||
import { useToaster } from '@prokyon/components/Toaster/hooks';
|
||||
|
||||
const { showToaster } = useToaster();
|
||||
|
||||
showToaster({ id: 'id', status: STATUS.none, message: 'message', title: 'title' });
|
||||
```
|
||||
|
||||
Or you can call outside of React component `showToaster` from `@prokyon/components/Toaster/context`.
|
||||
|
||||
## Example
|
||||
|
||||
<Unstyled>
|
||||
<ToasterWrapper>
|
||||
<Button
|
||||
label="Open Toaster"
|
||||
status={StatusEnum.info}
|
||||
onClick={() => {
|
||||
showToaster({
|
||||
id: 'none',
|
||||
title: 'Show toaster',
|
||||
label: 'Show toaster',
|
||||
message: 'Toaster message.',
|
||||
status: StatusEnum.info,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Toasters />
|
||||
</ToasterWrapper>
|
||||
</Unstyled>
|
44
stories/components/Toasters.mdx
Normal file
44
stories/components/Toasters.mdx
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { Canvas, Meta } from '@storybook/blocks';
|
||||
|
||||
import * as ToastersStories from './Toasters.stories';
|
||||
|
||||
<Meta of={ToastersStories} />
|
||||
|
||||
# Toasters
|
||||
|
||||
## Before start
|
||||
|
||||
### In root application use
|
||||
|
||||
```tsx
|
||||
import { Toasters } from '@prokyon/components/Toaster';
|
||||
import { ToasterWrapper } from '@prokyon/components/Toaster/context';
|
||||
|
||||
return (
|
||||
<ToasterWrapper>
|
||||
...
|
||||
<Toasters />
|
||||
</ToasterWrapper>
|
||||
);
|
||||
```
|
||||
|
||||
## Use hook `useToaster()`
|
||||
|
||||
```tsx
|
||||
import { useToaster } from '@prokyon/components/Toaster/hooks';
|
||||
|
||||
const { showToaster } = useToaster();
|
||||
showToaster({ id: 'id', status: STATUS.none, message: 'message', title: 'title' });
|
||||
```
|
||||
|
||||
<Canvas of={ToastersStories.Hook} withToolbar />
|
||||
|
||||
## Use function `showToaster()`
|
||||
|
||||
```tsx
|
||||
import { showToaster } from '@prokyon/components/Toaster/context';
|
||||
|
||||
showToaster({ id: 'id', status: STATUS.none, message: 'message', title: 'title' });
|
||||
```
|
||||
|
||||
<Canvas of={ToastersStories.OutsideReact} withToolbar />
|
89
stories/components/Toasters.stories.tsx
Normal file
89
stories/components/Toasters.stories.tsx
Normal file
|
@ -0,0 +1,89 @@
|
|||
import React from 'react';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { Button } from '@prokyon/components/Button';
|
||||
import { Toasters } from '@prokyon/components/Toaster';
|
||||
import { ToastersPosition } from '@prokyon/components/Toaster/components/Toasters';
|
||||
import { showToaster, ToasterWrapper } from '@prokyon/components/Toaster/context';
|
||||
import { useToaster } from '@prokyon/components/Toaster/hooks';
|
||||
import { StatusEnum } from '@prokyon/types/common';
|
||||
|
||||
type Story = StoryObj<typeof Toasters>;
|
||||
|
||||
export default {
|
||||
component: Toasters,
|
||||
argTypes: {
|
||||
position: {
|
||||
options: [
|
||||
ToastersPosition.TopLeft,
|
||||
ToastersPosition.TopCenter,
|
||||
ToastersPosition.TopRight,
|
||||
ToastersPosition.RightCenter,
|
||||
ToastersPosition.BottomLeft,
|
||||
ToastersPosition.BottomCenter,
|
||||
ToastersPosition.BottomRight,
|
||||
ToastersPosition.LeftCenter,
|
||||
],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="h-80">
|
||||
<ToasterWrapper>
|
||||
<Story />
|
||||
</ToasterWrapper>
|
||||
</div>
|
||||
),
|
||||
],
|
||||
} as Meta;
|
||||
|
||||
export const Hook: Story = {
|
||||
name: 'Hook',
|
||||
render: (args) => {
|
||||
const Comp = () => {
|
||||
const { showToaster } = useToaster();
|
||||
return (
|
||||
<Button
|
||||
label="Open Toaster message"
|
||||
onClick={() =>
|
||||
showToaster({
|
||||
id: 'toaster1',
|
||||
title: 'Title',
|
||||
message: 'Message',
|
||||
status: StatusEnum.info,
|
||||
})
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Comp />
|
||||
<Toasters {...args} />
|
||||
</>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const OutsideReact: Story = {
|
||||
name: 'Function',
|
||||
render: (args) => {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
label="Open Toaster message"
|
||||
onClick={() =>
|
||||
showToaster({
|
||||
id: 'toaster2',
|
||||
title: 'Title',
|
||||
message: 'Message',
|
||||
status: StatusEnum.success,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Toasters {...args} />
|
||||
</>
|
||||
);
|
||||
},
|
||||
};
|
Loading…
Add table
Reference in a new issue