diff --git a/apps/storybook/src/stories/notification-center.stories.tsx b/apps/storybook/src/stories/notification-center.stories.tsx index 52c4af537d..0b82836dd2 100644 --- a/apps/storybook/src/stories/notification-center.stories.tsx +++ b/apps/storybook/src/stories/notification-center.stories.tsx @@ -12,6 +12,12 @@ export default { } satisfies Meta; let id = 0; +const image = ( + +); export const Basic = () => { const push = useSetAtom(pushNotificationAtom); const expand = useAtomValue(expandNotificationCenterAtom); @@ -196,6 +202,27 @@ export const Basic = () => { dark error +
+ +
); diff --git a/packages/component/src/components/notification-center/index.css.ts b/packages/component/src/components/notification-center/index.css.ts index 938bce0fb4..64f78b0978 100644 --- a/packages/component/src/components/notification-center/index.css.ts +++ b/packages/component/src/components/notification-center/index.css.ts @@ -2,7 +2,12 @@ // License on the MIT // https://github.com/emilkowalski/sonner/blob/5cb703edc108a23fd74979235c2f3c4005edd2a7/src/styles.css -import { keyframes, style, styleVariants } from '@vanilla-extract/css'; +import { + globalStyle, + keyframes, + style, + styleVariants, +} from '@vanilla-extract/css'; const swipeOut = keyframes({ '0%': { @@ -19,12 +24,28 @@ const swipeOut = keyframes({ export const notificationCenterViewportStyle = style({ position: 'fixed', - bottom: '200px', - right: '60px', + height: '500px', + bottom: '20px', + right: '20px', width: '380px', - margin: 0, zIndex: 2147483647, outline: 'none', + display: 'flex', + alignItems: 'flex-end', +}); +export const notificationMultimediaStyle = style({ + position: 'relative', + width: '100%', + height: '230px', + borderRadius: '8px 8px 0 0', + overflow: 'hidden', + marginBottom: '16px', +}); +globalStyle(`${notificationMultimediaStyle} > *`, { + width: '100%', + height: '100%', + objectFit: 'cover', + cursor: 'unset', }); export const notificationStyle = style({ @@ -128,18 +149,32 @@ export const notificationStyle = style({ export const notificationIconStyle = style({ fontSize: '24px', marginLeft: '18px', - marginRight: '12px', + marginRight: '8px', color: 'var(--affine-processing-color)', display: 'flex', justifyContent: 'center', alignItems: 'center', }); +export const hasMediaStyle = style({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + paddingTop: '0', + paddingBottom: '16px', + width: '380px', + borderRadius: '8px', + boxShadow: 'var(--affine-shadow-1)', + border: '1px solid var(--affine-border-color)', + background: 'var(--affine-white)', + transition: 'all 0.3s', +}); export const notificationContentStyle = style({ display: 'flex', flexDirection: 'column', justifyContent: 'center', - padding: '16px 0', - width: '100%', + paddingTop: '16px', + paddingBottom: '16px', + width: '380px', borderRadius: '8px', boxShadow: 'var(--affine-shadow-1)', border: '1px solid var(--affine-border-color)', @@ -181,6 +216,26 @@ export const closeButtonStyle = style({ export const closeButtonWithoutUndoStyle = style({ marginLeft: '92px', }); +export const closeButtonWithMediaStyle = style({ + position: 'absolute', + width: '22px', + height: '22px', + fontSize: '16px', + top: '6px', + right: '6px', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + cursor: 'pointer', + borderRadius: '4px', + color: 'var(--affine-pure-black)', + ':hover': { + background: 'var(--affine-hover-color)', + }, +}); +export const closeButtonColorStyle = style({ + color: 'var(--affine-white)', +}); export const undoButtonStyle = style({ fontSize: 'var(--affine-font-sm)', background: 'var(--affine-hover-color)', @@ -189,6 +244,10 @@ export const undoButtonStyle = style({ color: 'var(--affine-processing-color)', cursor: 'pointer', }); +export const undoButtonWithMediaStyle = style({ + marginLeft: 'auto', + marginRight: '16px', +}); export const messageStyle = style({ fontSize: 'var(--affine-font-sm)', width: '200px', diff --git a/packages/component/src/components/notification-center/index.jotai.ts b/packages/component/src/components/notification-center/index.jotai.ts index 8ad5ba4e4e..3d9e17a905 100644 --- a/packages/component/src/components/notification-center/index.jotai.ts +++ b/packages/component/src/components/notification-center/index.jotai.ts @@ -8,6 +8,7 @@ export type Notification = { theme?: 'light' | 'dark'; timeout?: number; progressingBar?: boolean; + multimedia?: React.ReactNode | JSX.Element | HTMLElement; // actions undo?: () => Promise; }; diff --git a/packages/component/src/components/notification-center/index.tsx b/packages/component/src/components/notification-center/index.tsx index 11e3408e3f..d29c062c72 100644 --- a/packages/component/src/components/notification-center/index.tsx +++ b/packages/component/src/components/notification-center/index.tsx @@ -288,10 +288,20 @@ function NotificationCard(props: NotificationCardProps): ReactElement { }} >
+ {notification.multimedia ? ( +
+ <>{notification.multimedia} + + + +
+ ) : null} UNDO
)} - - - + {notification.multimedia ? null : ( + + + + )} { onSelect?.({ type: 'pdf' }); setPushNotification({ - key: 'export-to-pdf', + key: uuidv4(), title: t['com.affine.export.success.title'](), message: t['com.affine.export.success.message'](), type: 'success', @@ -45,7 +46,7 @@ export const ExportToPdfMenuItem = ({ .catch(err => { console.error(err); setPushNotification({ - key: 'export-to-pdf', + key: uuidv4(), title: t['com.affine.export.error.title'](), message: t['com.affine.export.error.message'](), type: 'error', @@ -59,7 +60,7 @@ export const ExportToPdfMenuItem = ({ .then(() => { onSelect?.({ type: 'pdf' }); setPushNotification({ - key: 'export-to-pdf', + key: uuidv4(), title: t['com.affine.export.success.title'](), message: t['com.affine.export.success.message'](), type: 'success', @@ -68,7 +69,7 @@ export const ExportToPdfMenuItem = ({ .catch(err => { console.error(err); setPushNotification({ - key: 'export-to-pdf', + key: uuidv4(), title: t['com.affine.export.error.title'](), message: t['com.affine.export.error.message'](), type: 'error', @@ -104,7 +105,7 @@ export const ExportToHtmlMenuItem = ({ .then(() => { onSelect?.({ type: 'html' }); setPushNotification({ - key: 'export-to-html', + key: uuidv4(), title: t['com.affine.export.success.title'](), message: t['com.affine.export.success.message'](), type: 'success', @@ -112,6 +113,12 @@ export const ExportToHtmlMenuItem = ({ }) .catch(err => { console.error(err); + setPushNotification({ + key: uuidv4(), + title: t['com.affine.export.error.title'](), + message: t['com.affine.export.error.message'](), + type: 'error', + }); }); onSelect?.({ type: 'html' }); }, [currentEditor, onSelect, setPushNotification, t]); @@ -146,7 +153,7 @@ export const ExportToPngMenuItem = ({ .then(() => { onSelect?.({ type: 'png' }); setPushNotification({ - key: 'export-to-png', + key: uuidv4(), title: t['com.affine.export.success.title'](), message: t['com.affine.export.success.message'](), type: 'success', @@ -155,7 +162,7 @@ export const ExportToPngMenuItem = ({ .catch(err => { console.error(err); setPushNotification({ - key: 'export-to-png', + key: uuidv4(), title: t['com.affine.export.error.title'](), message: t['com.affine.export.error.message'](), type: 'error', @@ -192,7 +199,7 @@ export const ExportToMarkdownMenuItem = ({ .then(() => { onSelect?.({ type: 'markdown' }); setPushNotification({ - key: 'export-to-markdown', + key: uuidv4(), title: t['com.affine.export.success.title'](), message: t['com.affine.export.success.message'](), type: 'success', @@ -201,7 +208,7 @@ export const ExportToMarkdownMenuItem = ({ .catch(err => { console.error(err); setPushNotification({ - key: 'export-to-markdown', + key: uuidv4(), title: t['com.affine.export.error.title'](), message: t['com.affine.export.error.message'](), type: 'error',