🪟 feat: DataTable update + Various UI enhancements (#9698)

* 🎨 feat: Enhance Import Conversations UI with loading state and new localization key

* fix: Correct pluralization in selected items message in translation.json

* Refactor Chat Input File Table Headers to Use SortFilterHeader Component

- Replaced button-based sorting headers in the Chat Input Files Table with a new SortFilterHeader component for better code organization and consistency.
- Updated the header for filename, updatedAt, and bytes columns to utilize the new component.

Enhance Navigation Component with Skeleton Loading States

- Added Skeleton loading states to the Nav component for better user experience during data fetching.
- Updated Suspense fallbacks for AgentMarketplaceButton and BookmarkNav components to display Skeletons.

Refactor Avatar Component for Improved UI

- Enhanced the Avatar component by adding a Label for drag-and-drop functionality.
- Improved styling and structure for the file upload area.

Update Shared Links Component for Better Error Handling and Sorting

- Improved error handling in the Shared Links component for fetching next pages and deleting shared links.
- Simplified the header rendering for sorting columns and added sorting functionality to the title and createdAt columns.

Refactor Archived Chats Component

- Merged ArchivedChats and ArchivedChatsTable components into a single ArchivedChats component for better maintainability.
- Implemented sorting and searching functionality with debouncing for improved performance.
- Enhanced the UI with better loading states and error handling.

Update DataTable Component for Sorting Icons

- Added sorting icons (ChevronUp, ChevronDown, ChevronsUpDown) to the DataTable headers for better visual feedback on sorting state.

Localization Updates

- Updated translation.json to fix missing translations and improve existing ones for better user experience.

*  feat: Update DataTable component to streamline props and enhance sorting icons

* fix: TS issues

* feat: polish and redefine DataTable + shared links and archived chats

* feat: enhance DataTable with column pinning and improve sorting functionality

* feat: enhance deepEqual function for array support and improve column style stability

* refactor: DataTable and ArchivedChats; fix: sorting ArchivedChats API

* feat(DataTable): Implement new DataTable component with hooks and optimized features

- Added DataTable component with support for virtual scrolling, row selection, and customizable columns.
- Introduced hooks for debouncing search input, managing row selection, and calculating column styles.
- Enhanced accessibility with keyboard navigation and selection checkboxes.
- Implemented skeleton loading state for better user experience during data fetching.
- Added DataTableSearch component for filtering data with debounced input.
- Created utility logger for improved debugging in development.
- Updated translations to support new UI elements and actions.

* refactor: update SharedLinks and ArchivedChats to use desktopOnly instead of hideOnMobile; remove unused DataTableColumnHeader component

* fix: ensure desktopOnly columns are hidden on mobile in DataTable

* refactor: reorganize imports in DataTable components and update index exports

* refactor: improve styling and animations in Artifacts, ArtifactsSubMenu, and MCPSubMenu components; update border-radius in style.css

* refactor(Artifacts): enhance button toggle functionality and manage expanded state with useEffect

* refactor: comment out desktopOnly property in SharedLinks and ArchivedChats components; update translation.json with new keys for link actions

* refactor(DataTable): streamline column visibility logic and enhance type definitions; improve cleanup timers and optimize rendering

* refactor(DataTable): enhance type definitions for processed data rows and update custom actions renderer type

* refactor(DataTable): optimize processed data handling and improve warning for missing IDs; streamline DataTableComponents imports

* refactor(DataTable): enhance accessibility features and improve localization for selection and loading states

* refactor: improve padding in dialog content and enhance row selection functionality in ArchivedChats and DataTable components

* refactor(DataTable): remove unnecessary role and tabindex attributes from select all button for improved accessibility

* refactor(translation): remove outdated error messages and unused UI strings for cleaner localization

* refactor(DataTable): enhance virtualization and scrolling performance with dynamic overscan adjustments

* refactor(DataTableErrorBoundary): enhance error handling and localization support

* refactor(DataTable): improve column sizing and visibility handling; remove deprecated features

* refactor: enhance UI components with improved class handling and state management

* refactor(DataTable): improve column width handling and responsiveness; disable row selection

* refactor(DataTable): enhance accessibility with row header support and improve column visibility handling

* chore(DataTable): comments update

* refactor(Table): add unwrapped prop for direct table rendering; adjust minWidth calculation for responsiveness

* refactor(DataTable): simplify search handling by removing unnecessary trimming; adjust column width handling for better responsiveness

* refactor(translation): remove redundant drag and drop UI text for clarity

* refactor(parsers): change uiResources to a constant and streamline artifacts handling

* chore: remove unused file, bump @librechat/client to 0.3.2; fix(SharedLinks): missing import;

* refactor: change button variant from destructive to ghost for delete actions in SharedLinks and ArchivedChats components

* refactor(DataTable): simplify aria-sort assignment for better readability

* refactor(DataTable): update aria-label and ariaLabel to use indexed placeholder for localization

* refactor(translation): update no data messages for consistency

* Refactor code structure for improved readability and maintainability

* chore: restore linting fixes

* chore: restore linting fixes 2; refactor: remove unused translation keys

* feat(tests): add unit tests for DataTable components and error handling

- Implement tests for SelectionCheckbox and SkeletonRows components in DataTable.
- Add tests for DataTableErrorBoundary to ensure proper error handling and UI rendering.
- Create tests for DataTableSearch to validate search functionality and accessibility.
- Update DialogTemplate tests to reflect hardcoded cancel text.
- Remove redundant IntersectionObserver mock in SplitText tests.
- Unmock react-i18next in Translation tests to validate actual i18n functionality.

* refactor: Remove jest-environment-jsdom dependency from package.json; fix: reset package-lock

* chore: revert lint fixes

* chore: clean up package.json by removing unused devDependencies and redundant test scripts

* chore: update package dependencies in package.json and package-lock.json

- Added new devDependencies: @babel/core, @babel/preset-env, @babel/preset-react, @babel/preset-typescript, @tanstack/react-table, @tanstack/react-virtual, @testing-library/jest-dom, identity-obj-proxy, jest, jest-environment-jsdom, and lucide-react.
- Updated existing devDependencies to their latest versions.
- Added new module @asamuzakjp/css-color to package-lock.json with its dependencies.
- Updated version of @babel/plugin-transform-destructuring and added @babel/plugin-transform-explicit-resource-management in package-lock.json.

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
Marco Beretta 2025-12-10 02:08:41 +01:00 committed by GitHub
parent e2915476c5
commit d8dab96361
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 7578 additions and 917 deletions

View file

@ -0,0 +1,122 @@
import { Component, ErrorInfo, ReactNode, createRef } from 'react';
import { RefreshCw } from 'lucide-react';
import { Button } from '../Button';
import { logger } from '~/utils';
import { useLocalize } from '~/hooks';
/**
* Error boundary specifically for DataTable component.
* Catches JavaScript errors in the table rendering and provides a fallback UI.
* Handles errors from virtualizer, cell renderers, fetch operations, and child components.
*/
interface DataTableErrorBoundaryState {
hasError: boolean;
error?: Error;
}
interface DataTableErrorBoundaryProps {
children: ReactNode;
onError?: (error: Error) => void;
onReset?: () => void;
}
interface DataTableErrorBoundaryInnerProps extends DataTableErrorBoundaryProps {
localize: ReturnType<typeof useLocalize>;
}
class DataTableErrorBoundaryInner extends Component<
DataTableErrorBoundaryInnerProps,
DataTableErrorBoundaryState
> {
private errorCardRef = createRef<HTMLDivElement>();
constructor(props: DataTableErrorBoundaryInnerProps) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): DataTableErrorBoundaryState {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
logger.error('DataTable Error Boundary caught an error:', error, errorInfo);
this.props.onError?.(error);
}
componentDidUpdate(
_prevProps: DataTableErrorBoundaryInnerProps,
prevState: DataTableErrorBoundaryState,
) {
if (!prevState.hasError && this.state.hasError && this.errorCardRef.current) {
this.errorCardRef.current.focus();
}
}
/**
* Reset the error state and attempt to re-render the children.
* This can be used to retry after a table error (e.g., network retry).
*/
private handleReset = () => {
this.setState({ hasError: false, error: undefined });
this.props.onReset?.();
};
render() {
if (this.state.hasError) {
return (
<div className="flex h-full w-full flex-col items-center justify-center p-8">
<div
ref={this.errorCardRef}
role="alert"
aria-live="assertive"
aria-labelledby="datatable-error-title"
aria-describedby="datatable-error-desc"
tabIndex={-1}
className="before:bg-surface-destructive/80 relative w-full max-w-md overflow-hidden rounded-lg border border-border-light bg-surface-primary-alt p-6 shadow-sm outline-none before:absolute before:left-0 before:top-0 before:h-full before:w-1 focus:ring-2 focus:ring-ring focus:ring-offset-2 dark:border-border-medium dark:bg-surface-secondary"
>
<div className="flex items-center gap-2">
<RefreshCw className="h-4 w-4 text-surface-destructive" />
<h3 id="datatable-error-title" className="text-sm font-medium text-text-primary">
{this.props.localize('com_ui_table_error')}
</h3>
</div>
<p id="datatable-error-desc" className="mt-2 text-sm text-text-secondary">
{this.props.localize('com_ui_table_error_description')}
</p>
<div className="mt-4 flex justify-center">
<Button
variant="outline"
onClick={this.handleReset}
className="flex items-center gap-2 px-3 py-1.5 text-sm hover:bg-surface-hover dark:hover:bg-surface-active"
aria-label="Retry loading table"
>
<RefreshCw className="h-3 w-3" />
{this.props.localize('com_ui_retry')}
</Button>
</div>
</div>
{import.meta.env.MODE === 'development' && this.state.error && (
<details className="mt-4 max-w-md rounded-md bg-surface-secondary p-3 text-xs dark:bg-surface-tertiary">
<summary className="cursor-pointer font-medium text-text-primary">
{this.props.localize('com_ui_error_details')}
</summary>
<pre className="mt-2 whitespace-pre-wrap text-text-secondary">
{this.state.error.message}
</pre>
</details>
)}
</div>
);
}
return this.props.children;
}
}
export function DataTableErrorBoundary(props: DataTableErrorBoundaryProps) {
const localize = useLocalize();
return <DataTableErrorBoundaryInner {...props} localize={localize} />;
}
export default DataTableErrorBoundary;