From bd570cc4732bc7812d2d483561d8e0bcd459915f Mon Sep 17 00:00:00 2001 From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:21:52 +0300 Subject: [PATCH] Merge pull request #17576 from overleaf/ii-bs5-alert [web] Bootstrap 5 notifications GitOrigin-RevId: 4409f1b76923d96f1b8297beb35a383d9aa7ec8c --- .../settings/components/emails-section.tsx | 14 +- .../bootstrap-5/notification-wrapper.tsx | 42 +++ .../abstracts/variable-overrides.scss | 6 +- .../stylesheets/bootstrap-5/bootstrap.scss | 16 +- .../bootstrap-5/components/all.scss | 1 + .../bootstrap-5/components/notifications.scss | 248 ++++++++++++++++++ .../bootstrap-5/foundations/typography.scss | 3 - .../stylesheets/bootstrap-5/main-style.scss | 7 - 8 files changed, 314 insertions(+), 23 deletions(-) create mode 100644 services/web/frontend/js/features/ui/components/bootstrap-5/notification-wrapper.tsx create mode 100644 services/web/frontend/stylesheets/bootstrap-5/components/notifications.scss diff --git a/services/web/frontend/js/features/settings/components/emails-section.tsx b/services/web/frontend/js/features/settings/components/emails-section.tsx index 0e640d8634..63e1845126 100644 --- a/services/web/frontend/js/features/settings/components/emails-section.tsx +++ b/services/web/frontend/js/features/settings/components/emails-section.tsx @@ -9,7 +9,7 @@ import EmailsHeader from './emails/header' import EmailsRow from './emails/row' import AddEmail from './emails/add-email' import Icon from '../../../shared/components/icon' -import { Alert } from 'react-bootstrap' +import NotificationWrapper from '@/features/ui/components/bootstrap-5/notification-wrapper' import { ExposedSettings } from '../../../../../types/exposed-settings' import { LeaversSurveyAlert } from './leavers-survey-alert' @@ -67,10 +67,14 @@ function EmailsSectionContent() { {isInitializingSuccess && } {isInitializingSuccess && !hideAddSecondaryEmail && } {isInitializingError && ( - - {' '} - {t('error_performing_request')} - + , + className: 'text-center', + }} + /> )} diff --git a/services/web/frontend/js/features/ui/components/bootstrap-5/notification-wrapper.tsx b/services/web/frontend/js/features/ui/components/bootstrap-5/notification-wrapper.tsx new file mode 100644 index 0000000000..aec9db8982 --- /dev/null +++ b/services/web/frontend/js/features/ui/components/bootstrap-5/notification-wrapper.tsx @@ -0,0 +1,42 @@ +import Notification from '@/shared/components/notification' +import { Alert, AlertProps } from 'react-bootstrap' +import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' +import classnames from 'classnames' + +type NotificationWrapperProps = React.ComponentProps & { + bs3Props?: { + icon: React.ReactElement + className?: string + } +} + +function NotificationWrapper(props: NotificationWrapperProps) { + const { bs3Props, ...notificationProps } = props + + const alertProps = { + // Map `error` to `danger` + bsStyle: + notificationProps.type === 'error' ? 'danger' : notificationProps.type, + className: classnames(notificationProps.className, bs3Props?.className), + onDismiss: notificationProps.onDismiss, + } as const satisfies AlertProps + + return ( + + {bs3Props?.icon} + {bs3Props?.icon && ' '} + {notificationProps.content} + + } + bs5={ +
+ +
+ } + /> + ) +} + +export default NotificationWrapper diff --git a/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss b/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss index 9f460e2025..106d521f23 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/abstracts/variable-overrides.scss @@ -4,8 +4,10 @@ $font-family-sans-serif: 'Noto Sans', sans-serif; $font-family-serif: 'Merriweather', serif; $font-family-monospace: 'DM Mono', monospace; -$font-size-base: $default-font-size; -$line-height-base: $default-line-height; + +$font-size-base: 1rem; +$font-size-sm: var(--font-size-02); +$line-height-base: 1.5; // Buttons $btn-font-family: $font-family-sans-serif; diff --git a/services/web/frontend/stylesheets/bootstrap-5/bootstrap.scss b/services/web/frontend/stylesheets/bootstrap-5/bootstrap.scss index 354d9b891c..16a2b46ff7 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/bootstrap.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/bootstrap.scss @@ -7,8 +7,8 @@ // Bootstrap itself because Bootstrap uses them to create the CSS variables it // uses, and in calculations to determine, for example, what color text to use // on a button based on contrast. -@import 'abstracts/all'; @import 'foundations/all'; +@import 'abstracts/all'; // Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets) @import 'bootstrap-5/scss/variables'; @@ -17,21 +17,25 @@ // Include remainder of required parts @import 'bootstrap-5/scss/maps'; @import 'bootstrap-5/scss/mixins'; -@import 'bootstrap-5/scss/root'; - -// Include any other optional parts as needed, including components @import 'bootstrap-5/scss/utilities'; + +// Layout & components +@import 'bootstrap-5/scss/root'; @import 'bootstrap-5/scss/reboot'; @import 'bootstrap-5/scss/type'; @import 'bootstrap-5/scss/images'; @import 'bootstrap-5/scss/containers'; @import 'bootstrap-5/scss/grid'; -@import 'bootstrap-5/scss/helpers'; @import 'bootstrap-5/scss/buttons'; @import 'bootstrap-5/scss/dropdown'; @import 'bootstrap-5/scss/modal'; -@import 'bootstrap-5/scss/utilities/api'; @import 'bootstrap-5/scss/spinners'; +// Helpers +@import 'bootstrap-5/scss/helpers'; + +// Utilities +@import 'bootstrap-5/scss/utilities/api'; + // Components custom style @import 'components/all'; diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/all.scss b/services/web/frontend/stylesheets/bootstrap-5/components/all.scss index 09ed41b29a..684cfac373 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/components/all.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/components/all.scss @@ -1,3 +1,4 @@ @import 'button'; @import 'dropdown-menu'; @import 'split-button'; +@import 'notifications'; diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/notifications.scss b/services/web/frontend/stylesheets/bootstrap-5/components/notifications.scss new file mode 100644 index 0000000000..0b18779748 --- /dev/null +++ b/services/web/frontend/stylesheets/bootstrap-5/components/notifications.scss @@ -0,0 +1,248 @@ +.notification-body { + // will be deprecated once notifications moved to use .notification (see below) + flex-grow: 1; + width: 90%; + @media (min-width: var(--bs-breakpoint-md)) { + width: auto; + } +} + +.notification-action { + $line-height-computed: $font-size-base * $line-height-base; // 24px + + // will be deprecated once notifications moved to use .notification (see below) + margin-top: calc($line-height-computed / 2); // match paragraph padding + order: 1; + @media (min-width: var(--bs-breakpoint-md)) { + margin-top: 0; + order: 0; + padding-left: $spacing-05; + } +} + +.notification-close { + // will be deprecated once notifications moved to use .notification (see below) + padding-left: $spacing-05; + text-align: right; + width: 10%; + + button { + aspect-ratio: 1; + border-radius: 50%; + display: flex; + float: right; + padding: 5.5px; + cursor: pointer; + background: transparent; + border: 0; + + &:hover, + &:focus { + background-color: rgba(var(--neutral-90), 0.08); + color: var(--content-secondary); + } + } + + @media (min-width: var(--bs-breakpoint-md)) { + width: auto; + } +} + +.notification { + border-radius: $border-radius-base; + color: var(--content-primary); + display: flex; + padding: 0 $spacing-06; // vertical padding added by elements within notification + width: 100%; + + a:not(.btn) { + text-decoration: underline; + } + + p { + margin-bottom: $spacing-02; + } + + .notification-icon { + flex-grow: 0; + padding: 18px $spacing-06 0 0; + } + + .notification-content-and-cta { + // shared container to align cta with text on smaller screens + display: flex; + flex-grow: 1; + flex-wrap: wrap; + + p:last-child { + margin-bottom: 0; + } + } + + .notification-content { + flex-grow: 1; + padding: $spacing-06 0; + width: 100%; + } + + .notification-cta { + padding-bottom: $spacing-06; + + a { + font-weight: 700; + } + + a, + button { + white-space: nowrap; + } + } + + .notification-disclaimer { + color: var(--neutral-60); + font-size: $font-size-sm; + padding-bottom: $spacing-06; + } + + .notification-close-btn { + height: $spacing-12; + align-items: center; + display: flex; + } + + .notification-close-btn { + padding: 0 0 0 $spacing-06; + + button { + aspect-ratio: 1; + border-radius: 50%; + display: flex; + float: right; + padding: 5.5px; + cursor: pointer; + background: transparent; + border: 0; + + &:hover, + &:focus { + background-color: rgba(var(--neutral-90), 0.08); + color: var(--content-secondary); + } + } + } + + &.notification-type-info { + background-color: var(--bg-info-03); + border: 1px solid var(--blue-20); + .notification-icon { + color: var(--blue-50); + } + } + &.notification-type-success { + background-color: var(--bg-accent-03); + border: 1px solid var(--green-20); + .notification-icon { + color: var(--green-50); + } + } + &.notification-type-warning { + background-color: var(--bg-warning-03); + border: 1px solid var(--yellow-20); + .notification-icon { + color: var(--yellow-40); + } + } + &.notification-type-error { + background-color: var(--bg-danger-03); + border: 1px solid var(--red-20); + .notification-icon { + color: var(--red-50); + } + } + &.notification-type-offer { + background-color: var(--bg-light-primary); + border: 1px solid var(--neutral-20); + .notification-icon { + color: var(--neutral-50); + } + } + + @media (min-width: var(--bs-breakpoint-md)) { + &:not(.notification-cta-below-content) { + .notification-content-and-cta { + flex-wrap: nowrap; + } + + .notification-content { + width: auto; + } + + .notification-cta { + height: $spacing-12; + padding-left: $spacing-06; + padding-bottom: 0; + align-items: center; + display: flex; + } + } + } +} + +.notification-with-scroll-margin { + scroll-margin: $spacing-06; +} + +.notification-list { + .notification { + margin-bottom: $spacing-07; + } +} + +// Reconfirmation notification + +.reconfirm-notification { + display: flex; + width: 100%; + .fa-warning { + margin-right: $spacing-05; + } + .btn-reconfirm { + float: right; + margin-left: $spacing-05; + text-transform: capitalize; + } +} + +.group-invitation-cancel-subscription-notification-buttons { + display: flex; + align-items: center; +} + +// Settings page +.affiliations-table { + .reconfirm-notification { + margin: 0 auto $spacing-05 auto !important; + padding: $spacing-07; + } + + .reconfirm-row { + td { + border: 0; + + .alert { + border: 0; + padding: 0; + } + + :not(.alert) { + .reconfirm-notification { + background-color: var(--neutral-10); + border-radius: $border-radius-base; + .fa-warning { + color: var(--yellow-40); + } + } + } + } + } +} diff --git a/services/web/frontend/stylesheets/bootstrap-5/foundations/typography.scss b/services/web/frontend/stylesheets/bootstrap-5/foundations/typography.scss index 42540c1b5a..b78ef8ab70 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/foundations/typography.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/foundations/typography.scss @@ -1,9 +1,6 @@ // This file provides CSS variables for font size and line height, plus Sass variables for base text size for Bootstrap @use 'sass:math'; -$default-font-size: 1rem; -$default-line-height: 1.5; - :root { --font-size-01: 0.75rem; // 12px --font-size-02: 0.875rem; // 14px diff --git a/services/web/frontend/stylesheets/bootstrap-5/main-style.scss b/services/web/frontend/stylesheets/bootstrap-5/main-style.scss index bbbdee6a99..92b2539412 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/main-style.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/main-style.scss @@ -14,13 +14,6 @@ $is-overleaf-light: false; // TODO Bootstrap 5: Check whether this works with Bootstrap 5, and whether we can replace it @import '../vendor/select/select'; -// Sass and CSS variables from Overleaf foundations -@import 'foundations/colors'; -@import 'foundations/spacing'; -@import 'foundations/typography'; -@import 'foundations/border-radius'; -@import 'foundations/elevation'; - // Boostrap-related // Note that files containing Bootstrap or Sass files that interact with