Merge pull request #20880 from overleaf/ii-bs5-submit-modal

[web] BS5 submit modal

GitOrigin-RevId: 1c66b3874844d9bdbe129acd18480af6e6e0ef6e
This commit is contained in:
Rebeka Dekany 2024-10-11 11:51:02 +02:00 committed by Copybot
parent f590d6d9a2
commit d71f82b1fa
8 changed files with 149 additions and 82 deletions

View file

@ -1,16 +1,20 @@
import { Card, CardBody } from 'react-bootstrap-5'
import { Card, CardBody, CardProps } from 'react-bootstrap-5'
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import { FC } from 'react'
// This wraps the Bootstrap 5 Card component but is restricted to the very
// basic way we're using it, which is as a container for page content. The
// Bootstrap 3 equivalent in our codebase is a div with class "card"
const OLCard: FC = ({ children }) => {
const OLCard: FC<CardProps> = ({ children, ...rest }) => {
return (
<BootstrapVersionSwitcher
bs3={<div className="card">{children}</div>}
bs3={
<div className="card" {...rest}>
{children}
</div>
}
bs5={
<Card>
<Card {...rest}>
<CardBody>{children}</CardBody>
</Card>
}

View file

@ -13,6 +13,7 @@ function OLFormLabel(props: OLFormLabelProps) {
children: rest.children,
htmlFor: rest.htmlFor,
srOnly: rest.visuallyHidden,
className: rest.className,
...bs3Props,
}

View file

@ -1,3 +1,4 @@
import { forwardRef } from 'react'
import { Form, FormSelectProps } from 'react-bootstrap-5'
import {
FormControl as BS3FormControl,
@ -10,7 +11,8 @@ type OLFormSelectProps = FormSelectProps & {
bs3Props?: Record<string, unknown>
}
function OLFormSelect(props: OLFormSelectProps) {
const OLFormSelect = forwardRef<HTMLSelectElement, OLFormSelectProps>(
(props, ref) => {
const { bs3Props, ...bs5Props } = props
const bs3FormSelectProps: BS3FormControlProps = {
@ -24,6 +26,13 @@ function OLFormSelect(props: OLFormSelectProps) {
required: bs5Props.required,
placeholder: bs5Props.placeholder,
className: bs5Props.className,
inputRef: (inputElement: HTMLInputElement) => {
if (typeof ref === 'function') {
ref(inputElement as unknown as HTMLSelectElement)
} else if (ref) {
ref.current = inputElement as unknown as HTMLSelectElement
}
},
...bs3Props,
}
@ -39,9 +48,11 @@ function OLFormSelect(props: OLFormSelectProps) {
{...extraProps}
/>
}
bs5={<Form.Select {...bs5Props} />}
bs5={<Form.Select ref={ref} {...bs5Props} />}
/>
)
}
)
OLFormSelect.displayName = 'OLFormSelect'
export default OLFormSelect

View file

@ -3,6 +3,7 @@ import Icon from './icon'
import { useEffect, useState } from 'react'
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import { Spinner } from 'react-bootstrap-5'
import { setTimeout } from '@/utils/window'
import classNames from 'classnames'
function LoadingSpinner({
@ -21,7 +22,7 @@ function LoadingSpinner({
const [show, setShow] = useState(false)
useEffect(() => {
const timer = window.setTimeout(() => {
const timer = setTimeout(() => {
setShow(true)
}, delay)

View file

@ -0,0 +1,3 @@
// Allows easy mocking of `window` methods in tests
export const setTimeout = window.setTimeout

View file

@ -1,46 +1,10 @@
.modal-body-publish {
@label-column-width: 10em;
@control-left-margin: 1em;
.form-control-box {
margin-bottom: 1.5ex;
margin-left: @control-left-margin;
label {
display: inline-block;
width: @label-column-width;
vertical-align: baseline;
}
label.checkbox-label {
width: auto;
}
.form-control {
display: inline-block;
width: 60%;
}
input[type='checkbox'] {
margin-right: 0.5em;
margin-top: 6px;
}
textarea {
vertical-align: baseline;
}
select {
padding-top: 1ex;
padding-bottom: 1ex;
padding-left: 1em;
padding-right: 1em;
}
option {
margin-left: -4px;
}
a.help {
margin-left: 0.6em;
}
}
.no-label {
margin-left: @label-column-width + @control-left-margin;
}
#search-input-container {
overflow: hidden;
margin: 5px 0 10px;
.gallery-export-license {
display: flex;
align-items: center;
}
.table-content-name {
width: 100%;
@ -70,6 +34,7 @@
.button-as-link {
color: green;
text-transform: none;
text-decoration: none;
background: none;
padding: 0;
border: none;
@ -101,12 +66,10 @@
border-radius: 9px;
}
.content-as-table {
.table-content,
.table-content > * {
display: table;
.table-content-main {
display: flex;
}
.table-content-icon {
float: left;
height: 100px;
width: 106px;
display: flex;
@ -118,7 +81,6 @@
}
}
.table-content-text {
float: right;
width: calc(~'100% - 106px');
vertical-align: top;
padding-left: 15px;

View file

@ -18,6 +18,7 @@
@import 'subscription';
@import 'editor/pdf';
@import 'editor/compile-button';
@import 'editor/publish-modal';
@import 'editor/share';
@import 'editor/tags-input';
@import 'website-redesign';

View file

@ -0,0 +1,84 @@
.modal-body-publish {
.gallery-export-license {
display: flex;
align-items: center;
}
.table-content-name {
width: 100%;
margin-bottom: var(--spacing-05);
font-weight: 300;
}
.table-content-category {
float: right;
font-weight: 300;
text-align: right;
font-style: italic;
width: 30%;
text-transform: capitalize;
}
.table-content-category ~ .table-content-name {
width: 70%;
display: inline-block;
}
.affix-content-title {
color: var(--neutral-40);
font-size: var(--spacing-07);
padding-left: var(--spacing-05);
}
.affix-subcontent {
margin: var(--spacing-03) 0 var(--spacing-11);
}
.card {
margin-top: calc(var(--line-height-03) / 2);
border: 1px solid var(--neutral-30);
border-radius: var(--border-radius-medium);
.card-body {
padding: calc(var(--line-height-03) / 2);
}
}
.content-as-table {
.table-content-main {
display: flex;
}
.table-content-icon {
height: 100px;
width: 106px;
display: flex;
align-items: flex-start;
overflow: hidden;
* {
border: 1px solid var(--neutral-10);
width: 100%;
}
}
.table-content-text {
width: calc(100% - 106px);
vertical-align: top;
padding-left: 15px;
}
.table-content-slogan {
height: 100px;
overflow: hidden;
}
.table-content-link {
padding-top: var(--spacing-05);
.btn {
white-space: normal;
}
}
}
}