🪟 style: Agent Marketplace UI Responsiveness, a11y, and Navigation (#9068)

* refactor: Agent Marketplace Button with access control

* fix(agent-marketplace): update marketplace UI and access control

* fix(agent-card): handle optional agent description for accessibility

* fix(agent-card): remove unnecessary icon checks from tests

* chore: remove unused keys

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
Marco Beretta 2025-08-15 20:59:10 +02:00 committed by GitHub
parent c78fd0fc83
commit 4ec7bcb60f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 164 additions and 162 deletions

View file

@ -1,11 +1,10 @@
import React, { useCallback, useContext } from 'react';
import { LayoutGrid } from 'lucide-react';
import React, { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQueryClient } from '@tanstack/react-query';
import { QueryKeys, Constants, PermissionTypes, Permissions } from 'librechat-data-provider';
import { QueryKeys, Constants } from 'librechat-data-provider';
import { TooltipAnchor, NewChatIcon, MobileSidebar, Sidebar, Button } from '@librechat/client';
import type { TMessage } from 'librechat-data-provider';
import { useLocalize, useNewConvo, useHasAccess, AuthContext } from '~/hooks';
import { useLocalize, useNewConvo } from '~/hooks';
import store from '~/store';
export default function NewChat({
@ -27,15 +26,6 @@ export default function NewChat({
const navigate = useNavigate();
const localize = useLocalize();
const { conversation } = store.useCreateConversationAtom(index);
const authContext = useContext(AuthContext);
const hasAccessToAgents = useHasAccess({
permissionType: PermissionTypes.AGENTS,
permission: Permissions.USE,
});
const hasAccessToMarketplace = useHasAccess({
permissionType: PermissionTypes.MARKETPLACE,
permission: Permissions.USE,
});
const clickHandler: React.MouseEventHandler<HTMLButtonElement> = useCallback(
(e) => {
@ -57,21 +47,6 @@ export default function NewChat({
[queryClient, conversation, newConvo, navigate, toggleNav, isSmallScreen],
);
const handleAgentMarketplace = useCallback(() => {
navigate('/agents');
if (isSmallScreen) {
toggleNav();
}
}, [navigate, isSmallScreen, toggleNav]);
// Check if auth is ready (avoid race conditions)
const authReady =
authContext?.isAuthenticated !== undefined &&
(authContext?.isAuthenticated === false || authContext?.user !== undefined);
// Show agent marketplace when marketplace permission is enabled, auth is ready, and user has access to agents
const showAgentMarketplace = authReady && hasAccessToAgents && hasAccessToMarketplace;
return (
<>
<div className="flex items-center justify-between py-[2px] md:py-2">
@ -91,25 +66,7 @@ export default function NewChat({
</Button>
}
/>
<div className="flex">
{showAgentMarketplace && (
<div className="flex">
<TooltipAnchor
description={localize('com_agents_marketplace')}
render={
<Button
variant="outline"
data-testid="nav-agents-marketplace-button"
aria-label={localize('com_agents_marketplace')}
className="rounded-full border-none bg-transparent p-2 hover:bg-surface-hover md:rounded-xl"
onClick={handleAgentMarketplace}
>
<LayoutGrid className="icon-md md:h-6 md:w-6" />
</Button>
}
/>
</div>
)}
<div className="flex gap-0.5">
{headerButtons}
<TooltipAnchor
@ -123,7 +80,7 @@ export default function NewChat({
className="rounded-full border-none bg-transparent p-2 hover:bg-surface-hover md:rounded-xl"
onClick={clickHandler}
>
<NewChatIcon className="icon-md md:h-6 md:w-6" />
<NewChatIcon className="icon-lg text-text-primary" />
</Button>
}
/>