Compare commits

...

3 Commits

Author SHA1 Message Date
abhi1992002
cc91768263 refactor(frontend): extract shared LibraryTab type to library/types.ts
Centralizes the tab descriptor type used across FavoritesSection,
LibraryAgentList, and LibrarySubSection to prevent cross-file drift.
2026-03-17 11:21:49 +05:30
abhi1992002
abb4a07aca fix(frontend): add useEffect cleanup for registerFavoritesTabRef
Clear the registered favorites tab ref on unmount to prevent stale
animation targets when the component is removed from the DOM.
2026-03-17 11:21:49 +05:30
abhi1992002
1a75ce6bbb feat(frontend): replace custom LibraryTabs with design system TabsLine
Replace the custom LibraryTabs component with the design system's TabsLine component throughout the library page. Add favorite animation ref registration for improved animation targeting. Also removes the unused agentGraphVersion field from the test fixture.
2026-03-17 11:21:49 +05:30
6 changed files with 79 additions and 19 deletions

View File

@@ -326,7 +326,6 @@ async def create_store_listing(
id=listing_id,
slug=metadata["slug"],
agentGraphId=graph_id,
agentGraphVersion=graph_version,
owningUserId=AUTOGPT_USER_ID,
hasApprovedVersion=is_approved,
useForOnboarding=metadata["use_for_onboarding"],

View File

@@ -1,19 +1,26 @@
"use client";
import { useEffect, useRef } from "react";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { LibraryAgentSort } from "@/app/api/__generated__/models/libraryAgentSort";
import { Text } from "@/components/atoms/Text/Text";
import { LoadingSpinner } from "@/components/atoms/LoadingSpinner/LoadingSpinner";
import { InfiniteScroll } from "@/components/contextual/InfiniteScroll/InfiniteScroll";
import {
TabsLine,
TabsLineList,
TabsLineTrigger,
} from "@/components/molecules/TabsLine/TabsLine";
import { HeartIcon } from "@phosphor-icons/react";
import { useFavoriteAnimation } from "../../context/FavoriteAnimationContext";
import { LibraryTab } from "../../types";
import { useFavoriteAgents } from "../../hooks/useFavoriteAgents";
import { LibraryAgentCard } from "../LibraryAgentCard/LibraryAgentCard";
import { LibraryTabs, Tab } from "../LibraryTabs/LibraryTabs";
import { LibraryActionSubHeader } from "../LibraryActionSubHeader/LibraryActionSubHeader";
interface Props {
searchTerm: string;
tabs: Tab[];
tabs: LibraryTab[];
activeTab: string;
onTabChange: (tabId: string) => void;
setLibrarySort: (value: LibraryAgentSort) => void;
@@ -35,17 +42,37 @@ export function FavoritesSection({
isFetchingNextPage,
} = useFavoriteAgents({ searchTerm });
const { registerFavoritesTabRef } = useFavoriteAnimation();
const favoritesRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
registerFavoritesTabRef(favoritesRef.current);
return () => {
registerFavoritesTabRef(null);
};
}, [registerFavoritesTabRef]);
return (
<>
<LibraryActionSubHeader
agentCount={agentCount}
setLibrarySort={setLibrarySort}
/>
<LibraryTabs
tabs={tabs}
activeTab={activeTab}
onTabChange={onTabChange}
/>
<TabsLine value={activeTab} onValueChange={onTabChange}>
<TabsLineList>
{tabs.map((tab) => (
<TabsLineTrigger
key={tab.id}
value={tab.id}
ref={tab.id === "favorites" ? favoritesRef : undefined}
className="inline-flex items-center gap-1.5"
>
<tab.icon size={16} />
{tab.title}
</TabsLineTrigger>
))}
</TabsLineList>
</TabsLine>
{isLoading ? (
<div className="flex h-[200px] items-center justify-center">

View File

@@ -9,7 +9,6 @@ import { LibraryFolder } from "../LibraryFolder/LibraryFolder";
import { LibrarySubSection } from "../LibrarySubSection/LibrarySubSection";
import { ArrowLeftIcon, HeartIcon } from "@phosphor-icons/react";
import { Text } from "@/components/atoms/Text/Text";
import { Tab } from "../LibraryTabs/LibraryTabs";
import {
AnimatePresence,
LayoutGroup,
@@ -18,6 +17,7 @@ import {
} from "framer-motion";
import { LibraryFolderEditDialog } from "../LibraryFolderEditDialog/LibraryFolderEditDialog";
import { LibraryFolderDeleteDialog } from "../LibraryFolderDeleteDialog/LibraryFolderDeleteDialog";
import { LibraryTab } from "../../types";
import { useLibraryAgentList } from "./useLibraryAgentList";
// cancels the current spring and starts a new one from current state.
@@ -68,7 +68,7 @@ interface Props {
setLibrarySort: (value: LibraryAgentSort) => void;
selectedFolderId: string | null;
onFolderSelect: (folderId: string | null) => void;
tabs: Tab[];
tabs: LibraryTab[];
activeTab: string;
onTabChange: (tabId: string) => void;
}

View File

@@ -1,20 +1,47 @@
import { useEffect, useRef } from "react";
import {
TabsLine,
TabsLineList,
TabsLineTrigger,
} from "@/components/molecules/TabsLine/TabsLine";
import { useFavoriteAnimation } from "../../context/FavoriteAnimationContext";
import { LibraryTab } from "../../types";
import LibraryFolderCreationDialog from "../LibraryFolderCreationDialog/LibraryFolderCreationDialog";
import { LibraryTabs, Tab } from "../LibraryTabs/LibraryTabs";
interface Props {
tabs: Tab[];
tabs: LibraryTab[];
activeTab: string;
onTabChange: (tabId: string) => void;
}
export function LibrarySubSection({ tabs, activeTab, onTabChange }: Props) {
const { registerFavoritesTabRef } = useFavoriteAnimation();
const favoritesRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
registerFavoritesTabRef(favoritesRef.current);
return () => {
registerFavoritesTabRef(null);
};
}, [registerFavoritesTabRef]);
return (
<div className="flex items-center justify-between gap-4">
<LibraryTabs
tabs={tabs}
activeTab={activeTab}
onTabChange={onTabChange}
/>
<TabsLine value={activeTab} onValueChange={onTabChange}>
<TabsLineList>
{tabs.map((tab) => (
<TabsLineTrigger
key={tab.id}
value={tab.id}
ref={tab.id === "favorites" ? favoritesRef : undefined}
className="inline-flex items-center gap-1.5"
>
<tab.icon size={16} />
{tab.title}
</TabsLineTrigger>
))}
</TabsLineList>
</TabsLine>
<LibraryFolderCreationDialog />
</div>
);

View File

@@ -5,11 +5,11 @@ import { HeartIcon, ListIcon } from "@phosphor-icons/react";
import { JumpBackIn } from "./components/JumpBackIn/JumpBackIn";
import { LibraryActionHeader } from "./components/LibraryActionHeader/LibraryActionHeader";
import { LibraryAgentList } from "./components/LibraryAgentList/LibraryAgentList";
import { Tab } from "./components/LibraryTabs/LibraryTabs";
import { useLibraryListPage } from "./components/useLibraryListPage";
import { FavoriteAnimationProvider } from "./context/FavoriteAnimationContext";
import { LibraryTab } from "./types";
const LIBRARY_TABS: Tab[] = [
const LIBRARY_TABS: LibraryTab[] = [
{ id: "all", title: "All", icon: ListIcon },
{ id: "favorites", title: "Favorites", icon: HeartIcon },
];

View File

@@ -0,0 +1,7 @@
import { Icon } from "@phosphor-icons/react";
export interface LibraryTab {
id: string;
title: string;
icon: Icon;
}