From 1033e7384454d3f71e529bec2f4b6a7b02c24403 Mon Sep 17 00:00:00 2001 From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:10:50 +0200 Subject: [PATCH] Merge pull request #21477 from overleaf/ii-bs5-table-generator [web] BS5 table generator GitOrigin-RevId: 3fe10c05fa36f026c47ff4f54b15f5d76f7c509e --- .../table-generator/column-size-indicator.tsx | 14 +- .../components/table-generator/help-modal.tsx | 31 ++-- .../components/table-generator/tabular.tsx | 65 ++++---- .../toolbar/column-width-modal/modal.tsx | 148 ++++++++++-------- .../toolbar/toolbar-button-menu.tsx | 26 +-- .../toolbar/toolbar-button.tsx | 6 +- .../toolbar/toolbar-dropdown.tsx | 21 +-- .../extensions/visual/table-generator.ts | 40 ++--- .../visual-widgets/table-rendering-error.ts | 24 +-- .../shared/components/copy-to-clipboard.tsx | 73 +++------ .../stylesheets/bootstrap-5/pages/all.scss | 1 + .../table-generator-column-width-modal.scss | 13 ++ 12 files changed, 238 insertions(+), 224 deletions(-) create mode 100644 services/web/frontend/stylesheets/bootstrap-5/pages/editor/table-generator-column-width-modal.scss diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/column-size-indicator.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/column-size-indicator.tsx index 91e303efa0..7efcb3696e 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/column-size-indicator.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/column-size-indicator.tsx @@ -1,9 +1,8 @@ import MaterialIcon from '@/shared/components/material-icon' import { WidthSelection } from './toolbar/column-width-modal/column-width' import { useMemo } from 'react' -import { Button } from 'react-bootstrap' import { useTranslation } from 'react-i18next' -import Tooltip from '@/shared/components/tooltip' +import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import { useSelectionContext } from './contexts/selection-context' function roundIfNeeded(width: number) { @@ -32,7 +31,7 @@ export const ColumnSizeIndicator = ({ } return ( - - - + + ) } diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/help-modal.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/help-modal.tsx index 48d79b9f4d..fcf90e3b98 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/help-modal.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/help-modal.tsx @@ -1,5 +1,10 @@ -import { Button, Modal } from 'react-bootstrap' -import AccessibleModal from '../../../../shared/components/accessible-modal' +import OLModal, { + OLModalBody, + OLModalFooter, + OLModalHeader, + OLModalTitle, +} from '@/features/ui/components/ol/ol-modal' +import OLButton from '@/features/ui/components/ol/ol-button' import { useTabularContext } from './contexts/tabular-context' import { Trans, useTranslation } from 'react-i18next' @@ -9,15 +14,15 @@ export const TableGeneratorHelpModal = () => { if (!helpShown) return null return ( - - - {t('help')} - - + + {t('help')} + +

{ ]} />

