Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,12 @@ module.exports = {

return {
ImportDeclaration(node) {
if (isImportSourceEquals(/^@leafygreen-ui/, node)) {
if (isImportSourceEquals(/^@(leafygreen-ui|lg-chat)/, node)) {
reportLeafygreenUsage(context, node, node.source);
}
},
CallExpression(node) {
if (isRequireSourceEquals(/^@leafygreen-ui/, node)) {
if (isRequireSourceEquals(/^@(leafygreen-ui|lg-chat)/, node)) {
reportLeafygreenUsage(context, node, node.arguments[0]);
}
},
Expand Down
3,012 changes: 2,595 additions & 417 deletions package-lock.json

Large diffs are not rendered by default.

23 changes: 22 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,27 @@
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0"
}
},
"@leafygreen-ui/emotion": "^4.0.9",
"@leafygreen-ui/lib": "^15.2.0",
"@leafygreen-ui/palette": "^4.1.3",
"@leafygreen-ui/tokens": "^2.11.3",
"@leafygreen-ui/leafygreen-provider": "^4.0.2",
"@leafygreen-ui/marketing-modal": "^5.0.2",
"@leafygreen-ui/typography": "^20.0.2",
"@leafygreen-ui/icon": "^13.1.2",
"@leafygreen-ui/popover": "^13.0.11",
"@leafygreen-ui/badge": "^9.0.2",
"@leafygreen-ui/banner": "^9.0.2",
"@leafygreen-ui/button": "^22.0.2",
"@leafygreen-ui/hooks": "^8.3.4",
"@leafygreen-ui/icon-button": "^16.0.2",
"@leafygreen-ui/input-option": "^3.0.4",
"@leafygreen-ui/polymorphic": "^2.0.5",
"@leafygreen-ui/search-input": "^5.0.2",
"@leafygreen-ui/code": "^16.0.2",
"@leafygreen-ui/text-area": "^10.0.2",
"@leafygreen-ui/card": "^12.0.2",
"@leafygreen-ui/logo": "^10.0.2"
}
}
3 changes: 2 additions & 1 deletion packages/compass-assistant/src/assistant-chat.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { expect } from 'chai';
import { createMockChat } from '../test/utils';
import type { AssistantMessage } from './compass-assistant-provider';

