Skip to content

Conversation

@michnowak
Copy link
Collaborator

@michnowak michnowak commented Dec 29, 2025

What does this PR do?

  • My bugfix

Related Ticket(s)

  • Notion Ticket

Key Changes

  • How does the code change address the issue? Describe, at a high level, what was done to affect change.
  • What side effects does this change have? This is the most important question to answer, as it can point out problems where you are making too many changes in one commit or branch. One or two bullet points for related changes may be okay, but five or six are likely indicators of a commit that is doing too many things.

How to test

  • Create a detailed description of what you need to do to set this PR up. ie: Does it need migrations? Do you need to install something?
  • Create a step by step list of what the engineer needs to do to test.

Media (Loom or gif)

  • Insert media here (if applicable)

Summary by CodeRabbit

  • New Features
    • Added a new product carousel component for displaying product collections with customizable titles, descriptions, and action elements. Includes support for product badges and configurable carousel settings to suit various layout requirements.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 29, 2025

Walkthrough

Introduces a new ProductCarousel component to the UI library with full TypeScript typing and Storybook documentation. The component renders a carousel of product cards with optional header, description, and action. Minor .gitignore update adds agent-os to the IDEs section.

Changes

Cohort / File(s) Summary
Gitignore maintenance
.gitignore
Added agent-os entry to IDEs section
ProductCarousel component
packages/ui/src/components/ProductCarousel/ProductCarousel.tsx
New React component that renders a header (title/description/action) and a Carousel of ProductCard items; accepts products array and optional configuration for carousel behavior, custom LinkComponent, and styling
ProductCarousel types
packages/ui/src/components/ProductCarousel/ProductCarousel.types.ts
Three new exported interfaces: ProductCarouselProps (main component props), ProductSummaryItem (product data structure), and ProductBadge (badge styling); includes imports from framework and frontend models
ProductCarousel stories
packages/ui/src/components/ProductCarousel/ProductCarousel.stories.tsx
Storybook story file with three stories (Default, WithDescription, WithAction) demonstrating component usage; includes sample ProductSummaryItem dataset and MockLinkComponent
Module exports
packages/ui/src/components/ProductCarousel/index.ts
Public re-exports of ProductCarousel component and types (ProductCarouselProps, ProductSummaryItem, ProductBadge)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • marcinkrasowski

Poem

🐰 A carousel new, with products on display,
Carousel of cards that brighten the day,
With badges and links and prices so fine,
This component will surely help sales align! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description uses the required template structure but fails to provide actual content—all sections contain only placeholder text with no concrete details about changes, testing steps, or related tickets. Replace all placeholders with actual information: specify the ticket, describe how the ProductCarousel addresses requirements, list any side effects, provide detailed setup and testing steps, and add media if applicable.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: product carousel component' clearly and accurately summarizes the main change—a new ProductCarousel component being added to the UI package.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@michnowak michnowak marked this pull request as ready for review January 2, 2026 09:24
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/ui/src/components/ProductCarousel/ProductCarousel.tsx (1)

45-61: Consider making the badge limit configurable.

Line 53 hardcodes a limit of 2 badges with .slice(0, 2). While this matches the ProductCard layout constraints, consider adding a prop like maxBadges?: number to ProductCarouselProps to make this configurable for different use cases.

🔎 Proposed enhancement

Add to ProductCarouselProps in ProductCarousel.types.ts:

export interface ProductCarouselProps {
    products: ProductSummaryItem[];
    title?: string;
    description?: Models.RichText.RichText;
    action?: React.ReactNode;
    LinkComponent: FrontendModels.Link.LinkComponent;
    carouselConfig?: Partial<CarouselProps>;
    detailsLabel: string;
    carouselClassName?: string;
+   maxBadges?: number;
}

Then update the component:

