Skip to content

Commit

Permalink
feat: add web notification
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardodouradol committed Aug 14, 2024
1 parent b84d876 commit f6fc68f
Show file tree
Hide file tree
Showing 7 changed files with 477 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/ocean-core/src/components/_all.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
@import 'chips';
@import 'unordered-list';
@import 'accordion';
@import 'web-notification';
183 changes: 183 additions & 0 deletions packages/ocean-core/src/components/_web-notification.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// $progress-default-timer: 4s;
// $progress-action-timer: 10s;
$slide-animate-timer: 150ms;

@mixin up-animate-function($timer, $side) {
animation-delay: 0s, calc($timer - 0.1s);
animation-duration: $slide-animate-timer, $slide-animate-timer;
animation-name: moveInDown, moveInDownBack;
animation-timing-function: ease-out forwards, ease-out forwards;
top: $font-size-xl;
#{$side}: $font-size-xl;
}

@mixin down-animate-function($timer, $side) {
animation-delay: 0s, calc($timer - 0.1s);
animation-duration: $slide-animate-timer, $slide-animate-timer;
animation-name: moveInUp, moveInUpBack;
animation-timing-function: ease-out forwards, ease-out forwards;
bottom: $font-size-xl;
#{$side}: $font-size-xl;
}

.ods-web-notification {
align-items: center;
background: $color-interface-dark-deep;
border-radius: $border-radius-sm;
display: flex;
min-height: 63px;
position: fixed;
width: 348px;

@media (max-width: 767px) {
left: 3%;
margin: 0;
right: 5%;
width: 93%;
}

// &__top-right-default {
// @include up-animate-function($progress-default-timer, right);
// }

// &__top-right-action {
// @include up-animate-function($progress-action-timer, right);
// }

// &__top-left-default {
// @include up-animate-function($progress-default-timer, left);
// }

// &__top-left-action {
// @include up-animate-function($progress-action-timer, left);
// }

// &__bottom-right-default {
// @include down-animate-function($progress-default-timer, right);
// }

// &__bottom-right-action {
// @include down-animate-function($progress-action-timer, right);
// }

// &__bottom-left-default {
// @include down-animate-function($progress-default-timer, left);
// }

// &__bottom-left-action {
// @include down-animate-function($progress-action-timer, left);
// }

&__content {
display: flex;
max-width: 328px;
padding: 12px $spacing-inline-xs;
width: 328px;
z-index: 1;
}

&__description {
align-items: center;
color: $color-interface-light-pure;
display: flex;
flex: 1;
font-family: $font-family-base;
font-size: $font-size-xxs;
font-weight: $font-weight-regular;
line-height: 21px;
margin: 0;
max-height: 42px;
overflow: hidden;
padding: 0 $spacing-inline-xs;
text-overflow: ellipsis;
}

&__action {
align-items: center;
color: $color-status-positive-pure;
cursor: pointer;
display: flex;
font-family: $font-family-base;
font-size: $font-size-xxs;
font-weight: $font-weight-bold;
justify-content: center;
}

&__action-text-info {
color: $color-brand-primary-up;
}

&__action-text-positive {
color: $color-status-positive-pure;
}

&__action-text-negative {
color: $color-status-negative-pure;
}

&__action-text-warning {
color: $color-status-warning-pure;
}
}

@keyframes moveInDown {
from {
opacity: 0;
transform: translateY(-3rem);
}

to {
opacity: 1;
transform: translateY(0);
}
}

@keyframes moveInDownBack {
from {
opacity: 1;
transform: translateY(0);
}

to {
opacity: 0;
transform: translateY(-3rem);
}
}

@keyframes moveInUp {
from {
opacity: 0;
transform: translateY(3rem);
}

to {
opacity: 1;
transform: translateY(0);
}
}

@keyframes moveInUpBack {
from {
opacity: 1;
transform: translateY(0);
}

to {
opacity: 0;
transform: translateY(3rem);
}
}

