Просмотр исходного кода

Merge pull request #24332 from overleaf/dp-review-panel

Add review panel to new editor

GitOrigin-RevId: 918a29d81fcfaf60bc4af8a20a25545d79c4a3ed
David 1 год назад
Родитель
Сommit
9cd7e49daf
18 измененных файлов с 231 добавлено и 160 удалено
  1. 0 14
      services/web/frontend/js/features/ide-redesign/components/breadcrumbs.tsx
  2. 9 3
      services/web/frontend/js/features/ide-redesign/components/rail.tsx
  3. 4 12
      services/web/frontend/js/features/review-panel-new/components/review-panel-container.tsx
  4. 9 4
      services/web/frontend/js/features/review-panel-new/components/review-panel-header.tsx
  5. 3 1
      services/web/frontend/js/features/review-panel-new/components/review-panel.tsx
  6. 20 2
      services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx
  7. 3 2
      services/web/frontend/js/features/review-panel-new/hooks/use-more-comments.ts
  8. 30 0
      services/web/frontend/js/features/review-panel-new/hooks/use-review-panel-layout.ts
  9. 0 7
      services/web/frontend/js/features/review-panel-new/hooks/use-review-panel-styles.ts
  10. 0 4
      services/web/frontend/js/features/source-editor/components/codemirror-editor.tsx
  11. 57 38
      services/web/frontend/js/features/source-editor/components/codemirror-toolbar.tsx
  12. 36 56
      services/web/frontend/js/features/source-editor/extensions/breadcrumbs-panel.ts
  13. 1 1
      services/web/frontend/js/features/source-editor/extensions/index.ts
  14. 3 1
      services/web/frontend/js/features/source-editor/extensions/toolbar/toolbar-panel.ts
  15. 0 8
      services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts
  16. 1 0
      services/web/frontend/stylesheets/bootstrap-5/components/panel-heading.scss
  17. 39 1
      services/web/frontend/stylesheets/bootstrap-5/pages/editor/review-panel-new.scss
  18. 16 6
      services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar.scss

+ 0 - 14
services/web/frontend/js/features/ide-redesign/components/breadcrumbs.tsx

@@ -3,14 +3,10 @@ import { useFileTreeOpenContext } from '@/features/ide-react/context/file-tree-o
 import { useOutlineContext } from '@/features/ide-react/context/outline-context'
 import useNestedOutline from '@/features/outline/hooks/use-nested-outline'
 import getChildrenLines from '@/features/outline/util/get-children-lines'
-import { useCodeMirrorViewContext } from '@/features/source-editor/components/codemirror-context'
 import MaterialIcon from '@/shared/components/material-icon'
 import { useFileTreeData } from '@/shared/context/file-tree-data-context'
-import { getPanel } from '@codemirror/view'
 import { Fragment, useMemo } from 'react'
 import { Outline } from '@/features/source-editor/utils/tree-operations/outline'