export const ProductCarousel: React.FC<ProductCarouselProps> = ({
    products,
    title,
    description,
    action,
    LinkComponent,
    carouselConfig,
    detailsLabel,
    carouselClassName,
+   maxBadges = 2,
}) => {
    // ...
    <ProductCard
        title={product.name}
        description={product.description}
        price={product.price}
        image={product.image}
-       tags={product.badges?.slice(0, 2)}
+       tags={product.badges?.slice(0, maxBadges)}
        link={{
            label: detailsLabel,
            url: product.link,
        }}
        LinkComponent={LinkComponent}
    />
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5345d94 and 322e9b2.

📒 Files selected for processing (5)
  • .gitignore
  • packages/ui/src/components/ProductCarousel/ProductCarousel.stories.tsx
  • packages/ui/src/components/ProductCarousel/ProductCarousel.tsx
  • packages/ui/src/components/ProductCarousel/ProductCarousel.types.ts
  • packages/ui/src/components/ProductCarousel/index.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/ui/src/components/ProductCarousel/ProductCarousel.stories.tsx (2)
packages/ui/src/components/ProductCarousel/ProductCarousel.tsx (1)
  • ProductCarousel (15-88)
packages/ui/src/components/ProductCarousel/ProductCarousel.types.ts (1)
  • ProductSummaryItem (19-27)
packages/ui/src/components/ProductCarousel/ProductCarousel.tsx (4)
packages/ui/src/components/ProductCarousel/ProductCarousel.types.ts (1)
  • ProductCarouselProps (8-17)
packages/ui/src/components/RichText/RichText.tsx (1)
  • RichText (48-252)
packages/ui/src/components/Cards/ProductCard/ProductCard.tsx (1)
  • ProductCard (16-94)
packages/ui/src/lib/utils.ts (1)
  • cn (5-7)
🔇 Additional comments (9)
.gitignore (1)

36-36: LGTM!

The addition of agent-os to the IDEs section follows the existing pattern and is appropriate.

packages/ui/src/components/ProductCarousel/ProductCarousel.types.ts (1)

1-32: LGTM! Well-structured type definitions.

The type definitions are comprehensive and follow framework conventions correctly. The required vs. optional field choices are appropriate, and the use of framework Models types ensures consistency across the codebase.

packages/ui/src/components/ProductCarousel/index.ts (1)

1-2: LGTM!

The re-exports follow best practices with proper export type syntax for type-only exports.

packages/ui/src/components/ProductCarousel/ProductCarousel.stories.tsx (3)

12-16: MockLinkComponent is appropriate for Storybook stories.

The simplified link component is sufficient for demonstration purposes in Storybook.


32-141: LGTM! Well-structured sample data.

The sample product data is comprehensive and demonstrates various product configurations with images, prices, descriptions, and badge combinations.


143-175: Stories demonstrate component usage effectively.

The three stories (Default, WithDescription, WithAction) provide good coverage of the component's capabilities. The console.log on line 168 is acceptable for Storybook demonstration purposes.

packages/ui/src/components/ProductCarousel/ProductCarousel.tsx (3)

25-27: LGTM! Proper guard clause.

The early return for empty products array prevents unnecessary rendering.


32-42: LGTM! Well-structured header section.

The conditional rendering and responsive layout for the header section (title, description, action) is well implemented.


62-85: Verify the carouselConfig spread order is intentional.

The {...carouselConfig} spread at line 84 allows consumers to override all the hardcoded Carousel props (slidesPerView, breakpoints, showNavigation, showPagination, className). While this provides flexibility, it could lead to unexpected behavior if important defaults are accidentally overridden.

Consider whether this level of override is intended, or if certain props should be protected from override.

Alternative approach if some defaults should be protected:

🔎 Suggested pattern for protected defaults
<Carousel
+   {...carouselConfig}
    slides={products.map((product) => (
        // ...
    ))}
    slidesPerView={1}
    spaceBetween={16}
    showNavigation={true}
    showPagination={true}
    className={cn(
        '[&_.swiper-slide]:h-auto [&_.swiper-pagination]:bottom-0 [&_.swiper-pagination-bullet]:bg-primary [&_.swiper-pagination-bullet-active]:bg-primary [&_.swiper-pagination-bullet]:opacity-100 [&_.swiper-pagination-bullet]:w-2.5 [&_.swiper-pagination-bullet]:h-2.5',
        carouselClassName,
+       carouselConfig?.className,
    )}
    breakpoints={{
            slidesPerView: 1,
            spaceBetween: 16,
        },
            slidesPerView: 2,
            spaceBetween: 20,
        },
            slidesPerView: 3,
            spaceBetween: 24,
        },
+       ...carouselConfig?.breakpoints,
    }}
-   {...carouselConfig}
/>

This pattern spreads carouselConfig first, then applies component defaults that can't be overridden, while still allowing selective override of className and breakpoints through explicit merging.

@michnowak
Copy link
Collaborator Author

it has already been merged into: #488

@michnowak michnowak closed this Jan 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants