Skip to content

Commit

Permalink
DS-Dapp Notification Component (#1801)
Browse files Browse the repository at this point in the history
* add in-app semantics and block files

* update notification component

* add localstorage identifier

* update library

* add duration option

* resolve comments

* update comment fixes

* fix comments

* testing notification

* update notification component

---------

Co-authored-by: rohitmalhotra1420 <[email protected]>
  • Loading branch information
corlard3y and rohitmalhotra1420 authored Aug 13, 2024
1 parent a0a3ddd commit ea96da6
Show file tree
Hide file tree
Showing 11 changed files with 1,154 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
"react-waypoint": "^9.0.3",
"secp256k1-v4": "https://github.com/HarshRajat/secp256k1-node",
"simple-peer": "9.11.1",
"sonner": "^1.5.0",
"stream-browserify": "3.0.0",
"styled-components": "^5.3.8",
"url": "0.11.0",
Expand Down
6 changes: 6 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import styled, { ThemeProvider } from 'styled-components';

import { ChatUIProvider, darkChatTheme, IChatTheme } from '@pushprotocol/uiweb';
import { createGlobalStyle } from 'styled-components';
import { Toaster } from 'sonner';

// Internal Compoonents
import InitState from 'components/InitState';
Expand Down Expand Up @@ -346,6 +347,11 @@ export default function App() {
<>
<GlobalStyle />
<InitState />
<Toaster
style={{ minWidth: '397px', height: '111px' }}
offset={15}
visibleToasts={5}
/>
<NavigationContextProvider>
<ChatUIProvider
user={userPushSDKInstance}
Expand Down
982 changes: 982 additions & 0 deletions src/blocks/illustrations/components/RewardPoints.tsx

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/blocks/illustrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export { default as Notification } from './components/Notification';
export { default as NotificationDark } from './components/NotificationDark';

export { default as RewardsBell } from './components/RewardsBell';

export { default as RewardPoints } from './components/RewardPoints';

export { default as Referral } from './components/Referral';

export { default as Twitter } from './components/Twitter';
Expand Down
1 change: 1 addition & 0 deletions src/blocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export { Link, type LinkProps } from './link';
export { Lozenge, type LozengeProps } from './lozenge';
export { Menu, type MenuProps, MenuItem, type MenuItemComponentProps } from './menu';
export { Modal, type ModalProps, modal } from './modal';
export { notification } from './notification';
export { ProgressBar, type ProgressBarProps } from './progressBar';
export { Separator, type SeparatorProps } from './separator';
export { Skeleton, type SkeletonProps } from './skeleton';
Expand Down
111 changes: 111 additions & 0 deletions src/blocks/notification/Notification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { FC } from 'react';
import styled from 'styled-components';
import { Cross } from '../icons';
import { NotificationProps } from './Notification.types';
import { toast } from 'sonner';
import { getTextVariantStyles } from 'blocks/Blocks.utils';

const NotificationContainer = styled.div`
position: relative;
background-color: var(--components-in-app-notification-background-default);
border-radius: var(--radius-xxs);
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: row;
align-items: stretch;
max-height: 111px;
min-width: 397px;
max-width: 100%;
cursor: pointer;
box-sizing: border-box;
border: var(--border-sm) solid var(--components-in-app-notification-stroke-bg);
`;

const TextContainer = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
padding: var(--spacing-sm);
flex: 1;
box-sizing: border-box;
`;

const NotificationTitle = styled.span`
${() => getTextVariantStyles('h5-semibold', 'components-in-app-notification-text-default')}
`;

const NotificationDescription = styled.span`
${() => getTextVariantStyles('bes-regular', 'components-in-app-notification-text-secondary')}
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
line-clamp: 3;
-webkit-box-orient: vertical;
`;

const IconContainer = styled.div`
padding: var(--spacing-sm) var(--spacing-xs);
border-radius: var(--radius-xxs) var(--radius-none) var(--radius-none) var(--radius-xxs);
background: radial-gradient(79.55% 79.55% at 50% 50%, #344efd 0%, #171717 100%);
`;

const CloseButton = styled.div`
background-color: var(--surface-transparent);
cursor: pointer;
color: var(--components-in-app-notification-icon-default);
padding: var(--spacing-none);
position: absolute;
right: var(--spacing-xxs);
top: var(--spacing-xxs);
`;

const Notification: FC<NotificationProps> = ({ onClose, title, description, image, onClick }) => {
const handleNotificationClick = () => onClick?.();

const handleNotificationClose = () => {
onClose?.();
notification.hide();
};

return (
<NotificationContainer onClick={handleNotificationClick}>
<IconContainer>{image}</IconContainer>
<CloseButton
onClick={(e) => {
e.stopPropagation();
handleNotificationClose();
}}
>
<Cross size={16} />
</CloseButton>
<TextContainer>
<NotificationTitle>{title}</NotificationTitle>
<NotificationDescription>{description}</NotificationDescription>
</TextContainer>
</NotificationContainer>
);
};

// Store the toastId(s) in an array to manage multiple notifications
const toastIds: Array<string | number> = [];

// Export the notification object with show and hide methods
const notification = {
show: (config: NotificationProps) => {
const toastId = toast.custom(() => <Notification {...config} />, {
duration: config.duration || Infinity,
position: config.position || 'bottom-right',
});
toastIds.push(toastId);
},
hide: () => {
if (toastIds.length > 0) {
const toastId = toastIds.pop();
toast.dismiss(toastId);
}
},
};

export { notification };
18 changes: 18 additions & 0 deletions src/blocks/notification/Notification.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ReactNode } from 'react';

export type NotificationProps = {
/* Svg React component to be passed as the image. */
image: ReactNode;
/* Title of the notification */
title: string;
/* Description of the notification */
description: string;
/* Optional onClick event for the notification */
onClick?: () => void;
/* Optional onClose action for the notification */
onClose?: () => void;
/* Position of the notification */
position?: 'bottom-right' | 'bottom-left';
/* Optional duration of the notification component */
duration?: number;
};
2 changes: 2 additions & 0 deletions src/blocks/notification/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './Notification';
export * from './Notification.types';
4 changes: 4 additions & 0 deletions src/blocks/theme/colors/colors.semantics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { dropdownSemantics } from '../semantics/semantics.dropdown';
import { iconSemantics } from '../semantics/semantics.icon';
import { inputSemantics } from '../semantics/semantics.input';
import { modalSemantics } from '../semantics/semantics.modal';
import { notificationsSemantics } from '../semantics/semantics.notifications';
import { progressBarSemantics } from '../semantics/semantics.progress-bar';
import { radioSemantics } from '../semantics/semantics.radio';
import { skeletonSemantics } from '../semantics/semantics.skeleton';
Expand All @@ -38,6 +39,7 @@ type SemanticKeys = {
icon: 'icon';
input: 'components-inputs';
modal: 'components-modal';
notifications: 'components-in-app-notification';
progressBar: 'components-progress-bar';
radio: 'components-radio-button';
surface: 'surface';
Expand All @@ -64,6 +66,7 @@ export const semanticKeys: SemanticKeys = {
icon: 'icon',
input: 'components-inputs',
modal: 'components-modal',
notifications: 'components-in-app-notification',
progressBar: 'components-progress-bar',
radio: 'components-radio-button',
surface: 'surface',
Expand All @@ -90,6 +93,7 @@ export const colorSemantics = {
[semanticKeys.icon]: iconSemantics,
[semanticKeys.input]: inputSemantics,
[semanticKeys.modal]: modalSemantics,
[semanticKeys.notifications]: notificationsSemantics,
[semanticKeys.progressBar]: progressBarSemantics,
[semanticKeys.radio]: radioSemantics,
[semanticKeys.surface]: surfaceSemantics,
Expand Down
15 changes: 15 additions & 0 deletions src/blocks/theme/semantics/semantics.notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { iconSemantics } from './semantics.icon';
import { strokeSemantics } from './semantics.stroke';
import { surfaceSemantics } from './semantics.surface';
import { textSemantics } from './semantics.text';

export const notificationsSemantics = {
'background-default': { light: surfaceSemantics['primary'].light, dark: surfaceSemantics['primary'].dark },
'stroke-bg': { light: strokeSemantics['secondary'].light, dark: strokeSemantics['secondary'].dark },
'text-default': {
light: textSemantics['primary'].light,
dark: textSemantics['primary'].dark,
},
'text-secondary': { light: textSemantics['tertiary'].light, dark: textSemantics['tertiary'].dark },
'icon-default': { light: iconSemantics['primary'].light, dark: iconSemantics['primary'].dark },
};
11 changes: 11 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18259,6 +18259,7 @@ __metadata:
react-waypoint: "npm:^9.0.3"
secp256k1-v4: "https://github.com/HarshRajat/secp256k1-node"
simple-peer: "npm:9.11.1"
sonner: "npm:^1.5.0"
stream-browserify: "npm:3.0.0"
styled-components: "npm:^5.3.8"
typescript: "npm:^5.2.2"
Expand Down Expand Up @@ -20209,6 +20210,16 @@ __metadata:
languageName: node
linkType: hard

"sonner@npm:^1.5.0":
version: 1.5.0
resolution: "sonner@npm:1.5.0"
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
checksum: 10/f189ec3cacf294b875eeb349faefa4be90d2ff4dcde6dc73b3b77a4a8ed6ff393a1d6a1b1b90ef86de861a4c84d988aec09558cabd39fcb1befddd384c4010b0
languageName: node
linkType: hard

"source-map-js@npm:^1.2.0":
version: 1.2.0
resolution: "source-map-js@npm:1.2.0"
Expand Down

0 comments on commit ea96da6

Please sign in to comment.