-import { createPortal } from 'react-dom'
-import { createBreadcrumbsPanel } from '@/features/source-editor/extensions/breadcrumbs-panel'
 
 const constructOutlineHierarchy = (
   items: Outline[],
@@ -37,16 +33,6 @@ const constructOutlineHierarchy = (
 }
 
 export default function Breadcrumbs() {
-  const view = useCodeMirrorViewContext()
-  const panel = getPanel(view, createBreadcrumbsPanel)
-
-  if (!panel) {
-    return null
-  }
-  return createPortal(<BreadcrumbsContent />, panel.dom)
-}
-
-function BreadcrumbsContent() {
   const { openEntity } = useFileTreeOpenContext()
   const { fileTreeData } = useFileTreeData()
   const outline = useNestedOutline()

+ 9 - 3
services/web/frontend/js/features/ide-redesign/components/rail.tsx

@@ -36,7 +36,7 @@ import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
 type RailElement = {
   icon: AvailableUnfilledIcon
   key: RailTabKey
-  component: ReactElement
+  component: ReactElement | null
   indicator?: ReactElement
   title: string
   hide?: boolean
@@ -111,7 +111,7 @@ export const RailLayout = () => {
         key: 'review-panel',
         icon: 'rate_review',
         title: t('review_panel'),
-        component: <>Review panel</>,
+        component: null,
       },
       {
         key: 'chat',
@@ -169,6 +169,8 @@ export const RailLayout = () => {
     [setSelectedTab, selectedTab, setIsOpen, togglePane, railTabs]
   )
 
+  const isReviewPanelOpen = selectedTab === 'review-panel'
+
   return (
     <TabContainer
       mountOnEnter // Only render when necessary (so that we can lazy load tab content)
@@ -200,6 +202,7 @@ export const RailLayout = () => {
       </div>
       <Panel
         id="ide-redesign-sidebar-panel"
+        className={classNames({ hidden: isReviewPanelOpen })}
         order={1}
         defaultSize={15}
         minSize={5}
@@ -211,7 +214,9 @@ export const RailLayout = () => {
       >
         {isHistoryView && <HistorySidebar />}
         <div
-          className={classNames('ide-rail-content', { hidden: isHistoryView })}
+          className={classNames('ide-rail-content', {
+            hidden: isHistoryView,
+          })}
         >
           <Tab.Content>
             {railTabs
@@ -225,6 +230,7 @@ export const RailLayout = () => {
         </div>
       </Panel>
       <HorizontalResizeHandle
+        className={classNames({ hidden: isReviewPanelOpen })}
         resizable
         hitAreaMargins={{ coarse: 0, fine: 0 }}
         onDoubleClick={togglePane}

+ 4 - 12
services/web/frontend/js/features/review-panel-new/components/review-panel-container.tsx

@@ -2,20 +2,15 @@ import ReactDOM from 'react-dom'
 import { useCodeMirrorViewContext } from '../../source-editor/components/codemirror-context'
 import { memo } from 'react'
 import ReviewPanel from './review-panel'
-import { useLayoutContext } from '@/shared/context/layout-context'
-import { useRangesContext } from '../context/ranges-context'
-import { useThreadsContext } from '@/features/review-panel-new/context/threads-context'
-import { hasActiveRange } from '@/features/review-panel-new/utils/has-active-range'
 import TrackChangesOnWidget from './track-changes-on-widget'
 import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
 import ReviewModeSwitcher from './review-mode-switcher'
 import getMeta from '@/utils/meta'
+import useReviewPanelLayout from '../hooks/use-review-panel-layout'
 
 function ReviewPanelContainer() {
   const view = useCodeMirrorViewContext()
-  const ranges = useRangesContext()
-  const threads = useThreadsContext()
-  const { reviewPanelOpen } = useLayoutContext()
+  const { showPanel, mini } = useReviewPanelLayout()
   const { wantTrackChanges } = useEditorManagerContext()
   const enableReviewerRole = getMeta('ol-isReviewerRoleEnabled')
 
@@ -23,16 +18,13 @@ function ReviewPanelContainer() {
     return null
   }
 
-  const hasCommentOrChange = hasActiveRange(ranges, threads)
-  const showPanel = reviewPanelOpen || hasCommentOrChange
-  const showTrackChangesWidget =
-    !enableReviewerRole && wantTrackChanges && !reviewPanelOpen
+  const showTrackChangesWidget = !enableReviewerRole && wantTrackChanges && mini
 
   return ReactDOM.createPortal(
     <>
       {showTrackChangesWidget && <TrackChangesOnWidget />}
       {enableReviewerRole && <ReviewModeSwitcher />}
-      {showPanel && <ReviewPanel mini={!reviewPanelOpen} />}
+      {showPanel && <ReviewPanel mini={mini} />}
     </>,
     view.scrollDOM
   )

+ 9 - 4
services/web/frontend/js/features/review-panel-new/components/review-panel-header.tsx

@@ -6,6 +6,8 @@ import { useLayoutContext } from '@/shared/context/layout-context'
 import { useTranslation } from 'react-i18next'
 import getMeta from '@/utils/meta'
 import { PanelHeading } from '@/shared/components/panel-heading'
+import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
+import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
 
 const isReviewerRoleEnabled = getMeta('ol-isReviewerRoleEnabled')
 
@@ -13,14 +15,17 @@ const ReviewPanelHeader: FC = () => {
   const [trackChangesMenuExpanded, setTrackChangesMenuExpanded] =
     useState(false)
   const { setReviewPanelOpen } = useLayoutContext()
+  const { setIsOpen: setRailIsOpen } = useRailContext()
   const { t } = useTranslation()
 
+  const newEditor = useIsNewEditorEnabled()
+  const handleClose = newEditor
+    ? () => setRailIsOpen(false)
+    : () => setReviewPanelOpen(false)
+
   return (
     <div className="review-panel-header">
-      <PanelHeading
-        title={t('review')}
-        handleClose={() => setReviewPanelOpen(false)}
-      >
+      <PanelHeading title={t('review')} handleClose={handleClose}>
         {isReviewerRoleEnabled && <ReviewPanelResolvedThreadsButton />}
       </PanelHeading>
       {!isReviewerRoleEnabled && (

+ 3 - 1
services/web/frontend/js/features/review-panel-new/components/review-panel.tsx

@@ -6,9 +6,11 @@ import { ReviewPanelOverview } from './review-panel-overview'
 import classnames from 'classnames'
 import { useReviewPanelStyles } from '@/features/review-panel-new/hooks/use-review-panel-styles'
 import { useReviewPanelViewContext } from '../context/review-panel-view-context'
+import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
 
 const ReviewPanel: FC<{ mini?: boolean }> = ({ mini = false }) => {
   const choosenSubView = useReviewPanelViewContext()
+  const newEditor = useIsNewEditorEnabled()
 
   const activeSubView = useMemo(
     () => (mini ? 'cur_file' : choosenSubView),
@@ -25,7 +27,7 @@ const ReviewPanel: FC<{ mini?: boolean }> = ({ mini = false }) => {
   return (
     <div className={className} style={style}>
       <div id="review-panel-inner" className="review-panel-inner">
-        {!mini && <ReviewPanelHeader />}
+        {!newEditor && !mini && <ReviewPanelHeader />}
 
         {activeSubView === 'cur_file' && <ReviewPanelCurrentFile />}
         {activeSubView === 'overview' && <ReviewPanelOverview />}

+ 20 - 2
services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx

@@ -35,6 +35,8 @@ import { useEditorManagerContext } from '@/features/ide-react/context/editor-man
 import classNames from 'classnames'
 import useEventListener from '@/shared/hooks/use-event-listener'
 import getMeta from '@/utils/meta'
+import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
+import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
 
 const isReviewerRoleEnabled = getMeta('ol-isReviewerRoleEnabled')
 const TRACK_CHANGES_ON_WIDGET_HEIGHT = 25
@@ -49,6 +51,9 @@ const ReviewTooltipMenu: FC = () => {
   const [show, setShow] = useState(true)
   const { setView } = useReviewPanelViewActionsContext()
   const { setReviewPanelOpen } = useLayoutContext()
+  const { setIsOpen: setRailIsOpen, setSelectedTab: setSelectedRailTab } =
+    useRailContext()
+  const newEditor = useIsNewEditorEnabled()
 
   const tooltipState = state.field(reviewTooltipStateField, false)?.tooltip
   const previousTooltipState = usePreviousValue(tooltipState)
@@ -65,7 +70,12 @@ const ReviewTooltipMenu: FC = () => {
       return
     }
 
-    setReviewPanelOpen(true)
+    if (newEditor) {
+      setSelectedRailTab('review-panel')
+      setRailIsOpen(true)
+    } else {
+      setReviewPanelOpen(true)
+    }
     setView('cur_file')
 
     const effects = isCursorNearViewportEdge(view, main.anchor)
@@ -77,7 +87,15 @@ const ReviewTooltipMenu: FC = () => {
 
     view.dispatch({ effects })
     setShow(false)
-  }, [setReviewPanelOpen, setView, setShow, view])
+  }, [
+    setReviewPanelOpen,
+    setView,
+    setShow,
+    view,
+    setSelectedRailTab,
+    setRailIsOpen,
+    newEditor,
+  ])
 
   useEventListener('add-new-review-comment', addComment)
 

+ 3 - 2
services/web/frontend/js/features/review-panel-new/hooks/use-more-comments.ts

@@ -8,7 +8,7 @@ import {
 import { DecorationSet, EditorView } from '@codemirror/view'
 import { EditorSelection } from '@codemirror/state'
 import _ from 'lodash'
-import { useLayoutContext } from '@/shared/context/layout-context'
+import useReviewPanelLayout from './use-review-panel-layout'
 
 const useMoreCommments = (
   changes: Change<EditOperation>[],
@@ -20,7 +20,8 @@ const useMoreCommments = (
   onMoreCommentsBelowClick: null | (() => void)
 } => {
   const view = useCodeMirrorViewContext()
-  const { reviewPanelOpen } = useLayoutContext()
+  const { showPanel, mini } = useReviewPanelLayout()
+  const reviewPanelOpen = showPanel && !mini
 
   const [positionAbove, setPositionAbove] = useState<number | null>(null)
   const [positionBelow, setPositionBelow] = useState<number | null>(null)

+ 30 - 0
services/web/frontend/js/features/review-panel-new/hooks/use-review-panel-layout.ts

@@ -0,0 +1,30 @@
+import { useLayoutContext } from '@/shared/context/layout-context'
+import { useRangesContext } from '../context/ranges-context'
+import { useThreadsContext } from '@/features/review-panel-new/context/threads-context'
+import { hasActiveRange } from '@/features/review-panel-new/utils/has-active-range'
+import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
+import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
+
+export default function useReviewPanelLayout(): {
+  showPanel: boolean
+  showHeader: boolean
+  mini: boolean
+} {
+  const ranges = useRangesContext()
+  const threads = useThreadsContext()
+  const { selectedTab: selectedRailTab, isOpen: railIsOpen } = useRailContext()
+  const { reviewPanelOpen: reviewPanelOpenOldEditor } = useLayoutContext()
+
+  const newEditor = useIsNewEditorEnabled()
+
+  const reviewPanelOpen = newEditor
+    ? selectedRailTab === 'review-panel' && railIsOpen
+    : reviewPanelOpenOldEditor
+
+  const hasCommentOrChange = hasActiveRange(ranges, threads)
+  const showPanel = reviewPanelOpen || !!hasCommentOrChange
+  const mini = !reviewPanelOpen
+  const showHeader = showPanel && !mini
+
+  return { showPanel, showHeader, mini }
+}

+ 0 - 7
services/web/frontend/js/features/review-panel-new/hooks/use-review-panel-styles.ts

@@ -30,13 +30,6 @@ export const useReviewPanelStyles = (mini: boolean) => {
     }))
   }, [])
 
-  useEffect(() => {
-    setStyles(value => ({
-      ...value,
-      '--review-panel-width': mini ? '22px' : '230px',
-    }))
-  }, [mini])
-
   useEffect(() => {
     if ('ResizeObserver' in window) {
       const scrollDomObserver = new window.ResizeObserver(entries =>

+ 0 - 4
services/web/frontend/js/features/source-editor/components/codemirror-editor.tsx

@@ -17,8 +17,6 @@ import {
   CodeMirrorViewContext,
 } from './codemirror-context'
 import MathPreviewTooltip from './math-preview-tooltip'
-import Breadcrumbs from '@/features/ide-redesign/components/breadcrumbs'
-import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
 import { useToolbarMenuBarEditorCommands } from '@/features/ide-redesign/hooks/use-toolbar-menu-editor-commands'
 
 // TODO: remove this when definitely no longer used
@@ -68,7 +66,6 @@ function CodeMirrorEditor() {
 }
 
 function CodeMirrorEditorComponents() {
-  const newEditor = useIsNewEditorEnabled()
   useToolbarMenuBarEditorCommands()
 
   return (
@@ -83,7 +80,6 @@ function CodeMirrorEditorComponents() {
           <Component key={path} />
         )
       )}
-      {newEditor && <Breadcrumbs />}
       <CodeMirrorCommandTooltip />
 
       <MathPreviewTooltip />

+ 57 - 38
services/web/frontend/js/features/source-editor/components/codemirror-toolbar.tsx

@@ -20,6 +20,11 @@ import { minimumListDepthForSelection } from '../utils/tree-operations/ancestors
 import { debugConsole } from '@/utils/debugging'
 import { useTranslation } from 'react-i18next'
 import { ToggleSearchButton } from '@/features/source-editor/components/toolbar/toggle-search-button'
+import ReviewPanelHeader from '@/features/review-panel-new/components/review-panel-header'
+import useReviewPanelLayout from '@/features/review-panel-new/hooks/use-review-panel-layout'
+import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
+import Breadcrumbs from '@/features/ide-redesign/components/breadcrumbs'
+import classNames from 'classnames'
 
 export const CodeMirrorToolbar = () => {
   const view = useCodeMirrorViewContext()
@@ -46,6 +51,9 @@ const Toolbar = memo(function Toolbar() {
 
   const listDepth = minimumListDepthForSelection(state)
 
+  const newEditor = useIsNewEditorEnabled()
+  const { showHeader: showReviewPanelHeader } = useReviewPanelLayout()
+
   const {
     open: overflowOpen,
     onToggle: setOverflowOpen,
@@ -131,50 +139,61 @@ const Toolbar = memo(function Toolbar() {
   const showActions = !state.readOnly && !insideTable
 
   return (
-    <div
-      role="toolbar"
-      aria-label={t('toolbar_editor')}
-      className="ol-cm-toolbar toolbar-editor"
-      ref={elementRef}
-    >
-      <EditorSwitch />
-      {showActions && (
-        <ToolbarItems
-          state={state}
-          languageName={languageName}
-          visual={visual}
-          listDepth={listDepth}
-        />
-      )}
-
-      <div className="ol-cm-toolbar-button-group ol-cm-toolbar-stretch">
-        {showActions && (
-          <ToolbarOverflow
-            overflowed={overflowed}
-            overflowOpen={overflowOpen}
-            setOverflowOpen={setOverflowOpen}
-            overflowRef={overflowRef}
-          >
+    <>
+      {newEditor && showReviewPanelHeader && <ReviewPanelHeader />}
+      <div
+        id="ol-cm-toolbar-wrapper"
+        className={classNames('ol-cm-toolbar-wrapper', {
+          'ol-cm-toolbar-wrapper-indented': newEditor && showReviewPanelHeader,
+        })}
+      >
+        <div
+          role="toolbar"
+          aria-label={t('toolbar_editor')}
+          className="ol-cm-toolbar toolbar-editor"
+          ref={elementRef}
+        >
+          <EditorSwitch />
+          {showActions && (
             <ToolbarItems
               state={state}
-              overflowed={overflowedItemsRef.current}
               languageName={languageName}
               visual={visual}
               listDepth={listDepth}
             />
-          </ToolbarOverflow>
-        )}
-      </div>
-
-      <div
-        className="ol-cm-toolbar-button-group ol-cm-toolbar-end"
-        ref={handleButtons}
-      >
-        <ToggleSearchButton state={state} />
-        <SwitchToPDFButton />
-        <DetacherSynctexControl />
-        <DetachCompileButtonWrapper />
+          )}
+
+          <div className="ol-cm-toolbar-button-group ol-cm-toolbar-stretch">
+            {showActions && (
+              <ToolbarOverflow
+                overflowed={overflowed}
+                overflowOpen={overflowOpen}
+                setOverflowOpen={setOverflowOpen}
+                overflowRef={overflowRef}
+              >
+                <ToolbarItems
+                  state={state}
+                  overflowed={overflowedItemsRef.current}
+                  languageName={languageName}
+                  visual={visual}
+                  listDepth={listDepth}
+                />
+              </ToolbarOverflow>
+            )}
+          </div>
+
+          <div
+            className="ol-cm-toolbar-button-group ol-cm-toolbar-end"
+            ref={handleButtons}
+          >
+            <ToggleSearchButton state={state} />
+            <SwitchToPDFButton />
+            <DetacherSynctexControl />
+            <DetachCompileButtonWrapper />
+          </div>
+        </div>
+        {newEditor && <Breadcrumbs />}
       </div>
-    </div>
+    </>
   )
 })

+ 36 - 56
services/web/frontend/js/features/source-editor/extensions/breadcrumbs-panel.ts

@@ -1,61 +1,41 @@
-import { canUseNewEditor } from '@/features/ide-redesign/utils/new-editor-utils'
-import { Compartment, Extension, TransactionSpec } from '@codemirror/state'
-import { EditorView, showPanel } from '@codemirror/view'
-
-export function createBreadcrumbsPanel() {
-  const dom = document.createElement('div')
-  dom.classList.add('ol-cm-breadcrumbs-portal')
-  return { dom, top: true }
-}
-
-const breadcrumbsTheme = EditorView.baseTheme({
-  '.ol-cm-breadcrumbs': {
-    display: 'flex',
-    alignItems: 'center',
-    gap: 'var(--spacing-01)',
-    fontSize: 'var(--font-size-01)',
-    padding: 'var(--spacing-02)',
-    overflow: 'auto',
-    scrollbarWidth: 'thin',
-    '& > *': {
-      flexShrink: '0',
-    },
-  },
-  '&light .ol-cm-breadcrumbs': {
-    color: 'var(--content-secondary)',
-    backgroundColor: 'var(--bg-light-primary)',
-    borderBottom: '1px solid #ddd',
-  },
-  '&light .ol-cm-breadcrumb-chevron': {
-    color: 'var(--neutral-30)',
-  },
-  '&dark .ol-cm-breadcrumbs': {
-    color: 'var(--content-secondary-dark)',
-    backgroundColor: 'var(--bg-dark-primary)',
-  },
-  '&dark .ol-cm-breadcrumb-chevron': {
-    color: 'var(--neutral-50)',
-  },
-})
-
-const breadcrumbsConf = new Compartment()
-
-const breadcrumbsEnabled: Extension = [
-  showPanel.of(createBreadcrumbsPanel),
-  breadcrumbsTheme,
-]
-const breadcrumbsDisabled: Extension = []
-
-export const setBreadcrumbsEnabled = (enabled: boolean): TransactionSpec => ({
-  effects: breadcrumbsConf.reconfigure(
-    enabled ? breadcrumbsEnabled : breadcrumbsDisabled
-  ),
-})
+import { EditorView } from '@codemirror/view'
 
 /**
  * A panel which contains the editor breadcrumbs
  */
-export const breadcrumbPanel = (enableNewEditor: boolean) => {
-  const enabled = canUseNewEditor() && enableNewEditor
-  return breadcrumbsConf.of(enabled ? breadcrumbsEnabled : breadcrumbsDisabled)
+export function breadcrumbPanel() {
+  return [
+    EditorView.editorAttributes.of({
+      style: '--breadcrumbs-height: 28px;',
+    }),
+    EditorView.baseTheme({
+      '.ol-cm-breadcrumbs-portal': {
+        display: 'flex',
+        pointerEvents: 'none !important',
+        '& > *': {
+          pointerEvents: 'all',
+        },
+      },
+      '.ol-cm-breadcrumbs': {
+        height: 'var(--breadcrumbs-height)',
+        flex: 1,
+        display: 'flex',
+        alignItems: 'center',
+        gap: 'var(--spacing-01)',
+        fontSize: 'var(--font-size-01)',
+        padding: 'var(--spacing-02)',
+        overflow: 'auto',
+        scrollbarWidth: 'thin',
+        '& > *': {
+          flexShrink: '0',
+        },
+      },
+      '&light .ol-cm-breadcrumb-chevron': {
+        color: 'var(--neutral-30)',
+      },
+      '&dark .ol-cm-breadcrumb-chevron': {
+        color: 'var(--neutral-50)',
+      },
+    }),
+  ]
 }

+ 1 - 1
services/web/frontend/js/features/source-editor/extensions/index.ts

@@ -148,7 +148,7 @@ export const createExtensions = (options: Record<string, any>): Extension[] => [
   mathPreview(options.settings.mathPreview),
   reviewTooltip(),
   toolbarPanel(),
-  breadcrumbPanel(options.settings.enableNewEditor),
+  breadcrumbPanel(),
   verticalOverflow(),
   highlightActiveLine(options.visual.visual),
   // The built-in extension that highlights the active line in the gutter.

+ 3 - 1
services/web/frontend/js/features/source-editor/extensions/toolbar/toolbar-panel.ts

@@ -23,9 +23,11 @@ export function createToolbarPanel() {
 }
 
 const toolbarTheme = EditorView.theme({
-  '.ol-cm-toolbar': {
+  '.ol-cm-toolbar-wrapper': {
     backgroundColor: 'var(--editor-toolbar-bg)',
     color: 'var(--toolbar-btn-color)',
+  },
+  '.ol-cm-toolbar': {
     flex: 1,
     display: 'flex',
     overflowX: 'hidden',

+ 0 - 8
services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts

@@ -53,7 +53,6 @@ import { useHunspell } from '@/features/source-editor/hooks/use-hunspell'
 import { Permissions } from '@/features/ide-react/types/permissions'
 import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
 import { useOnlineUsersContext } from '@/features/ide-react/context/online-users-context'
-import { setBreadcrumbsEnabled } from '../extensions/breadcrumbs-panel'
 
 function useCodeMirrorScope(view: EditorView) {
   const { fileTreeData } = useFileTreeData()
@@ -436,13 +435,6 @@ function useCodeMirrorScope(view: EditorView) {
     settingsRef.current.referencesSearchMode = referencesSearchMode
   }, [referencesSearchMode])
 
-  useEffect(() => {
-    settingsRef.current.enableNewEditor = enableNewEditor
-    window.setTimeout(() => {
-      view.dispatch(setBreadcrumbsEnabled(enableNewEditor))
-    })
-  }, [view, enableNewEditor])
-
   const emitSyncToPdf = useScopeEventEmitter('cursor:editor:syncToPdf')
 
   // select and scroll to position on editor:gotoLine event (from synctex)

+ 1 - 0
services/web/frontend/stylesheets/bootstrap-5/components/panel-heading.scss

@@ -11,6 +11,7 @@
 }
 
 .panel-heading {
+  color: var(--panel-heading-color);
   display: flex;
   align-items: center;
   padding: var(--spacing-03) var(--spacing-02);

+ 39 - 1
services/web/frontend/stylesheets/bootstrap-5/pages/editor/review-panel-new.scss

@@ -16,6 +16,8 @@ $rp-type-blue: #6b7797;
   --review-panel-empty-state-bg-color: var(--bg-light-primary);
   --review-panel-button-hover-bg-color: var(--bg-light-tertiary);
   --review-panel-border-color: var(--border-divider);
+  --review-panel-width: 230px;
+  --review-panel-width-mini: 24px;
 
   @include theme('default') {
     .ide-redesign-main {
@@ -32,6 +34,42 @@ $rp-type-blue: #6b7797;
   }
 }
 
+.ide-redesign-main {
+  .review-panel-container {
+    order: -1;
+  }
+
+  .review-panel-inner {
+    border-left: none;
+    border-right: 1px solid var(--border-divider);
+  }
+
+  .review-panel-header {
+    border-bottom: none;
+    flex: 0 0 var(--review-panel-width);
+  }
+
+  .review-panel-more-comments-button-container {
+    &.upwards {
+      top: calc(var(--review-panel-top) + 16px);
+    }
+  }
+
+  .review-panel-mini {
+    // This needs to have a higher z-index than the gutter
+    // so that the comment/change hover previews appear in
+    // front of the gutter
+    z-index: 201;
+
+    .review-panel-entry-hover {
+      .review-panel-entry-content {
+        left: auto;
+        right: -200px;
+      }
+    }
+  }
+}
+
 .review-panel-container {
   height: 100%;
   flex-shrink: 0;
@@ -646,7 +684,7 @@ del.review-panel-content-highlight {
   overflow: visible !important;
 
   .review-panel-inner {
-    width: 24px;
+    width: var(--review-panel-width-mini);
   }
 
   .review-panel-entry {

+ 16 - 6
services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar.scss

@@ -32,8 +32,22 @@
   --editor-toolbar-bg: var(--bg-dark-primary);
   --toolbar-filetree-bg-color: var(--neutral-80);
 
-  .cm-panels-top {
-    border-bottom: none;
+  .ol-cm-toolbar-portal {
+    display: flex;
+    align-items: center;
+    background-color: var(--editor-toolbar-bg);
+
+    .review-panel-header {
+      align-self: flex-start;
+    }
+  }
+
+  .ol-cm-toolbar-wrapper {
+    flex: 1;
+  }
+
+  .ol-cm-toolbar-wrapper-indented {
+    width: calc(100% - var(--review-panel-width));
   }
 }
 
@@ -64,10 +78,6 @@
     --toolbar-btn-hover-color: var(--white);
     --editor-toolbar-bg: var(--white);
     --toolbar-filetree-bg-color: var(--white);
-
-    .ol-cm-toolbar-portal {
-      border-bottom: 1px solid #ddd;
-    }
   }
 }