Răsfoiți Sursa

Merge pull request #17702 from overleaf/ii-bs5-to-bs3-classname-helper

[web] Bootstrap class name helper

GitOrigin-RevId: 9c2042aa2ea0e4d3828b32c321336e1c3a4a0ef8
ilkin-overleaf 2 ani în urmă
părinte
comite
a9436039b6

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

@@ -18,6 +18,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 { bsClassName } from '@/features/utils/bootstrap-5'
 
 function AddEmail() {
   const { t } = useTranslation()
@@ -133,7 +134,10 @@ function AddEmail() {
 
   const InputComponent = (
     <>
-      <label htmlFor="affiliations-email" className="sr-only">
+      <label
+        htmlFor="affiliations-email"
+        className={bsClassName({ bs5: 'visually-hidden', bs3: 'sr-only' })}
+      >
         {t('email')}
       </label>
       <Input
@@ -157,7 +161,12 @@ function AddEmail() {
             </Cell>
           </Col>
           <Col md={4}>
-            <Cell className="text-md-right">
+            <Cell
+              className={bsClassName({
+                bs5: 'text-md-end',
+                bs3: 'text-md-right',
+              })}
+            >
               <AddNewEmailBtn email={newEmail} disabled />
             </Cell>
           </Col>
@@ -197,7 +206,12 @@ function AddEmail() {
         </Col>
         {!isSsoAvailableForDomain ? (
           <Col md={4}>
-            <Cell className="text-md-right">
+            <Cell
+              className={bsClassName({
+                bs5: 'text-md-end',
+                bs3: 'text-md-right',
+              })}
+            >
               <AddNewEmailBtn
                 email={newEmail}
                 disabled={isLoading || state.isLoading}

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

@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'
 import { useCombobox } from 'downshift'
 import classnames from 'classnames'
 import countries, { CountryCode } from '../../../data/countries-list'
+import { bsClassName } from '@/features/utils/bootstrap-5'
 
 type CountryInputProps = {
   setValue: React.Dispatch<React.SetStateAction<CountryCode | null>>
@@ -55,7 +56,10 @@ function Downshift({ setValue, inputRef }: CountryInputProps) {
     >
       <div {...getComboboxProps()} className="ui-select-toggle">
         {/* eslint-disable-next-line jsx-a11y/label-has-for */}
-        <label {...getLabelProps()} className="sr-only">
+        <label
+          {...getLabelProps()}
+          className={bsClassName({ bs5: 'visually-hidden', bs3: 'sr-only' })}
+        >
           {t('country')}
         </label>
         <input

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

@@ -2,6 +2,7 @@ import { useState, useEffect, forwardRef } from 'react'
 import { useCombobox } from 'downshift'
 import classnames from 'classnames'
 import { escapeRegExp } from 'lodash'
+import { bsClassName } from '@/features/utils/bootstrap-5'
 
 type DownshiftInputProps = {
   highlightMatches?: boolean
@@ -86,7 +87,14 @@ function Downshift({
     >
       <div {...getComboboxProps()}>
         {/* eslint-disable-next-line jsx-a11y/label-has-for */}
-        <label {...getLabelProps()} className={showLabel ? '' : 'sr-only'}>
+        <label
+          {...getLabelProps()}
+          className={
+            showLabel
+              ? ''
+              : bsClassName({ bs5: 'visually-hidden', bs3: 'sr-only' })
+          }
+        >
           {label}
         </label>
         <input

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

@@ -1,6 +1,8 @@
 import { useTranslation } from 'react-i18next'
 import { Row, Col } from 'react-bootstrap'
 import EmailCell from './cell'
+import classnames from 'classnames'
+import { bsClassName } from '@/features/utils/bootstrap-5'
 
 function Header() {
   const { t } = useTranslation()
@@ -8,19 +10,41 @@ function Header() {
   return (
     <>
       <Row>
-        <Col md={4} className="hidden-xs">
+        <Col
+          md={4}
+          className={bsClassName({
+            bs5: 'd-none d-sm-block',
+            bs3: 'hidden-xs',
+          })}
+        >
           <EmailCell>
             <strong>{t('email')}</strong>
           </EmailCell>
         </Col>
-        <Col md={8} className="hidden-xs">
+        <Col
+          md={8}
+          className={bsClassName({
+            bs5: 'd-none d-sm-block',
+            bs3: 'hidden-xs',
+          })}
+        >
           <EmailCell>
             <strong>{t('institution_and_role')}</strong>
           </EmailCell>
         </Col>
       </Row>
-      <div className="hidden-xs horizontal-divider" />
-      <div className="hidden-xs horizontal-divider" />
+      <div
+        className={classnames(
+          bsClassName({ bs5: 'd-none d-sm-block', bs3: 'hidden-xs' }),
+          'horizontal-divider'
+        )}
+      />
+      <div
+        className={classnames(
+          bsClassName({ bs5: 'd-none d-sm-block', bs3: 'hidden-xs' }),
+          'horizontal-divider'
+        )}
+      />
     </>
   )
 }

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

@@ -13,6 +13,7 @@ import { ExposedSettings } from '../../../../../../types/exposed-settings'
 import { ssoAvailableForInstitution } from '../../utils/sso'
 import ReconfirmationInfo from './reconfirmation-info'
 import { useLocation } from '../../../../shared/hooks/use-location'
+import { bsClassName } from '@/features/utils/bootstrap-5'
 
 type EmailsRowProps = {
   userEmailData: UserEmailData
@@ -40,7 +41,12 @@ function EmailsRow({ userEmailData }: EmailsRowProps) {
           )}
         </Col>
         <Col md={3}>
-          <EmailCell className="text-md-right">
+          <EmailCell
+            className={bsClassName({
+              bs5: 'text-md-end',
+              bs3: 'text-md-right',
+            })}
+          >
             <Actions userEmailData={userEmailData} />
           </EmailCell>
         </Col>
@@ -144,7 +150,13 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
               </p>
             </EmailCell>
           </Col>
-          <Col md={3} className="text-md-right">
+          <Col
+            md={3}
+            className={bsClassName({
+              bs5: 'text-md-end',
+              bs3: 'text-md-right',
+            })}
+          >
             <EmailCell>
               <Button
                 bsStyle="primary"

+ 7 - 0
services/web/frontend/js/features/utils/bootstrap-5.ts

@@ -0,0 +1,7 @@
+import getMeta from '@/utils/meta'
+
+export const isBootstrap5 = getMeta('ol-bootstrapVersion') === 5
+
+export const bsClassName = ({ bs5, bs3 }: { bs5: string; bs3: string }) => {
+  return isBootstrap5 ? bs5 : bs3
+}

+ 6 - 1
services/web/frontend/js/shared/components/icon.tsx

@@ -1,4 +1,5 @@
 import classNames from 'classnames'
+import { bsClassName } from '@/features/utils/bootstrap-5'
 
 type IconOwnProps = {
   type: string
@@ -35,7 +36,11 @@ function Icon({
     <>
       <i className={iconClassName} aria-hidden="true" {...rest} />
       {accessibilityLabel && (
-        <span className="sr-only">{accessibilityLabel}</span>
+        <span
+          className={bsClassName({ bs5: 'visually-hidden', bs3: 'sr-only' })}
+        >
+          {accessibilityLabel}
+        </span>
       )}
     </>
   )