From bdccf2084d4d092eaf3861df06a12050e973d5b9 Mon Sep 17 00:00:00 2001 From: Stephen Lee Date: Mon, 13 Oct 2025 15:16:29 -0700 Subject: [PATCH 1/3] fix(drawer): overflow shadow only renders when scrollable is true (#3210) * fix(drawer): overflow shadow only renders when scrollable is true * chore(drawer): changeset --- .changeset/odd-kiwis-run.md | 5 +++++ packages/drawer/src/Drawer/Drawer.tsx | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 .changeset/odd-kiwis-run.md diff --git a/.changeset/odd-kiwis-run.md b/.changeset/odd-kiwis-run.md new file mode 100644 index 0000000000..0024311879 --- /dev/null +++ b/.changeset/odd-kiwis-run.md @@ -0,0 +1,5 @@ +--- +'@leafygreen-ui/drawer': patch +--- + +Fix `scrollable` prop so overflow shadow does not ever render if `scrollable={false}` diff --git a/packages/drawer/src/Drawer/Drawer.tsx b/packages/drawer/src/Drawer/Drawer.tsx index f4c55a9fe6..bd07301ccf 100644 --- a/packages/drawer/src/Drawer/Drawer.tsx +++ b/packages/drawer/src/Drawer/Drawer.tsx @@ -104,7 +104,6 @@ export const Drawer = forwardRef( const { ref: interceptRef, inView: isInterceptInView } = useInView({ initialInView: true, fallbackInView: true, - skip: !scrollable, }); const showCloseButton = !!onClose; @@ -282,7 +281,7 @@ export const Drawer = forwardRef(
@@ -296,7 +295,7 @@ export const Drawer = forwardRef( data-testid={lgIds.scrollContainer} > {/* Empty span element used to track if children container has scrolled down */} - + {scrollable && } {children}
) : ( From ceae87b55e3f8528ac33920f157d58e07b35fe87 Mon Sep 17 00:00:00 2001 From: Stephen Lee Date: Tue, 14 Oct 2025 14:40:11 -0700 Subject: [PATCH 2/3] fix(input-bar): center align disclaimer text (#3211) * fix(input-bar): center align disclaimer * chore(input-bar): changeset --- .changeset/stupid-vans-stare.md | 5 +++++ chat/input-bar/src/InputBar/InputBar.styles.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/stupid-vans-stare.md diff --git a/.changeset/stupid-vans-stare.md b/.changeset/stupid-vans-stare.md new file mode 100644 index 0000000000..5b4f79f2fe --- /dev/null +++ b/.changeset/stupid-vans-stare.md @@ -0,0 +1,5 @@ +--- +'@lg-chat/input-bar': patch +--- + +Fix disclaimer text alignment to be centered below input diff --git a/chat/input-bar/src/InputBar/InputBar.styles.ts b/chat/input-bar/src/InputBar/InputBar.styles.ts index 33ea07ce76..04b1458d5c 100644 --- a/chat/input-bar/src/InputBar/InputBar.styles.ts +++ b/chat/input-bar/src/InputBar/InputBar.styles.ts @@ -324,5 +324,5 @@ export const getHotkeyIndicatorStyles = ({ export const disclaimerTextStyles = css` margin-top: ${spacing[50]}px; - margin-left: ${spacing[200]}px; + text-align: center; `; From b5fb380a8c4b25b343c4d1d371926d95168ce308 Mon Sep 17 00:00:00 2001 From: Stephen Lee Date: Fri, 17 Oct 2025 09:36:08 -0700 Subject: [PATCH 3/3] feat(chat): update layout to use flexible height containers (#3212) * fix(leafygreen-chat-provider): set height to 100% * chore(leafygreen-chat-provider): changeset * feat(message-feed): remove fixed default height for MessageFeed component * chore(message-feed): changeset * fix(fixed-chat-window): add explicit height and fix stories * chore(fixed-chat-window): changeset * chore(chat-window): install @storybook/test and @leafygreen-ui/drawer dev deps * test(chat-window): add InDrawerLayout story and update baseMessages * feat(chat-window): add hidden spacer to fix vertical message flow and remove redundant container element * chore: changesets * fix(chat): stories --- .changeset/chat-styles-chat-window.md | 9 + .changeset/chat-styles-fixed-chat-window.md | 11 ++ .../chat-styles-leafygreen-chat-provider.md | 5 + .changeset/chat-styles-message-feed.md | 9 + chat/chat-window/package.json | 4 +- chat/chat-window/src/ChatWindow.stories.tsx | 172 ++++++++++++++++-- .../src/ChatWindow/ChatWindow.styles.ts | 13 +- .../chat-window/src/ChatWindow/ChatWindow.tsx | 6 +- chat/chat-window/src/utils/baseMessages.ts | 20 +- chat/chat-window/tsconfig.json | 3 + .../src/FixedChatWindow.stories.tsx | 15 +- .../FixedChatWindow/FixedChatWindow.styles.ts | 1 + .../LeafyGreenChatProvider.tsx | 2 +- .../src/MessageFeed/MessageFeed.styles.ts | 4 +- pnpm-lock.yaml | 6 + 15 files changed, 233 insertions(+), 47 deletions(-) create mode 100644 .changeset/chat-styles-chat-window.md create mode 100644 .changeset/chat-styles-fixed-chat-window.md create mode 100644 .changeset/chat-styles-leafygreen-chat-provider.md create mode 100644 .changeset/chat-styles-message-feed.md diff --git a/.changeset/chat-styles-chat-window.md b/.changeset/chat-styles-chat-window.md new file mode 100644 index 0000000000..8cabdb8eef --- /dev/null +++ b/.changeset/chat-styles-chat-window.md @@ -0,0 +1,9 @@ +--- +'@lg-chat/chat-window': major +--- + +Updated height of outer container to ensure `ChatWindow` takes up the full vertical space of its parent container element. Also, added a hidden spacer element to ensure messages vertically flow from the bottom of the scroll container when child `MessageFeed` instance does not take up the full vertical space. + +Note: this should be upgraded with the following packages to avoid UI regressions: + - `@lg-chat/leafygreen-chat-provider@5.1.0` + - `@lg-chat/message-feed@8.0.0` diff --git a/.changeset/chat-styles-fixed-chat-window.md b/.changeset/chat-styles-fixed-chat-window.md new file mode 100644 index 0000000000..dc34246f8f --- /dev/null +++ b/.changeset/chat-styles-fixed-chat-window.md @@ -0,0 +1,11 @@ +--- +'@lg-chat/fixed-chat-window': minor +--- + +Added fixed height of 640px to `FixedChatWindow` popover element. The latest version of `MessageFeed` no longer has a fixed height which requires setting a fixed height in `FixedChatWindow` to prevent the popover element from growing to the full height of its parent container. + +However, please note that this is a maintenance change, and this package will be deprecated shortly. It is recommended to migrate to `@lg-chat/chat-window`. + +Note: if using this package, it should be upgraded with the following packages to avoid UI regressions: + - `@lg-chat/leafygreen-chat-provider@5.1.0` + - `@lg-chat/message-feed@8.0.0` diff --git a/.changeset/chat-styles-leafygreen-chat-provider.md b/.changeset/chat-styles-leafygreen-chat-provider.md new file mode 100644 index 0000000000..5ef0726b29 --- /dev/null +++ b/.changeset/chat-styles-leafygreen-chat-provider.md @@ -0,0 +1,5 @@ +--- +'@lg-chat/leafygreen-chat-provider': minor +--- + +Added `height: 100%;` to wrapper div in `LeafyGreenChatProvider` diff --git a/.changeset/chat-styles-message-feed.md b/.changeset/chat-styles-message-feed.md new file mode 100644 index 0000000000..e33c7ad13c --- /dev/null +++ b/.changeset/chat-styles-message-feed.md @@ -0,0 +1,9 @@ +--- +'@lg-chat/message-feed': major +--- + +Removed fixed default height of 500px from `MessageFeed` component. Now, `MessageFeed` will grow to the bounds of its parent container. + +Note: this should be upgraded with the following packages to avoid UI regressions: + - `@lg-chat/leafygreen-chat-provider@5.1.0` + - `@lg-chat/chat-window@5.0.0` diff --git a/chat/chat-window/package.json b/chat/chat-window/package.json index fa54e8ad95..9def0731a4 100644 --- a/chat/chat-window/package.json +++ b/chat/chat-window/package.json @@ -22,13 +22,15 @@ "react-keyed-flatten-children": "^2.2.1" }, "devDependencies": { + "@leafygreen-ui/drawer": "workspace:^", "@lg-chat/avatar": "workspace:^", "@lg-chat/input-bar": "workspace:^", "@lg-chat/message": "workspace:^", "@lg-chat/message-feed": "workspace:^", "@lg-chat/message-feedback": "workspace:^", "@lg-chat/message-prompts": "workspace:^", - "@lg-tools/build": "workspace:^" + "@lg-tools/build": "workspace:^", + "@storybook/test": "^8.6.14" }, "peerDependencies": { "@leafygreen-ui/leafygreen-provider": "workspace:^", diff --git a/chat/chat-window/src/ChatWindow.stories.tsx b/chat/chat-window/src/ChatWindow.stories.tsx index 51295e2810..52676d23d7 100644 --- a/chat/chat-window/src/ChatWindow.stories.tsx +++ b/chat/chat-window/src/ChatWindow.stories.tsx @@ -7,16 +7,32 @@ import { } from '@lg-chat/leafygreen-chat-provider'; import { Message } from '@lg-chat/message'; import { MessageFeed } from '@lg-chat/message-feed'; -import { WithMessageRating as MessageFeedbackStory } from '@lg-chat/message-feedback/stories'; import { MessagePrompt, MessagePrompts } from '@lg-chat/message-prompts'; import { storybookArgTypes, StoryMetaType } from '@lg-tools/storybook-utils'; import { StoryFn, StoryObj } from '@storybook/react'; +import { userEvent, within } from '@storybook/test'; +import { DisplayMode, DrawerLayout } from '@leafygreen-ui/drawer'; +import { css } from '@leafygreen-ui/emotion'; import LeafyGreenProvider from '@leafygreen-ui/leafygreen-provider'; +import { spacing } from '@leafygreen-ui/tokens'; import baseMessages from './utils/baseMessages'; import { ChatWindow, ChatWindowProps } from '.'; +const getActionsChild = () => ( + console.log('Copy clicked')} + // eslint-disable-next-line no-console + onClickRetry={() => console.log('Retry clicked')} + // eslint-disable-next-line no-console + onRatingChange={() => console.log('Rating changed')} + // eslint-disable-next-line no-console + onSubmitFeedback={() => console.log('Feedback submitted')} + /> +); + const meta: StoryMetaType = { title: 'Composition/Chat/ChatWindow', component: ChatWindow, @@ -61,7 +77,7 @@ const MyMessage = ({ isMongo, messageBody, userName, - hasMessageRating, + hasMessageActions, }: any) => { return ( )} {/* @ts-ignore onChange is passed in the story itself */} - {hasMessageRating && } + {hasMessageActions && getActionsChild()} ); }; @@ -142,16 +158,24 @@ const EmptyComponent = ({ variant, ...props }: ChatWindowStoryProps) => { }; return ( - - - - {messages.map(messageFields => ( - - ))} - - - - +
+ + + + {messages.map(messageFields => ( + + ))} + + + + +
); }; export const Empty: StoryObj = { @@ -301,3 +325,125 @@ export const WithMessagePrompts: StoryObj = { }, }, }; + +const ChatDrawerContent = ({ + assistantName, + variant, +}: { + assistantName?: string; + variant: Variant; +}) => { + const [messages, setMessages] = useState>(baseMessages); + + const handleMessageSend = (messageBody: string) => { + const newMessage = { + id: messages.length, + messageBody, + userName: 'User', + }; + setMessages(prevMessages => [...prevMessages, newMessage]); + }; + + return ( + + + + {messages.map(messageFields => ( + + ))} + + + + + ); +}; + +const MainContent = () => { + return ( +
+
+

Chat Demo with Drawer

+

Sample chat interface in drawer layout

+

+ This example demonstrates how to use the ChatWindow component within a + Drawer layout. The chat interface is displayed in the drawer panel, + which can be toggled open or closed by clicking the chat icon in the + toolbar. +

+
+
+ ); +}; + +const getToolbarData = ({ + assistantName, + variant, +}: { + assistantName?: string; + variant: Variant; +}) => [ + { + id: 'assistant', + label: 'MongoDB Assistant', + glyph: 'Sparkle' as const, + title: 'MongoDB Assistant', + content: ( + + ), + hasPadding: false, + resizable: true, + scrollable: false, + }, +]; + +const InDrawerLayoutComponent: StoryFn = ({ + assistantName, + variant: _variant, + darkMode, +}) => { + return ( + +
+ + + +
+
+ ); +}; + +export const InDrawerLayout: StoryObj = { + render: InDrawerLayoutComponent, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const chatButton = canvas.getByRole('button', { + name: /MongoDB Assistant/i, + }); + await userEvent.click(chatButton); + }, + parameters: { + chromatic: { + delay: 400, + }, + }, +}; diff --git a/chat/chat-window/src/ChatWindow/ChatWindow.styles.ts b/chat/chat-window/src/ChatWindow/ChatWindow.styles.ts index 39f9086720..e51961b348 100644 --- a/chat/chat-window/src/ChatWindow/ChatWindow.styles.ts +++ b/chat/chat-window/src/ChatWindow/ChatWindow.styles.ts @@ -11,12 +11,15 @@ import { } from '@leafygreen-ui/tokens'; const baseContainerStyles = css` + overflow: hidden; + position: relative; width: 100%; + height: 100%; + max-height: 100%; justify-self: center; display: flex; flex-direction: column; - justify-content: space-between; - position: relative; + align-items: center; `; const getSpaciousContainerStyles = (theme: Theme) => css` @@ -47,10 +50,8 @@ export const getContainerStyles = ({ className, ); -export const contentContainerStyles = css` - display: flex; - flex-direction: column; - align-items: center; +export const hiddenSpacerStyles = css` + flex: 1; `; const baseInputBarWrapperStyles = css` diff --git a/chat/chat-window/src/ChatWindow/ChatWindow.tsx b/chat/chat-window/src/ChatWindow/ChatWindow.tsx index 18c8148a96..d9123d94b2 100644 --- a/chat/chat-window/src/ChatWindow/ChatWindow.tsx +++ b/chat/chat-window/src/ChatWindow/ChatWindow.tsx @@ -13,10 +13,10 @@ import { isComponentType } from '@leafygreen-ui/lib'; import { breakpoints } from '@leafygreen-ui/tokens'; import { - contentContainerStyles, getContainerStyles, getInputBarStyles, getInputBarWrapperStyles, + hiddenSpacerStyles, } from './ChatWindow.styles'; import { ChatWindowProps } from './ChatWindow.types'; @@ -77,7 +77,9 @@ export const ChatWindow = forwardRef( iconSlot={iconSlot} /> )} -
{renderedChildren}
+ {/* Hidden spacer to push messages and input bar to bottom when content is shorter than container */} + ); diff --git a/chat/chat-window/src/utils/baseMessages.ts b/chat/chat-window/src/utils/baseMessages.ts index 567d64ed55..7083f1bdcb 100644 --- a/chat/chat-window/src/utils/baseMessages.ts +++ b/chat/chat-window/src/utils/baseMessages.ts @@ -12,12 +12,6 @@ const baseMessages: Array = [ }, { id: 2, - messageBody: `This thing is \`something\`.`, - isMongo: true, - sourceType: 'text', - }, - { - id: 3, messageBody: `This should do the trick.\n \`\`\`typescript type HelloWorld = "Hello, world!" @@ -25,24 +19,22 @@ type HelloWorld = "Hello, world!" function helloWorld() { return "Hello, world!" satisfies HelloWorld; } -\`\`\` - `, +\`\`\``, isMongo: true, - hasMessageRating: true, + hasMessageActions: true, }, { - id: 4, + id: 3, messageBody: 'How about another question?', userName: 'Sean Park', }, { - id: 5, + id: 4, messageBody: `Sorry, MongoAI can't do that right now. -Refer to [LeafyGreen UI](mongodb.design) or [LeafyGreen UI](mongodb.design) for more details. I'm filling out this space to see if the message will line up to the right side. - `, +Refer to [LeafyGreen UI](mongodb.design) or [LeafyGreen UI](mongodb.design) for more details. I'm filling out this space to see if the message will line up to the right side.`, isMongo: true, - hasMessageRating: true, + hasMessageActions: true, }, ]; diff --git a/chat/chat-window/tsconfig.json b/chat/chat-window/tsconfig.json index 6cf9a64f5d..735a98098e 100644 --- a/chat/chat-window/tsconfig.json +++ b/chat/chat-window/tsconfig.json @@ -50,6 +50,9 @@ { "path": "../../packages/code" }, + { + "path": "../../packages/drawer" + }, { "path": "../../packages/emotion" }, diff --git a/chat/fixed-chat-window/src/FixedChatWindow.stories.tsx b/chat/fixed-chat-window/src/FixedChatWindow.stories.tsx index 88eca54229..602759bb55 100644 --- a/chat/fixed-chat-window/src/FixedChatWindow.stories.tsx +++ b/chat/fixed-chat-window/src/FixedChatWindow.stories.tsx @@ -1,7 +1,10 @@ import React, { useState } from 'react'; import { Avatar } from '@lg-chat/avatar'; import { InputBar } from '@lg-chat/input-bar'; -import { LeafyGreenChatProvider } from '@lg-chat/leafygreen-chat-provider'; +import { + LeafyGreenChatProvider, + Variant, +} from '@lg-chat/leafygreen-chat-provider'; import { Message } from '@lg-chat/message'; import { MessageFeed } from '@lg-chat/message-feed'; import { WithMessageRating as MessageFeedbackStory } from '@lg-chat/message-feedback/stories'; @@ -27,9 +30,7 @@ const meta: StoryMetaType = { StoryFn => (
@@ -93,7 +94,7 @@ export const Uncontrolled: StoryFn = props => { return (
- + = props => { return (
- + = props => { return (
- + -
+
{children}
diff --git a/chat/message-feed/src/MessageFeed/MessageFeed.styles.ts b/chat/message-feed/src/MessageFeed/MessageFeed.styles.ts index db19c30146..9228d3bdd1 100644 --- a/chat/message-feed/src/MessageFeed/MessageFeed.styles.ts +++ b/chat/message-feed/src/MessageFeed/MessageFeed.styles.ts @@ -3,10 +3,8 @@ import { Theme } from '@leafygreen-ui/lib'; import { palette } from '@leafygreen-ui/palette'; import { addOverflowShadow, Side } from '@leafygreen-ui/tokens'; -const DEFAULT_MESSAGE_FEED_HEIGHT = 500; - const baseWrapperStyles = css` - height: ${DEFAULT_MESSAGE_FEED_HEIGHT}px; + max-height: 100%; width: 100%; display: flex; justify-content: center; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b2ecb5c08..882baae377 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -365,6 +365,9 @@ importers: specifier: ^2.2.1 version: 2.2.1(react@18.3.1) devDependencies: + '@leafygreen-ui/drawer': + specifier: workspace:^ + version: link:../../packages/drawer '@lg-chat/avatar': specifier: workspace:^ version: link:../avatar @@ -386,6 +389,9 @@ importers: '@lg-tools/build': specifier: workspace:^ version: link:../../tools/build + '@storybook/test': + specifier: ^8.6.14 + version: 8.6.14(storybook@8.6.14(prettier@2.8.8)) chat/fixed-chat-window: dependencies: