diff --git a/.changeset/dull-parents-exercise.md b/.changeset/dull-parents-exercise.md new file mode 100644 index 00000000..a3504814 --- /dev/null +++ b/.changeset/dull-parents-exercise.md @@ -0,0 +1,5 @@ +--- +"@cube-dev/ui-kit": patch +--- + +Fixed description preset in notificaiton diff --git a/src/components/overlays/NewNotifications/Bar/FloatingNotification.tsx b/src/components/overlays/NewNotifications/Bar/FloatingNotification.tsx index 1d5fdafd..7f3d4b92 100644 --- a/src/components/overlays/NewNotifications/Bar/FloatingNotification.tsx +++ b/src/components/overlays/NewNotifications/Bar/FloatingNotification.tsx @@ -44,6 +44,7 @@ export const FloatingNotification = memo(function FloatingNotification( const chainedOnDismiss = useChainedCallback( () => onDismissNotification(id), () => onRemoveNotification(id), + notificationProps.onDismiss, ); const onKeyDown = useEvent>(({ key }) => { diff --git a/src/components/overlays/NewNotifications/NotificationView/NotificationCloseButton.tsx b/src/components/overlays/NewNotifications/NotificationView/NotificationCloseButton.tsx index 3a09220d..8c07323e 100644 --- a/src/components/overlays/NewNotifications/NotificationView/NotificationCloseButton.tsx +++ b/src/components/overlays/NewNotifications/NotificationView/NotificationCloseButton.tsx @@ -16,9 +16,9 @@ const CloseButton = tasty(Button, { top: '-0.75x', display: 'flex', placeItems: 'center', - padding: '0.75x', - width: '3.5x', - height: '3.5x', + padding: '0.625x', + width: '3x', + height: '3x', fill: '#white', shadow: '0 0.5x 2x #shadow', color: { '': '#dark-02', hovered: '#dark-03', pressed: '#dark-02' }, diff --git a/src/components/overlays/NewNotifications/NotificationView/NotificationDescription.tsx b/src/components/overlays/NewNotifications/NotificationView/NotificationDescription.tsx index bc6a19c9..74c452ea 100644 --- a/src/components/overlays/NewNotifications/NotificationView/NotificationDescription.tsx +++ b/src/components/overlays/NewNotifications/NotificationView/NotificationDescription.tsx @@ -1,4 +1,4 @@ -import { HTMLAttributes, memo, ReactNode } from 'react'; +import { HTMLAttributes, memo } from 'react'; import { tasty } from '../../../../tasty'; import { Paragraph } from '../../../content/Paragraph'; import { NotificationProps } from './types'; @@ -23,5 +23,9 @@ export const NotificationDescription = memo(function NotificationDescription( ) { const { description, ...descriptionProps } = props; - return {description}; + return ( + + {description} + + ); }); diff --git a/src/components/overlays/NewNotifications/NotificationView/NotificationHeader.tsx b/src/components/overlays/NewNotifications/NotificationView/NotificationHeader.tsx index af980a79..9b0324cb 100644 --- a/src/components/overlays/NewNotifications/NotificationView/NotificationHeader.tsx +++ b/src/components/overlays/NewNotifications/NotificationView/NotificationHeader.tsx @@ -7,16 +7,21 @@ export type NotificationHeaderProps = { header: NotificationProps['header']; } & HTMLAttributes; -const Header = tasty(Title, { gridArea: 'header', margin: '0.25x 0 0.5x' }); +const Header = tasty(Title, { + as: 'div', + preset: 'h6', + styles: { + gridArea: 'header', + '&:not(:empty)': { + margin: '0.25x 0 0.5x', + }, + }, +}); export const NotificationHeader = memo(function NotificationHeader( props: NotificationHeaderProps, ): JSX.Element { const { header, ...headerProps } = props; - return ( -
- {header} -
- ); + return
{header}
; }); diff --git a/src/components/overlays/NewNotifications/NotificationView/NotificationView.tsx b/src/components/overlays/NewNotifications/NotificationView/NotificationView.tsx index 2930c165..810b4160 100644 --- a/src/components/overlays/NewNotifications/NotificationView/NotificationView.tsx +++ b/src/components/overlays/NewNotifications/NotificationView/NotificationView.tsx @@ -33,16 +33,6 @@ const NotificationContainer = tasty({ '': '0 0 0 4bw #purple-04.0 inset', focused: '0 0 0 4bw #purple-04 inset', }, - '&::before': { - zIndex: 0, - content: '""', - position: 'absolute', - top: '-8px', - left: '0', - right: '-8px', - bottom: '0', - display: { '': 'none', 'is-dismissible': 'flex' }, - }, }, }); @@ -105,7 +95,7 @@ export const NotificationView = forwardRef(function NotificationView( > - {header && } + {description && ( component. Please, check if your component is descendant of component", - ); - - return context.api; -} diff --git a/src/components/overlays/NewNotifications/NotificationsContext/use-notifications.ts b/src/components/overlays/NewNotifications/NotificationsContext/use-notifications.ts index 02eb2a01..166f7fe1 100644 --- a/src/components/overlays/NewNotifications/NotificationsContext/use-notifications.ts +++ b/src/components/overlays/NewNotifications/NotificationsContext/use-notifications.ts @@ -29,7 +29,7 @@ export function useNotifications( newToasts.set(id, { id, isDismissible, - duration: isDismissible ? 5_000 : null, + duration: duration ?? isDismissible ? 5_000 : null, ...rest, } as CubeNotifyApiPropsWithID); diff --git a/src/components/overlays/NewNotifications/types.ts b/src/components/overlays/NewNotifications/types.ts index fa80fd8c..e3ca65ad 100644 --- a/src/components/overlays/NewNotifications/types.ts +++ b/src/components/overlays/NewNotifications/types.ts @@ -70,24 +70,7 @@ export type BaseNotificationProps = { | NotificationActionType; }; -export type CubeNotificationProps = BaseNotificationProps & - EitherDismissibleOrNotNotification; - -export type EitherDismissibleOrNotNotification = - | DismissibleNotification - | NonDismissibleNotification; - -type DismissibleNotification = { - isDismissible?: true; - onDismiss?: () => void; - duration?: number; -}; - -type NonDismissibleNotification = { - isDismissible: false; - onDismiss?: never | undefined; - duration?: null; -}; +export type CubeNotificationProps = BaseNotificationProps; export type CubeNotifyApiProps = { meta?: CubeNotificationMeta; diff --git a/src/components/overlays/Toasts/Toast.tsx b/src/components/overlays/Toasts/Toast.tsx index b455bfdb..e1f07d6d 100644 --- a/src/components/overlays/Toasts/Toast.tsx +++ b/src/components/overlays/Toasts/Toast.tsx @@ -2,6 +2,7 @@ import { useEffect } from 'react'; import { useId } from '@react-aria/utils'; import { useToastsApi } from './use-toasts-api'; import { CubeToastsApiProps } from './types'; +import { CubeNotifyApiProps } from '../NewNotifications'; export function Toast(props: CubeToastsApiProps) { const { id: propsId } = props; @@ -17,7 +18,7 @@ export function Toast(props: CubeToastsApiProps) { }, [id]); useEffect(() => { - update(id, props); + update(id, props as CubeNotifyApiProps); }); return null; diff --git a/src/components/overlays/Toasts/toast.test.tsx b/src/components/overlays/Toasts/toast.test.tsx new file mode 100644 index 00000000..d0073e20 --- /dev/null +++ b/src/components/overlays/Toasts/toast.test.tsx @@ -0,0 +1,30 @@ +import { Toast } from './Toast'; +import { renderWithRoot, screen } from '../../../test'; + +describe('useToastsApi', () => { + beforeAll(() => jest.useFakeTimers('modern')); + afterAll(() => jest.useRealTimers()); + + it('should add and dismiss toast on timeout', async () => { + const dismiss = jest.fn(); + renderWithRoot(); + + jest.runAllTimers(); + + expect( + screen.queryByTestId('floating-notification'), + ).not.toBeInTheDocument(); + expect(dismiss).toBeCalledTimes(1); + }); + + it('should not unmount if duration is null', async () => { + const dismiss = jest.fn(); + renderWithRoot( + , + ); + + jest.runAllTimers(); + expect(screen.getByTestId('floating-notification')).toBeInTheDocument(); + expect(dismiss).not.toBeCalled(); + }); +}); diff --git a/src/components/overlays/Toasts/types.ts b/src/components/overlays/Toasts/types.ts index d4556755..6d6e64f4 100644 --- a/src/components/overlays/Toasts/types.ts +++ b/src/components/overlays/Toasts/types.ts @@ -9,7 +9,7 @@ export type CubeToastsApiProps = { header?: ReactChild | ReactFragment; id?: Key; onDismiss?: () => void; - duration?: number; + duration?: number | null; icon?: ReactNode; type?: CubeNotificationType; }; diff --git a/src/components/overlays/Toasts/use-toasts-api.ts b/src/components/overlays/Toasts/use-toasts-api.ts index 107db533..8f7599d9 100644 --- a/src/components/overlays/Toasts/use-toasts-api.ts +++ b/src/components/overlays/Toasts/use-toasts-api.ts @@ -12,9 +12,7 @@ export function useToastsApi() { Object.assign( (props) => notify({ - isDismissible: true, putNotificationInDropdownOnDismiss: false, - duration: 5_000, ...unwrapProps(props), }), { @@ -32,19 +30,24 @@ export function useToastsApi() { function unwrapProps(props: CubeToastsApiProps | ReactChild | ReactFragment) { return { - ...(propsIsDescription(props) - ? { description: props } - : (props as CubeToastsApiProps)), + ...(propsIsToastProps(props) + ? { + isDismissible: props.duration !== null, + duration: 5_000, + ...(props as CubeToastsApiProps), + } + : { description: props, isDismissible: true, duration: 5_000 }), }; } -function propsIsDescription( +function propsIsToastProps( props: CubeToastsApiProps | ReactChild | ReactFragment, -) { - return ( +): props is CubeToastsApiProps { + const isReactNode = isElement(props) || isFragment(props) || typeof props === 'string' || - typeof props === 'number' - ); + typeof props === 'number'; + + return !isReactNode; }