describe('AssistantChat', function () {
// TODO: some internal logic in lg-chat breaks all these tests, re-enable the tests
describe.skip('AssistantChat', function () {
const mockMessages: AssistantMessage[] = [
{
id: 'user',
Expand Down
166 changes: 59 additions & 107 deletions packages/compass-assistant/src/assistant-chat.tsx
Original file line number Diff line number Diff line change
@@ -1,129 +1,81 @@
import React, { useCallback, useState } from 'react';
import React, { useCallback } from 'react';
import type { AssistantMessage } from './compass-assistant-provider';
import type { Chat } from './@ai-sdk/react/chat-react';
import { useChat } from './@ai-sdk/react/use-chat';
import {
LgChatChatWindow,
LgChatLeafygreenChatProvider,
LgChatMessage,
LgChatMessageFeed,
LgChatInputBar,
} from '@mongodb-js/compass-components';

const { ChatWindow } = LgChatChatWindow;
const { LeafyGreenChatProvider, Variant } = LgChatLeafygreenChatProvider;
const { Message } = LgChatMessage;
const { MessageFeed } = LgChatMessageFeed;
const { InputBar } = LgChatInputBar;

interface AssistantChatProps {
chat: Chat<AssistantMessage>;
}

/**
* This component is currently using placeholders as Leafygreen UI updates are not available yet.
* Before release, we will replace this with the actual Leafygreen chat components.
*/
export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
chat,
}) => {
const [inputValue, setInputValue] = useState('');
const { messages, sendMessage } = useChat({
const { messages, sendMessage, status } = useChat({
chat,
});

const handleInputSubmit = useCallback(
(e: React.FormEvent) => {
e.preventDefault();
if (inputValue.trim()) {
void sendMessage({ text: inputValue.trim() });
setInputValue('');
}
// Transform AI SDK messages to LeafyGreen chat format
const lgMessages = messages.map((message) => ({
id: message.id,
messageBody:
message.metadata?.displayText ||
message.parts
?.filter((part) => part.type === 'text')
.map((part) => part.text)
.join('') ||
'',
isSender: message.role === 'user',
}));

const handleMessageSend = useCallback(
(messageBody: string) => {
void sendMessage({ text: messageBody });
},
[inputValue, sendMessage]
[sendMessage]
);

return (
<div
style={{
display: 'flex',
flexDirection: 'column',
height: '100%',
width: '100%',
}}
data-testid="assistant-chat"
>
{/* Message Feed */}
<div
data-testid="assistant-chat-messages"
style={{
width: '100%',
flex: 1,
overflowY: 'auto',
display: 'flex',
flexDirection: 'column',
gap: '16px',
minHeight: 0,
}}
>
{messages.map((message) => (
<div
key={message.id}
data-testid={`assistant-message-${message.id}`}
style={{
marginBottom: '12px',
padding: '8px 12px',
borderRadius: '8px',
backgroundColor: message.role === 'user' ? '#207245' : '#e9ecef',
color: message.role === 'user' ? 'white' : '#333',
alignSelf: message.role === 'user' ? 'flex-end' : 'flex-start',
maxWidth: '80%',
wordWrap: 'break-word',
whiteSpace: 'pre-wrap',
<div data-testid="assistant-chat" style={{ height: '100%', width: '100%' }}>
<LeafyGreenChatProvider variant={Variant.Compact}>
<ChatWindow title="MongoDB Assistant">
<MessageFeed data-testid="assistant-chat-messages">
{lgMessages.map((messageFields) => (
<Message
key={messageFields.id}
{...messageFields}
data-testid={`assistant-message-${messageFields.id}`}
/>
))}
{status === 'submitted' && (
<Message
id="loading"
messageBody="Thinking..."
isSender={false}
/>
)}
</MessageFeed>
<InputBar
data-testid="assistant-chat-input"
onMessageSend={handleMessageSend}
textareaProps={{
placeholder: 'Ask MongoDB Assistant a question',
}}
>
{message.metadata?.displayText ||
message.parts
?.filter((part) => part.type === 'text')
.map((part) => part.text)
.join('') ||
''}
</div>
))}
</div>

{/* Input Bar */}
<form
data-testid="assistant-chat-form"
onSubmit={handleInputSubmit}
style={{
display: 'flex',
gap: '8px',
flexShrink: 0, // Prevents the input bar from shrinking
position: 'sticky',
bottom: 0,
backgroundColor: 'inherit',
paddingTop: '8px',
}}
>
<input
data-testid="assistant-chat-input"
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Ask MongoDB Assistant a question"
style={{
flex: 1,
padding: '8px 12px',
border: '1px solid #ddd',
borderRadius: '4px',
fontSize: '14px',
}}
/>
<button
data-testid="assistant-chat-send-button"
type="submit"
disabled={!inputValue.trim()}
style={{
padding: '8px 16px',
backgroundColor: '#207245',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: inputValue.trim() ? 'pointer' : 'not-allowed',
opacity: inputValue.trim() ? 1 : 0.6,
}}
>
Send
</button>
</form>
/>
</ChatWindow>
</LeafyGreenChatProvider>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ describe('AssistantProvider', function () {
);
});

describe('with existing chat instance', function () {
// TODO: some internal logic in lg-chat breaks all these tests, re-enable the tests
describe.skip('with existing chat instance', function () {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gagik @lerouxb just wanted to highlight: I can either revert switching assistant to new UI or keep this skip in this PR, whatever you prefer. If we keep the skip, we probably want to follow-up with fixing those right away. At a glance it's just jsdom missing some methods, so shouldn't be too hard, I'm just trying to keep this PR small

Copy link
Contributor

@gagik gagik Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working on a follow-up PR so we can just skip this here and I'll rebase and re-add those

before(function () {
// TODO(COMPASS-9618): skip in electron runtime for now, drawer has issues rendering
if ((process as any).type === 'renderer') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,9 @@ function useCollectionTabs(props: CollectionMetadata) {
</WithErrorBoundary>
),
title: (
<WithErrorBoundary name={name} type="header">
Copy link
Contributor

@lerouxb lerouxb Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: why the removed error boundary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it's this issue caused by the fact that @leafygreen-ui/lib@15 seems like the one that seems to be working for all our dependendecies more or less, but it does cause something weird in leafygreen tabs component specifically: the title that we pass there wrapped in a boundary starts to fail with this error (I'm guessing they are doing something with this value passed that triggers the constructor accidentally). Before tabs were installing their own version, but doing this very targeted override on top of other overrides is a pain in the butt, so I'm just getting around the issue here by removing the boundary from the rendering tree.

I'll leave a todo

<Provider {...props}>
<Header />
</Provider>
</WithErrorBoundary>
<Provider {...props}>
<Header />
</Provider>
),
};
});
Expand Down
23 changes: 21 additions & 2 deletions packages/compass-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@
"test-cov": "nyc --compact=false --produce-source-map=false -x \"**/*.spec.*\" --reporter=lcov --reporter=text --reporter=html npm run test",
"test-watch": "npm run test -- --watch",
"test-ci": "npm run test-cov",
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write .",
"postinstall": "node ./scripts/patch-leafygreen-button.js"
},
"dependencies": {
"@dnd-kit/core": "^6.0.7",
"@dnd-kit/sortable": "^7.0.2",
"@dnd-kit/utilities": "^3.2.1",
"@leafygreen-ui/avatar": "^3.1.0",
"@leafygreen-ui/badge": "^9.0.2",
"@leafygreen-ui/banner": "^9.0.2",
"@leafygreen-ui/button": "^22.0.2",
Expand All @@ -48,8 +50,9 @@
"@leafygreen-ui/guide-cue": "^7.0.2",
"@leafygreen-ui/hooks": "^8.3.4",
"@leafygreen-ui/icon": "^13.1.2",
"@leafygreen-ui/icon-button": "16.0.2",
"@leafygreen-ui/icon-button": "^16.0.2",
"@leafygreen-ui/info-sprinkle": "^4.0.2",
"@leafygreen-ui/input-option": "^3.0.12",
"@leafygreen-ui/leafygreen-provider": "^4.0.2",
"@leafygreen-ui/lib": "^15.2.0",
"@leafygreen-ui/logo": "^10.0.2",
Expand Down Expand Up @@ -77,6 +80,22 @@
"@leafygreen-ui/tokens": "^2.11.3",
"@leafygreen-ui/tooltip": "^13.0.13",
"@leafygreen-ui/typography": "^20.0.2",
"@lg-chat/avatar": "^7.0.0",
"@lg-chat/chat-disclaimer": "^4.0.6",
"@lg-chat/chat-window": "^4.1.1",
"@lg-chat/fixed-chat-window": "^4.0.4",
"@lg-chat/input-bar": "^10.0.1",
"@lg-chat/leafygreen-chat-provider": "^5.0.0",
"@lg-chat/lg-markdown": "^4.0.4",
"@lg-chat/message": "^8.0.0",
"@lg-chat/message-actions": "^1.0.0",
"@lg-chat/message-feed": "^7.0.0",
"@lg-chat/message-feedback": "^6.0.0",
"@lg-chat/message-prompts": "^4.0.3",
"@lg-chat/message-rating": "^5.0.0",
"@lg-chat/rich-links": "^3.1.1",
"@lg-chat/suggestions": "^0.2.1",
"@lg-chat/title-bar": "^4.0.5",
"@mongodb-js/compass-context-menu": "^0.2.5",
"@react-aria/interactions": "^3.9.1",
"@react-aria/utils": "^3.13.1",
Expand Down
26 changes: 26 additions & 0 deletions packages/compass-components/scripts/patch-leafygreen-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* We can't update @leafygreen-ui/button component to latest because it breaks
* the types across the whole application, but we also have to add a dependency
* on a new leafygreen package that depends on a new export from the button
* package, this new export is a one-liner color value. As a temporary
* workaround, we will patch leafygreen package and add the export manually. For
* more details see https://github.com/mongodb-js/compass/pull/7223
*/
const fs = require('fs');
const path = require('path');

const leafygreenButtonPackage = path.dirname(
require.resolve('@leafygreen-ui/button/package.json')
);

// eslint-disable-next-line no-console
console.log('Adding @leafygreen-ui/button/constants export...');

fs.writeFileSync(
path.join(leafygreenButtonPackage, 'constants.js'),
"module.exports = { PRIMARY_BUTTON_INTERACTIVE_GREEN: '#00593F' };"
);
fs.writeFileSync(
path.join(leafygreenButtonPackage, 'constants.d.ts'),
'export declare const PRIMARY_BUTTON_INTERACTIVE_GREEN = "#00593F";'
);
20 changes: 20 additions & 0 deletions packages/compass-components/src/components/leafygreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,23 @@ export {
ComboboxGroup,
ComboboxOption,
};

export * as Avatar from '@leafygreen-ui/avatar';
export * as InputOption from '@leafygreen-ui/input-option';

export * as LgChatAvatar from '@lg-chat/avatar';
export * as LgChatChatDisclaimer from '@lg-chat/chat-disclaimer';
export * as LgChatChatWindow from '@lg-chat/chat-window';
export * as LgChatFixedChatWindow from '@lg-chat/fixed-chat-window';
export * as LgChatInputBar from '@lg-chat/input-bar';
export * as LgChatLeafygreenChatProvider from '@lg-chat/leafygreen-chat-provider';
export * as LgChatLgMarkdown from '@lg-chat/lg-markdown';
export * as LgChatMessageActions from '@lg-chat/message-actions';
export * as LgChatMessageFeed from '@lg-chat/message-feed';
export * as LgChatMessageFeedback from '@lg-chat/message-feedback';
export * as LgChatMessagePrompts from '@lg-chat/message-prompts';
export * as LgChatMessageRating from '@lg-chat/message-rating';
export * as LgChatMessage from '@lg-chat/message';
export * as LgChatRichLinks from '@lg-chat/rich-links';
export * as LgChatSuggestions from '@lg-chat/suggestions';
export * as LgChatTitleBar from '@lg-chat/title-bar';
2 changes: 1 addition & 1 deletion packages/compass-data-modeling/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@mongodb-js/compass-user-data": "^0.9.0",
"@mongodb-js/compass-utils": "^0.9.10",
"@mongodb-js/compass-workspaces": "^0.51.0",
"@mongodb-js/diagramming": "^1.3.5",
"@mongodb-js/diagramming": "^1.5.1",
"bson": "^6.10.4",
"compass-preferences-model": "^2.50.0",
"html-to-image": "1.11.11",
Expand Down
Loading