Notification menu (#1652)
* Save notification menu prototype * Add dynamic links * Add timestamps * Mark as seen on click * Fix guest mode * Fix discussion links & channel thumbnails * Adjust some details * Adjust theme * Replaxe Menu with MuiMenu * Fix Mui behavior & transitions * Adjust Mui menu behavior * Adjust some padding * Fix read & see * Clean code * Adjust border on top notification * Add case for comment replies * Save * Make alignment pixel perfect * Clean code * Adjust gif avatars, stickers & tips * Add delete function * Add delete icon hover effect * Add outline to delete icon * Fix seeNotification call * Add case for empty notification listä
This commit is contained in:
parent
70695dfd3f
commit
54ee4ee94a
5 changed files with 506 additions and 58 deletions
|
@ -1,14 +1,26 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectUnseenNotificationCount } from 'redux/selectors/notifications';
|
||||
import { doSeeAllNotifications } from 'redux/actions/notifications';
|
||||
import { selectUser } from 'redux/selectors/user';
|
||||
import { selectNotifications, selectUnseenNotificationCount } from 'redux/selectors/notifications';
|
||||
import {
|
||||
doReadNotifications,
|
||||
doSeeNotifications,
|
||||
doDeleteNotification,
|
||||
doSeeAllNotifications,
|
||||
} from 'redux/actions/notifications';
|
||||
import { selectUser, selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import NotificationHeaderButton from './view';
|
||||
|
||||
const select = (state) => ({
|
||||
notifications: selectNotifications(state),
|
||||
unseenCount: selectUnseenNotificationCount(state),
|
||||
user: selectUser(state),
|
||||
authenticated: selectUserVerifiedEmail(state),
|
||||
});
|
||||
|
||||
export default connect(select, {
|
||||
doSeeAllNotifications,
|
||||
})(NotificationHeaderButton);
|
||||
const perform = (dispatch, ownProps) => ({
|
||||
readNotification: ([id]) => dispatch(doReadNotifications([id])),
|
||||
seeNotification: ([id]) => dispatch(doSeeNotifications([id])),
|
||||
deleteNotification: (id) => dispatch(doDeleteNotification(id)),
|
||||
doSeeAllNotifications: doSeeAllNotifications,
|
||||
});
|
||||
|
||||
export default connect(select, perform)(NotificationHeaderButton);
|
||||
|
|
|
@ -5,37 +5,229 @@ import { ENABLE_UI_NOTIFICATIONS } from 'config';
|
|||
import { useHistory } from 'react-router';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import Button from 'component/button';
|
||||
import Icon from 'component/common/icon';
|
||||
import NotificationBubble from 'component/notificationBubble';
|
||||
import React from 'react';
|
||||
import Tooltip from 'component/common/tooltip';
|
||||
import { formatLbryUrlForWeb } from 'util/url';
|
||||
import Notification from 'component/notification';
|
||||
import DateTime from 'component/dateTime';
|
||||
import ChannelThumbnail from 'component/channelThumbnail';
|
||||
import { Menu as MuiMenu } from '@mui/material';
|
||||
import Button from 'component/button';
|
||||
import ClickAwayListener from '@mui/material/ClickAwayListener';
|
||||
import { RULE } from 'constants/notifications';
|
||||
import UriIndicator from 'component/uriIndicator';
|
||||
import { generateNotificationTitle } from '../notification/helpers/title';
|
||||
import { generateNotificationText } from '../notification/helpers/text';
|
||||
import { parseURI } from 'util/lbryURI';
|
||||
|
||||
type Props = {
|
||||
notifications: Array<Notification>,
|
||||
unseenCount: number,
|
||||
user: ?User,
|
||||
authenticated: boolean,
|
||||
readNotification: (Array<number>) => void,
|
||||
seeNotification: (Array<number>) => void,
|
||||
deleteNotification: (number) => void,
|
||||
doSeeAllNotifications: () => void,
|
||||
};
|
||||
|
||||
export default function NotificationHeaderButton(props: Props) {
|
||||
const { unseenCount, user, doSeeAllNotifications } = props;
|
||||
const {
|
||||
notifications,
|
||||
unseenCount,
|
||||
user,
|
||||
authenticated,
|
||||
readNotification,
|
||||
seeNotification,
|
||||
deleteNotification,
|
||||
doSeeAllNotifications,
|
||||
} = props;
|
||||
const list = notifications.slice(0, 5);
|
||||
|
||||
const { push } = useHistory();
|
||||
const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui);
|
||||
const notificationsEnabled = authenticated && (ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui));
|
||||
|
||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||
const [clicked, setClicked] = React.useState(false);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = (event) => setAnchorEl(!anchorEl ? event.currentTarget : null);
|
||||
const handleClose = () => setAnchorEl(null);
|
||||
|
||||
const menuProps = {
|
||||
id: 'notification-menu',
|
||||
anchorEl,
|
||||
open,
|
||||
onClose: handleClose,
|
||||
MenuListProps: {
|
||||
'aria-labelledby': 'basic-button',
|
||||
sx: { padding: 'var(--spacing-xs)' },
|
||||
},
|
||||
className: 'menu__list--header menu__list--notifications',
|
||||
sx: { 'z-index': 2 },
|
||||
PaperProps: { className: 'MuiMenu-list--paper' },
|
||||
disableScrollLock: true,
|
||||
};
|
||||
|
||||
const handleClickAway = () => {
|
||||
if (!clicked) {
|
||||
if (open) setClicked(true);
|
||||
} else {
|
||||
setAnchorEl(null);
|
||||
setClicked(false);
|
||||
}
|
||||
};
|
||||
|
||||
const creatorIcon = (channelUrl, channelThumbnail) => (
|
||||
<UriIndicator uri={channelUrl} link showAtSign channelInfo={{ uri: channelUrl, name: '' }}>
|
||||
<ChannelThumbnail small thumbnailPreview={channelThumbnail} uri={channelThumbnail ? undefined : channelUrl} />
|
||||
</UriIndicator>
|
||||
);
|
||||
|
||||
function handleMenuClick() {
|
||||
if (unseenCount > 0) doSeeAllNotifications();
|
||||
push(`/$/${PAGES.NOTIFICATIONS}`);
|
||||
}
|
||||
|
||||
function handleNotificationDelete(e, id) {
|
||||
e.stopPropagation();
|
||||
deleteNotification(id);
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!open) setClicked(false);
|
||||
}, [open]);
|
||||
|
||||
if (!notificationsEnabled) return null;
|
||||
|
||||
function handleNotificationClick(notification) {
|
||||
const { id, notification_parameters, is_read } = notification;
|
||||
|
||||
if (!is_read) {
|
||||
seeNotification([id]);
|
||||
readNotification([id]);
|
||||
}
|
||||
let notificationLink = formatLbryUrlForWeb(notification_parameters.device.target);
|
||||
if (notification_parameters.dynamic.hash) {
|
||||
notificationLink += '?lc=' + notification_parameters.dynamic.hash + '&view=discussion';
|
||||
}
|
||||
push(notificationLink);
|
||||
}
|
||||
|
||||
function menuEntry(notification) {
|
||||
const { id, active_at, notification_rule, notification_parameters, is_read, type } = notification;
|
||||
|
||||
let channelUrl;
|
||||
let icon;
|
||||
switch (notification_rule) {
|
||||
case RULE.CREATOR_SUBSCRIBER:
|
||||
icon = <Icon icon={ICONS.SUBSCRIBE} sectionIcon />;
|
||||
break;
|
||||
case RULE.COMMENT:
|
||||
case RULE.CREATOR_COMMENT:
|
||||
channelUrl = notification_parameters.dynamic.comment_author;
|
||||
icon = creatorIcon(channelUrl, notification_parameters?.dynamic?.comment_author_thumbnail);
|
||||
break;
|
||||
case RULE.COMMENT_REPLY:
|
||||
channelUrl = notification_parameters.dynamic.reply_author;
|
||||
icon = creatorIcon(channelUrl, notification_parameters?.dynamic?.comment_author_thumbnail);
|
||||
break;
|
||||
case RULE.NEW_CONTENT:
|
||||
channelUrl = notification_parameters.dynamic.channel_url;
|
||||
icon = creatorIcon(channelUrl, notification_parameters?.dynamic?.channel_thumbnail);
|
||||
break;
|
||||
case RULE.NEW_LIVESTREAM:
|
||||
channelUrl = notification_parameters.dynamic.channel_url;
|
||||
icon = creatorIcon(channelUrl, notification_parameters?.dynamic?.channel_thumbnail);
|
||||
break;
|
||||
case RULE.WEEKLY_WATCH_REMINDER:
|
||||
case RULE.DAILY_WATCH_AVAILABLE:
|
||||
case RULE.DAILY_WATCH_REMIND:
|
||||
case RULE.MISSED_OUT:
|
||||
case RULE.REWARDS_APPROVAL_PROMPT:
|
||||
icon = <Icon icon={ICONS.LBC} sectionIcon />;
|
||||
break;
|
||||
case RULE.FIAT_TIP:
|
||||
icon = <Icon icon={ICONS.FINANCE} sectionIcon />;
|
||||
break;
|
||||
default:
|
||||
icon = <Icon icon={ICONS.NOTIFICATION} sectionIcon />;
|
||||
}
|
||||
|
||||
let channelName;
|
||||
if (channelUrl) {
|
||||
try {
|
||||
({ claimName: channelName } = parseURI(channelUrl));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<a onClick={() => handleNotificationClick(notification)}>
|
||||
<div
|
||||
className={
|
||||
is_read ? 'menu__list--notification' : 'menu__list--notification menu__list--notification-unread'
|
||||
}
|
||||
key={id}
|
||||
>
|
||||
<div className="notification__icon">{icon}</div>
|
||||
<div className="menu__list--notification-info">
|
||||
<div className="menu__list--notification-type">
|
||||
{generateNotificationTitle(notification_rule, notification_parameters, channelName)}
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
type === 'comments' ? 'menu__list--notification-title blockquote' : 'menu__list--notification-title'
|
||||
}
|
||||
>
|
||||
{generateNotificationText(notification_rule, notification_parameters)}
|
||||
</div>
|
||||
{!is_read && <span>•</span>}
|
||||
<DateTime timeAgo date={active_at} />
|
||||
</div>
|
||||
<div className="delete-notification" onClick={(e) => handleNotificationDelete(e, id)}>
|
||||
<Icon icon={ICONS.DELETE} sectionIcon />
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip title={__('Notifications')}>
|
||||
<Button onClick={handleMenuClick} className="header__navigationItem--icon">
|
||||
<Icon size={18} icon={ICONS.NOTIFICATION} aria-hidden />
|
||||
<NotificationBubble />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
notificationsEnabled && (
|
||||
<>
|
||||
<Tooltip title={__('Notifications')}>
|
||||
<Button className="header__navigationItem--icon" onClick={handleClick}>
|
||||
<Icon size={18} icon={ICONS.NOTIFICATION} aria-hidden />
|
||||
<NotificationBubble />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<ClickAwayListener onClickAway={handleClickAway}>
|
||||
<MuiMenu {...menuProps}>
|
||||
<div className="menu__list--notifications-header" />
|
||||
<div className="menu__list--notifications-list">
|
||||
{list.map((notification) => {
|
||||
return menuEntry(notification);
|
||||
})}
|
||||
{list.length === 0 && (
|
||||
<div className="menu__list--notification-empty">
|
||||
<div className="menu__list--notification-empty-title">{__('No notifications')}</div>
|
||||
<div className="menu__list--notification-empty-text">
|
||||
{__("You don't have any notifications yet, but they will be here when you do!")}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<a onClick={handleMenuClick}>
|
||||
<div className="menu__list--notifications-more">{__('View all')}</div>
|
||||
</a>
|
||||
</MuiMenu>
|
||||
</ClickAwayListener>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import React from 'react';
|
|||
import Skeleton from '@mui/material/Skeleton';
|
||||
import ChannelSelector from 'component/channelSelector';
|
||||
import Button from 'component/button';
|
||||
import ClickAwayListener from '@mui/material/ClickAwayListener';
|
||||
|
||||
type HeaderMenuButtonProps = {
|
||||
myChannelClaimIds: ?Array<string>,
|
||||
|
@ -28,6 +29,7 @@ export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
|||
const { myChannelClaimIds, activeChannelClaim, authenticated, email, signOut } = props;
|
||||
|
||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||
const [clicked, setClicked] = React.useState(false);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = (event) => setAnchorEl(!anchorEl ? event.currentTarget : null);
|
||||
const handleClose = () => setAnchorEl(null);
|
||||
|
@ -37,6 +39,19 @@ export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
|||
const noActiveChannel = activeChannelUrl === null;
|
||||
const pendingChannelFetch = !noActiveChannel && myChannelClaimIds === undefined;
|
||||
|
||||
const handleClickAway = () => {
|
||||
if (!clicked) {
|
||||
if (open) setClicked(true);
|
||||
} else {
|
||||
setAnchorEl(null);
|
||||
setClicked(false);
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!open) setClicked(false);
|
||||
}, [open]);
|
||||
|
||||
const menuProps = {
|
||||
id: 'basic-menu',
|
||||
anchorEl,
|
||||
|
@ -49,6 +64,7 @@ export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
|||
className: 'menu__list--header',
|
||||
sx: { 'z-index': 2 },
|
||||
PaperProps: { className: 'MuiMenu-list--paper' },
|
||||
disableScrollLock: true,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -87,46 +103,50 @@ export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
|||
</Button>
|
||||
)}
|
||||
{authenticated ? (
|
||||
<MuiMenu {...menuProps}>
|
||||
<ChannelSelector storeSelection isHeaderMenu />
|
||||
<ClickAwayListener onClickAway={handleClickAway}>
|
||||
<MuiMenu {...menuProps}>
|
||||
<ChannelSelector storeSelection isHeaderMenu />
|
||||
|
||||
<hr className="menu__separator" />
|
||||
<HeaderMenuLink useMui page={PAGES.UPLOADS} icon={ICONS.PUBLISH} name={__('Uploads')} />
|
||||
<HeaderMenuLink useMui page={PAGES.CHANNELS} icon={ICONS.CHANNEL} name={__('Channels')} />
|
||||
<HeaderMenuLink
|
||||
useMui
|
||||
page={PAGES.CREATOR_DASHBOARD}
|
||||
icon={ICONS.ANALYTICS}
|
||||
name={__('Creator Analytics')}
|
||||
/>
|
||||
<hr className="menu__separator" />
|
||||
<HeaderMenuLink useMui page={PAGES.UPLOADS} icon={ICONS.PUBLISH} name={__('Uploads')} />
|
||||
<HeaderMenuLink useMui page={PAGES.CHANNELS} icon={ICONS.CHANNEL} name={__('Channels')} />
|
||||
<HeaderMenuLink
|
||||
useMui
|
||||
page={PAGES.CREATOR_DASHBOARD}
|
||||
icon={ICONS.ANALYTICS}
|
||||
name={__('Creator Analytics')}
|
||||
/>
|
||||
|
||||
<hr className="menu__separator" />
|
||||
<HeaderMenuLink useMui page={PAGES.REWARDS} icon={ICONS.REWARDS} name={__('Rewards')} />
|
||||
<HeaderMenuLink useMui page={PAGES.INVITE} icon={ICONS.INVITE} name={__('Invites')} />
|
||||
<HeaderMenuLink useMui page={PAGES.ODYSEE_MEMBERSHIP} icon={ICONS.UPGRADE} name={__('Odysee Premium')} />
|
||||
<hr className="menu__separator" />
|
||||
<HeaderMenuLink useMui page={PAGES.REWARDS} icon={ICONS.REWARDS} name={__('Rewards')} />
|
||||
<HeaderMenuLink useMui page={PAGES.INVITE} icon={ICONS.INVITE} name={__('Invites')} />
|
||||
<HeaderMenuLink useMui page={PAGES.ODYSEE_MEMBERSHIP} icon={ICONS.UPGRADE} name={__('Odysee Premium')} />
|
||||
|
||||
<hr className="menu__separator" />
|
||||
<HeaderMenuLink useMui page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
||||
<HeaderMenuLink useMui page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
||||
<hr className="menu__separator" />
|
||||
<HeaderMenuLink useMui page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
||||
<HeaderMenuLink useMui page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
||||
|
||||
<hr className="menu__separator" />
|
||||
<MuiMenuItem onClick={signOut}>
|
||||
<div className="menu__link" style={{ flexDirection: 'column', alignItems: 'flex-start' }}>
|
||||
<div className="menu__link-label">
|
||||
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
|
||||
{__('Sign Out')}
|
||||
<hr className="menu__separator" />
|
||||
<MuiMenuItem onClick={signOut}>
|
||||
<div className="menu__link" style={{ flexDirection: 'column', alignItems: 'flex-start' }}>
|
||||
<div className="menu__link-label">
|
||||
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
|
||||
{__('Sign Out')}
|
||||
</div>
|
||||
<span className="menu__link-help">{email}</span>
|
||||
</div>
|
||||
<span className="menu__link-help">{email}</span>
|
||||
</div>
|
||||
</MuiMenuItem>
|
||||
</MuiMenu>
|
||||
</MuiMenuItem>
|
||||
</MuiMenu>
|
||||
</ClickAwayListener>
|
||||
) : (
|
||||
<MuiMenu {...menuProps}>
|
||||
<HeaderMenuLink useMui page={PAGES.AUTH_SIGNIN} icon={ICONS.SIGN_IN} name={__('Log In')} />
|
||||
<HeaderMenuLink useMui page={PAGES.AUTH} icon={ICONS.SIGN_UP} name={__('Sign Up')} />
|
||||
<HeaderMenuLink useMui page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
||||
<HeaderMenuLink useMui page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
||||
</MuiMenu>
|
||||
<ClickAwayListener onClickAway={handleClickAway}>
|
||||
<MuiMenu {...menuProps}>
|
||||
<HeaderMenuLink useMui page={PAGES.AUTH_SIGNIN} icon={ICONS.SIGN_IN} name={__('Log In')} />
|
||||
<HeaderMenuLink useMui page={PAGES.AUTH} icon={ICONS.SIGN_UP} name={__('Sign Up')} />
|
||||
<HeaderMenuLink useMui page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
||||
<HeaderMenuLink useMui page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
||||
</MuiMenu>
|
||||
</ClickAwayListener>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -243,9 +243,9 @@ $contentMaxWidth: 60rem;
|
|||
|
||||
.notification__title {
|
||||
position: relative;
|
||||
font-size: var(--font-small);
|
||||
color: var(--color-text);
|
||||
margin-bottom: var(--spacing-xxs);
|
||||
font-size: var(--font-xsmall);
|
||||
color: var(--color-text-subtitle);
|
||||
// margin-bottom: var(--spacing-xxs);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
|
@ -265,8 +265,8 @@ $contentMaxWidth: 60rem;
|
|||
}
|
||||
|
||||
.notification__text {
|
||||
font-size: var(--font-xsmall);
|
||||
color: var(--color-text-subtitle);
|
||||
font-size: var(--font-small);
|
||||
color: var(--color-text);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
|
@ -284,6 +284,7 @@ $contentMaxWidth: 60rem;
|
|||
blockquote {
|
||||
padding-left: var(--spacing-xs);
|
||||
border-left: 2px solid;
|
||||
color: var(--color-text) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -156,9 +156,10 @@ reach-portal {
|
|||
}
|
||||
|
||||
.MuiPaper-root {
|
||||
top: calc(var(--header-height) - 11px) !important;
|
||||
top: calc(var(--header-height) - 10px) !important;
|
||||
transition: none !important;
|
||||
@media (max-width: $breakpoint-small) {
|
||||
top: calc(var(--header-height-mobile) - 11px) !important;
|
||||
top: calc(var(--header-height-mobile) - 10px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,6 +191,230 @@ reach-portal {
|
|||
@extend .menu__list;
|
||||
}
|
||||
|
||||
.menu__list--notifications {
|
||||
.MuiMenu-list {
|
||||
padding: 0;
|
||||
backdrop-filter: blur(4px) !important;
|
||||
|
||||
background-color: unset !important;
|
||||
}
|
||||
.MuiMenu-list--paper {
|
||||
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
||||
background-color: unset !important;
|
||||
}
|
||||
|
||||
.menu__list--notifications-header {
|
||||
height: var(--spacing-xs);
|
||||
background-color: rgba(var(--color-header-background-base), 0.9);
|
||||
backdrop-filter: blur(4px) !important;
|
||||
}
|
||||
|
||||
a:nth-child(1) {
|
||||
.menu__list--notification {
|
||||
border-top: 1px solid rgba(var(--color-header-button-base), 0.95);
|
||||
}
|
||||
}
|
||||
|
||||
.menu__list--notifications-list {
|
||||
overflow: hidden !important;
|
||||
.menu__list--notification {
|
||||
position: relative;
|
||||
overflow: hidden !important;
|
||||
width: 440px;
|
||||
padding: var(--spacing-s);
|
||||
display: flex;
|
||||
background-color: rgba(var(--color-header-button-base), 0.95);
|
||||
border-top: 1px solid var(--color-header-background);
|
||||
transition: border-left 0.4s;
|
||||
|
||||
.notification__icon {
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
.channel-thumbnail {
|
||||
margin-right: var(--spacing-s);
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
img,
|
||||
canvas {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.menu__list--notification-channel-unread {
|
||||
border: 2px solid var(--color-primary);
|
||||
}
|
||||
|
||||
.menu__list--notification-info {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
.menu__list--notification-type {
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
gap: var(--spacing-xxxs);
|
||||
width: 100%;
|
||||
color: rgba(var(--color-text-base), 0.6);
|
||||
font-size: var(--font-xsmall);
|
||||
|
||||
.notification__claim-title {
|
||||
width: 100%;
|
||||
color: rgba(var(--color-text-base), 0.6);
|
||||
font-size: var(--font-xsmall);
|
||||
font-weight: 400;
|
||||
flex: 1;
|
||||
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.button__content {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
.channel-name {
|
||||
margin: 0;
|
||||
color: rgba(var(--color-text-base), 0.6);
|
||||
font-size: var(--font-xsmall);
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
margin-right: 0;
|
||||
.credit-amount {
|
||||
color: rgba(var(--color-text-base), 0.6);
|
||||
font-size: var(--font-xsmall);
|
||||
font-weight: 400;
|
||||
svg {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu__list--notification-title {
|
||||
color: var(--color-text);
|
||||
flex-grow: 1;
|
||||
margin-bottom: -3px;
|
||||
width: 100%;
|
||||
.notification__text {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
blockquote {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.date_time {
|
||||
color: rgba(var(--color-text-base), 0.6);
|
||||
}
|
||||
span {
|
||||
color: var(--color-primary);
|
||||
display: inline-block;
|
||||
font-size: var(--font-xxsmall);
|
||||
margin-right: var(--spacing-xxxs);
|
||||
}
|
||||
.sticker__comment {
|
||||
margin-left: 0;
|
||||
padding: var(--spacing-xxs);
|
||||
padding-left: 0;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: rgba(var(--color-header-background-base), 1);
|
||||
.menu__list--notification-info {
|
||||
.menu__list--notification-title {
|
||||
.notification__text {
|
||||
color: var(--color-primary);
|
||||
blockquote {
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.delete-notification {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu__list--notification-unread {
|
||||
border-left: 2px solid var(--color-primary);
|
||||
}
|
||||
|
||||
.menu__list--notification-empty {
|
||||
display: block;
|
||||
word-wrap: break-word;
|
||||
white-space: normal;
|
||||
width: 440px;
|
||||
padding: var(--spacing-m) var(--spacing-s);
|
||||
background-color: rgba(var(--color-header-button-base), 0.95);
|
||||
color: var(--color-text);
|
||||
text-align: center;
|
||||
.menu__list--notification-empty-title {
|
||||
font-weight: bold;
|
||||
font-size: var(--font-body);
|
||||
}
|
||||
.menu__list--notification-empty-text {
|
||||
color: rgba(var(--color-text-base), 0.6);
|
||||
font-size: var(--font-xsmall);
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-notification {
|
||||
position: absolute;
|
||||
top: var(--spacing-xs);
|
||||
right: var(--spacing-xxs);
|
||||
opacity: 0;
|
||||
.icon__wrapper {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding: 0;
|
||||
background-color: rgba(var(--color-header-button-base), 0.95);
|
||||
outline: 4px solid rgba(var(--color-header-background-base), 1);
|
||||
|
||||
svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.icon__wrapper {
|
||||
background-color: var(--color-primary);
|
||||
color: var(--color-primary-contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu__list--notifications-more {
|
||||
color: var(--color-text);
|
||||
background-color: rgba(var(--color-header-background-base), 1);
|
||||
padding: var(--spacing-s) var(--spacing-xs);
|
||||
text-align: center;
|
||||
border-top: 1px solid rgba(var(--color-header-button-base), 0.95);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.MuiMenuItem-root {
|
||||
margin-left: 0px !important;
|
||||
font-size: var(--font-small) !important;
|
||||
|
@ -199,8 +424,6 @@ reach-portal {
|
|||
.menu__link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// padding: var(--spacing-s);
|
||||
// padding-right: var(--spacing-l);
|
||||
padding: var(--spacing-xs) var(--spacing-s) var(--spacing-xs) var(--spacing-s);
|
||||
height: var(--button-height);
|
||||
color: var(--color-text);
|
||||
|
|
Loading…
Reference in a new issue