mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-02 22:30:18 +01:00
🎨 style: Theming and Consistency Improvements for Agent Marketplace
style: AccessRolesPicker to use DropdownPopup, theming, import order, localization refactor: Update localization keys for Agent Marketplace in NewChat component, remove duplicate key style: Adjust layout and font size in NewChat component for Agent Marketplace button style: theming in AgentGrid style: Update theming and text colors across Agent components for improved consistency chore: import order style: Replace Dialog with OGDialog and update content components in AgentDetail refactor: Simplify AgentDetail component by removing dropdown menu and replacing it with a copy link button style: Enhance scrollbar visibility and layout in AgentMarketplace and CategoryTabs components style: Adjust layout in AgentMarketplace component by removing unnecessary padding from the container style: Refactor layout in AgentMarketplace component by reorganizing hero section and sticky wrapper for improved structure with collapsible header effect style: Improve responsiveness and layout in AgentMarketplace component by adjusting header visibility and modifying container styles based on screen size fix: Update localization key for no categories message in CategoryTabs component and corresponding test style: Add className prop to OpenSidebar component for improved styling flexibility and update Header to utilize it for responsive design style: Enhance layout and scrolling behavior in CategoryTabs component by adding scroll snap properties and adjusting class names for improved user experience style: Update AgentGrid component layout and skeleton structure for improved visual consistency and responsiveness
This commit is contained in:
parent
411b44e203
commit
7e6206300c
13 changed files with 331 additions and 298 deletions
|
|
@ -1,7 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import type t from 'librechat-data-provider';
|
||||
|
||||
import useLocalize from '~/hooks/useLocalize';
|
||||
import { SmartLoader } from './SmartLoader';
|
||||
import { cn } from '~/utils';
|
||||
|
|
@ -50,16 +48,14 @@ const CategoryTabs: React.FC<CategoryTabsProps> = ({
|
|||
|
||||
// Loading skeleton component
|
||||
const loadingSkeleton = (
|
||||
<div className="mb-8">
|
||||
<div className="flex justify-center">
|
||||
<div className="flex flex-wrap items-center justify-center gap-6">
|
||||
{[...Array(6)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="h-6 min-w-[60px] animate-pulse rounded bg-gray-200 dark:bg-gray-700"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="w-full pb-2">
|
||||
<div className="no-scrollbar flex gap-1.5 overflow-x-auto px-4">
|
||||
{[...Array(6)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="h-[36px] min-w-[80px] animate-pulse rounded-md bg-surface-tertiary"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -106,52 +102,54 @@ const CategoryTabs: React.FC<CategoryTabsProps> = ({
|
|||
// Early return if no categories available
|
||||
if (!isLoading && (!categories || categories.length === 0)) {
|
||||
return (
|
||||
<div className="mb-8 text-center text-gray-500">{localize('com_agents_no_categories')}</div>
|
||||
<div className="text-center text-text-secondary">{localize('com_ui_no_categories')}</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Main tabs content
|
||||
const tabsContent = (
|
||||
<div className="mb-8">
|
||||
<div className="flex justify-center">
|
||||
{/* Accessible tab navigation with proper ARIA attributes */}
|
||||
<div
|
||||
className="flex flex-wrap items-center justify-center gap-6"
|
||||
role="tablist"
|
||||
aria-label={localize('com_agents_category_tabs_label')}
|
||||
aria-orientation="horizontal"
|
||||
>
|
||||
{categories.map((category, index) => (
|
||||
<button
|
||||
key={category.value}
|
||||
id={`category-tab-${category.value}`}
|
||||
onClick={() => onChange(category.value)}
|
||||
onKeyDown={(e) => handleKeyDown(e, category.value)}
|
||||
className={cn(
|
||||
'relative px-4 py-2 text-sm font-medium transition-colors duration-200',
|
||||
'focus:bg-gray-100 focus:outline-none dark:focus:bg-gray-800',
|
||||
'hover:text-gray-900 dark:hover:text-white',
|
||||
activeTab === category.value
|
||||
? 'text-gray-900 dark:text-white'
|
||||
: 'text-gray-600 dark:text-gray-400',
|
||||
)}
|
||||
role="tab"
|
||||
aria-selected={activeTab === category.value}
|
||||
aria-controls={`tabpanel-${category.value}`}
|
||||
tabIndex={activeTab === category.value ? 0 : -1}
|
||||
aria-label={`${getCategoryDisplayName(category)} tab (${index + 1} of ${categories.length})`}
|
||||
>
|
||||
<span className="truncate">{getCategoryDisplayName(category)}</span>
|
||||
{/* Underline for active tab */}
|
||||
{activeTab === category.value && (
|
||||
<div
|
||||
className="absolute bottom-0 left-0 right-0 h-0.5 rounded-full bg-gray-900 dark:bg-white"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="relative w-full pb-2">
|
||||
<div
|
||||
className="no-scrollbar flex gap-1.5 overflow-x-auto overscroll-x-contain px-4 [-webkit-overflow-scrolling:touch] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
||||
role="tablist"
|
||||
aria-label={localize('com_agents_category_tabs_label')}
|
||||
aria-orientation="horizontal"
|
||||
style={{
|
||||
scrollSnapType: 'x mandatory',
|
||||
WebkitOverflowScrolling: 'touch',
|
||||
}}
|
||||
>
|
||||
{categories.map((category, index) => (
|
||||
<button
|
||||
key={category.value}
|
||||
id={`category-tab-${category.value}`}
|
||||
onClick={() => onChange(category.value)}
|
||||
onKeyDown={(e) => handleKeyDown(e, category.value)}
|
||||
className={cn(
|
||||
'relative mt-1 cursor-pointer select-none whitespace-nowrap rounded-md px-3 py-2',
|
||||
activeTab === category.value
|
||||
? 'bg-surface-tertiary text-text-primary'
|
||||
: 'bg-surface-secondary text-text-secondary hover:bg-surface-hover hover:text-text-primary',
|
||||
)}
|
||||
style={{
|
||||
scrollSnapAlign: 'start',
|
||||
}}
|
||||
role="tab"
|
||||
aria-selected={activeTab === category.value}
|
||||
aria-controls={`tabpanel-${category.value}`}
|
||||
tabIndex={activeTab === category.value ? 0 : -1}
|
||||
aria-label={`${getCategoryDisplayName(category)} tab (${index + 1} of ${categories.length})`}
|
||||
>
|
||||
{getCategoryDisplayName(category)}
|
||||
{/* Underline for active tab */}
|
||||
{activeTab === category.value && (
|
||||
<div
|
||||
className="absolute bottom-0 left-0 right-0 h-0.5 bg-text-primary"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue