-
Notifications
You must be signed in to change notification settings - Fork 21
PM-2133 dismissable banner #1265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
419163e
PM-2133 - dismissable banner
vas3a 6f9bb56
update pr reviewer
vas3a 1fc2ecd
lint fixes
vas3a 7b7d7b7
PM-2133 - update desktop styles
vas3a a6d033a
PM-2133 - PR feedback
vas3a 53baf43
update workflow
vas3a 8f36483
test buddy v2
vas3a b9fe4ff
use only pr buddy v2
vas3a ca1e432
typo fix
vas3a File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| export * from './profile-context-data.model' | ||
| export { default as profileContext, defaultProfileContextData } from './profile.context' | ||
| export { default as profileContext, defaultProfileContextData, useProfileContext } from './profile.context' | ||
| export * from './profile.context-provider' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
src/libs/shared/lib/components/notifications/Notifications.container.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { FC } from 'react' | ||
|
|
||
| import { Notification } from '~/libs/ui' | ||
|
|
||
| import { NotificationContextType, useNotification } from './Notifications.context' | ||
| import styles from './NotificationsContainer.module.scss' | ||
|
|
||
| const NotificationsContainer: FC = () => { | ||
| const { notifications, removeNotification }: NotificationContextType = useNotification() | ||
|
|
||
| return ( | ||
| <div className={styles.wrap}> | ||
| {notifications.map(n => ( | ||
| <Notification key={n.id} notification={n} onClose={removeNotification} /> | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ))} | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| export default NotificationsContainer | ||
92 changes: 92 additions & 0 deletions
92
src/libs/shared/lib/components/notifications/Notifications.context.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| import React, { createContext, ReactNode, useCallback, useContext, useMemo, useState } from 'react' | ||
|
|
||
| import { useProfileContext } from '~/libs/core' | ||
|
|
||
| import { dismiss, wasDismissed } from './localstorage.utils' | ||
|
|
||
| export type NotificationType = 'success' | 'error' | 'info' | 'warning' | 'banner'; | ||
|
|
||
| export interface Notification { | ||
| id: string; | ||
| type: NotificationType; | ||
| icon?: ReactNode | ||
| message: string; | ||
| duration?: number; // in ms | ||
| } | ||
|
|
||
| type NotifyPayload = string | (Partial<Notification> & { message: string }) | ||
|
|
||
| export interface NotificationContextType { | ||
| notifications: Notification[]; | ||
| notify: (message: NotifyPayload, type?: NotificationType, duration?: number) => Notification | void; | ||
| showBannerNotification: (message: NotifyPayload) => Notification | void; | ||
| removeNotification: (id: string) => void; | ||
| } | ||
|
|
||
| const NotificationContext = createContext<NotificationContextType | undefined>(undefined) | ||
|
|
||
| export const useNotification = (): NotificationContextType => { | ||
| const context = useContext(NotificationContext) | ||
| if (!context) throw new Error('useNotification must be used within a NotificationProvider') | ||
| return context | ||
| } | ||
|
|
||
| export const NotificationProvider: React.FC<{ | ||
| children: ReactNode, | ||
| }> = props => { | ||
| const profileCtx = useProfileContext() | ||
| const uuid = profileCtx.profile?.userId ?? 'annon' | ||
| const [notifications, setNotifications] = useState<Notification[]>([]) | ||
|
|
||
| const removeNotification = useCallback((id: string, persist?: boolean) => { | ||
| setNotifications(prev => prev.filter(n => n.id !== id)) | ||
| if (persist) { | ||
| dismiss(id) | ||
| } | ||
| }, []) | ||
|
|
||
| const notify = useCallback( | ||
| (message: NotifyPayload, type: NotificationType = 'info', duration = 3000) => { | ||
| const id = `${uuid}[${typeof message === 'string' ? message : message.id}]` | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const newNotification: Notification | ||
| = typeof message === 'string' | ||
| ? { duration, id, message, type } | ||
| : { duration, type, ...message, id } | ||
|
|
||
| if (wasDismissed(id)) { | ||
| return undefined | ||
| } | ||
|
|
||
| setNotifications(prev => [...prev, newNotification]) | ||
|
|
||
| if (duration > 0) { | ||
| setTimeout(() => removeNotification(id), duration) | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| return newNotification | ||
| }, | ||
| [uuid], | ||
| ) | ||
|
|
||
| const showBannerNotification = useCallback(( | ||
| message: NotifyPayload, | ||
| ) => notify(message, 'banner', 0), [notify]) | ||
|
|
||
| const ctxValue = useMemo(() => ({ | ||
| notifications, | ||
| notify, | ||
| removeNotification, | ||
| showBannerNotification, | ||
| }), [ | ||
| notifications, | ||
| notify, | ||
| removeNotification, | ||
| showBannerNotification, | ||
| ]) | ||
|
|
||
| return ( | ||
| <NotificationContext.Provider value={ctxValue}> | ||
| {props.children} | ||
| </NotificationContext.Provider> | ||
| ) | ||
| } | ||
7 changes: 7 additions & 0 deletions
7
src/libs/shared/lib/components/notifications/NotificationsContainer.module.scss
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| @import "@libs/ui/styles/includes"; | ||
|
|
||
| .wrap { | ||
| position: relative; | ||
| width: 100%; | ||
| z-index: 1000; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { default as NotificationsContainer } from './Notifications.container' | ||
| export * from './Notifications.context' |
9 changes: 9 additions & 0 deletions
9
src/libs/shared/lib/components/notifications/localstorage.utils.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| const lsKeyPrefix = 'notificationDismissed' | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| export const wasDismissed = (id: string): boolean => ( | ||
kkartunov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| (localStorage.getItem(`${lsKeyPrefix}[${id}]`)) !== null | ||
| ) | ||
|
|
||
| export const dismiss = (id: string): void => { | ||
| localStorage.setItem(`${lsKeyPrefix}[${id}]`, JSON.stringify(true)) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import { FC, ReactNode, useCallback } from 'react' | ||
|
|
||
| import { NotificationBanner } from './banner' | ||
|
|
||
| interface NotificationProps { | ||
| notification: { | ||
| icon?: ReactNode; | ||
| id: string; | ||
| message: string; | ||
| type: string; | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| onClose: (id: string, save?: boolean) => void | ||
| } | ||
|
|
||
| const Notification: FC<NotificationProps> = props => { | ||
| const handleClose = useCallback((save?: boolean) => { | ||
| props.onClose(props.notification.id, save) | ||
| }, [props.onClose, props.notification.id]) | ||
|
|
||
| if (props.notification.type === 'banner') { | ||
| return ( | ||
| <NotificationBanner | ||
| icon={props.notification.icon} | ||
| content={props.notification.message} | ||
| onClose={handleClose} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| return <></> | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| export default Notification | ||
38 changes: 38 additions & 0 deletions
38
src/libs/ui/lib/components/notification/banner/NotificationBanner.module.scss
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| @import '../../../styles/includes'; | ||
|
|
||
| .wrap { | ||
| background: #60267D; | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| color: $tc-white; | ||
|
|
||
| font-family: "Nunito Sans", sans-serif; | ||
| font-size: 14px; | ||
| line-height: 20px; | ||
|
|
||
| .inner { | ||
| max-width: $xxl-min; | ||
| padding: $sp-2 0; | ||
| @include pagePaddings; | ||
| margin: 0 auto; | ||
| width: 100%; | ||
| display: flex; | ||
| justify-content: space-between; | ||
| align-items: center; | ||
| } | ||
| } | ||
|
|
||
| .close { | ||
| cursor: pointer; | ||
| color: $tc-white; | ||
| flex: 0 0; | ||
| margin-left: auto; | ||
| border-radius: 50%; | ||
| border: 2px solid white; | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| @include ltemd { | ||
| margin-left: $sp-3; | ||
| } | ||
| } | ||
|
|
||
| .icon { | ||
| flex: 0 0; | ||
| margin-right: $sp-2; | ||
| } | ||
29 changes: 29 additions & 0 deletions
29
src/libs/ui/lib/components/notification/banner/NotificationBanner.stories.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { Meta, StoryObj } from '@storybook/react' | ||
|
|
||
| import NotificationBanner from './NotificationBanner' | ||
|
|
||
| const meta: Meta<typeof NotificationBanner> = { | ||
| argTypes: { | ||
| content: { | ||
| description: 'Content displayed inside the notification banner', | ||
| }, | ||
| persistent: { | ||
| defaultValue: false, | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| description: 'Set to true to hide the close icon button', | ||
| }, | ||
| }, | ||
| component: NotificationBanner, | ||
| excludeStories: /.*Decorator$/, | ||
| tags: ['autodocs'], | ||
| title: 'Components/NotificationBanner', | ||
| } | ||
|
|
||
| export default meta | ||
|
|
||
| type Story = StoryObj<typeof NotificationBanner>; | ||
|
|
||
| export const Primary: Story = { | ||
| args: { | ||
| content: 'Help tooltip', | ||
| }, | ||
| } | ||
42 changes: 42 additions & 0 deletions
42
src/libs/ui/lib/components/notification/banner/NotificationBanner.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { FC, ReactNode, useCallback } from 'react' | ||
|
|
||
| import { InformationCircleIcon } from '@heroicons/react/outline' | ||
|
|
||
| import { IconOutline } from '../../svgs' | ||
|
|
||
| import styles from './NotificationBanner.module.scss' | ||
|
|
||
| interface NotificationBannerProps { | ||
| persistent?: boolean | ||
| content: ReactNode | ||
| icon?: ReactNode | ||
| onClose?: (save?: boolean) => void | ||
| } | ||
|
|
||
| const NotificationBanner: FC<NotificationBannerProps> = props => { | ||
| const handleClose = useCallback(() => { | ||
| props.onClose?.(true) | ||
| }, [props.onClose]) | ||
|
|
||
| return ( | ||
| <div className={styles.wrap}> | ||
| <div className={styles.inner}> | ||
| {props.icon || ( | ||
| <div className={styles.icon}> | ||
| <InformationCircleIcon className='icon-xl' /> | ||
| </div> | ||
| )} | ||
|
|
||
| {props.content} | ||
|
|
||
| {!props.persistent && ( | ||
| <div className={styles.close} onClick={handleClose}> | ||
vas3a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| <IconOutline.XIcon className='icon-lg' /> | ||
| </div> | ||
| )} | ||
| </div> | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| export default NotificationBanner | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { default as NotificationBanner } from './NotificationBanner' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export * from './banner' | ||
| export { default as Notification } from './Notification' |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.