From 898acab307ae27425f18e7a95c6cdd2c7e1db973 Mon Sep 17 00:00:00 2001 From: Rebeka Dekany <50901361+rebekadekany@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:12:25 +0200 Subject: [PATCH] Merge pull request #17990 from overleaf/rd-button-links [web] Migrating buttons to Bootstrap 5 on the Account Settings page GitOrigin-RevId: c9dfa9b1dee50f4c0b30abf8ac464e53cf98db95 --- .../components/account-info-section.tsx | 3 +- .../make-primary/confirmation-modal.tsx | 23 ++++--- .../actions/make-primary/make-primary.tsx | 2 +- .../actions/make-primary/primary-button.tsx | 19 +++--- .../settings/components/emails/add-email.tsx | 3 +- .../add-email/add-another-email-btn.tsx | 14 +++-- .../emails/add-email/add-new-email-btn.tsx | 24 ++++--- .../email-affiliated-with-institution.tsx | 17 +++-- .../emails/add-email/sso-linking-info.tsx | 11 ++-- .../emails/add-email/university-name.tsx | 10 ++- .../emails/institution-and-role.tsx | 35 +++++++---- .../components/emails/reconfirmation-info.tsx | 12 +++- .../resend-confirmation-email-button.tsx | 12 ++-- .../settings/components/emails/row.tsx | 11 ++-- .../settings/components/leave-section.tsx | 13 +++- .../components/leave/modal-content.tsx | 18 +++--- .../components/linking/enable-widget.tsx | 29 +++++---- .../components/linking/integration-widget.tsx | 63 ++++++++++++------- .../components/linking/sso-widget.tsx | 50 +++++++++------ .../settings/components/password-section.tsx | 3 +- .../settings/components/security-section.tsx | 8 ++- .../bootstrap-5/wrappers/button-wrapper.tsx | 4 +- .../ui/components/types/button-props.ts | 1 + .../stylesheets/bootstrap-5/base/links.scss | 4 +- .../bootstrap-5/components/button.scss | 34 ++++++++++ 25 files changed, 277 insertions(+), 146 deletions(-) diff --git a/services/web/frontend/js/features/settings/components/account-info-section.tsx b/services/web/frontend/js/features/settings/components/account-info-section.tsx index 3a8c0926b0..1827a9a7ad 100644 --- a/services/web/frontend/js/features/settings/components/account-info-section.tsx +++ b/services/web/frontend/js/features/settings/components/account-info-section.tsx @@ -124,7 +124,8 @@ function AccountInfoSection() { type="submit" variant="primary" form="account-info-form" - isLoading={isLoading || !isFormValid} + disabled={!isFormValid} + isLoading={isLoading} bs3Props={{ loading: isLoading ? `${t('saving')}…` : t('update'), }} diff --git a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx index d7130d3a0d..75ea0e5163 100644 --- a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx +++ b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx @@ -1,7 +1,8 @@ import { useTranslation, Trans } from 'react-i18next' -import { Modal, Button } from 'react-bootstrap' +import { Modal } from 'react-bootstrap' import AccessibleModal from '../../../../../../shared/components/accessible-modal' import { MergeAndOverride } from '../../../../../../../../types/utils' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' type ConfirmationModalProps = MergeAndOverride< React.ComponentProps, @@ -40,22 +41,24 @@ function ConfirmationModal({

{t('log_in_with_primary_email_address')}