@keyframes progress {
0% {
border-bottom-left-radius: $spacing-inline-xxxs;
border-top-left-radius: $spacing-inline-xxxs;
width: 0%;
}

100% {
border-bottom-right-radius: $spacing-inline-xxxs;
border-top-right-radius: $spacing-inline-xxxs;
width: 100%;
}
}
119 changes: 119 additions & 0 deletions packages/ocean-react/src/WebNotification/WebNotification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { Dispatch, SetStateAction } from 'react';
import { X } from '@useblu/ocean-icons-react';
import classNames from 'classnames';

import useWebNotification from './hook/useWebNotification';

export type Position =
| 'bottom-left'
| 'top-left'
| 'top-right'
| 'bottom-right';

export type WebNotificationProps = {
type?: 'info' | 'positive' | 'warning';
description?: string;
isOpen: boolean;
setIsOpen: Dispatch<SetStateAction<boolean>>;
action?: () => void;
actionLabel?: string;
position?: Position;
className?: string;
} & React.ComponentPropsWithoutRef<'div'>;

// let notificationCounter = -30;

const WebNotification = React.forwardRef<HTMLDivElement, WebNotificationProps>(
(
{
type = 'info',
description,
isOpen,
setIsOpen,
action,
actionLabel,
position = 'bottom-right',
className,
},
ref
) => {
const { closeWebNotification, dispatchAction } = useWebNotification({
type,
isOpen,
setIsOpen,
action,
});

// Increment counter and calculate z-index
// eslint-disable-next-line no-plusplus
// notificationCounter += 70;
// const zIndex = notificationCounter;

return (
<>
{isOpen && (
<div
className={classNames(
'ods-web-notification',
`ods-web-notification__${position}-${
action ? 'action' : 'default'
}`,
className
)}
ref={ref}
// style={{ bottom: zIndex }}
data-testid="web-notification-test"
>
<div className="ods-web-notification__content" style={{ gap: 12 }}>
<div
style={{
display: 'flex',
flexDirection: 'row',
width: '100%',
alignItems: 'center',
minHeight: 39,
gap: 12,
}}
>
<div
className="ods-web-notification__description"
style={{ padding: 0 }}
>
{description}
</div>
{action && (
<div
className="ods-web-notification__action"
onClick={dispatchAction}
>
<div
className={`ods-web-notification__action-text-${type}`}
>
{actionLabel ?? 'action'}
</div>
</div>
)}
</div>
<div
id="wrapper"
style={{
color: '#B6B9CC',
width: 24,
height: 20,
cursor: 'pointer',
}}
onClick={closeWebNotification}
>
<X size={16} />
</div>
</div>
</div>
)}
</>
);
}
);

WebNotification.displayName = 'WebNotification';

export default WebNotification;
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useRef, useEffect, useCallback } from 'react';
import { WebNotificationProps } from '../WebNotification';

type IWebNotificationProps = Pick<
WebNotificationProps,
'type' | 'isOpen' | 'setIsOpen' | 'action'
>;

interface IWebNotificationReturn {
closeWebNotification: () => void;
dispatchAction: () => void;
}

export default function useWebNotification({
setIsOpen,
action,
}: IWebNotificationProps): IWebNotificationReturn {
// const webNotificationTimer = useRef<ReturnType<typeof setTimeout> | null>(
// null
// );

const closeWebNotification = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);

const dispatchAction = useCallback(() => {
if (action) action();
}, [action]);

// const setWebNotificationTimer = useCallback(() => {
// const timer = action ? 100000000000 : 4000;

// webNotificationTimer.current = setTimeout(() => {
// if (action) action();
// closeWebNotification();
// }, timer);
// }, [action, closeWebNotification]);

// useEffect(() => {
// if (isOpen) setWebNotificationTimer();
// if (!isOpen) closeWebNotification();
// }, [closeWebNotification, isOpen, setWebNotificationTimer]);

return {
closeWebNotification,
dispatchAction,
// setWebNotificationTimer,
};
}
1 change: 1 addition & 0 deletions packages/ocean-react/src/WebNotification/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './WebNotification';
Loading

0 comments on commit f6fc68f

Please sign in to comment.