Kaynağa Gözat

Merge pull request #18331 from overleaf/rd-bs5-renaming

[web ] Bootstrap 5 - rename the wrapper components and restructure

GitOrigin-RevId: 7a76903df81cd546e9e469f24c4f203ea6a61672
Rebeka Dekany 2 yıl önce
ebeveyn
işleme
f78e619d87
53 değiştirilmiş dosya ile 387 ekleme ve 405 silme
  1. 21 21
      services/web/frontend/js/features/settings/components/account-info-section.tsx
  2. 2 2
      services/web/frontend/js/features/settings/components/emails-section.tsx
  3. 6 6
      services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx
  4. 3 3
      services/web/frontend/js/features/settings/components/emails/actions/make-primary/make-primary.tsx
  5. 4 6
      services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx
  6. 8 8
      services/web/frontend/js/features/settings/components/emails/actions/remove.tsx
  7. 13 13
      services/web/frontend/js/features/settings/components/emails/add-email.tsx
  8. 4 6
      services/web/frontend/js/features/settings/components/emails/add-email/add-another-email-btn.tsx
  9. 4 6
      services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx
  10. 2 2
      services/web/frontend/js/features/settings/components/emails/add-email/country-input.tsx
  11. 4 9
      services/web/frontend/js/features/settings/components/emails/add-email/email-affiliated-with-institution.tsx
  12. 3 3
      services/web/frontend/js/features/settings/components/emails/add-email/input.tsx
  13. 9 11
      services/web/frontend/js/features/settings/components/emails/add-email/institution-fields.tsx
  14. 4 4
      services/web/frontend/js/features/settings/components/emails/add-email/layout.tsx
  15. 3 3
      services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx
  16. 3 3
      services/web/frontend/js/features/settings/components/emails/add-email/university-name.tsx
  17. 2 2
      services/web/frontend/js/features/settings/components/emails/downshift-input.tsx
  18. 3 3
      services/web/frontend/js/features/settings/components/emails/email.tsx
  19. 8 8
      services/web/frontend/js/features/settings/components/emails/header.tsx
  20. 12 12
      services/web/frontend/js/features/settings/components/emails/institution-and-role.tsx
  21. 22 22
      services/web/frontend/js/features/settings/components/emails/reconfirmation-info.tsx
  22. 3 3
      services/web/frontend/js/features/settings/components/emails/resend-confirmation-email-button.tsx
  23. 27 27
      services/web/frontend/js/features/settings/components/emails/row.tsx
  24. 4 4
      services/web/frontend/js/features/settings/components/emails/sso-alert.tsx
  25. 3 3
      services/web/frontend/js/features/settings/components/leave-section.tsx
  26. 6 6
      services/web/frontend/js/features/settings/components/leave/modal-content.tsx
  27. 2 2
      services/web/frontend/js/features/settings/components/leave/modal-form-error.tsx
  28. 13 13
      services/web/frontend/js/features/settings/components/leave/modal-form.tsx
  29. 1 1
      services/web/frontend/js/features/settings/components/leave/modal.tsx
  30. 2 2
      services/web/frontend/js/features/settings/components/leavers-survey-alert.tsx
  31. 3 3
      services/web/frontend/js/features/settings/components/linking-section.tsx
  32. 9 9
      services/web/frontend/js/features/settings/components/linking/enable-widget.tsx
  33. 16 18
      services/web/frontend/js/features/settings/components/linking/integration-widget.tsx
  34. 12 12
      services/web/frontend/js/features/settings/components/linking/sso-widget.tsx
  35. 20 20
      services/web/frontend/js/features/settings/components/password-section.tsx
  36. 15 15
      services/web/frontend/js/features/settings/components/root.tsx
  37. 3 3
      services/web/frontend/js/features/settings/components/security-section.tsx
  38. 0 71
      services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/form-control-wrapper.tsx
  39. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-badge.tsx
  40. 4 4
      services/web/frontend/js/features/ui/components/ol/ol-button.tsx
  41. 2 2
      services/web/frontend/js/features/ui/components/ol/ol-card.tsx
  42. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-col.tsx
  43. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-form-checkbox.tsx
  44. 68 0
      services/web/frontend/js/features/ui/components/ol/ol-form-control.tsx
  45. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-form-group.tsx
  46. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-form-label.tsx
  47. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx
  48. 5 5
      services/web/frontend/js/features/ui/components/ol/ol-icon-button.tsx
  49. 0 0
      services/web/frontend/js/features/ui/components/ol/ol-modal.tsx
  50. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-notification.tsx
  51. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-row.tsx
  52. 3 3
      services/web/frontend/js/features/ui/components/ol/ol-tooltip.tsx
  53. 2 2
      services/web/frontend/js/shared/components/badge.tsx

+ 21 - 21
services/web/frontend/js/features/settings/components/account-info-section.tsx

@@ -8,11 +8,11 @@ import getMeta from '../../../utils/meta'
 import { ExposedSettings } from '../../../../../types/exposed-settings'
 import useAsync from '../../../shared/hooks/use-async'
 import { useUserContext } from '../../../shared/context/user-context'
