Merge pull request #21815 from overleaf/td-bs5-references-search

[BS5] Migrate references search modal

GitOrigin-RevId: 65496840e32af09e5ae7351aa1789ebf5cac5083
This commit is contained in:
Tim Down 2024-11-14 11:50:20 +00:00 committed by Copybot
parent 73b17dd694
commit daaff1d9c6
9 changed files with 127 additions and 19 deletions

View file

@ -1,13 +1,16 @@
import { forwardRef } from 'react' import { forwardRef } from 'react'
import { Form, FormControlProps } from 'react-bootstrap-5' import {
Form,
FormControlProps as BS5FormControlProps,
} from 'react-bootstrap-5'
import classnames from 'classnames' import classnames from 'classnames'
type OLFormControlProps = FormControlProps & { type FormControlProps = BS5FormControlProps & {
prepend?: React.ReactNode prepend?: React.ReactNode
append?: React.ReactNode append?: React.ReactNode
} }
const FormControl = forwardRef<HTMLInputElement, OLFormControlProps>( const FormControl = forwardRef<HTMLInputElement, FormControlProps>(
({ prepend, append, className, ...props }, ref) => { ({ prepend, append, className, ...props }, ref) => {
if (prepend || append) { if (prepend || append) {
const wrapperClassNames = classnames('form-control-wrapper', { const wrapperClassNames = classnames('form-control-wrapper', {

View file

@ -3,11 +3,14 @@ import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
import FormControl from '@/features/ui/components/bootstrap-5/form/form-control' import FormControl from '@/features/ui/components/bootstrap-5/form/form-control'
import BS3FormControl from '@/features/ui/components/bootstrap-3/form/form-control' import BS3FormControl from '@/features/ui/components/bootstrap-3/form/form-control'
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import OLSpinner from '@/features/ui/components/ol/ol-spinner'
import Icon from '@/shared/components/icon'
type OLFormControlProps = ComponentProps<typeof FormControl> & { type OLFormControlProps = ComponentProps<typeof FormControl> & {
bs3Props?: Record<string, unknown> bs3Props?: Record<string, unknown>
'data-ol-dirty'?: unknown 'data-ol-dirty'?: unknown
'main-field'?: any // For the CM6's benefit in the editor search panel 'main-field'?: any // For the CM6's benefit in the editor search panel
loading?: boolean
} }
type BS3FormControlProps = ComponentProps<typeof BS3FormControl> & { type BS3FormControlProps = ComponentProps<typeof BS3FormControl> & {
@ -16,7 +19,7 @@ type BS3FormControlProps = ComponentProps<typeof BS3FormControl> & {
const OLFormControl = forwardRef<HTMLInputElement, OLFormControlProps>( const OLFormControl = forwardRef<HTMLInputElement, OLFormControlProps>(
(props, ref) => { (props, ref) => {
const { bs3Props, ...rest } = props const { bs3Props, append, ...rest } = props
// Use a callback so that the ref passed to the BS3 FormControl is stable // Use a callback so that the ref passed to the BS3 FormControl is stable
const bs3InputRef = useCallback( const bs3InputRef = useCallback(
@ -55,7 +58,6 @@ const OLFormControl = forwardRef<HTMLInputElement, OLFormControlProps>(
onBlur: rest.onBlur as BS3FormControlProps['onBlur'], onBlur: rest.onBlur as BS3FormControlProps['onBlur'],
onInvalid: rest.onInvalid as BS3FormControlProps['onInvalid'], onInvalid: rest.onInvalid as BS3FormControlProps['onInvalid'],
prepend: rest.prepend, prepend: rest.prepend,
append: rest.append,
size: rest.htmlSize, size: rest.htmlSize,
'main-field': rest['main-field'], 'main-field': rest['main-field'],
...bs3Props, ...bs3Props,
@ -69,8 +71,19 @@ const OLFormControl = forwardRef<HTMLInputElement, OLFormControlProps>(
return ( return (
<BootstrapVersionSwitcher <BootstrapVersionSwitcher
bs3={<BS3FormControl {...bs3FormControlProps} />} bs3={
bs5={<FormControl ref={ref} {...rest} />} <BS3FormControl
{...bs3FormControlProps}
append={rest.loading ? <Icon type="spinner" spin /> : append}
/>
}
bs5={
<FormControl
ref={ref}
{...rest}
append={rest.loading ? <OLSpinner size="sm" /> : append}
/>
}
/> />
) )
} }

View file

@ -2,27 +2,38 @@ import { FormGroupProps } from 'react-bootstrap-5'
import { import {
FormGroup as BS3FormGroup, FormGroup as BS3FormGroup,
FormGroupProps as BS3FormGroupProps, FormGroupProps as BS3FormGroupProps,
FormControl,
} from 'react-bootstrap' } from 'react-bootstrap'
import FormGroup from '@/features/ui/components/bootstrap-5/form/form-group' import FormGroup from '@/features/ui/components/bootstrap-5/form/form-group'
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import classNames from 'classnames'
type OLFormGroupProps = FormGroupProps & { type OLFormGroupProps = FormGroupProps & {
bs3Props?: Record<string, unknown> bs3Props?: {
withFeedback?: boolean
hiddenLabel?: boolean
validationState?: BS3FormGroupProps['validationState']
}
} }
function OLFormGroup(props: OLFormGroupProps) { function OLFormGroup(props: OLFormGroupProps) {
const { bs3Props, className, ...rest } = props const { bs3Props, className, ...rest } = props
const { withFeedback, hiddenLabel, ...bs3PropsRest } = bs3Props || {}
const bs3FormGroupProps: BS3FormGroupProps = { const bs3FormGroupProps: BS3FormGroupProps = {
children: rest.children,
controlId: rest.controlId, controlId: rest.controlId,
className, className: classNames(className, { 'hidden-label': hiddenLabel }),
...bs3Props, ...bs3PropsRest,
} }
return ( return (
<BootstrapVersionSwitcher <BootstrapVersionSwitcher
bs3={<BS3FormGroup {...bs3FormGroupProps} />} bs3={
<BS3FormGroup {...bs3FormGroupProps}>
{rest.children}
{withFeedback ? <FormControl.Feedback /> : null}
</BS3FormGroup>
}
bs5={<FormGroup className={className} {...rest} />} bs5={<FormGroup className={className} {...rest} />}
/> />
) )

View file

@ -3,6 +3,7 @@ import classnames from 'classnames'
import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
import MaterialIcon from '@/shared/components/material-icon' import MaterialIcon from '@/shared/components/material-icon'
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import { bsVersion } from '@/features/utils/bootstrap-5'
type TooltipProps = { type TooltipProps = {
id: string id: string
@ -30,7 +31,9 @@ const BetaBadge: FC<{
}} }}
> >
<a href={url} target="_blank" rel="noopener noreferrer"> <a href={url} target="_blank" rel="noopener noreferrer">
<span className="sr-only">{tooltip.text}</span> <span className={bsVersion({ bs5: 'visually-hidden', bs3: 'sr-only' })}>
{tooltip.text}
</span>
<BootstrapVersionSwitcher <BootstrapVersionSwitcher
bs3={<span className={classnames('badge', badgeClass)} />} bs3={<span className={classnames('badge', badgeClass)} />}
bs5={ bs5={

View file

@ -519,8 +519,7 @@ CodeMirror
padding-left: 38px; padding-left: 38px;
padding-right: 38px; padding-right: 38px;
margin: auto; margin: auto;
background: white; background: rgba(255, 255, 255, 0.95);
opacity: 0.95;
border-radius: 8px; border-radius: 8px;
.message { .message {
margin-top: 15px; margin-top: 15px;
@ -531,9 +530,6 @@ CodeMirror
text-align: left; text-align: left;
} }
} }
a.btn {
opacity: 1;
}
} }
} }
.search-form { .search-form {

View file

@ -147,7 +147,6 @@
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 0;
} }
.form-control-start-icon { .form-control-start-icon {

View file

@ -27,6 +27,7 @@
@import 'editor/review-panel-new'; @import 'editor/review-panel-new';
@import 'editor/table-generator-column-width-modal'; @import 'editor/table-generator-column-width-modal';
@import 'editor/math-preview'; @import 'editor/math-preview';
@import 'editor/references-search';
@import 'website-redesign'; @import 'website-redesign';
@import 'group-settings'; @import 'group-settings';
@import 'templates-v2'; @import 'templates-v2';

View file

@ -0,0 +1,76 @@
.references-search-modal {
.references-search-upgrade-prompt {
padding: var(--spacing-08);
padding-bottom: var(--spacing-11);
.upgrade-prompt {
text-align: center;
width: 400px;
padding: var(--spacing-06) var(--spacing-10);
margin: auto;
background: rgb($white, 0.95);
border-radius: var(--border-radius-medium);
.message {
margin-top: var(--spacing-06);
&.call-to-action {
font-weight: bold;
}
ul.upgrade-benefits {
text-align: left;
li {
display: flex;
align-items: center;
}
}
}
}
}
.notification {
margin-top: var(--spacing-05);
margin-bottom: 0;
}
// search result items list
.search-results {
font-size: var(--font-size-01);
.no-results-message,
.too-many-results-message {
font-size: var(--font-size-03);
}
.search-results-scroll-container {
max-height: calc(100vh - 225px);
overflow-y: auto;
}
.search-result-hit {
&:hover {
cursor: pointer;
}
border-bottom: 1px solid var(--border-divider);
padding: var(--spacing-04);
&:last-child {
border-bottom: 1px solid transparent;
}
border-left: var(--spacing-02) solid transparent;
&.selected-search-result-hit {
color: var(--content-positive);
}
.hit-title {
font-size: var(--font-size-03);
font-style: italic;
}
}
}
}

View file

@ -159,6 +159,7 @@ output {
height: auto; height: auto;
border-radius: @border-radius-base; border-radius: @border-radius-base;
} }
// Smaller border-radius for `select` inputs // Smaller border-radius for `select` inputs
select& { select& {
border-radius: @border-radius-base; border-radius: @border-radius-base;
@ -295,6 +296,11 @@ input[type='checkbox'],
line-height: @input-height-base; line-height: @input-height-base;
text-align: center; text-align: center;
} }
// Position the feedback inside the input element when there's no label
&.hidden-label .form-control-feedback {
margin-top: -(@line-height-computed + 5);
}
} }
.has-feedback-left { .has-feedback-left {