fix FeaturedSection components and story

This commit is contained in:
Abhimanyu Yadav
2025-04-25 11:30:02 +05:30
parent 6b44ca536c
commit 073f9f4d58
4 changed files with 144 additions and 24 deletions

View File

@@ -27,7 +27,7 @@ export const FeaturedAgentCard: React.FC<FeaturedStoreCardProps> = ({
data-testid="featured-store-card"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
className={`flex h-[47rem] w-full flex-col md:w-[24rem] lg:w-[27.5rem] ${backgroundColor} rounded-[1.5rem] border-none px-5 pb-5 pt-7 transition-colors duration-200`}
className={`flex h-[47rem] w-full min-w-96 max-w-[27.5rem] flex-col md:w-[24rem] lg:w-[27.5rem] ${backgroundColor} rounded-[1.5rem] border-none px-5 pb-5 pt-7 transition-colors duration-200`}
>
<CardHeader className="mb-7 min-h-48 space-y-3 p-0">
<CardTitle className="line-clamp-3 font-poppins text-4xl font-medium text-neutral-900">

View File

@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react";
import { FeaturedSection } from "./FeaturedSection";
import { userEvent, within } from "@storybook/test";
import { userEvent, within, expect } from "@storybook/test";
import { StoreAgent } from "@/lib/autogpt-server-api";
const meta = {
@@ -12,7 +12,17 @@ const meta = {
fullscreen: true,
padding: 0,
},
viewport: {
defaultViewport: "responsive",
},
},
decorators: [
(Story) => (
<div className="flex items-center justify-center py-4 pl-4">
<Story />
</div>
),
],
tags: ["autodocs"],
argTypes: {
featuredAgents: { control: "object" },
@@ -98,36 +108,140 @@ const mockFeaturedAgents = [
export const Default: Story = {
args: {
featuredAgents: mockFeaturedAgents,
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
},
};
export const SingleAgent: Story = {
args: {
featuredAgents: [mockFeaturedAgents[0]],
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
},
};
export const NoAgents: Story = {
args: {
featuredAgents: [],
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
},
};
export const WithInteraction: Story = {
export const WithMissingData: Story = {
args: {
featuredAgents: [
{
...mockFeaturedAgents[0],
sub_heading: "",
agent_image: "",
creator_avatar: "",
},
mockFeaturedAgents[1],
],
},
};
export const WithExtremelyLongTexts: Story = {
args: {
featuredAgents: [
{
...mockFeaturedAgents[0],
agent_name:
"Universal Language Translator Pro with Advanced Neural Network Technology and Cross-Cultural Communication Capabilities for International Business and Education with Extended Support for Rare Dialects",
sub_heading:
"Breaking language barriers with cutting-edge AI translation technology that revolutionizes global communication for businesses and individuals across continents while preserving cultural nuances and contextual meanings in more than 150 languages including endangered dialects and specialized terminology",
description:
"Experience seamless communication across 150+ languages with our advanced neural translation engine. Perfect for international businesses, travelers, and language enthusiasts. Features real-time conversation translation, document processing, and cultural context adaptation to ensure your message is delivered exactly as intended in any language. Our proprietary machine learning algorithms continuously improve translation accuracy with each interaction, adapting to regional dialects and specialized terminology. The system includes voice recognition capabilities, image-to-text translation for signs and documents, and can operate offline in emergency situations where internet connectivity is limited. With dedicated mobile apps for iOS and Android plus browser extensions, you'll never encounter language barriers again, whether in business negotiations, academic research, or while exploring new destinations.",
creator:
"Global Linguistics Technologies International Corporation and Research Institute for Cross-Cultural Communication",
},
mockFeaturedAgents[1],
],
},
};
export const WithExtremeValues: Story = {
args: {
featuredAgents: [
{
...mockFeaturedAgents[0],
runs: 999999999999,
rating: 5,
},
{
...mockFeaturedAgents[1],
runs: 0,
rating: 0,
},
],
},
};
export const WithManyAgents: Story = {
args: {
featuredAgents: Array(20)
.fill(null)
.map((_, i) => ({
...mockFeaturedAgents[i % mockFeaturedAgents.length],
agent_name: `Agent ${i + 1}: ${mockFeaturedAgents[i % mockFeaturedAgents.length].agent_name}`,
slug: `agent-${i + 1}`,
})),
},
};
export const WithInvalidImageURLs: Story = {
args: {
featuredAgents: [
{
...mockFeaturedAgents[0],
agent_image: "https://invalid-url.jpg",
creator_avatar: "https://another-invalid-url.jpg",
},
mockFeaturedAgents[1],
],
},
};
export const WithSpecialCharacters: Story = {
args: {
featuredAgents: [
{
...mockFeaturedAgents[0],
agent_name: "Special &<>\"'/ Characters",
creator: "User with @#$%^&*()_+{}[]",
slug: "special-characters!@#$%",
},
mockFeaturedAgents[1],
],
},
};
export const MobileView: Story = {
args: {
featuredAgents: mockFeaturedAgents,
},
parameters: {
viewport: {
defaultViewport: "mobile2",
},
},
};
export const WithCardInteraction: Story = {
args: {
featuredAgents: mockFeaturedAgents,
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const featuredCard = canvas.getByText(
"Personalized Morning Coffee Newsletter example of three lines",
);
await userEvent.hover(featuredCard);
await userEvent.click(featuredCard);
// Find and interact with first card
const cards = canvas.getAllByTestId("featured-store-card");
await expect(cards.length).toBeGreaterThan(0);
const firstCard = cards[0];
await userEvent.hover(firstCard);
await new Promise((resolve) => setTimeout(resolve, 300));
// Check that link is present and clickable
const cardLink = firstCard.closest("a");
await expect(cardLink).toBeInTheDocument();
await userEvent.click(firstCard);
},
};

View File

@@ -15,9 +15,9 @@ import { StoreAgent } from "@/lib/autogpt-server-api";
import Link from "next/link";
const BACKGROUND_COLORS = [
"bg-violet-200 hover:bg-violet-100 dark:bg-violet-800", // #ddd6fe / #5b21b6
"bg-blue-200 hover:bg-blue-100 dark:bg-blue-800", // #bfdbfe / #1e3a8a
"bg-green-200 hover:bg-green-100 dark:bg-green-800", // #bbf7d0 / #065f46
"bg-violet-100 hover:bg-violet-200 dark:bg-violet-800", // #ddd6fe / #5b21b6
"bg-blue-100 hover:bg-blue-200 dark:bg-blue-800", // #bfdbfe / #1e3a8a
"bg-green-100 hover:bg-green-200 dark:bg-green-800", // #bbf7d0 / #065f46
];
interface FeaturedSectionProps {
@@ -46,22 +46,22 @@ export const FeaturedSection: React.FC<FeaturedSectionProps> = ({
};
return (
<section className="w-full">
<h2 className="mb-8 font-poppins text-2xl font-semibold leading-7 text-neutral-800 dark:text-neutral-200">
<section className="w-full space-y-8">
<h2 className="font-poppins text-lg font-semibold text-neutral-800">
Featured agents
</h2>
<Carousel
opts={{
align: "center",
align: "start",
containScroll: "trimSnaps",
}}
>
<CarouselContent>
<CarouselContent className="p-0">
{featuredAgents.map((agent, index) => (
<CarouselItem
key={index}
className="h-[480px] md:basis-1/2 lg:basis-1/3"
className={`w-fit flex-none ${index === featuredAgents.length - 1 ? "mr-4" : ""}`}
>
<Link
href={`/marketplace/agent/${encodeURIComponent(agent.creator)}/${encodeURIComponent(agent.slug)}`}
@@ -77,8 +77,14 @@ export const FeaturedSection: React.FC<FeaturedSectionProps> = ({
</CarouselContent>
<div className="relative mt-4">
<CarouselIndicator />
<CarouselPrevious afterClick={handlePrevSlide} />
<CarouselNext afterClick={handleNextSlide} />
<CarouselPrevious
afterClick={handlePrevSlide}
data-testid="Next slide Button"
/>
<CarouselNext
afterClick={handleNextSlide}
data-testid="Previous slide Button"
/>
</div>
</Carousel>
</section>

View File

@@ -186,7 +186,7 @@ const CarouselItem = React.forwardRef<
aria-roledescription="slide"
className={cn(
"min-w-0 shrink-0 grow-0 basis-full",
orientation === "horizontal" ? "pl-4" : "pt-4",
orientation === "horizontal" ? "pl-5" : "pt-5",
className,
)}
{...props}
@@ -211,7 +211,7 @@ const CarouselPrevious = React.forwardRef<
variant={variant}
size={size}
className={cn(
"absolute h-[52px] w-[52px] rounded-full",
"pointer absolute h-[52px] w-[52px] rounded-full",
orientation === "horizontal"
? "right-20 top-0"
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",