瀏覽代碼

[web] Changes to recompile button in Bootstrap 5 (#21586)

* Add Story for `PdfCompileButton`

* Set the CompileButton height so it's similar to BS3

* Add the CompileButton animations

* Remove `sm` from CompileButton: makes font size bigger

* Use MaterialIcon in compile-button dropdown-toggle

* Use MaterialIcon in LayoutDropdown

* Fix stripe alignment on Recompile button

* Set padding around dropdown caret

Per Alexandru's instructions

* Prevent border from disappearing on hover

* Set the padding of the compile button even on both sides

Before: left 12px, right 16px;
After: left 16px, right 16px;

* Change px values to spacing var

* Add some button classes for BS5 only

* Don't render the hidden "Compiling…" in BS5, it changes the button width

* Prevent `loading="[object Object]"` in the DOM

Co-authored-by: Rebeka <rebeka.dekany@overleaf.com>

---------

Co-authored-by: Rebeka <rebeka.dekany@overleaf.com>
GitOrigin-RevId: 34f1eed03e63f3459243a37c878612a623f321f8
Antoine Clausse 1 年之前
父節點
當前提交
1d4737ac69

+ 2 - 1
services/web/frontend/js/features/editor-navigation-toolbar/components/layout-dropdown-button.tsx

@@ -10,6 +10,7 @@ import {
   DropdownItem,
   DropdownMenu,
   DropdownToggle,
+  DropdownToggleCustom,
 } from '@/features/ui/components/bootstrap-5/dropdown-menu'
 import { Trans, useTranslation } from 'react-i18next'
 import Tooltip from '../../../shared/components/tooltip'
@@ -136,7 +137,7 @@ const LayoutDropdownToggleButton = forwardRef<
     onClick(e)
   }
 
-  return <button {...props} ref={ref} onClick={handleClick} />
+  return <DropdownToggleCustom {...props} ref={ref} onClick={handleClick} />
 })
 LayoutDropdownToggleButton.displayName = 'LayoutDropdownToggleButton'
 

+ 8 - 5
services/web/frontend/js/features/pdf-preview/components/detach-compile-button.tsx

