diff --git a/web/app/components/base/chat/chat/answer/__tests__/operation.spec.tsx b/web/app/components/base/chat/chat/answer/__tests__/operation.spec.tsx
index 094c5c987b..4eb8f37f19 100644
--- a/web/app/components/base/chat/chat/answer/__tests__/operation.spec.tsx
+++ b/web/app/components/base/chat/chat/answer/__tests__/operation.spec.tsx
@@ -248,6 +248,13 @@ describe('Operation', () => {
expect(screen.getByTestId('log-btn'))!.toBeInTheDocument()
})
+ it('should keep hover-only controls visible when a descendant popup is open', () => {
+ renderOperation({ ...baseProps, showPromptLog: true })
+
+ expect(screen.getByTestId('operation-actions')).toHaveClass('group-has-[[data-popup-open]]:flex')
+ expect(screen.getByTestId('log-btn').parentElement).toHaveClass('group-has-[[data-popup-open]]:block')
+ })
+
it('should not show prompt log for opening statements', () => {
const item = { ...baseItem, isOpeningStatement: true }
renderOperation({ ...baseProps, item, showPromptLog: true })
diff --git a/web/app/components/base/chat/chat/answer/operation.tsx b/web/app/components/base/chat/chat/answer/operation.tsx
index 6804271d64..178a5e8e3c 100644
--- a/web/app/components/base/chat/chat/answer/operation.tsx
+++ b/web/app/components/base/chat/chat/answer/operation.tsx
@@ -41,6 +41,8 @@ type FeedbackTooltipProps = {
}
const feedbackTooltipClassName = 'max-w-[260px]'
+const answerActiveFlexClassName = 'group-hover:flex group-has-[[data-popup-open]]:flex'
+const answerActiveBlockClassName = 'group-hover:block group-has-[[data-popup-open]]:block'
const FeedbackTooltip = ({ content, children }: FeedbackTooltipProps) => {
return (
@@ -199,7 +201,7 @@ function Operation({
{shouldShowUserFeedbackBar && !humanInputFormDataList?.length && (
{hasUserFeedback
@@ -241,7 +243,7 @@ function Operation({
{shouldShowAdminFeedbackBar && !humanInputFormDataList?.length && (
{displayUserFeedback?.rating && (
@@ -308,12 +310,12 @@ function Operation({
)}
{showPromptLog && !isOpeningStatement && (
-
+
)}
{!isOpeningStatement && (
-
+
{(config?.text_to_speech?.enabled && !humanInputFormDataList?.length) && (
{
expect(linkButton.closest('button')).toBeInTheDocument()
})
+ it('should keep upload button layout stable when remote_url popup opens', () => {
+ render(
+ ,
+ )
+
+ const localButton = screen.getByText(/fileUploader\.uploadFromComputer/).closest('button')
+ const linkButton = screen.getByText(/fileUploader\.pasteFileLink/).closest('button')
+ const uploadGroup = localButton?.parentElement?.parentElement
+
+ expect(uploadGroup?.children).toHaveLength(2)
+
+ fireEvent.click(linkButton!)
+
+ expect(uploadGroup?.children).toHaveLength(2)
+ expect(linkButton).toHaveAttribute('data-popup-open')
+ expect(localButton?.parentElement).toHaveClass('min-w-0', 'flex-1')
+ expect(linkButton?.parentElement).toHaveClass('min-w-0', 'flex-1')
+ expect(linkButton).toHaveClass('w-full', 'min-w-0')
+ })
+
it('should disable upload buttons when file limit is reached', () => {
const files = [
createFile({ id: 'f1' }),
diff --git a/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx b/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx
index b532bb7773..886b7ef4cc 100644
--- a/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx
+++ b/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx
@@ -55,13 +55,12 @@ const FileUploaderInAttachment = ({
const renderButton = useCallback((option: Option, open?: boolean) => {
return (