Merge pull request #20715 from overleaf/ii-bs5-chat-pane

[web] BS5 chat pane

GitOrigin-RevId: 8587aca1372b4d2087863d492e702f04a31c23e2
This commit is contained in:
ilkin-overleaf 2024-10-09 15:13:39 +03:00 committed by Copybot
parent e05c181af4
commit 6c7ee8f778
9 changed files with 195 additions and 18 deletions

View file

@ -1,6 +1,7 @@
import PropTypes from 'prop-types'
import { useTranslation } from 'react-i18next'
import { Button, Alert } from 'react-bootstrap'
import OLNotification from '@/features/ui/components/ol/ol-notification'
import OLButton from '@/features/ui/components/ol/ol-button'
function ChatFallbackError({ reconnect }) {
const { t } = useTranslation()
@ -8,12 +9,12 @@ function ChatFallbackError({ reconnect }) {
return (
<aside className="chat">
<div className="chat-error">
<Alert bsStyle="danger">{t('chat_error')}</Alert>
<OLNotification type="error" content={t('chat_error')} />
{reconnect && (
<p className="text-center">
<Button bsStyle="info" type="button" onClick={reconnect}>
<OLButton variant="secondary" onClick={reconnect}>
{t('reconnect')}
</Button>
</OLButton>
</p>
)}
</div>

View file

@ -11,6 +11,9 @@ import withErrorBoundary from '../../../infrastructure/error-boundary'
import { FetchError } from '../../../infrastructure/fetch-json'
import { useChatContext } from '../context/chat-context'
import LoadingSpinner from '../../../shared/components/loading-spinner'
import { bsVersion } from '@/features/utils/bootstrap-5'
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
import MaterialIcon from '@/shared/components/material-icon'
const MessageList = lazy(() => import('./message-list'))
@ -79,7 +82,9 @@ const ChatPane = React.memo(function ChatPane() {
itemCount={messageContentCount}
>
<div>
<h2 className="sr-only">{t('chat')}</h2>
<h2 className={bsVersion({ bs3: 'sr-only', bs5: 'visually-hidden' })}>
{t('chat')}
</h2>
<Suspense fallback={<LoadingSpinner delay={500} />}>
{status === 'pending' && <LoadingSpinner delay={500} />}
{shouldDisplayPlaceholder && <Placeholder />}
@ -107,7 +112,10 @@ function Placeholder() {
<div className="first-message text-center">
{t('send_first_message')}
<br />
<Icon type="arrow-down" />
<BootstrapVersionSwitcher
bs3={<Icon type="arrow-down" />}
bs5={<MaterialIcon type="arrow_downward" />}
/>
</div>
</>
)

View file

@ -1,4 +1,5 @@
import { useTranslation } from 'react-i18next'
import { bsVersion } from '@/features/utils/bootstrap-5'
type MessageInputProps = {
resetUnreadMessages: () => void
@ -26,7 +27,10 @@ function MessageInput({ resetUnreadMessages, sendMessage }: MessageInputProps) {
return (
<form className="new-message">
<label htmlFor="chat-input" className="sr-only">
<label
htmlFor="chat-input"
className={bsVersion({ bs3: 'sr-only', bs5: 'visually-hidden' })}
>
{t('your_message_to_collaborators')}
</label>
<textarea

View file

@ -44,7 +44,7 @@ function LoadingSpinner({
animation="border"
aria-hidden="true"
role="status"
className="align-bottom"
className="align-middle"
/>
&nbsp;
{loadingText || t('loading')}

View file

@ -1,11 +1,5 @@
@new-message-height: 80px;
#chat-wrapper {
> .ui-layout-resizer > .ui-layout-toggler {
display: none !important;
}
}
.chat {
.loading {
font-family: @font-family-serif;
@ -140,7 +134,3 @@
}
}
}
.break-word {
word-break: break-all;
}

View file

@ -1,3 +1,4 @@
@import 'mixins';
@import 'variables';
@import 'variable-overrides';
@import 'themes-common-variables';

View file

@ -0,0 +1,7 @@
:root {
--editor-border-color: var(--neutral-80);
}
@include theme('light') {
--editor-border-color: var(--neutral-20);
}

View file

@ -11,6 +11,7 @@
@import 'editor/outline';
@import 'editor/file-tree';
@import 'editor/figure-modal';
@import 'editor/chat';
@import 'subscription';
@import 'editor/pdf';
@import 'editor/compile-button';

View file

@ -0,0 +1,165 @@
:root {
--chat-bg: var(--neutral-80);
--chat-color: var(--white);
--chat-instructions-color: var(--neutral-20);
--chat-new-message-bg: var(--neutral-70);
--chat-new-message-textarea-color: var(--neutral-90);
--chat-new-message-textarea-bg: var(--neutral-20);
--chat-message-date-color: var(--neutral-40);
--chat-message-name-color: var(--white);
}
@include theme('light') {
--chat-bg: var(--white);
--chat-color: var(--neutral-70);
--chat-instructions-color: var(--neutral-70);
--chat-new-message-bg: var(--neutral-10);
--chat-new-message-textarea-color: var(--neutral-90);
--chat-new-message-textarea-bg: var(--white);
--chat-message-date-color: var(--neutral-70);
--chat-message-name-color: var(--neutral-70);
}
.chat {
$new-message-height: 80px;
color: var(--chat-color);
.no-messages {
padding: calc(var(--line-height-03) / 2);
color: var(--chat-instructions-color);
}
.first-message {
position: absolute;
bottom: 0;
width: 100%;
padding: calc(var(--line-height-03) / 2);
color: var(--chat-instructions-color);
}
.chat-error {
position: absolute;
top: 0;
bottom: 0;
background-color: var(--chat-bg);
padding: calc(var(--line-height-03) / 2);
text-align: center;
}
.messages {
position: absolute;
inset: 0;
bottom: $new-message-height;
overflow-x: hidden;
background-color: var(--chat-bg);
li.message {
margin: calc(var(--line-height-03) / 2);
.date {
font-size: var(--font-size-01);
color: var(--chat-message-date-color);
margin-bottom: calc(var(--line-height-03) / 2);
text-align: right;
}
.message-wrapper {
.name {
font-size: var(--font-size-01);
color: var(--chat-message-name-color);
margin-bottom: var(--spacing-02);
min-height: 16px;
}
.message {
border-left: 3px solid transparent;
font-size: var(--font-size-02);
box-shadow: none;
border-radius: var(--border-radius-base);
position: relative;
.message-content {
padding: var(--spacing-03) var(--spacing-05);
overflow-x: auto;
color: var(--white);
font-weight: bold;
a {
color: var(--white);
}
}
.arrow {
transform: rotate(90deg);
right: 90%;
top: -15px;
border: solid;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-top-color: transparent !important;
border-bottom-color: transparent !important;
border-width: 10px;
}
}
p {
margin-bottom: calc(var(--line-height-03) / 4);
&:last-child {
margin-bottom: 0;
}
}
}
&:not(.self) {
.message {
.arrow {
border-left-color: transparent !important;
}
}
}
&.self {
margin-top: var(--line-height-03);
.message-wrapper .message {
border-left: none;
border-right: 3px solid transparent;
.arrow {
left: 100%;
right: auto;
border-right-color: transparent !important;
}
}
}
}
}
.new-message {
@extend .full-size;
top: auto;
height: $new-message-height;
background-color: var(--chat-new-message-bg);
padding: calc(var(--line-height-03) / 4);
border-top: 1px solid var(--editor-border-color);
textarea {
overflow: auto;
resize: none;
border-radius: var(--border-radius-base);
border: 1px solid var(--editor-border-color);
height: 100%;
width: 100%;
color: var(--chat-new-message-textarea-color);
font-size: var(--font-size-02);
padding: calc(var(--line-height-03) / 4);
background-color: var(--chat-new-message-textarea-bg);
}
}
}