)
}
diff --git a/services/web/frontend/js/features/ide-redesign/components/chat/message.tsx b/services/web/frontend/js/features/ide-redesign/components/chat/message.tsx
new file mode 100644
index 0000000000..a3676e2216
--- /dev/null
+++ b/services/web/frontend/js/features/ide-redesign/components/chat/message.tsx
@@ -0,0 +1,60 @@
+import { MessageProps } from '@/features/chat/components/message'
+import { User } from '../../../../../../types/user'
+import { getHueForUserId } from '@/shared/utils/colors'
+import MessageContent from '@/features/chat/components/message-content'
+import classNames from 'classnames'
+
+function hue(user?: User) {
+ return user ? getHueForUserId(user.id) : 0
+}
+
+function getAvatarStyle(user?: User) {
+ return {
+ borderColor: `hsl(${hue(user)}, 85%, 40%)`,
+ backgroundColor: `hsl(${hue(user)}, 85%, 40%`,
+ }
+}
+
+function Message({ message, fromSelf }: MessageProps) {
+ return (
+
+ )
+}
+
+export default Message
diff --git a/services/web/frontend/js/features/ide-redesign/components/integrations-panel/integrations-panel.tsx b/services/web/frontend/js/features/ide-redesign/components/integrations-panel/integrations-panel.tsx
index bf25593387..d1e4358907 100644
--- a/services/web/frontend/js/features/ide-redesign/components/integrations-panel/integrations-panel.tsx
+++ b/services/web/frontend/js/features/ide-redesign/components/integrations-panel/integrations-panel.tsx
@@ -1,24 +1,18 @@
import { ElementType } from 'react'
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
-import MaterialIcon from '@/shared/components/material-icon'
-import OlButton from '@/features/ui/components/ol/ol-button'
-import { useRailContext } from '../../contexts/rail-context'
+import { RailPanelHeader } from '../rail'
+import { useTranslation } from 'react-i18next'
const integrationPanelComponents = importOverleafModules(
'integrationPanelComponents'
) as { import: { default: ElementType }; path: string }[]
export default function IntegrationsPanel() {
- const { handlePaneCollapse } = useRailContext()
+ const { t } = useTranslation()
return (
-
+
{integrationPanelComponents.map(
({ import: { default: Component }, path }) => (
diff --git a/services/web/frontend/js/features/ide-redesign/components/rail.tsx b/services/web/frontend/js/features/ide-redesign/components/rail.tsx
index 98c1bc78c3..8da9faf374 100644
--- a/services/web/frontend/js/features/ide-redesign/components/rail.tsx
+++ b/services/web/frontend/js/features/ide-redesign/components/rail.tsx
@@ -1,4 +1,4 @@
-import { ReactElement, useCallback, useMemo } from 'react'
+import { FC, ReactElement, useCallback, useMemo } from 'react'
import { Nav, NavLink, Tab, TabContainer } from 'react-bootstrap-5'
import MaterialIcon, {
AvailableUnfilledIcon,
@@ -8,13 +8,14 @@ import { useLayoutContext } from '@/shared/context/layout-context'
import { ErrorIndicator, ErrorPane } from './errors'
import { RailTabKey, useRailContext } from '../contexts/rail-context'
import FileTreeOutlinePanel from './file-tree-outline-panel'
-import { ChatIndicator, ChatPane } from './chat'
+import { ChatIndicator, ChatPane } from './chat/chat'
import getMeta from '@/utils/meta'
import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler'
import { useTranslation } from 'react-i18next'
import classNames from 'classnames'
import IntegrationsPanel from './integrations-panel/integrations-panel'
+import OLButton from '@/features/ui/components/ol/ol-button'
type RailElement = {
icon: AvailableUnfilledIcon
@@ -234,3 +235,15 @@ const RailActionElement = ({ action }: { action: RailAction }) => {
)
}
}
+
+export const RailPanelHeader: FC<{ title: string }> = ({ title }) => {
+ const { handlePaneCollapse } = useRailContext()
+ return (
+
+ )
+}
diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/integrations-panel.scss b/services/web/frontend/stylesheets/bootstrap-5/components/integrations-panel.scss
index 17dc42d6ab..7312053d05 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/components/integrations-panel.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/components/integrations-panel.scss
@@ -3,19 +3,6 @@
height: 100%;
}
-.integrations-panel-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: var(--spacing-03) var(--spacing-04);
-}
-
-.integrations-panel-title {
- font-size: var(--font-size-02);
- color: var(--content-primary);
- margin-bottom: 0;
-}
-
.integrations-panel-card-button {
all: unset;
background-color: var(--white);
diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/chat.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/chat.scss
index e0bcf91c83..f04fd1a905 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/chat.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/chat.scss
@@ -5,6 +5,8 @@
--chat-new-message-bg: var(--neutral-70);
--chat-new-message-textarea-color: var(--neutral-90);
--chat-new-message-textarea-bg: var(--neutral-20);
+ --chat-new-message-textarea-border: var(--editor-border-color);
+ --chat-new-message-border: var(--editor-border-color);
--chat-message-date-color: var(--neutral-40);
--chat-message-name-color: var(--white);
}
@@ -16,6 +18,8 @@
--chat-new-message-bg: var(--neutral-10);
--chat-new-message-textarea-color: var(--neutral-90);
--chat-new-message-textarea-bg: var(--white);
+ --chat-new-message-textarea-border: var(--editor-border-color);
+ --chat-new-message-border: var(--editor-border-color);
--chat-message-date-color: var(--neutral-70);
--chat-message-name-color: var(--neutral-70);
}
@@ -24,11 +28,14 @@
--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-bg: var(--white);
--chat-new-message-textarea-color: var(--neutral-90);
--chat-new-message-textarea-bg: var(--white);
+ --chat-new-message-textarea-border: var(--editor-border-color);
+ --chat-new-message-border: var(--white);
--chat-message-date-color: var(--neutral-70);
--chat-message-name-color: var(--neutral-70);
+ --chat-date-align: center;
}
.chat {
@@ -72,7 +79,7 @@
font-size: var(--font-size-01);
color: var(--chat-message-date-color);
margin-bottom: calc(var(--line-height-03) / 2);
- text-align: right;
+ text-align: var(--chat-date-align, right);
}
.message-wrapper {
@@ -158,13 +165,13 @@
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);
+ border-top: 1px solid var(--chat-new-message-border);
textarea {
overflow: auto;
resize: none;
border-radius: var(--border-radius-base);
- border: 1px solid var(--editor-border-color);
+ border: 1px solid var(--chat-new-message-textarea-border);
height: 100%;
width: 100%;
color: var(--chat-new-message-textarea-color);
@@ -174,3 +181,133 @@
}
}
}
+
+.chat-empty-state-placeholder {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ text-align: center;
+ height: 100%;
+ gap: var(--spacing-06);
+ padding: var(--spacing-02);
+
+ .chat-empty-state-icon {
+ padding: var(--spacing-08);
+ font-size: var(--font-size-08);
+ height: 80px;
+ width: 80px;
+ border-radius: 50%;
+ display: inline-block;
+ line-height: 32px;
+ background-color: var(--bg-light-secondary);
+
+ .material-symbols {
+ font-size: 32px;
+ }
+ }
+
+ .chat-empty-state-title {
+ font-size: var(--font-size-02);
+ line-height: var(--line-height-02);
+ font-weight: bold;
+ }
+
+ .chat-empty-state-body {
+ font-size: var(--font-size-02);
+ line-height: var(--line-height-02);
+ color: var(--content-secondary);
+ }
+}
+
+.chat-message-redesign {
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacing-01);
+
+ .message-row {
+ display: flex;
+ align-items: flex-end;
+ gap: var(--spacing-03);
+ }
+
+ .message-avatar,
+ .message-avatar-placeholder {
+ flex: 0 0 24px;
+ }
+
+ .message-avatar .avatar {
+ width: 24px;
+ height: 24px;
+ line-height: 24px;
+ border-radius: 50%;
+ text-align: center;
+ color: var(--white);
+ text-transform: uppercase;
+ }
+
+ .message-author,
+ .message-container {
+ flex: 1 1 auto;
+ max-width: calc(100% - 24px - var(--spacing-03));
+ }
+
+ .message-container {
+ display: flex;
+ justify-content: flex-start;
+ }
+
+ .message-author {
+ font-size: var(--font-size-01);
+ line-height: var(--line-height-01);
+ }
+
+ .message-content {
+ background-color: var(--bg-light-secondary);
+ border-radius: var(--border-radius-large);
+ padding: var(--spacing-03) var(--spacing-04);
+ width: fit-content;
+ max-width: 100%;
+ overflow-x: auto;
+
+ p {
+ margin: 0;
+ }
+ }
+
+ .message-container.message-from-self {
+ justify-content: flex-end;
+
+ .message-content {
+ background-color: var(--bg-accent-03);
+ }
+
+ &:not(.first-row-in-message) .message-content {
+ border-top-right-radius: var(--border-radius-base);
+ }
+
+ &:not(.last-row-in-message) .message-content {
+ border-bottom-right-radius: var(--border-radius-base);
+ }
+ }
+
+ .message-container:not(.message-from-self) {
+ &:not(.first-row-in-message) .message-content {
+ border-top-left-radius: var(--border-radius-base);
+ }
+
+ &:not(.last-row-in-message) .message-content {
+ border-bottom-left-radius: var(--border-radius-base);
+ }
+ }
+}
+
+.chat-panel {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+
+ .chat-wrapper {
+ flex: 1 1 auto;
+ position: relative;
+ }
+}
diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss
index aa1b3ab324..e4a0cf0729 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/rail.scss
@@ -6,6 +6,20 @@
--ide-rail-link-active-indicator-background: var(--neutral-90);
}
+.rail-panel-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: var(--spacing-03) var(--spacing-04);
+ background-color: var(--ide-rail-background);
+}
+
+.rail-panel-title {
+ font-size: var(--font-size-02);
+ color: var(--content-primary);
+ margin-bottom: 0;
+}
+
.ide-rail-tab-button {
border: 0;
background: none;
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index d8259e1cad..9f4a77b4c1 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -337,6 +337,7 @@
"collaborate_online_and_offline": "Collaborate online and offline, using your own workflow",
"collaboration": "Collaboration",
"collaborator": "Collaborator",
+ "collaborator_chat": "Collaborator chat",
"collabratec_account_not_registered": "IEEE Collabratecâ„¢ account not registered. Please connect to Overleaf from IEEE Collabratecâ„¢ or log in with a different account.",
"collabs_per_proj": "__collabcount__ collaborators per project",
"collabs_per_proj_single": "__collabcount__ collaborator per project",
@@ -1381,6 +1382,7 @@
"no_libraries_selected": "No libraries selected",
"no_members": "No members",
"no_messages": "No messages",
+ "no_messages_yet": "No messages yet",
"no_new_commits_in_github": "No new commits in GitHub since last merge.",
"no_one_has_commented_or_left_any_suggestions_yet": "No one has commented or left any suggestions yet.",
"no_other_projects_found": "No other projects found, please create another project first",
@@ -2067,6 +2069,7 @@
"start_by_fixing_the_first_error_in_your_doc": "Start by fixing the first error in your doc to avoid problems later on.",
"start_free_trial": "Start Free Trial!",
"start_free_trial_without_exclamation": "Start Free Trial",
+ "start_the_conversation_by_saying_hello_or_sharing_an_update": "Start the conversation by saying hello or sharing an update",
"start_typing_find_your_company": " Start typing to find your company",
"start_typing_find_your_organization": "Start typing to find your organization",
"start_typing_find_your_university": "Start typing to find your university",