- - + ) diff --git a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/make-primary.tsx b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/make-primary.tsx index 6ce1eb0fa7..72c6f4b0d4 100644 --- a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/make-primary.tsx +++ b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/make-primary.tsx @@ -82,7 +82,7 @@ function MakePrimary({ userEmailData, makePrimaryAsync }: MakePrimaryProps) { return ( <> {makePrimaryAsync.isLoading ? ( - + {t('processing_uppercase')}… ) : ( diff --git a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx index 140df2defc..4d22267848 100644 --- a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx +++ b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx @@ -1,19 +1,24 @@ import ButtonWrapper, { ButtonWrapperProps, } from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' -import { bsVersion } from '@/features/utils/bootstrap-5' -function PrimaryButton({ children, disabled, onClick }: ButtonWrapperProps) { +function PrimaryButton({ + children, + disabled, + isLoading, + onClick, +}: ButtonWrapperProps) { return ( {children} diff --git a/services/web/frontend/js/features/settings/components/emails/add-email.tsx b/services/web/frontend/js/features/settings/components/emails/add-email.tsx index 46c4da1ed4..85f3413c4e 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email.tsx @@ -214,7 +214,8 @@ function AddEmail() { > diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/add-another-email-btn.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/add-another-email-btn.tsx index d89a951001..3b895d9bb9 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email/add-another-email-btn.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email/add-another-email-btn.tsx @@ -1,18 +1,20 @@ import { useTranslation } from 'react-i18next' -import { Button, ButtonProps } from 'react-bootstrap' +import ButtonWrapper, { + ButtonWrapperProps, +} from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' -function AddAnotherEmailBtn({ onClick, ...props }: ButtonProps) { +function AddAnotherEmailBtn({ onClick, ...props }: ButtonWrapperProps) { const { t } = useTranslation() return ( - + ) } diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx index 33d5578f09..1834b1d88c 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx @@ -1,5 +1,7 @@ import { useTranslation } from 'react-i18next' -import { Button, ButtonProps } from 'react-bootstrap' +import ButtonWrapper, { + ButtonWrapperProps, +} from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' const isValidEmail = (email: string) => { return Boolean(email) @@ -7,20 +9,26 @@ const isValidEmail = (email: string) => { type AddNewEmailColProps = { email: string -} & ButtonProps +} & ButtonWrapperProps -function AddNewEmailBtn({ email, disabled, ...props }: AddNewEmailColProps) { +function AddNewEmailBtn({ + email, + disabled, + isLoading, + ...props +}: AddNewEmailColProps) { const { t } = useTranslation() return ( - + ) } diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/email-affiliated-with-institution.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/email-affiliated-with-institution.tsx index ea0db53dff..ec930fa0d2 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email/email-affiliated-with-institution.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email/email-affiliated-with-institution.tsx @@ -1,20 +1,25 @@ import { useTranslation } from 'react-i18next' -import { Button, ButtonProps } from 'react-bootstrap' +import ButtonWrapper, { + ButtonWrapperProps, +} from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' -function EmailAffiliatedWithInstitution({ onClick, ...props }: ButtonProps) { +function EmailAffiliatedWithInstitution({ + onClick, + ...props +}: ButtonWrapperProps) { const { t } = useTranslation() return (
{t('is_email_affiliated')} - +
) } diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx index 8bd5046ef2..57b279909e 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx @@ -1,10 +1,10 @@ import { useState } from 'react' -import { Button } from 'react-bootstrap' import { Trans, useTranslation } from 'react-i18next' import { DomainInfo } from './input' import { ExposedSettings } from '../../../../../../../types/exposed-settings' import getMeta from '../../../../../utils/meta' import { useLocation } from '../../../../../shared/hooks/use-location' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' type SSOLinkingInfoProps = { domainInfo: DomainInfo @@ -54,14 +54,15 @@ function SsoLinkingInfo({ domainInfo, email }: SSOLinkingInfoProps) { {t('find_out_more_about_institution_login')}.

- + ) } diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/university-name.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/university-name.tsx index 10d877e3eb..5236e50e7b 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email/university-name.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email/university-name.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next' -import { Button } from 'react-bootstrap' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' type UniversityNameProps = { name: string @@ -14,9 +14,13 @@ function UniversityName({ name, onClick }: UniversityNameProps) { {name} {' '} - +

) diff --git a/services/web/frontend/js/features/settings/components/emails/institution-and-role.tsx b/services/web/frontend/js/features/settings/components/emails/institution-and-role.tsx index d4f0183e2d..bd36dca917 100644 --- a/services/web/frontend/js/features/settings/components/emails/institution-and-role.tsx +++ b/services/web/frontend/js/features/settings/components/emails/institution-and-role.tsx @@ -1,7 +1,6 @@ import { useState, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' import { UserEmailData } from '../../../../../../types/user-email' -import { Button } from 'react-bootstrap' import { isChangingAffiliation } from '../../utils/selectors' import { useUserEmailsContext } from '../../context/user-email-context' import DownshiftInput from './downshift-input' @@ -10,6 +9,7 @@ import { getJSON, postJSON } from '../../../../infrastructure/fetch-json' import defaultRoles from '../../data/roles' import defaultDepartments from '../../data/departments' import { University } from '../../../../../../types/university' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' type InstitutionAndRoleProps = { userEmailData: UserEmailData @@ -107,11 +107,15 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
)} - + ) : (
@@ -135,23 +139,30 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) { setValue={setDepartment} />
- + {t('save_or_cancel-save')} + {!isLoading && ( <> {t('save_or_cancel-or')} - + )} diff --git a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info.tsx b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info.tsx index 39eb239ec6..e1f844803b 100644 --- a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info.tsx +++ b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info.tsx @@ -146,9 +146,13 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) { ) : ( {t('resend_confirmation_email')} @@ -157,7 +161,8 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) { ) : ( @@ -200,9 +205,10 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) { ) : ( {t('resend_confirmation_email')} diff --git a/services/web/frontend/js/features/settings/components/emails/resend-confirmation-email-button.tsx b/services/web/frontend/js/features/settings/components/emails/resend-confirmation-email-button.tsx index 3584b2d386..58b39dc1ff 100644 --- a/services/web/frontend/js/features/settings/components/emails/resend-confirmation-email-button.tsx +++ b/services/web/frontend/js/features/settings/components/emails/resend-confirmation-email-button.tsx @@ -1,11 +1,11 @@ import { useEffect } from 'react' import { useTranslation } from 'react-i18next' import Icon from '../../../../shared/components/icon' -import { Button } from 'react-bootstrap' import { FetchError, postJSON } from '../../../../infrastructure/fetch-json' import useAsync from '../../../../shared/hooks/use-async' import { UserEmailData } from '../../../../../../types/user-email' import { useUserEmailsContext } from '../../context/user-email-context' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' type ResendConfirmationEmailButtonProps = { email: UserEmailData['email'] @@ -47,14 +47,14 @@ function ResendConfirmationEmailButton({ return ( <> - +
{isError && (
diff --git a/services/web/frontend/js/features/settings/components/emails/row.tsx b/services/web/frontend/js/features/settings/components/emails/row.tsx index afbc0d4460..4590bec9cb 100644 --- a/services/web/frontend/js/features/settings/components/emails/row.tsx +++ b/services/web/frontend/js/features/settings/components/emails/row.tsx @@ -1,7 +1,6 @@ import { useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import { UserEmailData } from '../../../../../../types/user-email' -import { Button } from 'react-bootstrap' import Email from './email' import InstitutionAndRole from './institution-and-role' import EmailCell from './cell' @@ -16,6 +15,7 @@ import { useLocation } from '../../../../shared/hooks/use-location' import RowWrapper from '@/features/ui/components/bootstrap-5/wrappers/row-wrapper' import ColWrapper from '@/features/ui/components/bootstrap-5/wrappers/col-wrapper' import { bsVersion } from '@/features/utils/bootstrap-5' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' type EmailsRowProps = { userEmailData: UserEmailData @@ -160,14 +160,15 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) { })} > - + diff --git a/services/web/frontend/js/features/settings/components/leave-section.tsx b/services/web/frontend/js/features/settings/components/leave-section.tsx index 26000aa244..603c5f3e77 100644 --- a/services/web/frontend/js/features/settings/components/leave-section.tsx +++ b/services/web/frontend/js/features/settings/components/leave-section.tsx @@ -2,6 +2,8 @@ import { useState, useCallback } from 'react' import { useTranslation } from 'react-i18next' import LeaveModal from './leave/modal' import getMeta from '../../../utils/meta' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' +import { bsVersion } from '@/features/utils/bootstrap-5' function LeaveSection() { const { t } = useTranslation() @@ -28,9 +30,16 @@ function LeaveSection() { return ( <> {t('need_to_leave')}{' '} - + ) diff --git a/services/web/frontend/js/features/settings/components/leave/modal-content.tsx b/services/web/frontend/js/features/settings/components/leave/modal-content.tsx index 96d0d758d2..b1edcf995d 100644 --- a/services/web/frontend/js/features/settings/components/leave/modal-content.tsx +++ b/services/web/frontend/js/features/settings/components/leave/modal-content.tsx @@ -1,9 +1,10 @@ import { useState, Dispatch, SetStateAction } from 'react' -import { Modal, Button } from 'react-bootstrap' +import { Modal } from 'react-bootstrap' import { useTranslation, Trans } from 'react-i18next' import getMeta from '../../../../utils/meta' import LeaveModalForm, { LeaveModalFormProps } from './modal-form' import { ExposedSettings } from '../../../../../../types/exposed-settings' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' type LeaveModalContentProps = { handleHide: () => void @@ -68,24 +69,23 @@ function LeaveModalContent({ - + - + ) diff --git a/services/web/frontend/js/features/settings/components/linking/enable-widget.tsx b/services/web/frontend/js/features/settings/components/linking/enable-widget.tsx index 92d4d7b900..b6f2c35107 100644 --- a/services/web/frontend/js/features/settings/components/linking/enable-widget.tsx +++ b/services/web/frontend/js/features/settings/components/linking/enable-widget.tsx @@ -1,8 +1,8 @@ import { ReactNode } from 'react' import { useTranslation } from 'react-i18next' -import { Button } from 'react-bootstrap' import { sendMB } from '@/infrastructure/event-tracking' import BadgeWrapper from '@/features/ui/components/bootstrap-5/wrappers/badge-wrapper' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' function trackUpgradeClick() { sendMB('settings-upgrade-click') @@ -92,36 +92,39 @@ function ActionButton({ const { t } = useTranslation() if (!hasFeature) { return ( - + ) } else if (linked) { return ( - + ) } else { return ( - + ) } } diff --git a/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx b/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx index 873aa08033..aae910dcde 100644 --- a/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx +++ b/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx @@ -1,10 +1,12 @@ import { useCallback, useState, ReactNode } from 'react' import { useTranslation } from 'react-i18next' import AccessibleModal from '../../../../shared/components/accessible-modal' +import { Modal } from 'react-bootstrap' import BadgeWrapper from '@/features/ui/components/bootstrap-5/wrappers/badge-wrapper' -import { Button, Modal } from 'react-bootstrap' import getMeta from '../../../../utils/meta' import { sendMB } from '../../../../infrastructure/event-tracking' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' +import { bsVersion } from '@/features/utils/bootstrap-5' function trackUpgradeClick() { sendMB('settings-upgrade-click') @@ -107,43 +109,52 @@ function ActionButton({ const { t } = useTranslation() if (!hasFeature) { return ( - + ) } else if (linked) { return ( - + ) } else { return ( <> {disabled ? ( - + ) : ( - {t('link')} - + )} ) @@ -167,9 +178,7 @@ function UnlinkConfirmationModal({ }: UnlinkConfirmModalProps) { const { t } = useTranslation() - const handleCancel = ( - event: React.MouseEvent - ) => { + const handleCancel = (event: React.MouseEvent) => { event.preventDefault() handleHide() } @@ -186,15 +195,23 @@ function UnlinkConfirmationModal({
- - +
diff --git a/services/web/frontend/js/features/settings/components/linking/sso-widget.tsx b/services/web/frontend/js/features/settings/components/linking/sso-widget.tsx index 551681de3e..b5bd379a7f 100644 --- a/services/web/frontend/js/features/settings/components/linking/sso-widget.tsx +++ b/services/web/frontend/js/features/settings/components/linking/sso-widget.tsx @@ -1,12 +1,14 @@ import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Button, Modal } from 'react-bootstrap' +import { Modal } from 'react-bootstrap' import { FetchError } from '../../../../infrastructure/fetch-json' import AccessibleModal from '../../../../shared/components/accessible-modal' import IEEELogo from '../../../../shared/svgs/ieee-logo' import GoogleLogo from '../../../../shared/svgs/google-logo' import OrcidLogo from '../../../../shared/svgs/orcid-logo' import LinkingStatus from './status' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' +import { bsVersion } from '@/features/utils/bootstrap-5' const providerLogos: { readonly [p: string]: JSX.Element } = { collabratec: , @@ -112,28 +114,37 @@ function ActionButton({ const { t } = useTranslation() if (unlinkRequestInflight) { return ( - + ) } else if (accountIsLinked) { return ( - + ) } else { return ( - {t('link')} - + ) } } @@ -166,20 +177,23 @@ function UnlinkConfirmModal({ - - + ) diff --git a/services/web/frontend/js/features/settings/components/password-section.tsx b/services/web/frontend/js/features/settings/components/password-section.tsx index 2c6c96fae6..3d42fb040e 100644 --- a/services/web/frontend/js/features/settings/components/password-section.tsx +++ b/services/web/frontend/js/features/settings/components/password-section.tsx @@ -201,7 +201,8 @@ function PasswordForm() { form="password-change-form" type="submit" variant="primary" - disabled={isLoading || !isFormValid} + disabled={!isFormValid} + isLoading={isLoading} bs3Props={{ loading: isLoading ? `${t('saving')}…` : t('change'), }} diff --git a/services/web/frontend/js/features/settings/components/security-section.tsx b/services/web/frontend/js/features/settings/components/security-section.tsx index 4ecc615001..34394f6848 100644 --- a/services/web/frontend/js/features/settings/components/security-section.tsx +++ b/services/web/frontend/js/features/settings/components/security-section.tsx @@ -2,6 +2,7 @@ import MaterialIcon from '@/shared/components/material-icon' import { Trans, useTranslation } from 'react-i18next' import { GroupSSOLinkingStatus } from '../../../../../types/subscription/sso' import getMeta from '../../../utils/meta' +import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper' function SecuritySection() { const { t } = useTranslation() @@ -84,12 +85,13 @@ function SecuritySection() {
{linked ? null : (
- {t('set_up_sso')} - +
)} diff --git a/services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/button-wrapper.tsx b/services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/button-wrapper.tsx index 1fed56ca54..0929e2f163 100644 --- a/services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/button-wrapper.tsx +++ b/services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/button-wrapper.tsx @@ -7,6 +7,7 @@ import Button from '../button' export type ButtonWrapperProps = ButtonProps & { bs3Props?: { bsStyle?: string | null + className?: string loading?: React.ReactNode } } @@ -26,11 +27,12 @@ export default function ButtonWrapper(props: ButtonWrapperProps) { const { bs3Props, ...rest } = props const bs3ButtonProps: BS3ButtonProps = { - bsStyle: rest.variant, + bsStyle: rest.variant === 'secondary' ? 'default' : rest.variant, bsSize: mapBsButtonSizes(rest.size), className: rest.className, disabled: rest.isLoading || rest.disabled, form: rest.form, + href: rest.href, onClick: rest.onClick, type: rest.type, ...bs3Props, diff --git a/services/web/frontend/js/features/ui/components/types/button-props.ts b/services/web/frontend/js/features/ui/components/types/button-props.ts index 5e6e37f47a..a22670a4ca 100644 --- a/services/web/frontend/js/features/ui/components/types/button-props.ts +++ b/services/web/frontend/js/features/ui/components/types/button-props.ts @@ -19,4 +19,5 @@ export type ButtonProps = { | 'danger' | 'danger-ghost' | 'premium' + | 'link' } diff --git a/services/web/frontend/stylesheets/bootstrap-5/base/links.scss b/services/web/frontend/stylesheets/bootstrap-5/base/links.scss index 2ba62993dd..2848f5dc44 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/base/links.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/base/links.scss @@ -2,12 +2,12 @@ // Use CSS variables for link colors to make it easy to override in marketing page :root { - --link-color: var(--link-ui-visited); + --link-color: var(--link-ui); --link-hover-color: var(--link-ui-hover); --link-visited-color: var(--link-ui-visited); } -a { +a:not([role='button']) { color: var(--link-color); &:hover { diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/button.scss b/services/web/frontend/stylesheets/bootstrap-5/components/button.scss index d2ead1bfcf..7fee06da9d 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/components/button.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/components/button.scss @@ -87,10 +87,44 @@ } } +// Link buttons +// ------------------------- + +// Make a button look and behave like a link +.btn-link { + color: var(--link-ui); + font-weight: normal; + cursor: pointer; + border-radius: 0; + text-decoration: underline; + padding: 0; + font-size: inherit; + vertical-align: inherit; + + &, + &:active, + &[disabled], + fieldset[disabled] & { + background-color: transparent; + @include box-shadow(none); + } + &:hover, + &:focus { + color: var(--link-ui-hover); + text-decoration: none; + background-color: transparent; + } + + &.btn-danger { + color: var(--content-danger); + } +} + .button-loading { align-items: center; display: inline-grid; grid-template-areas: 'container'; // Define a single grid area + pointer-events: none; } .button-loading > * {