-import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
-import FormGroupWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-group-wrapper'
-import FormLabelWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-label-wrapper'
-import FormControlWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-control-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
+import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
+import OLFormLabel from '@/features/ui/components/ol/ol-form-label'
+import OLFormControl from '@/features/ui/components/ol/ol-form-control'
 import FormText from '@/features/ui/components/bootstrap-5/form/form-text'
 
 function AccountInfoSection() {
@@ -107,23 +107,23 @@ function AccountInfoSection() {
           required={false}
         />
         {isSuccess ? (
-          <FormGroupWrapper>
-            <NotificationWrapper
+          <OLFormGroup>
+            <OLNotification
               type="success"
               content={t('thanks_settings_updated')}
             />
-          </FormGroupWrapper>
+          </OLFormGroup>
         ) : null}
         {isError ? (
-          <FormGroupWrapper>
-            <NotificationWrapper
+          <OLFormGroup>
+            <OLNotification
               type="error"
               content={getUserFacingMessage(error) ?? ''}
             />
-          </FormGroupWrapper>
+          </OLFormGroup>
         ) : null}
         {canUpdateEmail || canUpdateNames ? (
-          <ButtonWrapper
+          <OLButton
             type="submit"
             variant="primary"
             form="account-info-form"
@@ -134,7 +134,7 @@ function AccountInfoSection() {
             }}
           >
             {t('update')}
-          </ButtonWrapper>
+          </OLButton>
         ) : null}
       </form>
     </>
@@ -175,17 +175,17 @@ function ReadOrWriteFormGroup({
 
   if (!canEdit) {
     return (
-      <FormGroupWrapper controlId={id}>
-        <FormLabelWrapper>{label}</FormLabelWrapper>
-        <FormControlWrapper type="text" readOnly value={value} />
-      </FormGroupWrapper>
+      <OLFormGroup controlId={id}>
+        <OLFormLabel>{label}</OLFormLabel>
+        <OLFormControl type="text" readOnly value={value} />
+      </OLFormGroup>
     )
   }
 
   return (
-    <FormGroupWrapper controlId={id}>
-      <FormLabelWrapper>{label}</FormLabelWrapper>
-      <FormControlWrapper
+    <OLFormGroup controlId={id}>
+      <OLFormLabel>{label}</OLFormLabel>
+      <OLFormControl
         type={type}
         required={required}
         value={value}
@@ -194,7 +194,7 @@ function ReadOrWriteFormGroup({
         onInvalid={handleInvalid}
       />
       {validationMessage && <FormText isError>{validationMessage}</FormText>}
-    </FormGroupWrapper>
+    </OLFormGroup>
   )
 }
 

+ 2 - 2
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 NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
 import { ExposedSettings } from '../../../../../types/exposed-settings'
 import { LeaversSurveyAlert } from './leavers-survey-alert'
 
@@ -67,7 +67,7 @@ function EmailsSectionContent() {
         {isInitializingSuccess && <LeaversSurveyAlert />}
         {isInitializingSuccess && !hideAddSecondaryEmail && <AddEmail />}
         {isInitializingError && (
-          <NotificationWrapper
+          <OLNotification
             type="error"
             content={t('error_performing_request')}
             bs3Props={{

+ 6 - 6
services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx

@@ -1,13 +1,13 @@
 import { useTranslation, Trans } from 'react-i18next'
 import AccessibleModal from '../../../../../../shared/components/accessible-modal'
 import { MergeAndOverride } from '../../../../../../../../types/utils'
-import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
 import OLModal, {
   OLModalBody,
   OLModalFooter,
   OLModalHeader,
   OLModalTitle,
-} from '@/features/ui/components/bootstrap-5/wrappers/ol-modal'
+} from '@/features/ui/components/ol/ol-modal'
 
 type ConfirmationModalProps = MergeAndOverride<
   React.ComponentProps<typeof AccessibleModal>,
@@ -46,7 +46,7 @@ function ConfirmationModal({
         <p className="mb-0">{t('log_in_with_primary_email_address')}</p>
       </OLModalBody>
       <OLModalFooter>
-        <ButtonWrapper
+        <OLButton
           variant="secondary"
           onClick={onHide}
           bs3Props={{
@@ -55,15 +55,15 @@ function ConfirmationModal({
           }}
         >
           {t('cancel')}
-        </ButtonWrapper>
-        <ButtonWrapper
+        </OLButton>
+        <OLButton
           variant="primary"
           disabled={isConfirmDisabled}
           onClick={onConfirm}
           bs3Props={{ bsStyle: null, className: 'btn-primary' }}
         >
           {t('confirm')}
-        </ButtonWrapper>
+        </OLButton>
       </OLModalFooter>
     </OLModal>
   )

+ 3 - 3
services/web/frontend/js/features/settings/components/emails/actions/make-primary/make-primary.tsx

@@ -14,7 +14,7 @@ import { UserEmailData } from '../../../../../../../../types/user-email'
 import { UseAsyncReturnType } from '../../../../../../shared/hooks/use-async'
 import { ssoAvailableForInstitution } from '../../../../utils/sso'
 import ConfirmationModal from './confirmation-modal'
-import TooltipWrapper from '@/features/ui/components/bootstrap-5/wrappers/tooltip-wrapper'
+import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
 
 const getDescription = (
   t: (s: string) => string,
@@ -86,7 +86,7 @@ function MakePrimary({ userEmailData, makePrimaryAsync }: MakePrimaryProps) {
           {t('processing_uppercase')}&hellip;
         </PrimaryButton>
       ) : (
-        <TooltipWrapper
+        <OLTooltip
           id={`make-primary-${userEmailData.email}`}
           description={getDescription(t, state, userEmailData)}
         >
@@ -102,7 +102,7 @@ function MakePrimary({ userEmailData, makePrimaryAsync }: MakePrimaryProps) {
               {t('make_primary')}
             </PrimaryButton>
           </span>
-        </TooltipWrapper>
+        </OLTooltip>
       )}
       <ConfirmationModal
         email={userEmailData.email}

+ 4 - 6
services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx

@@ -1,15 +1,13 @@
-import ButtonWrapper, {
-  ButtonWrapperProps,
-} from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton, { OLButtonProps } from '@/features/ui/components/ol/ol-button'
 
 function PrimaryButton({
   children,
   disabled,
   isLoading,
   onClick,
-}: ButtonWrapperProps) {
+}: OLButtonProps) {
   return (
-    <ButtonWrapper
+    <OLButton
       size="small"
       disabled={disabled && !isLoading}
       isLoading={isLoading}
@@ -21,7 +19,7 @@ function PrimaryButton({
       }}
     >
       {children}
-    </ButtonWrapper>
+    </OLButton>
   )
 }
 

+ 8 - 8
services/web/frontend/js/features/settings/components/emails/actions/remove.tsx

@@ -3,14 +3,14 @@ import { UserEmailData } from '../../../../../../../types/user-email'
 import { useUserEmailsContext } from '../../../context/user-email-context'
 import { postJSON } from '../../../../../infrastructure/fetch-json'
 import { UseAsyncReturnType } from '../../../../../shared/hooks/use-async'
-import TooltipWrapper from '@/features/ui/components/bootstrap-5/wrappers/tooltip-wrapper'
-import IconButtonWrapper, {
-  IconButtonWrapperProps,
-} from '@/features/ui/components/bootstrap-5/wrappers/icon-button-wrapper'
+import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
+import OLIconButton, {
+  OLIconButtonProps,
+} from '@/features/ui/components/ol/ol-icon-button'
 import { bsVersion } from '@/features/utils/bootstrap-5'
 
 type DeleteButtonProps = Pick<
-  IconButtonWrapperProps,
+  OLIconButtonProps,
   'disabled' | 'isLoading' | 'onClick'
 >
 
@@ -18,7 +18,7 @@ function DeleteButton({ disabled, isLoading, onClick }: DeleteButtonProps) {
   const { t } = useTranslation()
 
   return (
-    <IconButtonWrapper
+    <OLIconButton
       variant="danger"
       disabled={disabled}
       isLoading={isLoading}
@@ -67,7 +67,7 @@ function Remove({ userEmailData, deleteEmailAsync }: RemoveProps) {
   }
 
   return (
-    <TooltipWrapper
+    <OLTooltip
       id={userEmailData.email}
       description={
         userEmailData.default
@@ -82,7 +82,7 @@ function Remove({ userEmailData, deleteEmailAsync }: RemoveProps) {
           onClick={handleRemoveUserEmail}
         />
       </span>
-    </TooltipWrapper>
+    </OLTooltip>
   )
 }
 

+ 13 - 13
services/web/frontend/js/features/settings/components/emails/add-email.tsx

@@ -17,7 +17,7 @@ import { isValidEmail } from '../../../../shared/utils/email'
 import getMeta from '../../../../utils/meta'
 import { ReCaptcha2 } from '../../../../shared/components/recaptcha-2'
 import { useRecaptcha } from '../../../../shared/hooks/use-recaptcha'
-import ColWrapper from '@/features/ui/components/bootstrap-5/wrappers/col-wrapper'
+import OLCol from '@/features/ui/components/ol/ol-col'
 import { bsVersion } from '@/features/utils/bootstrap-5'
 
 function AddEmail() {
@@ -109,7 +109,7 @@ function AddEmail() {
   if (!isFormVisible) {
     return (
       <Layout isError={isError} error={error}>
-        <ColWrapper md={12}>
+        <OLCol md={12}>
           <Cell>
             {state.data.emailCount >= emailAddressLimit ? (
               <span className="small">
@@ -127,7 +127,7 @@ function AddEmail() {
               <AddAnotherEmailBtn onClick={handleShowAddEmailForm} />
             )}
           </Cell>
-        </ColWrapper>
+        </OLCol>
       </Layout>
     )
   }
@@ -152,15 +152,15 @@ function AddEmail() {
       <form>
         <Layout isError={isError} error={error}>
           <ReCaptcha2 page="addEmail" ref={recaptchaRef} />
-          <ColWrapper md={8}>
+          <OLCol md={8}>
             <Cell>
               {InputComponent}
               <div className="affiliations-table-cell-tabbed">
                 <div>{t('start_by_adding_your_email')}</div>
               </div>
             </Cell>
-          </ColWrapper>
-          <ColWrapper md={4}>
+          </OLCol>
+          <OLCol md={4}>
             <Cell
               className={bsVersion({
                 bs5: 'text-md-end',
@@ -169,7 +169,7 @@ function AddEmail() {
             >
               <AddNewEmailBtn email={newEmail} disabled />
             </Cell>
-          </ColWrapper>
+          </OLCol>
         </Layout>
       </form>
     )
@@ -182,7 +182,7 @@ function AddEmail() {
     <form>
       <Layout isError={isError} error={error}>
         <ReCaptcha2 page="addEmail" ref={recaptchaRef} />
-        <ColWrapper md={8}>
+        <OLCol md={8}>
           <Cell>
             {InputComponent}
             {!isSsoAvailableForDomain ? (
@@ -203,9 +203,9 @@ function AddEmail() {
               </div>
             ) : null}
           </Cell>
-        </ColWrapper>
+        </OLCol>
         {!isSsoAvailableForDomain ? (
-          <ColWrapper md={4}>
+          <OLCol md={4}>
             <Cell
               className={bsVersion({
                 bs5: 'text-md-end',
@@ -219,9 +219,9 @@ function AddEmail() {
                 onClick={handleAddNewEmail}
               />
             </Cell>
-          </ColWrapper>
+          </OLCol>
         ) : (
-          <ColWrapper md={12}>
+          <OLCol md={12}>
             <Cell>
               <div className="affiliations-table-cell-tabbed">
                 <SsoLinkingInfo
@@ -230,7 +230,7 @@ function AddEmail() {
                 />
               </div>
             </Cell>
-          </ColWrapper>
+          </OLCol>
         )}
       </Layout>
     </form>

+ 4 - 6
services/web/frontend/js/features/settings/components/emails/add-email/add-another-email-btn.tsx

@@ -1,20 +1,18 @@
 import { useTranslation } from 'react-i18next'
-import ButtonWrapper, {
-  ButtonWrapperProps,
-} from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton, { OLButtonProps } from '@/features/ui/components/ol/ol-button'
 
-function AddAnotherEmailBtn({ onClick, ...props }: ButtonWrapperProps) {
+function AddAnotherEmailBtn({ onClick, ...props }: OLButtonProps) {
   const { t } = useTranslation()
 
   return (
-    <ButtonWrapper
+    <OLButton
       variant="link"
       onClick={onClick}
       {...props}
       bs3Props={{ bsStyle: null, className: 'btn-inline-link' }}
     >
       {t('add_another_email')}
-    </ButtonWrapper>
+    </OLButton>
   )
 }
 

+ 4 - 6
services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx

@@ -1,7 +1,5 @@
 import { useTranslation } from 'react-i18next'
-import ButtonWrapper, {
-  ButtonWrapperProps,
-} from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton, { OLButtonProps } from '@/features/ui/components/ol/ol-button'
 
 const isValidEmail = (email: string) => {
   return Boolean(email)
@@ -9,7 +7,7 @@ const isValidEmail = (email: string) => {
 
 type AddNewEmailColProps = {
   email: string
-} & ButtonWrapperProps
+} & OLButtonProps
 
 function AddNewEmailBtn({
   email,
@@ -20,7 +18,7 @@ function AddNewEmailBtn({
   const { t } = useTranslation()
 
   return (
-    <ButtonWrapper
+    <OLButton
       size="small"
       variant="primary"
       disabled={(disabled && !isLoading) || !isValidEmail(email)}
@@ -28,7 +26,7 @@ function AddNewEmailBtn({
       {...props}
     >
       {t('add_new_email')}
-    </ButtonWrapper>
+    </OLButton>
   )
 }
 

+ 2 - 2
services/web/frontend/js/features/settings/components/emails/add-email/country-input.tsx

@@ -4,7 +4,7 @@ import { useCombobox } from 'downshift'
 import classnames from 'classnames'
 import countries, { CountryCode } from '../../../data/countries-list'
 import { bsVersion } from '@/features/utils/bootstrap-5'
-import FormControlWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-control-wrapper'
+import OLFormControl from '@/features/ui/components/ol/ol-form-control'
 
 type CountryInputProps = {
   setValue: React.Dispatch<React.SetStateAction<CountryCode | null>>
@@ -63,7 +63,7 @@ function Downshift({ setValue, inputRef }: CountryInputProps) {
         >
           {t('country')}
         </label>
-        <FormControlWrapper
+        <OLFormControl
           {...getInputProps({
             onChange: (event: React.ChangeEvent<HTMLInputElement>) => {
               setInputValue(event.target.value)

+ 4 - 9
services/web/frontend/js/features/settings/components/emails/add-email/email-affiliated-with-institution.tsx

@@ -1,25 +1,20 @@
 import { useTranslation } from 'react-i18next'
-import ButtonWrapper, {
-  ButtonWrapperProps,
-} from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton, { OLButtonProps } from '@/features/ui/components/ol/ol-button'
 
-function EmailAffiliatedWithInstitution({
-  onClick,
-  ...props
-}: ButtonWrapperProps) {
+function EmailAffiliatedWithInstitution({ onClick, ...props }: OLButtonProps) {
   const { t } = useTranslation()
 
   return (
     <div className="mt-1">
       {t('is_email_affiliated')}
-      <ButtonWrapper
+      <OLButton
         variant="link"
         onClick={onClick}
         bs3Props={{ bsStyle: null, className: 'btn-inline-link' }}
         {...props}
       >
         {t('let_us_know')}
-      </ButtonWrapper>
+      </OLButton>
     </div>
   )
 }

+ 3 - 3
services/web/frontend/js/features/settings/components/emails/add-email/input.tsx

@@ -11,7 +11,7 @@ import { getJSON } from '../../../../../infrastructure/fetch-json'
 import useAbortController from '../../../../../shared/hooks/use-abort-controller'
 import domainBlocklist from '../../../domain-blocklist'
 import { debugConsole } from '@/utils/debugging'
-import FormControlWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-control-wrapper'
+import OLFormControl from '@/features/ui/components/ol/ol-form-control'
 
 const LOCAL_AND_DOMAIN_REGEX = /([^@]+)@(.+)/
 
@@ -162,13 +162,13 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
 
   return (
     <div className="input-suggestions">
-      <FormControlWrapper
+      <OLFormControl
         data-testid="affiliations-email-shadow"
         readOnly
         className="input-suggestions-shadow"
         value={suggestion || ''}
       />
-      <FormControlWrapper
+      <OLFormControl
         id="affiliations-email"
         data-testid="affiliations-email"
         className="input-suggestions-main"

+ 9 - 11
services/web/frontend/js/features/settings/components/emails/add-email/institution-fields.tsx

@@ -11,7 +11,7 @@ import { DomainInfo } from './input'
 import { getJSON } from '../../../../../infrastructure/fetch-json'
 import useAsync from '../../../../../shared/hooks/use-async'
 import UniversityName from './university-name'
-import FormGroupWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-group-wrapper'
+import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
 
 type InstitutionFieldsProps = {
   countryCode: CountryCode | null
@@ -152,16 +152,14 @@ function InstitutionFields({
       ) : (
         // Display the country and university fields
         <>
-          <FormGroupWrapper className="mb-2">
+          <OLFormGroup className="mb-2">
             <CountryInput
               id="new-email-country-input"
               setValue={setCountryCode}
               ref={countryRef}
             />
-          </FormGroupWrapper>
-          <FormGroupWrapper
-            className={isRoleAndDepartmentVisible ? 'mb-2' : 'mb-0'}
-          >
+          </OLFormGroup>
+          <OLFormGroup className={isRoleAndDepartmentVisible ? 'mb-2' : 'mb-0'}>
             <DownshiftInput
               items={getUniversityItems()}
               inputValue={universityName}
@@ -170,12 +168,12 @@ function InstitutionFields({
               setValue={setUniversityName}
               disabled={!countryCode}
             />
-          </FormGroupWrapper>
+          </OLFormGroup>
         </>
       )}
       {isRoleAndDepartmentVisible && (
         <>
-          <FormGroupWrapper className="mb-2">
+          <OLFormGroup className="mb-2">
             <DownshiftInput
               items={[...defaultRoles]}
               inputValue={role}
@@ -183,8 +181,8 @@ function InstitutionFields({
               label={t('role')}
               setValue={setRole}
             />
-          </FormGroupWrapper>
-          <FormGroupWrapper className="mb-0">
+          </OLFormGroup>
+          <OLFormGroup className="mb-0">
             <DownshiftInput
               items={departments}
               inputValue={department}
@@ -192,7 +190,7 @@ function InstitutionFields({
               label={t('department')}
               setValue={setDepartment}
             />
-          </FormGroupWrapper>
+          </OLFormGroup>
         </>
       )}
     </>

+ 4 - 4
services/web/frontend/js/features/settings/components/emails/add-email/layout.tsx

@@ -1,8 +1,8 @@
 import Icon from '../../../../../shared/components/icon'
 import { UseAsyncReturnType } from '../../../../../shared/hooks/use-async'
 import { getUserFacingMessage } from '../../../../../infrastructure/fetch-json'
-import RowWrapper from '@/features/ui/components/bootstrap-5/wrappers/row-wrapper'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
+import OLRow from '@/features/ui/components/ol/ol-row'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
 
 type LayoutProps = {
   children: React.ReactNode
@@ -13,9 +13,9 @@ type LayoutProps = {
 function Layout({ isError, error, children }: LayoutProps) {
   return (
     <div className="affiliations-table-row--highlighted">
-      <RowWrapper>{children}</RowWrapper>
+      <OLRow>{children}</OLRow>
       {isError && (
-        <NotificationWrapper
+        <OLNotification
           type="error"
           content={getUserFacingMessage(error) ?? ''}
           bs3Props={{

+ 3 - 3
services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx

@@ -4,7 +4,7 @@ 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'
+import OLButton from '@/features/ui/components/ol/ol-button'
 
 type SSOLinkingInfoProps = {
   domainInfo: DomainInfo
@@ -54,7 +54,7 @@ function SsoLinkingInfo({ domainInfo, email }: SSOLinkingInfoProps) {
           {t('find_out_more_about_institution_login')}.
         </a>
       </p>
-      <ButtonWrapper
+      <OLButton
         variant="primary"
         className="btn-link-accounts"
         size="small"
@@ -62,7 +62,7 @@ function SsoLinkingInfo({ domainInfo, email }: SSOLinkingInfoProps) {
         onClick={handleLinkAccountsButtonClick}
       >
         {t('link_accounts_and_add_email')}
-      </ButtonWrapper>
+      </OLButton>
     </>
   )
 }

+ 3 - 3
services/web/frontend/js/features/settings/components/emails/add-email/university-name.tsx

@@ -1,5 +1,5 @@
 import { useTranslation } from 'react-i18next'
-import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
 
 type UniversityNameProps = {
   name: string
@@ -14,13 +14,13 @@ function UniversityName({ name, onClick }: UniversityNameProps) {
       {name}
       <span className="small">
         {' '}
-        <ButtonWrapper
+        <OLButton
           variant="link"
           onClick={onClick}
           bs3Props={{ bsStyle: null, className: 'btn-inline-link' }}
         >
           {t('change')}
-        </ButtonWrapper>
+        </OLButton>
       </span>
     </p>
   )

+ 2 - 2
services/web/frontend/js/features/settings/components/emails/downshift-input.tsx

@@ -3,7 +3,7 @@ import { useCombobox } from 'downshift'
 import classnames from 'classnames'
 import { escapeRegExp } from 'lodash'
 import { bsVersion } from '@/features/utils/bootstrap-5'
-import FormControlWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-control-wrapper'
+import OLFormControl from '@/features/ui/components/ol/ol-form-control'
 
 type DownshiftInputProps = {
   highlightMatches?: boolean
@@ -98,7 +98,7 @@ function Downshift({
         >
           {label}
         </label>
-        <FormControlWrapper
+        <OLFormControl
           {...getInputProps({
             onChange: (event: React.ChangeEvent<HTMLInputElement>) => {
               setValue(event.target.value)

+ 3 - 3
services/web/frontend/js/features/settings/components/emails/email.tsx

@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next'
 import { UserEmailData } from '../../../../../../types/user-email'
 import ResendConfirmationEmailButton from './resend-confirmation-email-button'
 import { ssoAvailableForInstitution } from '../../utils/sso'
-import BadgeWrapper from '@/features/ui/components/bootstrap-5/wrappers/badge-wrapper'
+import OLBadge from '@/features/ui/components/ol/ol-badge'
 import { isBootstrap5 } from '@/features/utils/bootstrap-5'
 import classnames from 'classnames'
 
@@ -43,11 +43,11 @@ function Email({ userEmailData }: EmailProps) {
         <div className={classnames({ small: !isBootstrap5 })}>
           {isPrimary && (
             <>
-              <BadgeWrapper bg="info">Primary</BadgeWrapper>{' '}
+              <OLBadge bg="info">Primary</OLBadge>{' '}
             </>
           )}
           {isProfessional && (
-            <BadgeWrapper bg="primary">{t('professional')}</BadgeWrapper>
+            <OLBadge bg="primary">{t('professional')}</OLBadge>
           )}
         </div>
       )}

+ 8 - 8
services/web/frontend/js/features/settings/components/emails/header.tsx

@@ -1,7 +1,7 @@
 import { useTranslation } from 'react-i18next'
 import EmailCell from './cell'
-import ColWrapper from '@/features/ui/components/bootstrap-5/wrappers/col-wrapper'
-import RowWrapper from '@/features/ui/components/bootstrap-5/wrappers/row-wrapper'
+import OLCol from '@/features/ui/components/ol/ol-col'
+import OLRow from '@/features/ui/components/ol/ol-row'
 import classnames from 'classnames'
 import { bsVersion } from '@/features/utils/bootstrap-5'
 
@@ -10,8 +10,8 @@ function Header() {
 
   return (
     <>
-      <RowWrapper>
-        <ColWrapper
+      <OLRow>
+        <OLCol
           md={4}
           className={bsVersion({
             bs5: 'd-none d-sm-block',
@@ -21,8 +21,8 @@ function Header() {
           <EmailCell>
             <strong>{t('email')}</strong>
           </EmailCell>
-        </ColWrapper>
-        <ColWrapper
+        </OLCol>
+        <OLCol
           md={8}
           className={bsVersion({
             bs5: 'd-none d-sm-block',
@@ -32,8 +32,8 @@ function Header() {
           <EmailCell>
             <strong>{t('institution_and_role')}</strong>
           </EmailCell>
-        </ColWrapper>
-      </RowWrapper>
+        </OLCol>
+      </OLRow>
       <div
         className={classnames(
           bsVersion({ bs5: 'd-none d-sm-block', bs3: 'hidden-xs' }),

+ 12 - 12
services/web/frontend/js/features/settings/components/emails/institution-and-role.tsx

@@ -9,8 +9,8 @@ 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'
-import FormGroupWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-group-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
+import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
 
 type InstitutionAndRoleProps = {
   userEmailData: UserEmailData
@@ -108,7 +108,7 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
               <br />
             </>
           )}
-          <ButtonWrapper
+          <OLButton
             onClick={handleChangeAffiliation}
             variant="link"
             bs3Props={{ className: 'btn-inline-link' }}
@@ -116,12 +116,12 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
             {!affiliation.department && !affiliation.role
               ? t('add_role_and_department')
               : t('change')}
-          </ButtonWrapper>
+          </OLButton>
         </div>
       ) : (
         <div className="affiliation-change-container small">
           <form onSubmit={handleSubmit}>
-            <FormGroupWrapper className="mb-2">
+            <OLFormGroup className="mb-2">
               <DownshiftInput
                 items={[...defaultRoles]}
                 inputValue={role}
@@ -130,8 +130,8 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
                 setValue={setRole}
                 ref={roleRef}
               />
-            </FormGroupWrapper>
-            <FormGroupWrapper className="mb-2">
+            </OLFormGroup>
+            <OLFormGroup className="mb-2">
               <DownshiftInput
                 items={departments}
                 inputValue={department}
@@ -139,8 +139,8 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
                 label={t('department')}
                 setValue={setDepartment}
               />
-            </FormGroupWrapper>
-            <ButtonWrapper
+            </OLFormGroup>
+            <OLButton
               size="small"
               variant="primary"
               type="submit"
@@ -153,17 +153,17 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
               }}
             >
               {t('save_or_cancel-save')}
-            </ButtonWrapper>
+            </OLButton>
             {!isLoading && (
               <>
                 <span className="mx-1">{t('save_or_cancel-or')}</span>
-                <ButtonWrapper
+                <OLButton
                   variant="link"
                   onClick={handleCancelAffiliationChange}
                   bs3Props={{ className: 'btn-inline-link' }}
                 >
                   {t('save_or_cancel-cancel')}
-                </ButtonWrapper>
+                </OLButton>
               </>
             )}
           </form>

+ 22 - 22
services/web/frontend/js/features/settings/components/emails/reconfirmation-info.tsx

@@ -3,9 +3,9 @@ import { UserEmailData } from '../../../../../../types/user-email'
 import getMeta from '../../../../utils/meta'
 import ReconfirmationInfoSuccess from './reconfirmation-info/reconfirmation-info-success'
 import ReconfirmationInfoPromptText from './reconfirmation-info/reconfirmation-info-prompt-text'
-import RowWrapper from '@/features/ui/components/bootstrap-5/wrappers/row-wrapper'
-import ColWrapper from '@/features/ui/components/bootstrap-5/wrappers/col-wrapper'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
+import OLRow from '@/features/ui/components/ol/ol-row'
+import OLCol from '@/features/ui/components/ol/ol-col'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
 import { isBootstrap5 } from '@/features/utils/bootstrap-5'
 import Icon from '@/shared/components/icon'
 import { useUserEmailsContext } from '@/features/settings/context/user-email-context'
@@ -16,7 +16,7 @@ import { Trans, useTranslation } from 'react-i18next'
 import useAsync from '@/shared/hooks/use-async'
 import { ExposedSettings } from '../../../../../../types/exposed-settings'
 import { useLocation } from '@/shared/hooks/use-location'
-import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
 import classnames from 'classnames'
 
 type ReconfirmationInfoProps = {
@@ -80,9 +80,9 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
     userEmailData.samlProviderId === reconfirmedViaSAML
   ) {
     return (
-      <RowWrapper>
-        <ColWrapper md={12}>
-          <NotificationWrapper
+      <OLRow>
+        <OLCol md={12}>
+          <OLNotification
             type="info"
             content={
               <ReconfirmationInfoSuccess
@@ -91,17 +91,17 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
             }
             bs3Props={{ className: 'settings-reconfirm-info small' }}
           />
-        </ColWrapper>
-      </RowWrapper>
+        </OLCol>
+      </OLRow>
     )
   }
 
   if (userEmailData.affiliation.inReconfirmNotificationPeriod) {
     return (
-      <RowWrapper>
-        <ColWrapper md={12}>
+      <OLRow>
+        <OLCol md={12}>
           {isBootstrap5 ? (
-            <NotificationWrapper
+            <OLNotification
               type="info"
               content={
                 <>
@@ -145,7 +145,7 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
                         <Icon type="refresh" spin fw /> {t('sending')}...
                       </>
                     ) : (
-                      <ButtonWrapper
+                      <OLButton
                         variant="link"
                         disabled={state.isLoading}
                         onClick={handleRequestReconfirmation}
@@ -155,11 +155,11 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
                         }}
                       >
                         {t('resend_confirmation_email')}
-                      </ButtonWrapper>
+                      </OLButton>
                     )}
                   </>
                 ) : (
-                  <ButtonWrapper
+                  <OLButton
                     variant="secondary"
                     disabled={isPending}
                     isLoading={isLoading}
@@ -173,7 +173,7 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
                     ) : (
                       t('confirm_affiliation')
                     )}
-                  </ButtonWrapper>
+                  </OLButton>
                 )
               }
             />
@@ -204,14 +204,14 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
                       <Icon type="refresh" spin fw /> {t('sending')}...
                     </>
                   ) : (
-                    <ButtonWrapper
+                    <OLButton
                       variant="link"
                       disabled={state.isLoading}
                       onClick={handleRequestReconfirmation}
                       bs3Props={{ className: 'btn-inline-link', bsStyle: null }}
                     >
                       {t('resend_confirmation_email')}
-                    </ButtonWrapper>
+                    </OLButton>
                   )}
                   <br />
                   {isError && (
@@ -236,7 +236,7 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
                     />
                   </div>
                   <div className="setting-reconfirm-info-right">
-                    <ButtonWrapper
+                    <OLButton
                       variant="secondary"
                       disabled={state.isLoading || isPending}
                       onClick={handleRequestReconfirmation}
@@ -249,7 +249,7 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
                       ) : (
                         t('confirm_affiliation')
                       )}
-                    </ButtonWrapper>
+                    </OLButton>
                     <br />
                     {isError && (
                       <div className="text-danger">
@@ -263,8 +263,8 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
               )}
             </div>
           )}
-        </ColWrapper>
-      </RowWrapper>
+        </OLCol>
+      </OLRow>
     )
   }
 

+ 3 - 3
services/web/frontend/js/features/settings/components/emails/resend-confirmation-email-button.tsx

@@ -5,7 +5,7 @@ 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'
+import OLButton from '@/features/ui/components/ol/ol-button'
 
 type ResendConfirmationEmailButtonProps = {
   email: UserEmailData['email']
@@ -47,14 +47,14 @@ function ResendConfirmationEmailButton({
 
   return (
     <>
-      <ButtonWrapper
+      <OLButton
         variant="link"
         disabled={state.isLoading || isLoading}
         onClick={handleResendConfirmationEmail}
         bs3Props={{ bsStyle: null, className: 'btn-inline-link' }}
       >
         {t('resend_confirmation_email')}
-      </ButtonWrapper>
+      </OLButton>
       <br />
       {isError && (
         <div className="text-danger">

+ 27 - 27
services/web/frontend/js/features/settings/components/emails/row.tsx

@@ -12,10 +12,10 @@ import { ExposedSettings } from '../../../../../../types/exposed-settings'
 import { ssoAvailableForInstitution } from '../../utils/sso'
 import ReconfirmationInfo from './reconfirmation-info'
 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 OLRow from '@/features/ui/components/ol/ol-row'
+import OLCol from '@/features/ui/components/ol/ol-col'
 import { bsVersion } from '@/features/utils/bootstrap-5'
-import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
 
 type EmailsRowProps = {
   userEmailData: UserEmailData
@@ -29,20 +29,20 @@ function EmailsRow({ userEmailData }: EmailsRowProps) {
 
   return (
     <>
-      <RowWrapper>
-        <ColWrapper md={4}>
+      <OLRow>
+        <OLCol md={4}>
           <EmailCell>
             <Email userEmailData={userEmailData} />
           </EmailCell>
-        </ColWrapper>
-        <ColWrapper md={5}>
+        </OLCol>
+        <OLCol md={5}>
           {userEmailData.affiliation?.institution && (
             <EmailCell>
               <InstitutionAndRole userEmailData={userEmailData} />
             </EmailCell>
           )}
-        </ColWrapper>
-        <ColWrapper md={3}>
+        </OLCol>
+        <OLCol md={3}>
           <EmailCell
             className={bsVersion({
               bs5: 'text-md-end',
@@ -51,8 +51,8 @@ function EmailsRow({ userEmailData }: EmailsRowProps) {
           >
             <Actions userEmailData={userEmailData} />
           </EmailCell>
-        </ColWrapper>
-      </RowWrapper>
+        </OLCol>
+      </OLRow>
 
       {hasSSOAffiliation && (
         <SSOAffiliationInfo userEmailData={userEmailData} />
@@ -93,8 +93,8 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
 
   if (userEmailData.samlProviderId) {
     return (
-      <RowWrapper>
-        <ColWrapper md={{ span: 8, offset: 4 }}>
+      <OLRow>
+        <OLCol md={{ span: 8, offset: 4 }}>
           <EmailCell>
             <p>
               <Trans
@@ -111,17 +111,17 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
               />
             </p>
           </EmailCell>
-        </ColWrapper>
-      </RowWrapper>
+        </OLCol>
+      </OLRow>
     )
   }
 
   return (
-    <RowWrapper>
-      <ColWrapper md={{ span: 8, offset: 4 }}>
+    <OLRow>
+      <OLCol md={{ span: 8, offset: 4 }}>
         <div className="horizontal-divider" />
-        <RowWrapper>
-          <ColWrapper md={9}>
+        <OLRow>
+          <OLCol md={9}>
             <EmailCell>
               <p className="small">
                 <Trans
@@ -151,8 +151,8 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
                 </a>
               </p>
             </EmailCell>
-          </ColWrapper>
-          <ColWrapper
+          </OLCol>
+          <OLCol
             md={3}
             className={bsVersion({
               bs5: 'text-md-end',
@@ -160,7 +160,7 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
             })}
           >
             <EmailCell>
-              <ButtonWrapper
+              <OLButton
                 variant="primary"
                 className="btn-link-accounts"
                 disabled={linkAccountsButtonDisabled}
@@ -168,12 +168,12 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
                 size="small"
               >
                 {t('link_accounts')}
-              </ButtonWrapper>
+              </OLButton>
             </EmailCell>
-          </ColWrapper>
-        </RowWrapper>
-      </ColWrapper>
-    </RowWrapper>
+          </OLCol>
+        </OLRow>
+      </OLCol>
+    </OLRow>
   )
 }
 

+ 4 - 4
services/web/frontend/js/features/settings/components/emails/sso-alert.tsx

@@ -2,7 +2,7 @@ import { useState } from 'react'
 import { useTranslation, Trans } from 'react-i18next'
 import Icon from '../../../../shared/components/icon'
 import getMeta from '../../../../utils/meta'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
 
 type InstitutionLink = {
   universityName: string
@@ -36,7 +36,7 @@ export function SSOAlert() {
 
   if (samlError) {
     return !errorClosed ? (
-      <NotificationWrapper
+      <OLNotification
         type="error"
         content={
           <>
@@ -68,7 +68,7 @@ export function SSOAlert() {
   return (
     <>
       {!infoClosed && (
-        <NotificationWrapper
+        <OLNotification
           type="info"
           content={
             <>
@@ -102,7 +102,7 @@ export function SSOAlert() {
         />
       )}
       {!warningClosed && institutionEmailNonCanonical && (
-        <NotificationWrapper
+        <OLNotification
           type="warning"
           content={
             <Trans

+ 3 - 3
services/web/frontend/js/features/settings/components/leave-section.tsx

@@ -2,7 +2,7 @@ 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 OLButton from '@/features/ui/components/ol/ol-button'
 import { bsVersion } from '@/features/utils/bootstrap-5'
 
 function LeaveSection() {
@@ -30,7 +30,7 @@ function LeaveSection() {
   return (
     <>
       {t('need_to_leave')}{' '}
-      <ButtonWrapper
+      <OLButton
         className={bsVersion({
           bs3: 'btn btn-inline-link btn-danger',
           bs5: 'btn-link',
@@ -39,7 +39,7 @@ function LeaveSection() {
         onClick={handleOpen}
       >
         {t('delete_your_account')}
-      </ButtonWrapper>
+      </OLButton>
       <LeaveModal isOpen={isModalOpen} handleClose={handleClose} />
     </>
   )

+ 6 - 6
services/web/frontend/js/features/settings/components/leave/modal-content.tsx

@@ -3,13 +3,13 @@ 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'
+import OLButton from '@/features/ui/components/ol/ol-button'
 import {
   OLModalBody,
   OLModalFooter,
   OLModalHeader,
   OLModalTitle,
-} from '@/features/ui/components/bootstrap-5/wrappers/ol-modal'
+} from '@/features/ui/components/ol/ol-modal'
 
 type LeaveModalContentProps = {
   handleHide: () => void
@@ -74,23 +74,23 @@ function LeaveModalContent({
       </OLModalBody>
 
       <OLModalFooter>
-        <ButtonWrapper
+        <OLButton
           disabled={inFlight}
           onClick={handleHide}
           variant="secondary"
           bs3Props={{ bsStyle: null, className: 'btn-secondary' }}
         >
           {t('cancel')}
-        </ButtonWrapper>
+        </OLButton>
 
-        <ButtonWrapper
+        <OLButton
           form="leave-form"
           type="submit"
           variant="danger"
           disabled={inFlight || !isFormValid}
         >
           {inFlight ? <>{t('deleting')}…</> : t('delete')}
-        </ButtonWrapper>
+        </OLButton>
       </OLModalFooter>
     </>
   )

+ 2 - 2
services/web/frontend/js/features/settings/components/leave/modal-form-error.tsx

@@ -2,7 +2,7 @@ import { useTranslation, Trans } from 'react-i18next'
 import getMeta from '../../../../utils/meta'
 import { FetchError } from '../../../../infrastructure/fetch-json'
 import { ExposedSettings } from '../../../../../../types/exposed-settings'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
 
 type LeaveModalFormErrorProps = {
   error: FetchError
@@ -32,7 +32,7 @@ function LeaveModalFormError({ error }: LeaveModalFormErrorProps) {
   }
 
   return (
-    <NotificationWrapper
+    <OLNotification
       type="error"
       content={
         <>

+ 13 - 13
services/web/frontend/js/features/settings/components/leave/modal-form.tsx

@@ -4,10 +4,10 @@ import { postJSON, FetchError } from '../../../../infrastructure/fetch-json'
 import getMeta from '../../../../utils/meta'
 import LeaveModalFormError from './modal-form-error'
 import { useLocation } from '../../../../shared/hooks/use-location'
-import FormGroupWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-group-wrapper'
-import FormLabelWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-label-wrapper'
-import FormControlWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-control-wrapper'
-import FormCheckboxWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-checkbox-wrapper'
+import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
+import OLFormLabel from '@/features/ui/components/ol/ol-form-label'
+import OLFormControl from '@/features/ui/components/ol/ol-form-control'
+import OLFormCheckbox from '@/features/ui/components/ol/ol-form-checkbox'
 
 export type LeaveModalFormProps = {
   setInFlight: Dispatch<SetStateAction<boolean>>
@@ -73,27 +73,27 @@ function LeaveModalForm({
 
   return (
     <form id="leave-form" onSubmit={handleSubmit}>
-      <FormGroupWrapper controlId="email-input">
-        <FormLabelWrapper>{t('email')}</FormLabelWrapper>
-        <FormControlWrapper
+      <OLFormGroup controlId="email-input">
+        <OLFormLabel>{t('email')}</OLFormLabel>
+        <OLFormControl
           type="text"
           placeholder={t('email')}
           required
           value={email}
           onChange={handleEmailChange}
         />
-      </FormGroupWrapper>
-      <FormGroupWrapper controlId="password-input">
-        <FormLabelWrapper>{t('password')}</FormLabelWrapper>
-        <FormControlWrapper
+      </OLFormGroup>
+      <OLFormGroup controlId="password-input">
+        <OLFormLabel>{t('password')}</OLFormLabel>
+        <OLFormControl
           type="password"
           placeholder={t('password')}
           required
           value={password}
           onChange={handlePasswordChange}
         />
-      </FormGroupWrapper>
-      <FormCheckboxWrapper
+      </OLFormGroup>
+      <OLFormCheckbox
         id="confirm-account-deletion"
         required
         checked={confirmation}

+ 1 - 1
services/web/frontend/js/features/settings/components/leave/modal.tsx

@@ -1,6 +1,6 @@
 import { useState, useCallback } from 'react'
 import LeaveModalContent from './modal-content'
-import OLModal from '@/features/ui/components/bootstrap-5/wrappers/ol-modal'
+import OLModal from '@/features/ui/components/ol/ol-modal'
 
 type LeaveModalProps = {
   isOpen: boolean

+ 2 - 2
services/web/frontend/js/features/settings/components/leavers-survey-alert.tsx

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
 import usePersistedState from '../../../shared/hooks/use-persisted-state'
 import { useUserEmailsContext } from '../context/user-email-context'
 import { sendMB } from '../../../infrastructure/event-tracking'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
 
 function sendMetrics(segmentation: 'view' | 'click' | 'close') {
   sendMB('institutional-leavers-survey-notification', { type: segmentation })
@@ -47,7 +47,7 @@ export function LeaversSurveyAlert() {
   }
 
   return (
-    <NotificationWrapper
+    <OLNotification
       type="info"
       content={
         <>

+ 3 - 3
services/web/frontend/js/features/settings/components/linking-section.tsx

@@ -6,7 +6,7 @@ import { SSOLinkingWidget } from './linking/sso-widget'
 import getMeta from '../../../utils/meta'
 import { useBroadcastUser } from '@/shared/hooks/user-channel/use-broadcast-user'
 import { useFeatureFlag } from '@/shared/context/split-test-context'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
 
 function LinkingSection() {
   useBroadcastUser()
@@ -122,7 +122,7 @@ function LinkingSection() {
             {t('project_synchronisation')}
           </h3>
           {projectSyncSuccessMessage ? (
-            <NotificationWrapper
+            <OLNotification
               type="success"
               content={projectSyncSuccessMessage}
             />
@@ -166,7 +166,7 @@ function LinkingSection() {
             {t('linked_accounts')}
           </h3>
           {ssoErrorMessage ? (
-            <NotificationWrapper
+            <OLNotification
               type="error"
               content={`${t('sso_link_error')}: ${ssoErrorMessage}`}
             />

+ 9 - 9
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 { 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'
+import OLBadge from '@/features/ui/components/ol/ol-badge'
+import OLButton from '@/features/ui/components/ol/ol-button'
 
 function trackUpgradeClick() {
   sendMB('settings-upgrade-click')
@@ -49,7 +49,7 @@ export function EnableWidget({
         <div className="title-row">
           <h4>{title}</h4>
           {!hasFeature && isPremiumFeature && (
-            <BadgeWrapper bg="info">{t('premium_feature')}</BadgeWrapper>
+            <OLBadge bg="info">{t('premium_feature')}</OLBadge>
           )}
         </div>
         <p className="small">
@@ -92,29 +92,29 @@ function ActionButton({
   const { t } = useTranslation()
   if (!hasFeature) {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="primary"
         href="/user/subscription/plans"
         onClick={trackUpgradeClick}
         bs3Props={{ bsStyle: null, className: 'btn-primary' }}
       >
         <span className="text-capitalize">{t('upgrade')}</span>
-      </ButtonWrapper>
+      </OLButton>
     )
   } else if (linked) {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="danger-ghost"
         onClick={handleUnlinkClick}
         disabled={disabled}
         bs3Props={{ bsStyle: null, className: 'btn-danger-ghost' }}
       >
         {t('turn_off')}
-      </ButtonWrapper>
+      </OLButton>
     )
   } else {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="secondary"
         disabled={disabled}
         onClick={handleLinkClick}
@@ -124,7 +124,7 @@ function ActionButton({
         }}
       >
         {t('turn_on')}
-      </ButtonWrapper>
+      </OLButton>
     )
   }
 }

+ 16 - 18
services/web/frontend/js/features/settings/components/linking/integration-widget.tsx

@@ -1,16 +1,16 @@
 import { useCallback, useState, ReactNode } from 'react'
 import { useTranslation } from 'react-i18next'
-import BadgeWrapper from '@/features/ui/components/bootstrap-5/wrappers/badge-wrapper'
+import OLBadge from '@/features/ui/components/ol/ol-badge'
 import getMeta from '../../../../utils/meta'
 import { sendMB } from '../../../../infrastructure/event-tracking'
-import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
 import { bsVersion } from '@/features/utils/bootstrap-5'
 import OLModal, {
   OLModalBody,
   OLModalFooter,
   OLModalHeader,
   OLModalTitle,
-} from '@/features/ui/components/bootstrap-5/wrappers/ol-modal'
+} from '@/features/ui/components/ol/ol-modal'
 
 function trackUpgradeClick(integration: string) {
   sendMB('settings-upgrade-click', { integration })
@@ -67,9 +67,7 @@ export function IntegrationLinkingWidget({
       <div className="description-container">
         <div className="title-row">
           <h4>{title}</h4>
-          {!hasFeature && (
-            <BadgeWrapper bg="info">{t('premium_feature')}</BadgeWrapper>
-          )}
+          {!hasFeature && <OLBadge bg="info">{t('premium_feature')}</OLBadge>}
         </div>
         <p className="small">
           {description}{' '}
@@ -121,31 +119,31 @@ function ActionButton({
   const { t } = useTranslation()
   if (!hasFeature) {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="primary"
         href="/user/subscription/plans"
         onClick={() => trackUpgradeClick(integration)}
         bs3Props={{ bsStyle: null, className: 'btn-primary' }}
       >
         <span className="text-capitalize">{t('upgrade')}</span>
-      </ButtonWrapper>
+      </OLButton>
     )
   } else if (linked) {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="danger-ghost"
         onClick={handleUnlinkClick}
         disabled={disabled}
         bs3Props={{ bsStyle: null, className: 'btn-danger-ghost' }}
       >
         {t('unlink')}
-      </ButtonWrapper>
+      </OLButton>
     )
   } else {
     return (
       <>
         {disabled ? (
-          <ButtonWrapper
+          <OLButton
             disabled
             variant="secondary"
             className={bsVersion({
@@ -154,9 +152,9 @@ function ActionButton({
             })}
           >
             {t('link')}
-          </ButtonWrapper>
+          </OLButton>
         ) : (
-          <ButtonWrapper
+          <OLButton
             variant="secondary"
             href={linkPath}
             className={bsVersion({
@@ -167,7 +165,7 @@ function ActionButton({
             onClick={() => trackLinkingClick(integration)}
           >
             {t('link')}
-          </ButtonWrapper>
+          </OLButton>
         )}
       </>
     )
@@ -217,7 +215,7 @@ function UnlinkConfirmationModal({
       <OLModalFooter>
         <form action={unlinkPath} method="POST" className="form-inline">
           <input type="hidden" name="_csrf" value={getMeta('ol-csrfToken')} />
-          <ButtonWrapper
+          <OLButton
             variant="secondary"
             onClick={handleCancel}
             bs3Props={{
@@ -226,15 +224,15 @@ function UnlinkConfirmationModal({
             }}
           >
             {t('cancel')}
-          </ButtonWrapper>
-          <ButtonWrapper
+          </OLButton>
+          <OLButton
             type="submit"
             variant="danger-ghost"
             bs3Props={{ bsStyle: null, className: 'btn-danger-ghost' }}
             onClick={handleConfirm}
           >
             {t('unlink')}
-          </ButtonWrapper>
+          </OLButton>
         </form>
       </OLModalFooter>
     </OLModal>

+ 12 - 12
services/web/frontend/js/features/settings/components/linking/sso-widget.tsx

@@ -5,14 +5,14 @@ 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 OLButton from '@/features/ui/components/ol/ol-button'
 import { bsVersion } from '@/features/utils/bootstrap-5'
 import OLModal, {
   OLModalBody,
   OLModalFooter,
   OLModalHeader,
   OLModalTitle,
-} from '@/features/ui/components/bootstrap-5/wrappers/ol-modal'
+} from '@/features/ui/components/ol/ol-modal'
 
 const providerLogos: { readonly [p: string]: JSX.Element } = {
   collabratec: <IEEELogo />,
@@ -118,27 +118,27 @@ function ActionButton({
   const { t } = useTranslation()
   if (unlinkRequestInflight) {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="danger-ghost"
         disabled
         bs3Props={{ bsStyle: null, className: 'btn-danger-ghost' }}
       >
         {t('unlinking')}
-      </ButtonWrapper>
+      </OLButton>
     )
   } else if (accountIsLinked) {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="danger-ghost"
         onClick={onUnlinkClick}
         bs3Props={{ bsStyle: null, className: 'btn-danger-ghost' }}
       >
         {t('unlink')}
-      </ButtonWrapper>
+      </OLButton>
     )
   } else {
     return (
-      <ButtonWrapper
+      <OLButton
         variant="secondary"
         href={linkPath}
         bs3Props={{ bsStyle: null }}
@@ -148,7 +148,7 @@ function ActionButton({
         })}
       >
         {t('link')}
-      </ButtonWrapper>
+      </OLButton>
     )
   }
 }
@@ -181,7 +181,7 @@ function UnlinkConfirmModal({
       </OLModalBody>
 
       <OLModalFooter>
-        <ButtonWrapper
+        <OLButton
           variant="secondary"
           onClick={handleHide}
           bs3Props={{
@@ -190,14 +190,14 @@ function UnlinkConfirmModal({
           }}
         >
           {t('cancel')}
-        </ButtonWrapper>
-        <ButtonWrapper
+        </OLButton>
+        <OLButton
           variant="danger-ghost"
           onClick={handleConfirmation}
           bs3Props={{ bsStyle: null, className: 'btn-danger-ghost' }}
         >
           {t('unlink')}
-        </ButtonWrapper>
+        </OLButton>
       </OLModalFooter>
     </OLModal>
   )

+ 20 - 20
services/web/frontend/js/features/settings/components/password-section.tsx

@@ -9,12 +9,12 @@ import getMeta from '../../../utils/meta'
 import { ExposedSettings } from '../../../../../types/exposed-settings'
 import { PasswordStrengthOptions } from '../../../../../types/password-strength-options'
 import useAsync from '../../../shared/hooks/use-async'
-import ButtonWrapper from '@/features/ui/components/bootstrap-5/wrappers/button-wrapper'
-import NotificationWrapper from '@/features/ui/components/bootstrap-5/wrappers/notification-wrapper'
-import FormGroupWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-group-wrapper'
-import FormLabelWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-label-wrapper'
-import FormControlWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-control-wrapper'
-import FormTextWrapper from '@/features/ui/components/bootstrap-5/wrappers/form-text-wrapper'
+import OLButton from '@/features/ui/components/ol/ol-button'
+import OLNotification from '@/features/ui/components/ol/ol-notification'
+import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
+import OLFormLabel from '@/features/ui/components/ol/ol-form-label'
+import OLFormControl from '@/features/ui/components/ol/ol-form-control'
+import OLFormText from '@/features/ui/components/ol/ol-form-text'
 
 type PasswordUpdateResult = {
   message?: {
@@ -159,13 +159,13 @@ function PasswordForm() {
         autoComplete="new-password"
       />
       {isSuccess && data?.message?.text ? (
-        <FormGroupWrapper>
-          <NotificationWrapper type="success" content={data.message.text} />
-        </FormGroupWrapper>
+        <OLFormGroup>
+          <OLNotification type="success" content={data.message.text} />
+        </OLFormGroup>
       ) : null}
       {isError ? (
-        <FormGroupWrapper>
-          <NotificationWrapper
+        <OLFormGroup>
+          <OLNotification
             type="error"
             content={
               getErrorMessageKey(error) === 'password-must-be-strong' ? (
@@ -198,9 +198,9 @@ function PasswordForm() {
               )
             }
           />
-        </FormGroupWrapper>
+        </OLFormGroup>
       ) : null}
-      <ButtonWrapper
+      <OLButton
         form="password-change-form"
         type="submit"
         variant="primary"
@@ -211,7 +211,7 @@ function PasswordForm() {
         }}
       >
         {t('change')}
-      </ButtonWrapper>
+      </OLButton>
     </form>
   )
 }
@@ -255,9 +255,9 @@ function PasswordFormGroup({
   )
 
   return (
-    <FormGroupWrapper controlId={id}>
-      <FormLabelWrapper>{label}</FormLabelWrapper>
-      <FormControlWrapper
+    <OLFormGroup controlId={id}>
+      <OLFormLabel>{label}</OLFormLabel>
+      <OLFormControl
         type="password"
         placeholder="*********"
         autoComplete={autoComplete}
@@ -270,11 +270,11 @@ function PasswordFormGroup({
         isInvalid={isInvalid}
       />
       {isInvalid && (
-        <FormTextWrapper isError>
+        <OLFormText isError>
           {parentValidationMessage || validationMessage}
-        </FormTextWrapper>
+        </OLFormText>
       )}
-    </FormGroupWrapper>
+    </OLFormGroup>
   )
 }
 

+ 15 - 15
services/web/frontend/js/features/settings/components/root.tsx

@@ -20,9 +20,9 @@ import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
 import useScrollToIdOnLoad from '../../../shared/hooks/use-scroll-to-id-on-load'
 import { ExposedSettings } from '../../../../../types/exposed-settings'
 import { SSOAlert } from './emails/sso-alert'
-import RowWrapper from '@/features/ui/components/bootstrap-5/wrappers/row-wrapper'
-import ColWrapper from '@/features/ui/components/bootstrap-5/wrappers/col-wrapper'
-import CardWrapper from '@/features/ui/components/bootstrap-5/wrappers/card-wrapper'
+import OLRow from '@/features/ui/components/ol/ol-row'
+import OLCol from '@/features/ui/components/ol/ol-col'
+import OLCard from '@/features/ui/components/ol/ol-card'
 
 function SettingsPageRoot() {
   const { isReady } = useWaitForI18n()
@@ -34,11 +34,11 @@ function SettingsPageRoot() {
 
   return (
     <div className="container">
-      <RowWrapper>
-        <ColWrapper md={12} lg={{ span: 10, offset: 1 }}>
+      <OLRow>
+        <OLCol md={12} lg={{ span: 10, offset: 1 }}>
           {isReady ? <SettingsPageContent /> : null}
-        </ColWrapper>
-      </RowWrapper>
+        </OLCol>
+      </OLRow>
     </div>
   )
 }
@@ -51,7 +51,7 @@ function SettingsPageContent() {
 
   return (
     <UserProvider>
-      <CardWrapper>
+      <OLCard>
         <div className="page-header">
           <h1>{t('account_settings')}</h1>
         </div>
@@ -59,14 +59,14 @@ function SettingsPageContent() {
           <ManagedAccountAlert />
           <EmailsSection />
           <SSOAlert />
-          <RowWrapper>
-            <ColWrapper md={5}>
+          <OLRow>
+            <OLCol md={5}>
               <AccountInfoSection />
-            </ColWrapper>
-            <ColWrapper md={{ span: 5, offset: 1 }}>
+            </OLCol>
+            <OLCol md={{ span: 5, offset: 1 }}>
               <PasswordSection />
-            </ColWrapper>
-          </RowWrapper>
+            </OLCol>
+          </OLRow>
           <hr />
           <SecuritySection />
           <SplitTestProvider>
@@ -96,7 +96,7 @@ function SettingsPageContent() {
             </>
           ) : null}
         </div>
-      </CardWrapper>
+      </OLCard>
     </UserProvider>
   )
 }

+ 3 - 3
services/web/frontend/js/features/settings/components/security-section.tsx

@@ -2,7 +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'
+import OLButton from '@/features/ui/components/ol/ol-button'
 
 function SecuritySection() {
   const { t } = useTranslation()
@@ -85,13 +85,13 @@ function SecuritySection() {
                 </div>
                 {linked ? null : (
                   <div className="button-column">
-                    <ButtonWrapper
+                    <OLButton
                       variant="primary"
                       bs3Props={{ className: 'btn btn-primary', bsStyle: null }}
                       href={`/subscription/${groupId}/sso_enrollment`}
                     >
                       {t('set_up_sso')}
-                    </ButtonWrapper>
+                    </OLButton>
                   </div>
                 )}
               </div>

+ 0 - 71
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/form-control-wrapper.tsx

@@ -1,71 +0,0 @@
-import { forwardRef } from 'react'
-import { Form } from 'react-bootstrap-5'
-import { FormControl as BS3FormControl } from 'react-bootstrap'
-import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
-
-type FormControlWrapperProps = React.ComponentProps<
-  (typeof Form)['Control']
-> & {
-  bs3Props?: Record<string, unknown>
-}
-
-const FormControlWrapper = forwardRef<
-  HTMLInputElement,
-  FormControlWrapperProps
->((props, ref) => {
-  const { bs3Props, ...rest } = props
-
-  let bs3FormControlProps: React.ComponentProps<typeof BS3FormControl> = {
-    id: rest.id,
-    className: rest.className,
-    style: rest.style,
-    type: rest.type,
-    value: rest.value,
-    required: rest.required,
-    disabled: rest.disabled,
-    placeholder: rest.placeholder,
-    readOnly: rest.readOnly,
-    autoComplete: rest.autoComplete,
-    minLength: rest.minLength,
-    maxLength: rest.maxLength,
-    onChange: rest.onChange as (e: React.ChangeEvent<unknown>) => void,
-    onKeyDown: rest.onKeyDown as (e: React.KeyboardEvent<unknown>) => void,
-    onFocus: rest.onFocus as (e: React.FocusEvent<unknown>) => void,
-    onInvalid: rest.onInvalid as (e: React.InvalidEvent<unknown>) => void,
-    inputRef: (inputElement: HTMLInputElement) => {
-      if (typeof ref === 'function') {
-        ref(inputElement)
-      } else if (ref) {
-        ref.current = inputElement
-      }
-    },
-    ...bs3Props,
-  }
-
-  // get all `aria-*` and `data-*` attributes
-  const extraProps = Object.entries(rest).reduce(
-    (acc, [key, value]) => {
-      if (key.startsWith('aria-') || key.startsWith('data-')) {
-        acc[key] = value
-      }
-      return acc
-    },
-    {} as Record<string, string>
-  )
-
-  bs3FormControlProps = {
-    ...bs3FormControlProps,
-    ...extraProps,
-    'data-ol-dirty': rest['data-ol-dirty'],
-  } as typeof bs3FormControlProps & Record<string, unknown>
-
-  return (
-    <BootstrapVersionSwitcher
-      bs3={<BS3FormControl {...bs3FormControlProps} />}
-      bs5={<Form.Control ref={ref} {...rest} />}
-    />
-  )
-})
-FormControlWrapper.displayName = 'FormControlWrapper'
-
-export default FormControlWrapper

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/badge-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-badge.tsx

@@ -3,13 +3,13 @@ import Badge from '@/features/ui/components/bootstrap-5/badge'
 import BS3Badge from '@/shared/components/badge'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 
-type BadgeWrapperProps = React.ComponentProps<typeof Badge> & {
+type OLBadgeProps = React.ComponentProps<typeof Badge> & {
   bs3Props?: {
     bsStyle?: React.ComponentProps<typeof Label>['bsStyle'] | null
   }
 }
 
-function BadgeWrapper(props: BadgeWrapperProps) {
+function OLBadge(props: OLBadgeProps) {
   const { bs3Props, ...rest } = props
 
   let bs3BadgeProps: React.ComponentProps<typeof BS3Badge> = {
@@ -38,4 +38,4 @@ function BadgeWrapper(props: BadgeWrapperProps) {
   )
 }
 
-export default BadgeWrapper
+export default OLBadge

+ 4 - 4
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/button-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-button.tsx

@@ -1,10 +1,10 @@
-import BootstrapVersionSwitcher from '../bootstrap-version-switcher'
+import BootstrapVersionSwitcher from '../bootstrap-5/bootstrap-version-switcher'
 import { Button as BS3Button } from 'react-bootstrap'
 import type { ButtonProps } from '@/features/ui/components/types/button-props'
 import type { ButtonProps as BS3ButtonPropsBase } from 'react-bootstrap'
-import Button from '../button'
+import Button from '../bootstrap-5/button'
 
-export type ButtonWrapperProps = ButtonProps & {
+export type OLButtonProps = ButtonProps & {
   bs3Props?: {
     bsStyle?: string | null
     className?: string
@@ -23,7 +23,7 @@ export const mapBsButtonSizes = (
 ): 'sm' | 'lg' | undefined =>
   size === 'small' ? 'sm' : size === 'large' ? 'lg' : undefined
 
-export default function ButtonWrapper(props: ButtonWrapperProps) {
+export default function OLButton(props: OLButtonProps) {
   const { bs3Props, ...rest } = props
 
   const bs3ButtonProps: BS3ButtonProps = {

+ 2 - 2
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/card-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-card.tsx

@@ -5,7 +5,7 @@ import { FC } from 'react'
 // This wraps the Bootstrap 5 Card component but is restricted to the very
 // basic way we're using it, which is as a container for page content. The
 // Bootstrap 3 equivalent in our codebase is a div with class "card"
-const CardWrapper: FC = ({ children }) => {
+const OLCard: FC = ({ children }) => {
   return (
     <BootstrapVersionSwitcher
       bs3={<div className="card">{children}</div>}
@@ -18,4 +18,4 @@ const CardWrapper: FC = ({ children }) => {
   )
 }
 
-export default CardWrapper
+export default OLCard

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/col-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-col.tsx

@@ -2,11 +2,11 @@ import { Col } from 'react-bootstrap-5'
 import { Col as BS3Col } from 'react-bootstrap'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 
-type ColWrapperProps = React.ComponentProps<typeof Col> & {
+type OLColProps = React.ComponentProps<typeof Col> & {
   bs3Props?: Record<string, unknown>
 }
 
-function ColWrapper(props: ColWrapperProps) {
+function OLCol(props: OLColProps) {
   const { bs3Props, ...rest } = props
   const sizes = new Set(['xs', 'sm', 'md', 'lg', 'xl', 'xxl'])
 
@@ -42,4 +42,4 @@ function ColWrapper(props: ColWrapperProps) {
   )
 }
 
-export default ColWrapper
+export default OLCol

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/form-checkbox-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-form-checkbox.tsx

@@ -2,11 +2,11 @@ import { Form } from 'react-bootstrap-5'
 import { Checkbox as BS3Checkbox } from 'react-bootstrap'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 
-type FormCheckboxWrapperProps = React.ComponentProps<(typeof Form)['Check']> & {
+type OLFormCheckboxProps = React.ComponentProps<(typeof Form)['Check']> & {
   bs3Props?: Record<string, unknown>
 }
 
-function FormCheckboxWrapper(props: FormCheckboxWrapperProps) {
+function OLFormCheckbox(props: OLFormCheckboxProps) {
   const { bs3Props, ...rest } = props
 
   const bs3FormLabelProps: React.ComponentProps<typeof BS3Checkbox> = {
@@ -29,4 +29,4 @@ function FormCheckboxWrapper(props: FormCheckboxWrapperProps) {
   )
 }
 
-export default FormCheckboxWrapper
+export default OLFormCheckbox

+ 68 - 0
services/web/frontend/js/features/ui/components/ol/ol-form-control.tsx

@@ -0,0 +1,68 @@
+import { forwardRef } from 'react'
+import { Form } from 'react-bootstrap-5'
+import { FormControl as BS3FormControl } from 'react-bootstrap'
+import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
+
+type OLFormControlProps = React.ComponentProps<(typeof Form)['Control']> & {
+  bs3Props?: Record<string, unknown>
+}
+
+const OLFormControl = forwardRef<HTMLInputElement, OLFormControlProps>(
+  (props, ref) => {
+    const { bs3Props, ...rest } = props
+
+    let bs3FormControlProps: React.ComponentProps<typeof BS3FormControl> = {
+      id: rest.id,
+      className: rest.className,
+      style: rest.style,
+      type: rest.type,
+      value: rest.value,
+      required: rest.required,
+      disabled: rest.disabled,
+      placeholder: rest.placeholder,
+      readOnly: rest.readOnly,
+      autoComplete: rest.autoComplete,
+      minLength: rest.minLength,
+      maxLength: rest.maxLength,
+      onChange: rest.onChange as (e: React.ChangeEvent<unknown>) => void,
+      onKeyDown: rest.onKeyDown as (e: React.KeyboardEvent<unknown>) => void,
+      onFocus: rest.onFocus as (e: React.FocusEvent<unknown>) => void,
+      onInvalid: rest.onInvalid as (e: React.InvalidEvent<unknown>) => void,
+      inputRef: (inputElement: HTMLInputElement) => {
+        if (typeof ref === 'function') {
+          ref(inputElement)
+        } else if (ref) {
+          ref.current = inputElement
+        }
+      },
+      ...bs3Props,
+    }
+
+    // get all `aria-*` and `data-*` attributes
+    const extraProps = Object.entries(rest).reduce(
+      (acc, [key, value]) => {
+        if (key.startsWith('aria-') || key.startsWith('data-')) {
+          acc[key] = value
+        }
+        return acc
+      },
+      {} as Record<string, string>
+    )
+
+    bs3FormControlProps = {
+      ...bs3FormControlProps,
+      ...extraProps,
+      'data-ol-dirty': rest['data-ol-dirty'],
+    } as typeof bs3FormControlProps & Record<string, unknown>
+
+    return (
+      <BootstrapVersionSwitcher
+        bs3={<BS3FormControl {...bs3FormControlProps} />}
+        bs5={<Form.Control ref={ref} {...rest} />}
+      />
+    )
+  }
+)
+OLFormControl.displayName = 'OLFormControl'
+
+export default OLFormControl

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/form-group-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-form-group.tsx

@@ -2,11 +2,11 @@ import { Form } from 'react-bootstrap-5'
 import { FormGroup as BS3FormGroup } from 'react-bootstrap'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 
-type FormGroupWrapperProps = React.ComponentProps<(typeof Form)['Group']> & {
+type OLFormGroupProps = React.ComponentProps<(typeof Form)['Group']> & {
   bs3Props?: Record<string, unknown>
 }
 
-function FormGroupWrapper(props: FormGroupWrapperProps) {
+function OLFormGroup(props: OLFormGroupProps) {
   const { bs3Props, className, ...rest } = props
 
   const classNames = className ?? 'mb-3'
@@ -26,4 +26,4 @@ function FormGroupWrapper(props: FormGroupWrapperProps) {
   )
 }
 
-export default FormGroupWrapper
+export default OLFormGroup

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/form-label-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-form-label.tsx

@@ -2,11 +2,11 @@ import { Form } from 'react-bootstrap-5'
 import { ControlLabel as BS3FormLabel } from 'react-bootstrap'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 
-type FormLabelWrapperProps = React.ComponentProps<(typeof Form)['Label']> & {
+type OLFormLabelProps = React.ComponentProps<(typeof Form)['Label']> & {
   bs3Props?: Record<string, unknown>
 }
 
-function FormLabelWrapper(props: FormLabelWrapperProps) {
+function OLFormLabel(props: OLFormLabelProps) {
   const { bs3Props, ...rest } = props
 
   const bs3FormLabelProps: React.ComponentProps<typeof BS3FormLabel> = {
@@ -24,4 +24,4 @@ function FormLabelWrapper(props: FormLabelWrapperProps) {
   )
 }
 
-export default FormLabelWrapper
+export default OLFormLabel

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/form-text-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx

@@ -5,11 +5,11 @@ import PolymorphicComponent from '@/shared/components/polymorphic-component'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 import classnames from 'classnames'
 
-type FormTextWrapperProps = React.ComponentProps<typeof FormText> & {
+type OLFormTextProps = React.ComponentProps<typeof FormText> & {
   bs3Props?: Record<string, unknown>
 }
 
-function FormTextWrapper(props: FormTextWrapperProps) {
+function OLFormText(props: OLFormTextProps) {
   const { bs3Props, ...rest } = props
 
   const bs3HelpBlockProps = {
@@ -35,4 +35,4 @@ function FormTextWrapper(props: FormTextWrapperProps) {
   )
 }
 
-export default FormTextWrapper
+export default OLFormText

+ 5 - 5
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/icon-button-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-icon-button.tsx

@@ -1,18 +1,18 @@
-import { BS3ButtonProps, mapBsButtonSizes } from './button-wrapper'
+import { BS3ButtonProps, mapBsButtonSizes } from './ol-button'
 import { Button as BS3Button } from 'react-bootstrap'
 import type { IconButtonProps } from '@/features/ui/components/types/icon-button-props'
-import BootstrapVersionSwitcher from '../bootstrap-version-switcher'
+import BootstrapVersionSwitcher from '../bootstrap-5/bootstrap-version-switcher'
 import Icon, { IconProps } from '@/shared/components/icon'
-import IconButton from '../icon-button'
+import IconButton from '../bootstrap-5/icon-button'
 
-export type IconButtonWrapperProps = IconButtonProps & {
+export type OLIconButtonProps = IconButtonProps & {
   bs3Props?: {
     loading?: React.ReactNode
     fw?: IconProps['fw']
   }
 }
 
-export default function IconButtonWrapper(props: IconButtonWrapperProps) {
+export default function OLIconButton(props: OLIconButtonProps) {
   const { bs3Props, ...rest } = props
 
   const { fw, ...filterBs3Props } = bs3Props || {}

+ 0 - 0
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/ol-modal.tsx → services/web/frontend/js/features/ui/components/ol/ol-modal.tsx


+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/notification-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-notification.tsx

@@ -3,14 +3,14 @@ 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<typeof Notification> & {
+type OLNotificationProps = React.ComponentProps<typeof Notification> & {
   bs3Props?: {
     icon?: React.ReactElement
     className?: string
   }
 }
 
-function NotificationWrapper(props: NotificationWrapperProps) {
+function OLNotification(props: OLNotificationProps) {
   const { bs3Props, ...notificationProps } = props
 
   const alertProps = {
@@ -39,4 +39,4 @@ function NotificationWrapper(props: NotificationWrapperProps) {
   )
 }
 
-export default NotificationWrapper
+export default OLNotification

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/row-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-row.tsx

@@ -2,9 +2,9 @@ import { Row } from 'react-bootstrap-5'
 import { Row as BS3Row } from 'react-bootstrap'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 
-type RowWrapperProps = React.ComponentProps<typeof Row>
+type OLRowProps = React.ComponentProps<typeof Row>
 
-function RowWrapper(props: RowWrapperProps) {
+function OLRow(props: OLRowProps) {
   return (
     <BootstrapVersionSwitcher
       bs3={<BS3Row className={props.className}>{props.children}</BS3Row>}
@@ -13,4 +13,4 @@ function RowWrapper(props: RowWrapperProps) {
   )
 }
 
-export default RowWrapper
+export default OLRow

+ 3 - 3
services/web/frontend/js/features/ui/components/bootstrap-5/wrappers/tooltip-wrapper.tsx → services/web/frontend/js/features/ui/components/ol/ol-tooltip.tsx

@@ -2,11 +2,11 @@ import Tooltip from '@/features/ui/components/bootstrap-5/tooltip'
 import BS3Tooltip from '@/shared/components/tooltip'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 
-type TooltipWrapperProps = React.ComponentProps<typeof Tooltip> & {
+type OLTooltipProps = React.ComponentProps<typeof Tooltip> & {
   bs3Props?: Record<string, unknown>
 }
 
-function TooltipWrapper(props: TooltipWrapperProps) {
+function OLTooltip(props: OLTooltipProps) {
   const { bs3Props, ...bs5Props } = props
 
   const bs3TooltipProps: React.ComponentProps<typeof BS3Tooltip> = {
@@ -38,4 +38,4 @@ function TooltipWrapper(props: TooltipWrapperProps) {
   )
 }
 
-export default TooltipWrapper
+export default OLTooltip

+ 2 - 2
services/web/frontend/js/shared/components/badge.tsx

@@ -1,6 +1,6 @@
 import classnames from 'classnames'
 import { MergeAndOverride } from '../../../../types/utils'
-import BadgeWrapper from '@/features/ui/components/bootstrap-5/wrappers/badge-wrapper'
+import OLBadge from '@/features/ui/components/ol/ol-badge'
 
 type BadgeProps = MergeAndOverride<
   React.ComponentProps<'span'>,
@@ -10,7 +10,7 @@ type BadgeProps = MergeAndOverride<
     closeBtnProps?: React.ComponentProps<'button'>
     className?: string
     bsStyle?: NonNullable<
-      React.ComponentProps<typeof BadgeWrapper>['bs3Props']
+      React.ComponentProps<typeof OLBadge>['bs3Props']
     >['bsStyle']
   }
 >