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 : (
)}
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 > * {