Frontend audit: refinements (#2083)

* (fix:attachements) sep id for redux ops

* (fix:ui) popups, toast, share modal

* (feat:agentsPreview) stable preview, ui fixes

* (fix:ui) light theme icon, sleek scroll

---------

Co-authored-by: GH Action - Upstream Sync <action@github.com>
This commit is contained in:
Manish Madan
2025-10-22 14:42:05 +05:30
committed by GitHub
parent 5aa4ec1b9f
commit c4e8daf50e
21 changed files with 121 additions and 86 deletions

View File

@@ -91,8 +91,10 @@ export default function MessageInput({
const apiHost = import.meta.env.VITE_API_HOST;
const xhr = new XMLHttpRequest();
const uniqueId = crypto.randomUUID();
const newAttachment = {
id: uniqueId,
fileName: file.name,
progress: 0,
status: 'uploading' as const,
@@ -106,7 +108,7 @@ export default function MessageInput({
const progress = Math.round((event.loaded / event.total) * 100);
dispatch(
updateAttachment({
taskId: newAttachment.taskId,
id: uniqueId,
updates: { progress },
}),
);
@@ -119,7 +121,7 @@ export default function MessageInput({
if (response.task_id) {
dispatch(
updateAttachment({
taskId: newAttachment.taskId,
id: uniqueId,
updates: {
taskId: response.task_id,
status: 'processing',
@@ -131,7 +133,7 @@ export default function MessageInput({
} else {
dispatch(
updateAttachment({
taskId: newAttachment.taskId,
id: uniqueId,
updates: { status: 'failed' },
}),
);
@@ -141,7 +143,7 @@ export default function MessageInput({
xhr.onerror = () => {
dispatch(
updateAttachment({
taskId: newAttachment.taskId,
id: uniqueId,
updates: { status: 'failed' },
}),
);
@@ -167,7 +169,7 @@ export default function MessageInput({
if (data.status === 'SUCCESS') {
dispatch(
updateAttachment({
taskId: attachment.taskId!,
id: attachment.id,
updates: {
status: 'completed',
progress: 100,
@@ -179,14 +181,14 @@ export default function MessageInput({
} else if (data.status === 'FAILURE') {
dispatch(
updateAttachment({
taskId: attachment.taskId!,
id: attachment.id,
updates: { status: 'failed' },
}),
);
} else if (data.status === 'PROGRESS' && data.result?.current) {
dispatch(
updateAttachment({
taskId: attachment.taskId!,
id: attachment.id,
updates: { progress: data.result.current },
}),
);
@@ -195,7 +197,7 @@ export default function MessageInput({
.catch(() => {
dispatch(
updateAttachment({
taskId: attachment.taskId!,
id: attachment.id,
updates: { status: 'failed' },
}),
);
@@ -260,12 +262,12 @@ export default function MessageInput({
};
return (
<div className="mx-2 flex w-full flex-col">
<div className="flex w-full flex-col">
<div className="border-dark-gray bg-lotion dark:border-grey relative flex w-full flex-col rounded-[23px] border dark:bg-transparent">
<div className="flex flex-wrap gap-1.5 px-2 py-2 sm:gap-2 sm:px-3">
{attachments.map((attachment, index) => (
{attachments.map((attachment) => (
<div
key={index}
key={attachment.id}
className={`group dark:text-bright-gray relative flex items-center rounded-xl bg-[#EFF3F4] px-2 py-1 text-[12px] text-[#5D5D5D] sm:px-3 sm:py-1.5 sm:text-[14px] dark:bg-[#393B3D] ${
attachment.status !== 'completed' ? 'opacity-70' : 'opacity-100'
}`}
@@ -327,11 +329,7 @@ export default function MessageInput({
<button
className="ml-1.5 flex items-center justify-center rounded-full p-1"
onClick={() => {
if (attachment.id) {
dispatch(removeAttachment(attachment.id));
} else if (attachment.taskId) {
dispatch(removeAttachment(attachment.taskId));
}
dispatch(removeAttachment(attachment.id));
}}
aria-label={t('conversation.attachments.remove')}
>

View File

@@ -33,7 +33,7 @@ export default function Sidebar({
return (
<div ref={sidebarRef} className="h-vh relative">
<div
className={`dark:bg-chinese-black fixed top-0 right-0 z-50 h-full w-72 transform bg-white shadow-xl transition-all duration-300 sm:w-96 ${
className={`dark:bg-chinese-black fixed top-0 right-0 z-50 h-full w-64 transform bg-white shadow-xl transition-all duration-300 sm:w-80 ${
isOpen ? 'translate-x-[10px]' : 'translate-x-full'
} border-l border-[#9ca3af]/10`}
>

View File

@@ -1,4 +1,5 @@
import React, { useRef, useEffect, useState, useLayoutEffect } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { Doc } from '../models/misc';
@@ -107,7 +108,7 @@ export default function SourcesPopup({
onClose();
};
return (
const popupContent = (
<div
ref={popupRef}
className="bg-lotion dark:bg-charleston-green-2 fixed z-50 flex flex-col rounded-xl shadow-[0px_9px_46px_8px_#0000001F,0px_24px_38px_3px_#00000024,0px_11px_15px_-7px_#00000033]"
@@ -218,7 +219,7 @@ export default function SourcesPopup({
</>
) : (
<div className="dark:text-bright-gray p-4 text-center text-gray-500 dark:text-[14px]">
{t('noSourcesAvailable')}
{t('conversation.sources.noSourcesAvailable')}
</div>
)}
</div>
@@ -245,4 +246,6 @@ export default function SourcesPopup({
</div>
</div>
);
return createPortal(popupContent, document.body);
}

View File

@@ -1,4 +1,5 @@
import React, { useEffect, useRef, useState, useLayoutEffect } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { selectToken } from '../preferences/preferenceSlice';
@@ -133,10 +134,10 @@ export default function ToolsPopup({
tool.displayName.toLowerCase().includes(searchTerm.toLowerCase()),
);
return (
const popupContent = (
<div
ref={popupRef}
className="border-light-silver bg-lotion dark:border-dim-gray dark:bg-charleston-green-2 fixed z-9999 rounded-lg border shadow-[0px_9px_46px_8px_#0000001F,0px_24px_38px_3px_#00000024,0px_11px_15px_-7px_#00000033]"
className="border-light-silver bg-lotion dark:border-dim-gray dark:bg-charleston-green-2 fixed z-50 rounded-lg border shadow-[0px_9px_46px_8px_#0000001F,0px_24px_38px_3px_#00000024,0px_11px_15px_-7px_#00000033]"
style={{
top: popupPosition.showAbove ? popupPosition.top : undefined,
bottom: popupPosition.showAbove
@@ -242,4 +243,6 @@ export default function ToolsPopup({
</div>
</div>
);
return createPortal(popupContent, document.body);
}

View File

@@ -44,7 +44,10 @@ export default function UploadToast() {
};
return (
<div className="fixed right-4 bottom-4 z-50 flex max-w-md flex-col gap-2">
<div
className="fixed right-4 bottom-4 z-50 flex max-w-md flex-col gap-2"
onMouseDown={(e) => e.stopPropagation()}
>
{uploadTasks
.filter((task) => !task.dismissed)
.map((task) => {