@@ -46,7 +46,7 @@ function DetachCompileButton() {
           size="sm"
           isLoading={compiling}
           bs3Props={{
-            loading: (
+            loading: compiling && (
               <>
                 <Icon type="refresh" spin={compiling} />
                 <span className="detach-compile-button-label">
@@ -58,11 +58,14 @@ function DetachCompileButton() {
         >
           <BootstrapVersionSwitcher
             bs3={
-              <span className="detach-compile-button-label">
-                {compileButtonLabel}
-              </span>
+              <>
+                <Icon type="refresh" spin={compiling} />
+                <span className="detach-compile-button-label">
+                  {compileButtonLabel}
+                </span>
+              </>
             }
-            bs5={compileButtonLabel}
+            bs5={t('recompile')}
           />
         </OLButton>
       </OLTooltip>

+ 16 - 8
services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.tsx

@@ -9,6 +9,7 @@ import * as eventTracking from '../../../infrastructure/event-tracking'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
 import {
+  DropdownToggleCustom,
   Dropdown,
   DropdownDivider,
   DropdownHeader,
@@ -18,7 +19,7 @@ import {
 } from '@/features/ui/components/bootstrap-5/dropdown-menu'
 import OLButton from '@/features/ui/components/ol/ol-button'
 import OLButtonGroup from '@/features/ui/components/ol/ol-button-group'
-import { bsVersion } from '@/features/utils/bootstrap-5'
+import { bsVersion, isBootstrap5 } from '@/features/utils/bootstrap-5'
 import { useLayoutContext } from '@/shared/context/layout-context'
 
 const modifierKey = /Mac/i.test(navigator.platform) ? 'Cmd' : 'Ctrl'
@@ -78,15 +79,18 @@ function PdfCompileButton() {
     {
       'detach-compile-button-animate': animateCompileDropdownArrow,
       'btn-striped-animated': hasChanges,
-      'no-left-border': true,
     },
+    'no-left-border',
     bsVersion({ bs5: 'dropdown-button-toggle' })
   )
 
-  const buttonClassName = classNames({
-    'btn-striped-animated': hasChanges,
-    'no-left-radius': true,
-  })
+  const buttonClassName = classNames(
+    {
+      'btn-striped-animated': hasChanges,
+      'align-items-center py-0': isBootstrap5(),
+    },
+    'no-left-radius px-3'
+  )
 
   return (
     <BootstrapVersionSwitcher
@@ -207,7 +211,11 @@ function PdfCompileButton() {
         </SplitMenu>
       }
       bs5={
-        <Dropdown as={OLButtonGroup} autoClose="outside">
+        <Dropdown
+          as={OLButtonGroup}
+          autoClose="outside"
+          className="compile-button-group"
+        >
           <OLTooltip
             description={tooltipElement}
             id="compile"
@@ -219,7 +227,6 @@ function PdfCompileButton() {
           >
             <OLButton
               variant="primary"
-              size="sm"
               disabled={compiling}
               isLoading={compiling}
               onClick={() => startCompile()}
@@ -230,6 +237,7 @@ function PdfCompileButton() {
           </OLTooltip>
 
           <DropdownToggle
+            as={DropdownToggleCustom}
             split
             variant="primary"
             id="pdf-recompile-dropdown"

+ 16 - 0
services/web/frontend/js/features/ui/components/bootstrap-5/dropdown-menu.tsx

@@ -6,6 +6,8 @@ import {
   DropdownItem as BS5DropdownItem,
   DropdownDivider as BS5DropdownDivider,
   DropdownHeader as BS5DropdownHeader,
+  Button as BS5Button,
+  type ButtonProps,
 } from 'react-bootstrap-5'
 import type {
   DropdownProps,
@@ -103,6 +105,20 @@ const ForwardReferredDropdownItem = fixedForwardRef(DropdownItem, {
 
 export { ForwardReferredDropdownItem as DropdownItem }
 
+export const DropdownToggleCustom = forwardRef<HTMLButtonElement, ButtonProps>(
+  ({ children, className, ...props }, ref) => (
+    <BS5Button
+      ref={ref}
+      className={classnames('custom-toggle', className)}
+      {...props}
+    >
+      {children}
+      <MaterialIcon type="expand_more" />
+    </BS5Button>
+  )
+)
+DropdownToggleCustom.displayName = 'CustomCaret'
+
 export const DropdownToggle = forwardRef<
   typeof BS5DropdownToggle,
   DropdownToggleProps

+ 56 - 0
services/web/frontend/stories/editor/pdf-compile-button.stories.tsx

@@ -0,0 +1,56 @@
+import { FC } from 'react'
+import type { Meta } from '@storybook/react'
+import PdfCompileButton from '@/features/pdf-preview/components/pdf-compile-button'
+import { ScopeDecorator } from '../decorators/scope'
+import { CompileContext } from '@/shared/context/local-compile-context'
+import { DetachCompileContext } from '@/shared/context/detach-compile-context'
+import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
+
+export const CompileButton: FC<CompileContext> = (props: CompileContext) => (
+  <DetachCompileContext.Provider value={props}>
+    <div className="pdf m-5">
+      <div className="toolbar toolbar-pdf toolbar-pdf-hybrid btn-toolbar">
+        <div className="toolbar-pdf-left">
+          <PdfCompileButton />
+        </div>
+      </div>
+    </div>
+  </DetachCompileContext.Provider>
+)
+
+const args: Partial<CompileContext> = {
+  autoCompile: false,
+  compiling: false,
+  draft: false,
+  hasChanges: false,
+  stopOnFirstError: false,
+  stopOnValidationError: false,
+  animateCompileDropdownArrow: false,
+}
+
+const meta: Meta<typeof CompileButton> = {
+  title: 'Editor / Toolbar / Compile Button',
+  component: CompileButton,
+  // @ts-ignore
+  decorators: [ScopeDecorator],
+  argTypes: {
+    ...bsVersionDecorator.argTypes,
+    startCompile: { action: 'startCompile' },
+    setAutoCompile: { action: 'setAutoCompile' },
+    setCompiling: { action: 'setCompiling' },
+    setDraft: { action: 'setDraft' },
+    setStopOnFirstError: { action: 'setStopOnFirstError' },
+    setError: { action: 'setError' },
+    setHasLintingError: { action: 'setHasLintingError' },
+    setPosition: { action: 'setPosition' },
+    setStopOnValidationError: { action: 'setStopOnValidationError' },
+    recompileFromScratch: { action: 'recompileFromScratch' },
+    stopCompile: { action: 'stopCompile' },
+    setAnimateCompileDropdownArrow: {
+      action: 'setAnimateCompileDropdownArrow',
+    },
+  },
+  args,
+}
+
+export default meta

+ 15 - 0
services/web/frontend/stylesheets/bootstrap-5/components/dropdown-menu.scss

@@ -1,5 +1,20 @@
 .dropdown {
   display: inline-flex;
+
+  .no-left-border {
+    border-left: none;
+  }
+
+  .custom-toggle {
+    &::after {
+      content: none !important;
+    }
+
+    padding-left: var(--spacing-04);
+    padding-right: var(--spacing-05);
+    display: flex;
+    align-items: center;
+  }
 }
 
 .dropdown-header {

+ 40 - 0
services/web/frontend/stylesheets/bootstrap-5/pages/editor/compile-button.scss

@@ -29,3 +29,43 @@ $stripe-width: 20px;
     cursor: not-allowed;
   }
 }
+
+@keyframes compile-button-flash {
+  0%,
+  100% {
+    background: rgb(0 0 0 / 0%);
+  }
+
+  25%,
+  75% {
+    background: rgb(0 0 0 / 20%);
+  }
+}
+
+@keyframes compile-button-bounce {
+  0%,
+  50%,
+  100% {
+    transform: translateY(0);
+  }
+
+  25%,
+  75% {
+    transform: translateY(2px);
+  }
+}
+
+.detach-compile-button-animate {
+  animation-duration: 1.2s;
+  animation-fill-mode: both;
+  animation-timing-function: ease-in-out;
+  animation-name: compile-button-flash;
+}
+
+.detach-compile-button-animate .material-symbols {
+  animation-duration: 0.6s;
+  animation-delay: 0.4s;
+  animation-fill-mode: both;
+  animation-timing-function: cubic-bezier(0.76, 0, 0.24, 1);
+  animation-name: compile-button-bounce;
+}

+ 11 - 0
services/web/frontend/stylesheets/bootstrap-5/pages/editor/pdf.scss

@@ -26,6 +26,17 @@
 .toolbar-pdf-left {
   gap: var(--spacing-02);
 
+  .compile-button-group {
+    height: 28px;
+    border-top-left-radius: 0;
+    border-bottom-left-radius: 0;
+    background-color: var(--bg-accent-01);
+
+    .btn-primary:hover {
+      z-index: auto; // prevents border from being hidden
+    }
+  }
+
   .dropdown > .btn {
     border-top-left-radius: 0;
     border-bottom-left-radius: 0;