LibreChat/client/src/components/Chat/Messages/Content/DialogImage.tsx

444 lines
14 KiB
TypeScript
Raw Normal View History

import { useState, useEffect, useCallback, useRef } from 'react';
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { Button, TooltipAnchor } from '@librechat/client';
import { X, ArrowDownToLine, PanelLeftOpen, PanelLeftClose, RotateCcw } from 'lucide-react';
import { useLocalize } from '~/hooks';
const getQualityStyles = (quality: string): string => {
if (quality === 'high') {
return 'bg-green-100 text-green-800';
}
if (quality === 'low') {
return 'bg-orange-100 text-orange-800';
}
return 'bg-gray-100 text-gray-800';
};
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
export default function DialogImage({
isOpen,
onOpenChange,
src = '',
downloadImage,
args,
triggerRef,
}: {
isOpen: boolean;
onOpenChange: (open: boolean) => void;
src?: string;
downloadImage: () => void;
args?: {
prompt?: string;
quality?: string;
size?: string;
[key: string]: unknown;
};
triggerRef?: React.RefObject<HTMLButtonElement>;
}) {
const localize = useLocalize();
const [isPromptOpen, setIsPromptOpen] = useState(false);
const [imageSize, setImageSize] = useState<string | null>(null);
// Zoom and pan state
const [zoom, setZoom] = useState(1);
const [panX, setPanX] = useState(0);
const [panY, setPanY] = useState(0);
const [isDragging, setIsDragging] = useState(false);
const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
const containerRef = useRef<HTMLDivElement>(null);
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
const imageRef = useRef<HTMLImageElement>(null);
const closeButtonRef = useRef<HTMLButtonElement>(null);
const getImageSize = useCallback(async (url: string) => {
try {
const response = await fetch(url, { method: 'HEAD' });
const contentLength = response.headers.get('Content-Length');
if (contentLength) {
const bytes = parseInt(contentLength, 10);
return formatFileSize(bytes);
}
const fullResponse = await fetch(url);
const blob = await fullResponse.blob();
return formatFileSize(blob.size);
} catch (error) {
console.error('Error getting image size:', error);
return null;
}
}, []);
const formatFileSize = (bytes: number): string => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
const resetZoom = useCallback(() => {
setZoom(1);
setPanX(0);
setPanY(0);
}, []);
const getCursor = () => {
if (zoom <= 1) return 'default';
return isDragging ? 'grabbing' : 'grab';
};
const handleDoubleClick = useCallback(() => {
if (zoom > 1) {
resetZoom();
} else {
setZoom(2);
}
}, [zoom, resetZoom]);
const handleWheel = useCallback(
(e: React.WheelEvent<HTMLDivElement>) => {
e.preventDefault();
if (!containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
const newZoom = Math.min(Math.max(zoom * zoomFactor, 1), 5);
if (newZoom === zoom) return;
if (newZoom === 1) {
setZoom(1);
setPanX(0);
setPanY(0);
return;
}
const containerCenterX = rect.width / 2;
const containerCenterY = rect.height / 2;
const zoomRatio = newZoom / zoom;
const deltaX = (mouseX - containerCenterX - panX) * (zoomRatio - 1);
const deltaY = (mouseY - containerCenterY - panY) * (zoomRatio - 1);
setZoom(newZoom);
setPanX(panX - deltaX);
setPanY(panY - deltaY);
},
[zoom, panX, panY],
);
const handleMouseDown = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault();
if (zoom <= 1) return;
setIsDragging(true);
setDragStart({
x: e.clientX - panX,
y: e.clientY - panY,
});
},
[zoom, panX, panY],
);
const handleMouseMove = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
if (!isDragging || zoom <= 1) return;
const newPanX = e.clientX - dragStart.x;
const newPanY = e.clientY - dragStart.y;
setPanX(newPanX);
setPanY(newPanY);
},
[isDragging, dragStart, zoom],
);
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
const handleMouseUp = useCallback(() => {
setIsDragging(false);
}, []);
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
// Handle click on empty areas to close (only if clicking overlay/content directly, not children)
const handleBackgroundClick = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
// Only close if clicking directly on overlay/content background
if (e.target !== e.currentTarget) {
return;
}
// Don't close if zoomed (user might be panning)
if (zoom > 1) {
return;
}
onOpenChange(false);
},
[onOpenChange, zoom],
);
useEffect(() => {
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
if (!isOpen) return;
const onKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
if (zoom > 1) {
resetZoom();
} else {
onOpenChange(false);
}
}
};
document.addEventListener('keydown', onKey);
return () => document.removeEventListener('keydown', onKey);
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
}, [resetZoom, onOpenChange, isOpen, zoom]);
useEffect(() => {
if (isOpen && src) {
getImageSize(src).then(setImageSize);
resetZoom();
}
}, [isOpen, src, getImageSize, resetZoom]);
useEffect(() => {
if (zoom === 1) {
setPanX(0);
setPanY(0);
}
}, [zoom]);
useEffect(() => {
if (zoom === 1) {
setPanX(0);
setPanY(0);
}
}, [isPromptOpen, zoom]);
feat: Vision Support + New UI (#1203) * feat: add timer duration to showToast, show toast for preset selection * refactor: replace old /chat/ route with /c/. e2e tests will fail here * refactor: move typedefs to root of /api/ and add a few to assistant types in TS * refactor: reorganize data-provider imports, fix dependency cycle, strategize new plan to separate react dependent packages * feat: add dataService for uploading images * feat(data-provider): add mutation keys * feat: file resizing and upload * WIP: initial API image handling * fix: catch JSON.parse of localStorage tools * chore: experimental: use module-alias for absolute imports * refactor: change temp_file_id strategy * fix: updating files state by using Map and defining react query callbacks in a way that keeps them during component unmount, initial delete handling * feat: properly handle file deletion * refactor: unexpose complete filepath and resize from server for higher fidelity * fix: make sure resized height, width is saved, catch bad requests * refactor: use absolute imports * fix: prevent setOptions from being called more than once for OpenAIClient, made note to fix for PluginsClient * refactor: import supportsFiles and models vars from schemas * fix: correctly replace temp file id * refactor(BaseClient): use absolute imports, pass message 'opts' to buildMessages method, count tokens for nested objects/arrays * feat: add validateVisionModel to determine if model has vision capabilities * chore(checkBalance): update jsdoc * feat: formatVisionMessage: change message content format dependent on role and image_urls passed * refactor: add usage to File schema, make create and updateFile, correctly set and remove TTL * feat: working vision support TODO: file size, type, amount validations, making sure they are styled right, and making sure you can add images from the clipboard/dragging * feat: clipboard support for uploading images * feat: handle files on drop to screen, refactor top level view code to Presentation component so the useDragHelpers hook has ChatContext * fix(Images): replace uploaded images in place * feat: add filepath validation to protect sensitive files * fix: ensure correct file_ids are push and not the Map key values * fix(ToastContext): type issue * feat: add basic file validation * fix(useDragHelpers): correct context issue with `files` dependency * refactor: consolidate setErrors logic to setError * feat: add dialog Image overlay on image click * fix: close endpoints menu on click * chore: set detail to auto, make note for configuration * fix: react warning (button desc. of button) * refactor: optimize filepath handling, pass file_ids to images for easier re-use * refactor: optimize image file handling, allow re-using files in regen, pass more file metadata in messages * feat: lazy loading images including use of upload preview * fix: SetKeyDialog closing, stopPropagation on Dialog content click * style(EndpointMenuItem): tighten up the style, fix dark theme showing in lightmode, make menu more ux friendly * style: change maxheight of all settings textareas to 138px from 300px * style: better styling for textarea and enclosing buttons * refactor(PresetItems): swap back edit and delete icons * feat: make textarea placeholder dynamic to endpoint * style: show user hover buttons only on hover when message is streaming * fix: ordered list not going past 9, fix css * feat: add User/AI labels; style: hide loading spinner * feat: add back custom footer, change original footer text * feat: dynamic landing icons based on endpoint * chore: comment out assistants route * fix: autoScroll to newest on /c/ view * fix: Export Conversation on new UI * style: match message style of official more closely * ci: fix api jest unit tests, comment out e2e tests for now as they will fail until addressed * feat: more file validation and use blob in preview field, not filepath, to fix temp deletion * feat: filefilter for multer * feat: better AI labels based on custom name, model, and endpoint instead of `ChatGPT`
2023-11-21 20:12:48 -05:00
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
// Lock body scroll when dialog is open
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
return () => {
document.body.style.overflow = '';
};
}, [isOpen]);
const imageDetailsLabel = isPromptOpen
? localize('com_ui_hide_image_details')
: localize('com_ui_show_image_details');
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
// Calculate image max dimensions accounting for side panel (w-80 = 320px)
const getImageMaxWidth = () => {
if (isPromptOpen) {
// On mobile, panel overlays so use full width; on desktop, subtract panel width
return typeof window !== 'undefined' && window.innerWidth >= 640
? 'calc(90vw - 320px)'
: '90vw';
}
return '90vw';
};
feat: Vision Support + New UI (#1203) * feat: add timer duration to showToast, show toast for preset selection * refactor: replace old /chat/ route with /c/. e2e tests will fail here * refactor: move typedefs to root of /api/ and add a few to assistant types in TS * refactor: reorganize data-provider imports, fix dependency cycle, strategize new plan to separate react dependent packages * feat: add dataService for uploading images * feat(data-provider): add mutation keys * feat: file resizing and upload * WIP: initial API image handling * fix: catch JSON.parse of localStorage tools * chore: experimental: use module-alias for absolute imports * refactor: change temp_file_id strategy * fix: updating files state by using Map and defining react query callbacks in a way that keeps them during component unmount, initial delete handling * feat: properly handle file deletion * refactor: unexpose complete filepath and resize from server for higher fidelity * fix: make sure resized height, width is saved, catch bad requests * refactor: use absolute imports * fix: prevent setOptions from being called more than once for OpenAIClient, made note to fix for PluginsClient * refactor: import supportsFiles and models vars from schemas * fix: correctly replace temp file id * refactor(BaseClient): use absolute imports, pass message 'opts' to buildMessages method, count tokens for nested objects/arrays * feat: add validateVisionModel to determine if model has vision capabilities * chore(checkBalance): update jsdoc * feat: formatVisionMessage: change message content format dependent on role and image_urls passed * refactor: add usage to File schema, make create and updateFile, correctly set and remove TTL * feat: working vision support TODO: file size, type, amount validations, making sure they are styled right, and making sure you can add images from the clipboard/dragging * feat: clipboard support for uploading images * feat: handle files on drop to screen, refactor top level view code to Presentation component so the useDragHelpers hook has ChatContext * fix(Images): replace uploaded images in place * feat: add filepath validation to protect sensitive files * fix: ensure correct file_ids are push and not the Map key values * fix(ToastContext): type issue * feat: add basic file validation * fix(useDragHelpers): correct context issue with `files` dependency * refactor: consolidate setErrors logic to setError * feat: add dialog Image overlay on image click * fix: close endpoints menu on click * chore: set detail to auto, make note for configuration * fix: react warning (button desc. of button) * refactor: optimize filepath handling, pass file_ids to images for easier re-use * refactor: optimize image file handling, allow re-using files in regen, pass more file metadata in messages * feat: lazy loading images including use of upload preview * fix: SetKeyDialog closing, stopPropagation on Dialog content click * style(EndpointMenuItem): tighten up the style, fix dark theme showing in lightmode, make menu more ux friendly * style: change maxheight of all settings textareas to 138px from 300px * style: better styling for textarea and enclosing buttons * refactor(PresetItems): swap back edit and delete icons * feat: make textarea placeholder dynamic to endpoint * style: show user hover buttons only on hover when message is streaming * fix: ordered list not going past 9, fix css * feat: add User/AI labels; style: hide loading spinner * feat: add back custom footer, change original footer text * feat: dynamic landing icons based on endpoint * chore: comment out assistants route * fix: autoScroll to newest on /c/ view * fix: Export Conversation on new UI * style: match message style of official more closely * ci: fix api jest unit tests, comment out e2e tests for now as they will fail until addressed * feat: more file validation and use blob in preview field, not filepath, to fix temp deletion * feat: filefilter for multer * feat: better AI labels based on custom name, model, and endpoint instead of `ChatGPT`
2023-11-21 20:12:48 -05:00
return (
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<DialogPrimitive.Root open={isOpen} onOpenChange={onOpenChange}>
<DialogPrimitive.Portal>
<DialogPrimitive.Overlay
className="fixed inset-0 z-[100] bg-black/90"
onClick={handleBackgroundClick}
/>
<DialogPrimitive.Content
className="fixed inset-0 z-[100] flex items-center justify-center outline-none"
onOpenAutoFocus={(e) => {
e.preventDefault();
closeButtonRef.current?.focus();
}}
onCloseAutoFocus={(e) => {
e.preventDefault();
triggerRef?.current?.focus();
}}
onPointerDownOutside={(e) => e.preventDefault()}
onClick={handleBackgroundClick}
>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
{/* Close button - top left */}
<div className="absolute left-4 top-4 z-20">
<TooltipAnchor
description={localize('com_ui_close')}
render={
<Button
ref={closeButtonRef}
onClick={() => onOpenChange(false)}
variant="ghost"
className="h-10 w-10 p-0 text-white hover:bg-white/10"
aria-label={localize('com_ui_close')}
>
<X className="size-6" aria-hidden="true" />
</Button>
}
/>
</div>
{/* Action buttons - top right (336px = 320px panel + 16px gap) */}
<div
className={`absolute top-4 z-20 flex items-center gap-2 transition-[right] duration-300 ${isPromptOpen ? 'right-[336px]' : 'right-4'}`}
>
{zoom > 1 && (
<TooltipAnchor
description={localize('com_ui_reset_zoom')}
render={
<Button
onClick={resetZoom}
variant="ghost"
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
className="h-10 w-10 p-0 text-white hover:bg-white/10"
aria-label={localize('com_ui_reset_zoom')}
>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<RotateCcw className="size-5" aria-hidden="true" />
</Button>
}
/>
)}
<TooltipAnchor
description={localize('com_ui_download')}
render={
<Button
onClick={() => downloadImage()}
variant="ghost"
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
className="h-10 w-10 p-0 text-white hover:bg-white/10"
aria-label={localize('com_ui_download')}
>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<ArrowDownToLine className="size-5" aria-hidden="true" />
</Button>
}
/>
<TooltipAnchor
description={imageDetailsLabel}
render={
<Button
onClick={() => setIsPromptOpen(!isPromptOpen)}
variant="ghost"
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
className="h-10 w-10 p-0 text-white hover:bg-white/10"
aria-label={imageDetailsLabel}
>
{isPromptOpen ? (
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<PanelLeftOpen className="size-5" aria-hidden="true" />
) : (
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<PanelLeftClose className="size-5" aria-hidden="true" />
)}
</Button>
}
/>
</div>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
{/* Image container - centered */}
<div
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
className={`transition-[margin] duration-300 ${isPromptOpen ? 'mr-80' : ''}`}
onClick={(e) => e.stopPropagation()}
>
<div
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
ref={containerRef}
className="relative"
onWheel={handleWheel}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
onDoubleClick={handleDoubleClick}
style={{ cursor: getCursor() }}
>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<div
className="transition-transform duration-100 ease-out"
style={{
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
transform: `translate(${panX}px, ${panY}px) scale(${zoom})`,
transformOrigin: 'center center',
}}
>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<img
ref={imageRef}
src={src}
alt="Image"
className="block max-h-[85vh] object-contain"
style={{
maxWidth: getImageMaxWidth(),
}}
draggable={false}
/>
</div>
</div>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
</div>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
{/* Side Panel */}
<div
data-side-panel
className={`fixed right-0 top-0 z-30 h-full w-80 transform border-l border-white/10 bg-surface-primary shadow-2xl transition-transform duration-300 ${
isPromptOpen ? 'translate-x-0' : 'translate-x-full'
}`}
onClick={(e) => e.stopPropagation()}
>
<div className="h-full overflow-y-auto p-6">
<div className="mb-4 flex items-center justify-between">
<h3 className="text-lg font-semibold text-text-primary">
{localize('com_ui_image_details')}
</h3>
<Button
onClick={() => setIsPromptOpen(false)}
variant="ghost"
className="h-10 w-10 p-0 sm:hidden"
>
<X className="size-5" aria-hidden="true" />
</Button>
</div>
<div className="mb-4 h-px bg-border-medium"></div>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
<div className="space-y-6">
{/* Prompt Section */}
<div>
<h4 className="mb-2 text-sm font-medium text-text-primary">
{localize('com_ui_prompt')}
</h4>
<div className="rounded-md bg-surface-tertiary p-3">
<p className="text-sm leading-relaxed text-text-primary">
{args?.prompt || 'No prompt available'}
</p>
</div>
</div>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
{/* Generation Settings */}
<div>
<h4 className="mb-3 text-sm font-medium text-text-primary">
{localize('com_ui_generation_settings')}
</h4>
<div className="space-y-3">
<div className="flex items-center justify-between">
<span className="text-sm text-text-primary">{localize('com_ui_size')}:</span>
<span className="text-sm font-medium text-text-primary">
{args?.size || 'Unknown'}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-text-primary">
{localize('com_ui_quality')}:
</span>
<span
className={`rounded px-2 py-1 text-xs font-medium capitalize ${getQualityStyles(args?.quality || '')}`}
>
{args?.quality || 'Standard'}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-text-primary">
{localize('com_ui_file_size')}:
</span>
<span className="text-sm font-medium text-text-primary">
{imageSize || 'Loading...'}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
🏞️ fix: Image Preview Refactor with Accessibility Enhancements (#11217) * 🔧 fix: Prevent race condition by saving user messages before final event in ResumableAgentController - Updated the ResumableAgentController to save user messages prior to sending the final event. This change addresses a potential race condition where the client might refetch data before the database is updated. - Removed redundant message saving logic that was previously located after the final event handling, ensuring a more reliable message processing flow. * style: improve image preview dialogs with ChatGPT-like UX and accessibility Refactored image preview dialogs (DialogImage and ImagePreview) to provide a cleaner, more intuitive user experience similar to ChatGPT's implementation. ## DialogImage.tsx (generated images) - Replaced OGDialog/OGDialogContent with direct Radix Dialog primitives for finer control over behavior - Full-screen dark overlay (bg-black/90) that closes on click outside image - Restructured component so all interactive elements (close, download, details panel buttons) are inside DialogPrimitive.Content for proper focus trap and keyboard navigation - Added onOpenAutoFocus to focus close button when dialog opens - Added onCloseAutoFocus to return focus to trigger element on close - Added triggerRef prop to enable focus restoration - Removed animate-in/animate-out classes that caused stuttering on open - Changed transition-all to transition-[margin] to prevent animation jank - Added proper TypeScript types for component props ## ImagePreview.tsx (uploaded file thumbnails) - Same Radix Dialog primitive refactor for consistent behavior - Click-outside-to-close functionality - Proper focus management with closeButtonRef and triggerRef - Made button the container element to prevent focus ring clipping - Added focus-visible ring styling for keyboard navigation visibility ## Image.tsx (image display component) - Restructured so button is the outer container instead of being nested inside a div with overflow-hidden (which was clipping focus ring) - Added visible focus-visible:ring styling with ring-offset - Added aria-haspopup="dialog" for screen reader context - Added triggerRef and passed to DialogImage for focus restoration ## Accessibility improvements - Keyboard navigation now works properly (Tab cycles through buttons) - Escape key closes dialog (or resets zoom if zoomed in) - Focus is trapped within dialog when open - Focus returns to trigger element when dialog closes - Visible focus indicators on image buttons when focused via keyboard - Proper ARIA attributes (aria-label, aria-haspopup, aria-hidden) ## UX improvements - Click anywhere outside the image to close (not just specific regions) - No more weird scroll/navigation issues - Instant dialog open without stuttering animations - Clean, minimal overlay without container/header chrome * refactor: Improve click handling in image preview dialogs Updated the click handling logic in ImagePreview and DialogImage components to ensure that the dialog only closes when clicking directly on the overlay or content background, enhancing user experience by preventing unintended closures when interacting with child elements. Additionally, clarified comments to reflect the new behavior. * chore: import order
2026-01-05 16:31:35 -05:00
</DialogPrimitive.Content>
</DialogPrimitive.Portal>
</DialogPrimitive.Root>
feat: Vision Support + New UI (#1203) * feat: add timer duration to showToast, show toast for preset selection * refactor: replace old /chat/ route with /c/. e2e tests will fail here * refactor: move typedefs to root of /api/ and add a few to assistant types in TS * refactor: reorganize data-provider imports, fix dependency cycle, strategize new plan to separate react dependent packages * feat: add dataService for uploading images * feat(data-provider): add mutation keys * feat: file resizing and upload * WIP: initial API image handling * fix: catch JSON.parse of localStorage tools * chore: experimental: use module-alias for absolute imports * refactor: change temp_file_id strategy * fix: updating files state by using Map and defining react query callbacks in a way that keeps them during component unmount, initial delete handling * feat: properly handle file deletion * refactor: unexpose complete filepath and resize from server for higher fidelity * fix: make sure resized height, width is saved, catch bad requests * refactor: use absolute imports * fix: prevent setOptions from being called more than once for OpenAIClient, made note to fix for PluginsClient * refactor: import supportsFiles and models vars from schemas * fix: correctly replace temp file id * refactor(BaseClient): use absolute imports, pass message 'opts' to buildMessages method, count tokens for nested objects/arrays * feat: add validateVisionModel to determine if model has vision capabilities * chore(checkBalance): update jsdoc * feat: formatVisionMessage: change message content format dependent on role and image_urls passed * refactor: add usage to File schema, make create and updateFile, correctly set and remove TTL * feat: working vision support TODO: file size, type, amount validations, making sure they are styled right, and making sure you can add images from the clipboard/dragging * feat: clipboard support for uploading images * feat: handle files on drop to screen, refactor top level view code to Presentation component so the useDragHelpers hook has ChatContext * fix(Images): replace uploaded images in place * feat: add filepath validation to protect sensitive files * fix: ensure correct file_ids are push and not the Map key values * fix(ToastContext): type issue * feat: add basic file validation * fix(useDragHelpers): correct context issue with `files` dependency * refactor: consolidate setErrors logic to setError * feat: add dialog Image overlay on image click * fix: close endpoints menu on click * chore: set detail to auto, make note for configuration * fix: react warning (button desc. of button) * refactor: optimize filepath handling, pass file_ids to images for easier re-use * refactor: optimize image file handling, allow re-using files in regen, pass more file metadata in messages * feat: lazy loading images including use of upload preview * fix: SetKeyDialog closing, stopPropagation on Dialog content click * style(EndpointMenuItem): tighten up the style, fix dark theme showing in lightmode, make menu more ux friendly * style: change maxheight of all settings textareas to 138px from 300px * style: better styling for textarea and enclosing buttons * refactor(PresetItems): swap back edit and delete icons * feat: make textarea placeholder dynamic to endpoint * style: show user hover buttons only on hover when message is streaming * fix: ordered list not going past 9, fix css * feat: add User/AI labels; style: hide loading spinner * feat: add back custom footer, change original footer text * feat: dynamic landing icons based on endpoint * chore: comment out assistants route * fix: autoScroll to newest on /c/ view * fix: Export Conversation on new UI * style: match message style of official more closely * ci: fix api jest unit tests, comment out e2e tests for now as they will fail until addressed * feat: more file validation and use blob in preview field, not filepath, to fix temp deletion * feat: filefilter for multer * feat: better AI labels based on custom name, model, and endpoint instead of `ChatGPT`
2023-11-21 20:12:48 -05:00
);
}