mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-04-03 22:37:20 +02:00
🔄 refactor: Migrate to react-resizable-panels v4 with Artifacts Header polish (#12356)
* chore: Update react-resizable-panels dependency to version 4.7.4 - Upgraded the "react-resizable-panels" package in package-lock.json, package.json, and client package.json files to ensure compatibility with the latest features and improvements. - Adjusted peer dependencies for React and ReactDOM to align with the new version requirements. * refactor: Update Share and SidePanel components to `react-resizable-panels` v4 - Refactored the ShareArtifactsContainer to utilize a new layout change handler, enhancing artifact panel resizing functionality. - Updated ArtifactsPanel to use the new `usePanelRef` hook, improving panel reference management. - Simplified SidePanelGroup by removing unnecessary layout normalization and integrating default layout handling with localStorage. - Removed the deprecated `normalizeLayout` utility function to streamline the codebase. - Adjusted Resizable components to ensure consistent sizing and layout behavior across panels. * style: Enhance scrollbar appearance across application - Added custom scrollbar styles to both artifacts and markdown files, improving aesthetics and user experience. - Implemented dark mode adjustments for scrollbar visibility, ensuring consistency across different color schemes. * style: Standardize button sizes and layout in Artifacts components - Updated button dimensions to a consistent height of 9 units across various components including Artifacts, Code, and DownloadArtifact. - Adjusted padding and layout properties in the Artifacts header for improved visual consistency. - Enhanced the Radio component to accept a new `buttonClassName` prop for better customization of button styles. * chore: import order
This commit is contained in:
parent
733a9364c0
commit
676641f3da
14 changed files with 92 additions and 118 deletions
|
|
@ -13,6 +13,7 @@ interface RadioProps {
|
|||
onChange?: (value: string) => void;
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
buttonClassName?: string;
|
||||
fullWidth?: boolean;
|
||||
'aria-labelledby'?: string;
|
||||
}
|
||||
|
|
@ -23,6 +24,7 @@ const Radio = memo(function Radio({
|
|||
onChange,
|
||||
disabled = false,
|
||||
className = '',
|
||||
buttonClassName = '',
|
||||
fullWidth = false,
|
||||
'aria-labelledby': ariaLabelledBy,
|
||||
}: RadioProps) {
|
||||
|
|
@ -45,7 +47,7 @@ const Radio = memo(function Radio({
|
|||
if (selectedButton && container) {
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const buttonRect = selectedButton.getBoundingClientRect();
|
||||
const offsetLeft = buttonRect.left - containerRect.left - 4;
|
||||
const offsetLeft = buttonRect.left - containerRect.left;
|
||||
setBackgroundStyle({
|
||||
width: `${buttonRect.width}px`,
|
||||
transform: `translateX(${offsetLeft}px)`,
|
||||
|
|
@ -94,13 +96,13 @@ const Radio = memo(function Radio({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`relative ${fullWidth ? 'flex' : 'inline-flex'} items-center rounded-lg bg-muted p-1 ${className}`}
|
||||
className={`relative ${fullWidth ? 'flex' : 'inline-flex'} items-center rounded-lg bg-muted ${className}`}
|
||||
role="radiogroup"
|
||||
aria-labelledby={ariaLabelledBy}
|
||||
>
|
||||
{selectedIndex >= 0 && isMounted && (
|
||||
<div
|
||||
className="pointer-events-none absolute inset-y-1 rounded-md border border-border/50 bg-background shadow-sm transition-all duration-300 ease-out"
|
||||
className="pointer-events-none absolute inset-y-0 rounded-md border border-border/50 bg-background shadow-sm transition-all duration-300 ease-out"
|
||||
style={backgroundStyle}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -117,7 +119,7 @@ const Radio = memo(function Radio({
|
|||
disabled={disabled}
|
||||
className={`relative z-10 flex h-[34px] items-center justify-center gap-2 rounded-md px-4 text-sm font-medium transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${
|
||||
currentValue === option.value ? 'text-foreground' : 'text-foreground'
|
||||
} ${disabled ? 'cursor-not-allowed opacity-50' : ''} ${fullWidth ? 'flex-1' : ''}`}
|
||||
} ${disabled ? 'cursor-not-allowed opacity-50' : ''} ${fullWidth ? 'flex-1' : ''} ${buttonClassName}`}
|
||||
>
|
||||
{option.icon && (
|
||||
<span className="flex-shrink-0" aria-hidden="true">
|
||||
|
|
|
|||
|
|
@ -1,30 +1,24 @@
|
|||
import { GripVertical } from 'lucide-react';
|
||||
import * as ResizablePrimitive from 'react-resizable-panels';
|
||||
|
||||
import { Group, Panel, Separator } from 'react-resizable-panels';
|
||||
import type { ComponentProps } from 'react';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
const ResizablePanelGroup = ({
|
||||
className = '',
|
||||
...props
|
||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
|
||||
<ResizablePrimitive.PanelGroup
|
||||
className={cn('flex h-full w-full data-[panel-group-direction=vertical]:flex-col', className)}
|
||||
{...props}
|
||||
/>
|
||||
const ResizablePanelGroup = ({ className = '', ...props }: ComponentProps<typeof Group>) => (
|
||||
<Group className={cn('h-full w-full', className)} {...props} />
|
||||
);
|
||||
|
||||
const ResizablePanel = ResizablePrimitive.Panel;
|
||||
const ResizablePanel = Panel;
|
||||
|
||||
const ResizableHandle = ({
|
||||
withHandle,
|
||||
className = '',
|
||||
...props
|
||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
||||
}: ComponentProps<typeof Separator> & {
|
||||
withHandle?: boolean;
|
||||
}) => (
|
||||
<ResizablePrimitive.PanelResizeHandle
|
||||
<Separator
|
||||
className={cn(
|
||||
'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
|
||||
'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -34,29 +28,29 @@ const ResizableHandle = ({
|
|||
<GripVertical className="h-2.5 w-2.5" />
|
||||
</div>
|
||||
)}
|
||||
</ResizablePrimitive.PanelResizeHandle>
|
||||
</Separator>
|
||||
);
|
||||
|
||||
const ResizableHandleAlt = ({
|
||||
withHandle,
|
||||
className = '',
|
||||
...props
|
||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
||||
}: ComponentProps<typeof Separator> & {
|
||||
withHandle?: boolean;
|
||||
}) => (
|
||||
<ResizablePrimitive.PanelResizeHandle
|
||||
<Separator
|
||||
className={cn(
|
||||
'group relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
|
||||
'group relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{withHandle && (
|
||||
<div className="invisible z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border group-hover:visible group-active:visible group-data-[resize-handle-active]:visible">
|
||||
<div className="invisible z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border group-hover:visible group-active:visible group-data-[separator=active]:visible">
|
||||
<GripVertical className="h-2.5 w-2.5" />
|
||||
</div>
|
||||
)}
|
||||
</ResizablePrimitive.PanelResizeHandle>
|
||||
</Separator>
|
||||
);
|
||||
|
||||
export { ResizablePanelGroup, ResizablePanel, ResizableHandle, ResizableHandleAlt };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue