Skip to content

Commit

Permalink
feat: toast position support
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaliy-p44 committed Jul 31, 2024
1 parent eeaba9c commit 8f112db
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/ten-rabbits-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@project44-manifest/react': minor
---

toast position support
16 changes: 16 additions & 0 deletions packages/react/src/components/Toast/Toast.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import type { IconButton } from '../button';

export type ToastVariant = 'default' | 'error' | 'info' | 'success' | 'warning';

export type ToastPosition =
| 'bottom-center'
| 'bottom-left'
| 'bottom-right'
| 'top-center'
| 'top-left'
| 'top-right';

export type ToastElement = 'div';

export interface ToastProps {
Expand Down Expand Up @@ -48,6 +56,10 @@ export interface ToastProps {
* @default 'default'
*/
variant?: ToastVariant;
/**
* The position
*/
position?: ToastPosition;
}

export interface ToastOptions {
Expand Down Expand Up @@ -95,4 +107,8 @@ export interface ToastOptions {
* The display variant of the toast.
*/
variant?: ToastVariant;
/**
* The position
*/
position?: ToastPosition;
}
48 changes: 47 additions & 1 deletion packages/react/src/components/Toast/story/Toast.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { Button, toast, Toaster, ToasterProps } from '../../..';
import { Button, ButtonGroup, Flex, toast, Toaster, ToasterProps } from '../../..';

export default {
title: 'Components/Toast',
Expand Down Expand Up @@ -123,3 +123,49 @@ export const Error = (args: ToasterProps) => {
</>
);
};

export const Positioning = (args: ToasterProps) => {
const handlePress = (position: string): void => {
toast.info('Lorem ipsum dolor', {
description:
'consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
duration: 1000,
position,
});
};

const handleTopLeft = React.useCallback(() => {
handlePress('top-left');
}, []);
const handleTopCenter = React.useCallback(() => {
handlePress('top-center');
}, []);
const handleTopRight = React.useCallback(() => {
handlePress('top-right');
}, []);
const handleBottomLeft = React.useCallback(() => {
handlePress('bottom-left');
}, []);
const handleBottomCenter = React.useCallback(() => {
handlePress('bottom-center');
}, []);
const handleBottomRight = React.useCallback(() => {
handlePress('bottom-right');
}, []);

return (
<Flex css={{ width: 600, height: 400 }}>
<Toaster {...args} />
<Flex>
<ButtonGroup>
<Button onPress={handleTopLeft}>top-left</Button>
<Button onPress={handleTopCenter}>top-center</Button>
<Button onPress={handleTopRight}>top-right</Button>
<Button onPress={handleBottomLeft}>bottom-left</Button>
<Button onPress={handleBottomCenter}>bottom-center</Button>
<Button onPress={handleBottomRight}>bottom-right</Button>
</ButtonGroup>
</Flex>
</Flex>
);
};
15 changes: 4 additions & 11 deletions packages/react/src/components/Toaster/Toaster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,7 @@ import type { ToastOptions } from '../Toast';
import { Toast } from '../Toast';
import { StyledToaster } from './Toaster.styles';
import type { ToasterElement, ToasterProps } from './Toaster.types';

const getPositionStyle = (offset: number): React.CSSProperties => ({
position: 'absolute',
right: 0,
top: 0,
transform: `translateY(${Number(offset)}px)`,
transition: 'all 200ms cubic-bezier(0.4, 0.14, 0.3, 1)',
});
import { getPositionStyle } from './utils';

export const Toaster = React.forwardRef((props, forwardedRef) => {
const { as, className: classNameProp, css: cssProp, duration = 5000, ...other } = props;
Expand Down Expand Up @@ -56,19 +49,19 @@ export const Toaster = React.forwardRef((props, forwardedRef) => {
message,
onDismiss,
variant,
position = 'top-right',
} = rest as ToastOptions;

const offset = handlers.calculateOffset(toast, {
gutter: 8,
defaultPosition: 'top-right',
defaultPosition: position,
});

const styles = getPositionStyle(offset);
const styles = getPositionStyle(position as string, offset);

const toastRef = (element: HTMLElement | null) => {
if (element && typeof toast.height !== 'number') {
const { height } = element.getBoundingClientRect();

updateHeight(toast.id, height);
}
};
Expand Down
55 changes: 55 additions & 0 deletions packages/react/src/components/Toaster/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export const getPositionStyle = (position: string, offset: number): React.CSSProperties => {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const styles: React.CSSProperties = {
position: 'absolute',
transition: 'all 200ms cubic-bezier(0.4, 0.14, 0.3, 1)',
} as React.CSSProperties;

switch (position) {
case 'top-left':
return {
...styles,
top: 0,
left: 0,
transform: `translateY(${offset}px)`,
};

case 'top-center':
return {
...styles,
top: 0,
left: '50%',
transform: `translate(-50%,${offset}px)`,
};
case 'top-right':
return {
...styles,
top: 0,
right: 0,
transform: `translateY(${offset}px)`,
};
case 'bottom-left':
return {
...styles,
bottom: 0,
left: 0,
transform: `translateY(${-offset}px)`,
};
case 'bottom-center':
return {
...styles,
bottom: 0,
left: '50%',
transform: `translate(-50%, ${-offset}px)`,
};
case 'bottom-right':
return {
...styles,
bottom: 0,
right: 0,
transform: `translateY(${-offset}px)`,
};
default:
return styles;
}
};

0 comments on commit 8f112db

Please sign in to comment.