mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-05 18:18:51 +01:00
feat: Introduce InfoHoverCard component and refactor enums for better organization
This commit is contained in:
parent
4cc3351c42
commit
741025a461
8 changed files with 56 additions and 38 deletions
|
|
@ -108,24 +108,9 @@ const AgentGrid: React.FC<AgentGridProps> = ({ category, searchQuery, onSelectAg
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the appropriate title for the agents grid based on current state
|
||||
*/
|
||||
const getGridTitle = () => {
|
||||
if (searchQuery) {
|
||||
return localize('com_agents_results_for', { query: searchQuery });
|
||||
}
|
||||
|
||||
return getCategoryDisplayName(category);
|
||||
};
|
||||
|
||||
// Loading skeleton component
|
||||
const loadingSkeleton = (
|
||||
<div className="space-y-6">
|
||||
<div className="mb-4">
|
||||
<div className="mb-2 h-6 w-48 animate-pulse rounded-md bg-surface-tertiary"></div>
|
||||
<div className="h-4 w-64 animate-pulse rounded-md bg-surface-tertiary"></div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
{Array(6)
|
||||
.fill(0)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
||||
import React, { useState, useEffect, useMemo, useRef, useCallback } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
|
|
@ -124,15 +124,18 @@ const AgentMarketplace: React.FC<AgentMarketplaceProps> = ({ className = '' }) =
|
|||
*/
|
||||
const orderedTabs = useMemo<string[]>(() => {
|
||||
const dynamic = (categoriesQuery.data || []).map((c) => c.value);
|
||||
// Ensure unique and stable order
|
||||
const set = new Set<string>(['promoted', 'all', ...dynamic]);
|
||||
// Ensure unique and stable order - 'all' should be last to match server response
|
||||
const set = new Set<string>(['promoted', ...dynamic, 'all']);
|
||||
return Array.from(set);
|
||||
}, [categoriesQuery.data]);
|
||||
|
||||
const getTabIndex = (tab: string): number => {
|
||||
const idx = orderedTabs.indexOf(tab);
|
||||
return idx >= 0 ? idx : 0;
|
||||
};
|
||||
const getTabIndex = useCallback(
|
||||
(tab: string): number => {
|
||||
const idx = orderedTabs.indexOf(tab);
|
||||
return idx >= 0 ? idx : 0;
|
||||
},
|
||||
[orderedTabs],
|
||||
);
|
||||
|
||||
/**
|
||||
* Handle category tab selection changes with directional animation
|
||||
|
|
@ -199,7 +202,7 @@ const AgentMarketplace: React.FC<AgentMarketplaceProps> = ({ className = '' }) =
|
|||
return () => {
|
||||
window.clearTimeout(timeoutId);
|
||||
};
|
||||
}, [activeTab, displayCategory, isTransitioning, orderedTabs]);
|
||||
}, [activeTab, displayCategory, isTransitioning, getTabIndex]);
|
||||
|
||||
// No longer needed with keyframes
|
||||
|
||||
|
|
|
|||
13
packages/client/src/common/enum.ts
Normal file
13
packages/client/src/common/enum.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
export enum ESide {
|
||||
Top = 'top',
|
||||
Right = 'right',
|
||||
Bottom = 'bottom',
|
||||
Left = 'left',
|
||||
}
|
||||
|
||||
export enum NotificationSeverity {
|
||||
INFO = 'info',
|
||||
SUCCESS = 'success',
|
||||
WARNING = 'warning',
|
||||
ERROR = 'error',
|
||||
}
|
||||
|
|
@ -1,11 +1,5 @@
|
|||
export type {
|
||||
TShowToast,
|
||||
Option,
|
||||
OptionWithIcon,
|
||||
DropdownValueSetter,
|
||||
MentionOption,
|
||||
} from './types';
|
||||
export * from './types';
|
||||
|
||||
export { NotificationSeverity } from './types';
|
||||
export * from './enum';
|
||||
|
||||
export type { MenuItemProps } from './menus';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
export enum NotificationSeverity {
|
||||
INFO = 'info',
|
||||
SUCCESS = 'success',
|
||||
WARNING = 'warning',
|
||||
ERROR = 'error',
|
||||
}
|
||||
import { NotificationSeverity } from './enum';
|
||||
|
||||
export type TShowToast = {
|
||||
message: string;
|
||||
|
|
|
|||
27
packages/client/src/components/InfoHoverCard.tsx
Normal file
27
packages/client/src/components/InfoHoverCard.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { CircleHelpIcon } from 'lucide-react';
|
||||
import { HoverCard, HoverCardTrigger, HoverCardPortal, HoverCardContent } from './HoverCard';
|
||||
import { ESide } from '~/common';
|
||||
|
||||
type InfoHoverCardProps = {
|
||||
side?: ESide;
|
||||
text: string;
|
||||
};
|
||||
|
||||
const InfoHoverCard = ({ side, text }: InfoHoverCardProps) => {
|
||||
return (
|
||||
<HoverCard openDelay={50}>
|
||||
<HoverCardTrigger className="cursor-help">
|
||||
<CircleHelpIcon className="h-5 w-5 text-text-tertiary" />{' '}
|
||||
</HoverCardTrigger>
|
||||
<HoverCardPortal>
|
||||
<HoverCardContent side={side} className="z-[999] w-80">
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm text-text-secondary">{text}</p>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCardPortal>
|
||||
</HoverCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default InfoHoverCard;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as RadixToast from '@radix-ui/react-toast';
|
||||
import { NotificationSeverity } from '~/common/types';
|
||||
import { NotificationSeverity } from '~/common';
|
||||
import { useToast } from '~/hooks';
|
||||
|
||||
export function Toast() {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export { default as MultiSelect } from './MultiSelect';
|
|||
export { default as DropdownPopup } from './DropdownPopup';
|
||||
export { default as DelayedRender } from './DelayedRender';
|
||||
export { default as ThemeSelector } from './ThemeSelector';
|
||||
export { default as InfoHoverCard } from './InfoHoverCard';
|
||||
export { default as CheckboxButton } from './CheckboxButton';
|
||||
export { default as DialogTemplate } from './DialogTemplate';
|
||||
export { default as SelectDropDown } from './SelectDropDown';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue