0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2024-12-30 22:34:01 -05:00

Updated Portal notification styles (#20538)

closes https://linear.app/ghost/issue/DES-548/update-portal-notification-style

Portal popup notification styles look outdated and harsh. Also in-popup notifications have several visual design issues such as positioning, alignment, typography and so on. This PR fixes these issues by applying a much more standard design to Portal notifications.
This commit is contained in:
Peter Zimon 2024-12-17 13:37:00 +01:00 committed by GitHub
parent 65bec88187
commit 58ac19ada6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 39 additions and 124 deletions

View file

@ -23,6 +23,7 @@ import EmailReceivingFAQ from './pages/EmailReceivingFAQ.css';
import {TipsAndDonationsSuccessStyle} from './pages/SupportSuccess';
import {TipsAndDonationsErrorStyle} from './pages/SupportError';
import {RecommendationsPageStyles} from './pages/RecommendationsPage';
import NotificationStyle from './Notification.styles';
// Global styles
const FrameStyles = `
@ -1275,6 +1276,7 @@ export function getFrameStyles({site}) {
MagicLinkStyles +
SignupPageStyles +
OfferPageStyles({site}) +
NotificationStyle +
PopupNotificationStyles +
MobileStyles +
MultipleProductsGlobalStyles +

View file

@ -26,7 +26,7 @@ export const GlobalStyles = `
--red: #f02525;
--darkerRed: #C50202;
--yellow: #FFDC15;
--green: #7FC724;
--green: #30CF43;
}
/* Globals

View file

@ -15,9 +15,9 @@ const Styles = () => {
position: 'fixed',
top: '0',
right: '0',
maxWidth: '415px',
maxWidth: '481px',
width: '100%',
height: '120px',
height: '220px',
animation: '250ms ease 0s 1 normal none running animation-bhegco',
transition: 'opacity 0.3s ease 0s',
overflow: 'hidden'
@ -34,13 +34,13 @@ const NotificationText = ({type, status, context}) => {
const firstname = context.member.firstname || '';
return (
<p>
{firstname ? t('Welcome back, {{name}}!', {name: firstname}) : t('Welcome back!')}<br />{t('You\'ve successfully signed in.')}
<strong>{firstname ? t('Welcome back, {{name}}!', {name: firstname}) : t('Welcome back!')}</strong><br />{t('You\'ve successfully signed in.')}
</p>
);
} else if (type === 'signin' && status === 'error') {
return (
<p>
{t('Could not sign in. Login link expired.')} <a href={signinPortalLink} target="_parent">{t('Click here to retry')}</a>
{t('Could not sign in. Login link expired.')} <br /><a href={signinPortalLink} target="_parent">{t('Click here to retry')}</a>
</p>
);
} else if (type === 'signup' && status === 'success') {

View file

@ -11,21 +11,22 @@ const NotificationStyles = `
.gh-portal-notification {
position: absolute;
display: flex;
align-items: center;
gap: 12px;
align-items: flex-start;
top: 12px;
right: 12px;
width: 100%;
padding: 14px 44px 18px 20px;
padding: 16px;
max-width: 380px;
min-height: 66px;
font-size: 1.3rem;
letter-spacing: 0.2px;
background: rgba(var(--grey1rgb),0.95);
background: var(--white);
backdrop-filter: blur(8px);
color: var(--white);
color: var(--grey0);
border-radius: 7px;
box-shadow: 0 3.2px 3.6px rgba(var(--black), 0.024), 0 8.8px 10px -5px rgba(var(--black), 0.08);
box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.30), 0px 51px 40px 0px rgba(0, 0, 0, 0.05), 0px 15.375px 12.059px 0px rgba(0, 0, 0, 0.03), 0px 6.386px 5.009px 0px rgba(0, 0, 0, 0.03), 0px 2.31px 1.812px 0px rgba(0, 0, 0, 0.02);
animation: notification-slidein 0.55s cubic-bezier(0.215, 0.610, 0.355, 1.000);
z-index: 99999;
}
html[dir="rtl"] .gh-portal-notification {
@ -49,16 +50,15 @@ const NotificationStyles = `
text-align: start;
margin: 0;
padding: 0;
color: var(--grey13);
padding-inline-start: 40px;
color: var(--grey0);
}
.gh-portal-notification p strong {
color: var(--white);
color: var(--grey0);
}
.gh-portal-notification a {
color: var(--white);
color: var(--grey0);
text-decoration: underline;
transition: all 0.2s ease-in-out;
outline: none;
@ -69,11 +69,10 @@ const NotificationStyles = `
}
.gh-portal-notification-icon {
position: absolute;
top: calc(50% - 14px);
left: 17px;
width: 28px;
height: 28px;
width: 18px;
height: 18px;
min-width: 18px;
margin-top: 2px;
}
html[dir="rtl"] .gh-portal-notification-icon {
right: 17px;
@ -89,22 +88,22 @@ const NotificationStyles = `
}
.gh-portal-notification-closeicon {
position: absolute;
top: 5px;
bottom: 0;
right: 5px;
color: var(--white);
color: var(--grey8);
cursor: pointer;
width: 12px;
min-width: 12px;
height: 12px;
padding: 10px;
margin-top: -6px;
margin-right: -6px;
margin-bottom: -6px;
transition: all 0.2s ease-in-out forwards;
opacity: 0.8;
}
.gh-portal-notification-closeicon:hover {
opacity: 1.0;
}
}
@keyframes notification-slidein {
0% { transform: translateX(380px); }
@ -130,7 +129,7 @@ const NotificationStyles = `
100% { transform: translateY(-150px); }
}
@media (max-width: 414px) {
@media (max-width: 480px) {
.gh-portal-notification {
left: 12px;
max-width: calc(100% - 24px);

View file

@ -215,9 +215,9 @@ class PopupContent extends React.Component {
return (
<>
<div className={'gh-portal-popup-wrapper ' + pageClass} onClick={e => this.handlePopupClose(e)}>
{this.renderPopupNotification()}
<div className={containerClassName} style={pageStyle} ref={node => (this.node = node)} tabIndex={-1}>
<CookieDisabledBanner message={cookieBannerText} />
{this.renderPopupNotification()}
{this.renderActivePage()}
{(popupSize === 'full' ?
<div className={'gh-portal-powered inside ' + (hasMode(['preview']) ? 'hidden ' : '') + pageClass}>

View file

@ -10,103 +10,17 @@ import {SYNTAX_I18NEXT} from '@doist/react-interpolate';
export const PopupNotificationStyles = `
.gh-portal-popupnotification {
position: absolute;
top: 16px;
right: 16px;
left: 16px;
padding: 12px;
background: var(--grey2);
z-index: 11000;
border-radius: 5px;
font-size: 1.5rem;
box-shadow: 0px 0.8151839971542358px 0.8151839971542358px 0px rgba(var(--blackrgb),0.01),
0px 2.2538793087005615px 2.2538793087005615px 0px rgba(var(--blackrgb),0.02),
0px 5.426473140716553px 5.426473140716553px 0px rgba(var(--blackrgb),0.03),
0px 18px 18px 0px rgba(var(--blackrgb),0.04);
animation: popupnotification-slidein 0.3s ease-in-out;
right: 42px;
}
.gh-portal-popupnotification.slideout {
animation: popupnotification-slideout 0.48s ease-in;
}
.gh-portal-popupnotification p {
color: var(--white);
margin: 0 0 0 8px;
padding: 0 20px;
font-size: 1.5rem;
line-height: 1.5em;
letter-spacing: 0.2px;
text-align: left;
}
.gh-portal-popupnotification a {
color: var(--white);
}
.gh-portal-popupnotification-icon {
position: absolute;
top: 12px;
left: 12px;
width: 20px;
height: 20px;
}
html[dir="rtl"] .gh-portal-popupnotification-icon {
left: unset;
right: 12px;
}
.gh-portal-popupnotification-icon.success {
color: var(--green);
}
.gh-portal-popupnotification-icon.error {
color: var(--red);
}
.gh-portal-popupnotification .closeicon {
position: absolute;
top: 3px;
bottom: 0;
right: 3px;
color: var(--white);
cursor: pointer;
width: 16px;
height: 16px;
padding: 12px;
transition: all 0.15s ease-in-out forwards;
opacity: 0.8;
}
html[dir="rtl"] .gh-portal-popupnotification .closeicon {
html[dir="rtl"] .gh-portal-notification {
right: unset;
left: 3px;
left: 42px;
}
.gh-portal-popupnotification .closeicon:hover {
opacity: 1.0;
}
@keyframes popupnotification-slidein {
0% {
transform: translateY(-10px);
opacity: 0;
}
60% { transform: translateY(2px); }
100% {
transform: translateY(0);
opacity: 1.0;
}
}
@keyframes popupnotification-slideout {
0% {
transform: translateY(0);
opacity: 1.0;
}
40% { transform: translateY(2px); }
100% {
transform: translateY(-10px);
opacity: 0;
@media (max-width: 480px) {
.gh-portal-notification {
max-width: calc(100% - 54px);
}
}
`;
@ -116,7 +30,7 @@ const CloseButton = ({hide = false, onClose}) => {
return null;
}
return (
<CloseIcon className='closeicon' alt='Close' onClick={onClose} />
<CloseIcon className='gh-portal-notification-closeicon' alt='Close' onClick={onClose} />
);
};
@ -155,7 +69,7 @@ export default class PopupNotification extends React.Component {
onAnimationEnd(e) {
const {popupNotification} = this.context;
const {type} = popupNotification || {};
if (e.animationName === 'popupnotification-slideout') {
if (e.animationName === 'notification-slideout' || e.animationName === 'notification-slideout-mobile') {
if (type === 'stripe:billing-update') {
clearURLParams(['stripe']);
}
@ -212,8 +126,8 @@ export default class PopupNotification extends React.Component {
const slideClass = className ? ` ${className}` : '';
return (
<div className={`gh-portal-popupnotification${statusClass}${slideClass}`} onAnimationEnd={e => this.onAnimationEnd(e)}>
{(status === 'error' ? <WarningIcon className='gh-portal-popupnotification-icon error' alt=''/> : <CheckmarkIcon className='gh-portal-popupnotification-icon success' alt=''/>)}
<div className={`gh-portal-notification gh-portal-popupnotification ${statusClass}${slideClass}`} onAnimationEnd={e => this.onAnimationEnd(e)}>
{(status === 'error' ? <WarningIcon className='gh-portal-notification-icon error' alt=''/> : <CheckmarkIcon className='gh-portal-notification-icon success' alt=''/>)}
<NotificationText type={type} status={status} message={message} site={site} t={t} />
<CloseButton hide={!closeable} onClose={e => this.closeNotification(e)}/>
</div>