-
- - - -
+ + + + {t('close')} + + + ) } diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/tabular.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/tabular.tsx index d466a66bf5..c012cda12e 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/tabular.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/tabular.tsx @@ -14,7 +14,6 @@ import { } from './contexts/editing-context' import { EditorView } from '@codemirror/view' import { ErrorBoundary } from 'react-error-boundary' -import { Alert, Button } from 'react-bootstrap' import { EditorSelection } from '@codemirror/state' import { CodeMirrorViewContext, @@ -22,13 +21,14 @@ import { } from '../codemirror-context' import { TableProvider } from './contexts/table-context' import { TabularProvider, useTabularContext } from './contexts/tabular-context' -import Icon from '../../../../shared/components/icon' import { BorderTheme } from './toolbar/commands' import { TableGeneratorHelpModal } from './help-modal' import { SplitTestProvider } from '../../../../shared/context/split-test-context' import { useTranslation } from 'react-i18next' import { ColumnWidthModal } from './toolbar/column-width-modal/modal' import { WidthSelection } from './toolbar/column-width-modal/column-width' +import Notification from '@/shared/components/notification' +import OLButton from '@/features/ui/components/ol/ol-button' export type ColumnDefinition = { alignment: 'left' | 'center' | 'right' | 'paragraph' @@ -198,35 +198,40 @@ export const TableRenderingError: FC<{ codePosition?: number }> = ({ view, codePosition }) => { const { t } = useTranslation() + return ( - - - - -
-

- {t('sorry_your_table_cant_be_displayed_at_the_moment')} -

-

- {t( - 'this_could_be_because_we_cant_support_some_elements_of_the_table' - )} -

-
- {codePosition !== undefined && ( - - )} -
+ +

+ + {t('sorry_your_table_cant_be_displayed_at_the_moment')} + +

+

+ {t( + 'this_could_be_because_we_cant_support_some_elements_of_the_table' + )} +

+ + } + action={ + codePosition !== undefined ? ( + + view.dispatch({ + selection: EditorSelection.cursor(codePosition), + }) + } + size="sm" + > + {t('view_code')} + + ) : undefined + } + /> ) } diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/column-width-modal/modal.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/column-width-modal/modal.tsx index 2894b07230..1e27ab72ee 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/column-width-modal/modal.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/column-width-modal/modal.tsx @@ -1,5 +1,3 @@ -import AccessibleModal from '@/shared/components/accessible-modal' -import { Button, Modal, Form, FormGroup } from 'react-bootstrap' import { useTabularContext } from '../../contexts/tabular-context' import { Select } from '@/shared/components/select' import { Trans, useTranslation } from 'react-i18next' @@ -18,8 +16,24 @@ import { setColumnWidth } from '../commands' import { UNITS, WidthSelection, WidthUnit } from './column-width' import { useCodeMirrorViewContext } from '../../../codemirror-context' import { CopyToClipboard } from '@/shared/components/copy-to-clipboard' -import Tooltip from '@/shared/components/tooltip' import Icon from '@/shared/components/icon' +import OLModal, { + OLModalBody, + OLModalFooter, + OLModalHeader, + OLModalTitle, +} from '@/features/ui/components/ol/ol-modal' +import OLTooltip from '@/features/ui/components/ol/ol-tooltip' +import OLButton from '@/features/ui/components/ol/ol-button' +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 OLCol from '@/features/ui/components/ol/ol-col' +import OLRow from '@/features/ui/components/ol/ol-row' +import OLForm from '@/features/ui/components/ol/ol-form' +import { bsVersion } from '@/features/utils/bootstrap-5' +import MaterialIcon from '@/shared/components/material-icon' +import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' type UnitDescription = { label: string; tooltip?: string } | undefined @@ -93,7 +107,7 @@ const ColumnWidthModalBody = () => { } }, [columnWidthModalShown, selection, table]) - const onSubmit: FormEventHandler
= useCallback( + const onSubmit: FormEventHandler = useCallback( e => { e.preventDefault() if (selection && currentUnit) { @@ -121,60 +135,67 @@ const ColumnWidthModalBody = () => { ) return ( - - - - {t('set_column_width')} - - -
- - - setCurrentWidth(e.target.value)} - type={currentUnit === 'custom' ? 'text' : 'number'} - className="form-control" - ref={inputRef} - /> - - - +  {t('length_unit')} + + } + items={UNITS} + itemToKey={x => x ?? ''} + itemToString={x => (x === 'custom' ? t('custom') : (x ?? ''))} + onSelectedItemChanged={item => setCurrentUnit(item)} + defaultItem={currentUnit} + /> + + + {unitHelp && (

{unitHelp.label}{' '} {unitHelp.tooltip && ( - - - + + } + bs5={ + + } + /> + + )}

)} @@ -196,22 +217,25 @@ const ColumnWidthModalBody = () => { tooltipId="table-generator-array-copy" />
-
- - - - - -
+ + + + { + closeColumnWidthModal() + }} + > + {t('cancel')} + + + {t('ok')} + + + ) } diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button-menu.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button-menu.tsx index e70bf1dd0e..231db0e9f4 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button-menu.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button-menu.tsx @@ -1,9 +1,12 @@ import { FC, memo, useRef } from 'react' import useDropdown from '../../../../../shared/hooks/use-dropdown' -import { ListGroup, Overlay, Popover } from 'react-bootstrap' -import Tooltip from '../../../../../shared/components/tooltip' +import OLListGroup from '@/features/ui/components/ol/ol-list-group' +import OLOverlay from '@/features/ui/components/ol/ol-overlay' +import OLPopover from '@/features/ui/components/ol/ol-popover' +import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import MaterialIcon from '../../../../../shared/components/material-icon' import { useTabularContext } from '../contexts/tabular-context' +import { bsVersion } from '@/features/utils/bootstrap-5' export const ToolbarButtonMenu: FC<{ id: string @@ -45,36 +48,37 @@ export const ToolbarButtonMenu: FC<{ ) const overlay = tableContainerRef.current && ( - onToggle(false)} > - - { onToggle(false) }} + className={bsVersion({ bs5: 'd-block' })} > {children} - - - + + + ) return ( <> - + {overlay} ) diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx index a745999ab4..6368da025b 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-button.tsx @@ -1,7 +1,7 @@ import { EditorView } from '@codemirror/view' import classNames from 'classnames' import { memo, useCallback } from 'react' -import Tooltip from '../../../../../shared/components/tooltip' +import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import MaterialIcon from '../../../../../shared/components/material-icon' import { useCodeMirrorViewContext } from '../../codemirror-context' import { emitTableGeneratorEvent } from '../analytics' @@ -64,12 +64,12 @@ export const ToolbarButton = memo<{ disabled && disabledLabel ?
{disabledLabel}
:
{label}
return ( - {button} - + ) }) diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx index 3c7d2e0aa1..6fab575472 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/toolbar-dropdown.tsx @@ -1,8 +1,9 @@ import { ButtonHTMLAttributes, FC, useCallback, useRef } from 'react' import useDropdown from '../../../../../shared/hooks/use-dropdown' -import { Overlay, Popover } from 'react-bootstrap' +import OLTooltip from '@/features/ui/components/ol/ol-tooltip' +import OLOverlay from '@/features/ui/components/ol/ol-overlay' +import OLPopover from '@/features/ui/components/ol/ol-popover' import MaterialIcon from '../../../../../shared/components/material-icon' -import Tooltip from '../../../../../shared/components/tooltip' import { useTabularContext } from '../contexts/tabular-context' import { emitTableGeneratorEvent } from '../analytics' import { useCodeMirrorViewContext } from '../../codemirror-context' @@ -55,17 +56,17 @@ export const ToolbarDropdown: FC<{ ) const overlay = tabularRef.current && ( - onToggle(false)} > - {children} - - + + ) if (tooltip || (disabled && disabledTooltip)) { return ( <> - + {overlay} ) diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/table-generator.ts b/services/web/frontend/js/features/source-editor/extensions/visual/table-generator.ts index 4a11cbb896..4d6cd51ec5 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/table-generator.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/table-generator.ts @@ -1,4 +1,5 @@ import { EditorView } from '@codemirror/view' +import { isBootstrap5 } from '@/features/utils/bootstrap-5' export const tableGeneratorTheme = EditorView.baseTheme({ '&dark .table-generator': { @@ -309,14 +310,14 @@ export const tableGeneratorTheme = EditorView.baseTheme({ '.table-generator-button-menu-popover': { 'background-color': 'var(--table-generator-toolbar-background) !important', - '& .popover-content': { + '& .popover-content, & .popover-body': { padding: '4px', }, '& .list-group': { margin: '0', padding: '0', }, - '& > .arrow': { + '& > .arrow, & > .popover-arrow': { display: 'none', }, }, @@ -348,7 +349,7 @@ export const tableGeneratorTheme = EditorView.baseTheme({ gap: '6px', 'align-items': 'flex-start', 'max-width': '240px', - 'font-family': 'Lato', + 'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato', '& .info-icon': { flex: ' 0 0 24px', @@ -369,7 +370,7 @@ export const tableGeneratorTheme = EditorView.baseTheme({ display: 'flex', 'align-items': 'center', 'justify-content': 'space-between', - 'font-family': 'Lato', + 'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato', height: '36px', '&:not(:first-child)': { @@ -387,11 +388,11 @@ export const tableGeneratorTheme = EditorView.baseTheme({ 'max-width': '300px', background: 'var(--table-generator-toolbar-background) !important', - '& .popover-content': { + '& .popover-content, & .popover-body': { padding: '0', }, - '& > .arrow': { + '& > .arrow, & > .popover-arrow': { display: 'none', }, }, @@ -416,7 +417,7 @@ export const tableGeneratorTheme = EditorView.baseTheme({ 'column-gap': '8px', 'align-self': 'stretch', padding: '12px 8px', - 'font-family': 'Lato', + 'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato', '& .table-generator-button-label': { 'align-self': 'stretch', @@ -482,32 +483,9 @@ export const tableGeneratorTheme = EditorView.baseTheme({ '.ol-cm-environment-table.table-generator-error-container, .ol-cm-environment-table.ol-cm-tabular': { background: 'rgba(125, 125, 125, 0.05)', + 'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato', }, - '.table-generator-error': { - background: 'var(--table-generator-error-background)', - display: 'flex', - 'justify-content': 'space-between', - color: 'var(--table-generator-error-color)', - border: '1px solid var(--table-generator-error-border-color)', - 'font-family': 'Lato', - margin: '0 16px 0 16px', - '& .table-generator-error-message': { - flex: '1 1 auto', - }, - '& .table-generator-error-message-header': { - fontWeight: 'bold', - marginBottom: '2px', - }, - '& .table-generator-error-show-code-button': { - alignSelf: 'baseline', - }, - '& .table-generator-error-icon': { - color: '#3265B2', - 'margin-right': '12px', - }, - }, - '.table-generator-filler-row': { border: 'none !important', '& td': { diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/table-rendering-error.ts b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/table-rendering-error.ts index b5bffce6d4..63ad0a297a 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/table-rendering-error.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/table-rendering-error.ts @@ -10,28 +10,34 @@ export class TableRenderingErrorWidget extends WidgetType { toDOM(view: EditorView): HTMLElement { const warning = document.createElement('div') - warning.classList.add('table-generator-error', 'alert') + warning.classList.add('notification', 'notification-type-info') warning.role = 'alert' - const icon = document.createElement('span') - icon.classList.add('table-generator-error-icon') - const iconType = document.createElement('i') - iconType.classList.add('fa', 'fa-info-circle') + const icon = document.createElement('div') + icon.classList.add('notification-icon') + const iconType = document.createElement('span') + iconType.classList.add('material-symbols') + iconType.setAttribute('aria-hidden', 'true') + iconType.textContent = 'info' icon.appendChild(iconType) warning.appendChild(icon) + const messageWrapper = document.createElement('div') + messageWrapper.classList.add('notification-content-and-cta') const message = document.createElement('div') - message.classList.add('table-generator-error-message') + message.classList.add('notification-content') const messageHeader = document.createElement('p') - messageHeader.classList.add('table-generator-error-message-header') - messageHeader.textContent = view.state.phrase( + const messageHeaderInner = document.createElement('strong') + messageHeaderInner.textContent = view.state.phrase( 'sorry_your_table_cant_be_displayed_at_the_moment' ) + messageHeader.appendChild(messageHeaderInner) const messageBody = document.createElement('p') messageBody.textContent = view.state.phrase( 'this_could_be_because_we_cant_support_some_elements_of_the_table' ) message.appendChild(messageHeader) message.appendChild(messageBody) - warning.appendChild(message) + messageWrapper.appendChild(message) + warning.appendChild(messageWrapper) const element = document.createElement('div') element.classList.add('table-generator', 'table-generator-error-container') element.appendChild(warning) diff --git a/services/web/frontend/js/shared/components/copy-to-clipboard.tsx b/services/web/frontend/js/shared/components/copy-to-clipboard.tsx index 1395ed5998..517d8ba9ff 100644 --- a/services/web/frontend/js/shared/components/copy-to-clipboard.tsx +++ b/services/web/frontend/js/shared/components/copy-to-clipboard.tsx @@ -1,4 +1,4 @@ -import { FC, memo, MouseEventHandler, useCallback, useState } from 'react' +import { memo, useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import OLButton from '@/features/ui/components/ol/ol-button' import OLTooltip from '@/features/ui/components/ol/ol-tooltip' @@ -33,54 +33,31 @@ export const CopyToClipboard = memo<{ description={copied ? `${t('copied')}!` : t('copy')} overlayProps={{ delay: copied ? 1000 : 250 }} > - - {kind === 'text' ? ( - - ) : ( - - )} - + {kind === 'text' ? ( + + {t('copy')} + + ) : ( + + )} ) }) CopyToClipboard.displayName = 'CopyToClipboard' - -const TextButton: FC<{ - handleClick: MouseEventHandler -}> = ({ handleClick }) => { - const { t } = useTranslation() - - return ( - - {t('copy')} - - ) -} - -const IconButton: FC<{ - handleClick: MouseEventHandler - copied: boolean -}> = ({ handleClick, copied }) => { - const { t } = useTranslation() - - return ( - - ) -} diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss index a8057b2401..1179c038a8 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss @@ -24,6 +24,7 @@ @import 'editor/share'; @import 'editor/tags-input'; @import 'editor/review-panel-new'; +@import 'editor/table-generator-column-width-modal'; @import 'website-redesign'; @import 'group-settings'; @import 'templates-v2'; diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/table-generator-column-width-modal.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/table-generator-column-width-modal.scss new file mode 100644 index 0000000000..48e1c1df63 --- /dev/null +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/table-generator-column-width-modal.scss @@ -0,0 +1,13 @@ +.table-generator-width-modal { + .table-generator-width-label { + width: 100%; + } + + .table-generator-usepackage-copy { + display: flex; + justify-content: space-between; + padding: var(--spacing-03) var(--spacing-05); + background: var(--bg-light-secondary); + border: 1px solid var(--border-primary-dark); + } +}