Skip to content

feat: DR-7735 enterprise#7716

Open
carlagn wants to merge 13 commits intomainfrom
feat/DR-7735-enterprise
Open

feat: DR-7735 enterprise#7716
carlagn wants to merge 13 commits intomainfrom
feat/DR-7735-enterprise

Conversation

@carlagn
Copy link
Copy Markdown
Contributor

@carlagn carlagn commented Mar 27, 2026

Summary by CodeRabbit

  • New Features

    • Launched Enterprise landing page with multi-section layout, carousels, FAQs, and embedded contact form
    • Added viewport-aware animation component and partner logo ticker
    • Added carousel item, scrollable enterprise carousel, footer accordion, enterprise tab switcher, technology tooltip/button
  • Enhancements

    • Homepage card visuals now support a new "other" visual type
    • Added a new button style variant ("orm-reverse")
  • Chores

    • Added runtime dependencies for animations and intersection observation
  • SEO

    • Updated homepage metadata for richer social/OG previews

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview, Comment Mar 28, 2026 2:39am
docs Ready Ready Preview, Comment Mar 28, 2026 2:39am
eclipse Ready Ready Preview, Comment Mar 28, 2026 2:39am
site Ready Ready Preview, Comment Mar 28, 2026 2:39am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds an Enterprise landing page and several new client components (Rive animation, logo ticker, scroll carousel, tab switcher, form, accordion), updates homepage metadata and a card type, augments global Tally types, adds two npm dependencies, and introduces a new button variant.

Changes

Cohort / File(s) Summary
Package & Enterprise page
apps/site/package.json, apps/site/src/app/enterprise/page.tsx
Added dependencies @rive-app/react-webgl2 and react-intersection-observer; new Enterprise App Router page exporting metadata and default EnterprisePage composed from many section components and module-level data constants.
Enterprise components
apps/site/src/components/enterprise/...
apps/site/src/components/enterprise/carousel-item.tsx, apps/site/src/components/enterprise/footer-accordion.tsx, apps/site/src/components/enterprise/form.tsx, apps/site/src/components/enterprise/switch-enterprise.tsx, apps/site/src/components/enterprise/scroll-carousel.tsx
New components: CarouselItem (+EnterpriseCarouselCard type), FooterAccordion, EnterpriseForm (Tally iframe + embed loader), SwitchEnterprise (tabbed content, desktop/mobile render paths), and EnterpriseScrollCarousel (scroll-snap carousel with per-item navigation and bounds tracking).
Animation & logo parade
apps/site/src/components/animation.tsx, apps/site/src/components/logo-parade.tsx
Added Animation (Rive via useRive, visibility-driven play/pause using intersection observer) and LogoParade (duplicated logo list, inline keyframes, pause-on-hover ticker).
Homepage metadata & card-section
apps/site/src/app/(index)/page.tsx, apps/site/src/components/homepage/card-section/card-section.tsx
Enhanced homepage metadata (canonical, OpenGraph, Twitter card and image) and extended TwoColumnItem.visualType to include "other" with optional other?: ReactNode; changed image wrapper from fragment to <div>.
Technology UI & global types
apps/site/src/components/technology.tsx, apps/site/src/types/global.d.ts
Added Technology tooltip-wrapped button component (label, tooltip text, optional URL) and global augmentation Window.Tally?: { loadEmbeds: () => void } (file exports a module).
Design system button variant
packages/eclipse/src/components/button.tsx
Added new buttonVariants key orm-reverse (distinct Tailwind class set) and exposed it through VariantProps for Button props.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: DR-7735 enterprise' is vague and relies on an internal ticket identifier rather than describing what the feature actually adds. Revise the title to describe the actual feature or page being added, e.g., 'feat: add enterprise landing page with Rive animations' or 'feat: build enterprise section with carousel and accordion components'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@argos-ci
Copy link
Copy Markdown

argos-ci bot commented Mar 27, 2026

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Mar 28, 2026, 2:45 AM

Copy link
Copy Markdown
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: 6

🧹 Nitpick comments (14)
apps/site/src/components/enterprise/carousel-item.tsx (1)

18-18: Remove ineffective key prop from inside the component.

key should be set where CarouselItem is rendered in a list, not on an internal <Card>. Keeping it here is misleading and has no effect.

Proposed fix
-    <Card
-      key={card.title}
+    <Card
       className={cn(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/carousel-item.tsx` at line 18, Remove the
ineffective key prop from inside the CarouselItem component: delete the internal
prop key={card.title} on the <Card> rendered by CarouselItem and ensure callers
provide a key when rendering <CarouselItem> in a list (e.g., key={card.title} at
the place where CarouselItem is mapped/instantiated). Update any tests or usages
that assumed an internal key to verify keys are applied by the parent renderers
instead.
apps/site/src/app/enterprise/page.tsx (3)

4-4: Unused import: Script from next/script.

This import isn't used in this file since EnterpriseForm handles the Tally script internally.

-import Script from "next/script";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/enterprise/page.tsx` at line 4, Remove the unused import of
Script from next/script in the module (the identifier Script is not referenced);
since EnterpriseForm handles the Tally script internally, delete the line
importing Script to avoid unused-import lint errors and keep the file imports
minimal.

475-475: Remove commented-out code before merging.

This comment references a component that's either not implemented or being deferred. Either implement it or remove the comment to keep the codebase clean.

-      {/* <CarouselItem className="bg-background-default" card={development_efficiency[0]} /> use this item inside the carousel */}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/enterprise/page.tsx` at line 475, Remove the leftover
commented-out JSX referencing CarouselItem and development_efficiency: either
implement the CarouselItem usage inside the carousel or delete the comment line
entirely; locate the commented line that reads "<CarouselItem
className="bg-background-default" card={development_efficiency[0]} />" near the
carousel rendering and either replace it with the proper CarouselItem component
usage (ensuring props match CarouselItem's signature) or remove the comment so
no dead/commented JSX remains.

279-279: Component name SiteHome doesn't reflect its purpose.

This is the enterprise page, but the component is named SiteHome. Consider renaming to EnterprisePage or similar for clarity.

-export default function SiteHome() {
+export default function EnterprisePage() {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/enterprise/page.tsx` at line 279, The component is
misnamed: rename the default-exported function SiteHome to a clearer name like
EnterprisePage (update the function declaration and the export default to
EnterprisePage) and then update any references/imports/usages of SiteHome
elsewhere in the repo to the new name (search for SiteHome and replace with
EnterprisePage); ensure file-level React/Next conventions remain valid after
renaming (e.g., default export matches the function name) and run type checks to
catch any missed references.
apps/site/src/components/technology.tsx (1)

10-10: Unused import: useState is imported but never used.

This import can be safely removed to keep the code clean.

-import { useState } from "react";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/technology.tsx` at line 10, The import list in
components/technology.tsx includes an unused symbol `useState`; remove
`useState` from the import statement (i.e., only import what is actually used)
so the module no longer contains the unused import and lints cleanly—look for
the import line that currently reads `import { useState } from "react";` and
update it to import only the needed React symbols or remove the line if none are
required.
apps/site/src/components/logo-parade.tsx (2)

2-2: Unused import: useRef is imported but never used.

-import { useState, useRef } from "react";
+import { useState } from "react";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/logo-parade.tsx` at line 2, The import list in
logo-parade.tsx includes an unused symbol useRef; remove useRef from the import
statement (leave useState) or if you intended to use a ref, add its usage inside
the LogoParade component (e.g., create and reference a ref via useRef in the
component). Update the import line that currently reads import { useState,
useRef } from "react" to only import what’s used.

105-105: Unused variables: speeds, speed, and setSpeed.

These are defined but never used. The animation duration is hardcoded to 110s on line 132 instead of using the speeds object. Either remove these unused variables or wire them up to make speed configurable.

♻️ Option 1: Remove unused code
-const speeds = { slow: "100s", normal: "30s", fast: "15s" };
 export default function LogoParade() {
-  const [speed, setSpeed] = useState("normal");
   const [paused, setPaused] = useState(false);
♻️ Option 2: Use the speed configuration
         style={{
-          animation: `scroll-left 110s linear infinite`,
+          animation: `scroll-left ${speeds[speed]} linear infinite`,

Also applies to: 115-116

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/logo-parade.tsx` at line 105, The component defines
unused variables speeds, speed, and setSpeed (in LogoParade) while the marquee
animationDuration is hardcoded to "110s"; either remove the speeds object and
the useState hook (speed, setSpeed) and related unused imports, or wire them up
by replacing the hardcoded "110s" with a dynamic value derived from
speeds[speed], ensure the useState default (e.g., "normal") is used, and update
any controls or JSX that should call setSpeed so the animationDuration updates
when speed changes.
apps/site/src/components/enterprise/form.tsx (1)

16-17: Use proper typing instead of @ts-ignore.

Since you've declared Tally on the Window interface in global.d.ts, you can access it through window.Tally with optional chaining. This provides type safety and removes the need for the ignore comment.

     <Script
       src="https://tally.so/widgets/embed.js"
-      //@ts-ignore
-      onLoad={() => Tally.loadEmbeds()}
+      onLoad={() => window.Tally?.loadEmbeds()}
     />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/form.tsx` around lines 16 - 17, Replace
the use of the `@ts-ignore` and direct `Tally` reference in the `onLoad` handler
with a type-safe access via the declared global `Tally` on `window` (use
optional chaining to safely call the embed loader). Update the `onLoad` callback
that currently calls `Tally.loadEmbeds()` to call the `loadEmbeds` method
through `window` (e.g., using optional chaining) so TypeScript recognizes the
global from `global.d.ts` and no `@ts-ignore` is needed; ensure you reference
`onLoad` and the `Tally` global when making this change.
apps/site/src/components/enterprise/switch-enterprise.tsx (2)

36-55: Significant JSX duplication across desktop and mobile views.

The card rendering logic (icon + title + description) is repeated three times with minimal differences. Extracting a ContentCard sub-component would reduce duplication and make future styling changes easier to maintain.

♻️ Example extraction
const ContentCard = ({ box, idx }: { box: ContentBox; idx: number }) => (
  <div className="flex flex-col gap-4 relative z-2" key={idx}>
    <div className="flex gap-4 items-center">
      <Action color="orm" size="4xl">
        <i className={cn("text-foreground-orm-strong text-2xl", box.icon)} />
      </Action>
      <h3 className="text-foreground-neutral font-sans-display text-xl stretch-display mt-0 mb-1 font-bold line-clamp-2 hover:line-clamp-none">
        {box.title}
      </h3>
    </div>
    <p className="text-foreground-neutral dark:text-foreground-neutral-weak text-sm font-normal m-0">
      {box.description}
    </p>
  </div>
);

Also applies to: 61-80, 93-112

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/switch-enterprise.tsx` around lines 36 -
55, Duplicate JSX for the card (icon + title + description) should be extracted
into a small reusable component (e.g., ContentCard) and used in place of the
repeated blocks around the map calls; create a ContentCard component that
accepts props { box, idx } and renders the same structure (Action, <i
className={cn(..., box.icon)} />, title h3, and description p) and then replace
each occurrence (the map rendering over content[activeTab] and the two other
identical blocks) with <ContentCard box={box} idx={idx} /> (ensure the key is
applied to the outermost element inside ContentCard or to the map wrapper,
preserve existing classNames and imports like Action and cn).

9-9: Consider defining a proper type instead of Array<any>.

Using any loses type safety and IDE autocompletion. A simple interface would improve maintainability:

interface ContentBox {
  icon: string;
  title: string;
  description: string;
}

content: ContentBox[][];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/switch-enterprise.tsx` at line 9, The
field currently typed as "content: Array<any>;" loses type safety—define a
dedicated interface (e.g., ContentBox with properties icon: string, title:
string, description: string) and replace the loose Array<any> usage by typing
the content field as ContentBox[][] (or ContentBox[] if it’s a
single-dimensional array) so the "content" property in switch-enterprise.tsx is
strongly typed and provides proper IDE autocompletion.
apps/site/src/components/animation.tsx (4)

32-33: Remove debug console logs before shipping.

These console.log and console.error calls are useful during development but should be removed (or replaced with proper observability/error tracking) for production code. They add noise to the browser console and can leak internal details.

♻️ Proposed fix
   const { rive, RiveComponent } = useRive({
     src: `/animations/${name}.riv`,
     autoplay: autoplay || false,
-    onLoad: () => console.log("Rive loaded successfully"),
-    onLoadError: (e) => console.error("Rive load error:", e),
     layout: new Layout({
       fit: fit,
       alignment: Alignment.Center,
     }),
   });

If you need error tracking in production, consider integrating with your error monitoring service instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/animation.tsx` around lines 32 - 33, Remove the
debug console statements in the Rive component props: eliminate the onLoad: ()
=> console.log("Rive loaded successfully") and onLoadError: (e) =>
console.error("Rive load error:", e) calls; either remove the onLoad handler
entirely and replace onLoadError with a call to your observability API (e.g.,
captureException(e) / telemetry.report(e)) or no-op handlers if you must keep
the props (refer to the onLoad and onLoadError properties in the animation
component) so no debug console output is emitted in production.

51-51: Remove leftover debug comment.

The // <- this comment appears to be a development note that should be cleaned up before merging. The cleanup function itself is a good practice for preventing orphaned playback.

🧹 Proposed cleanup
-    return () => rive?.pause(); // <- this
+    return () => rive?.pause();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/animation.tsx` at line 51, Remove the leftover dev
comment after the cleanup return in the animation component; specifically edit
the cleanup returned by the effect (the line containing "return () =>
rive?.pause();") to remove the trailing "// <- this" comment so the file
(apps/site/src/components/animation.tsx) only contains the cleanup function with
no inline debug note.

23-23: Redundant state: isVisible simply mirrors isInView.

The isVisible state and its synchronization effect add unnecessary complexity. The useInView hook already provides the reactive isInView boolean you can use directly in your playback effect. This eliminates one state variable and one effect.

♻️ Proposed simplification
-  const [isVisible, setVisible] = useState<boolean>(false);
-
   const [reference, isInView] = useInView({
     threshold: threshold ?? 0.2,
   });
   
   // ... useRive hook ...

-  useEffect(() => {
-    if (isInView) setVisible(true);
-    else setVisible(false);
-  }, [isInView]);
-
   useEffect(() => {
     if (rive) {
-      if (isVisible) {
+      if (isInView) {
         rive.play();
       } else rive.pause();
     }
     return () => rive?.pause();
-  }, [isVisible, rive]);
+  }, [isInView, rive]);

Also applies to: 40-43

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/animation.tsx` at line 23, The isVisible state and
its setter (isVisible / setVisible) are redundant because useInView already
exposes isInView; remove the useState declaration and the effect that syncs
isVisible with isInView, then update the playback/useEffect logic that currently
references isVisible to use isInView directly (keep the useInView hook and any
refs intact). Ensure no leftover references to setVisible remain and remove any
now-unused imports/variables.

59-59: Simplify the style prop assignment.

The spread syntax {...{ style: style }} is unnecessarily verbose. You can directly assign the prop, which is clearer and more idiomatic.

♻️ Proposed simplification
     <div
       ref={reference}
       data-testid="rive-animation"
       className={className}
-      {...{ style: style }}
+      style={style}
     >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/animation.tsx` at line 59, Replace the verbose
spread assignment {...{ style: style }} with a direct prop assignment
style={style} in the component (look for the JSX element rendering the style
prop in animation.tsx, e.g., within the Animation component or the element that
currently uses {...{ style: style }}), ensuring the prop name remains "style"
and the value remains the same variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/site/src/app/enterprise/page.tsx`:
- Around line 145-196: The enterprises array contains identical placeholder
descriptions for every feature; update each object in the enterprises array
(match by title values like "Dedicated support", "Risk and compliance", "Custom
solutions", etc.) to provide a unique, concise description that accurately
reflects that feature's value proposition (keep tone/length consistent and
adjust any related UI copy if needed); ensure you edit the description property
for each entry rather than duplicating the placeholder text.
- Around line 274-277: The exported metadata object for the enterprise page
currently uses SITE_HOME_TITLE and SITE_HOME_DESCRIPTION which are for the
homepage; create enterprise-specific constants (e.g., SITE_ENTERPRISE_TITLE and
SITE_ENTERPRISE_DESCRIPTION) and replace the values used in the export const
metadata to reference those enterprise constants so the enterprise landing page
has correct SEO title and description.

In `@apps/site/src/components/animation.tsx`:
- Line 26: The current truthy check for the threshold value (the line setting
"threshold: threshold ? threshold : 0.2") incorrectly treats 0 as falsy and
replaces it with 0.2; update the assignment to use nullish coalescing so only
null/undefined fall back to 0.2, keeping explicit 0 values intact (locate the
threshold variable/prop usage in animation.tsx where the object property
"threshold" is assigned).

In `@apps/site/src/components/enterprise/carousel-item.tsx`:
- Around line 7-15: The component destructures a prop "last = false" but the
props type annotation (the object with "card" and optional "className") does not
include "last", causing a TypeScript error; either add "last?: boolean" to the
props type or remove "last" from the destructuring if it's unused—update the
props type definition adjacent to the destructured params in carousel-item.tsx
(the object containing card: { title, description, icon } and className?) to
include last?: boolean, or delete the "last = false" entry from the parameter
list and any references to "last" inside the component.

In `@apps/site/src/components/logo-parade.tsx`:
- Line 36: The url property in the logo object in
apps/site/src/components/logo-parade.tsx contains a leading space ("
https://www.panther.co/") which will produce a malformed link; remove the
leading whitespace so the url value is "https://www.panther.co/" (update the url
string in the logo object or wherever the url property is defined in the
LogoParade component).

In `@apps/site/src/components/technology.tsx`:
- Line 31: The className in the Technology component contains conflicting
font-family utilities ("font-sans-display!" and "font-mono!"); decide which font
family is intended and remove the other from the class list (look for the
className string in apps/site/src/components/technology.tsx where those tokens
appear) so only a single font-family utility remains and the "!"/important
modifiers are preserved only for the chosen font.

---

Nitpick comments:
In `@apps/site/src/app/enterprise/page.tsx`:
- Line 4: Remove the unused import of Script from next/script in the module (the
identifier Script is not referenced); since EnterpriseForm handles the Tally
script internally, delete the line importing Script to avoid unused-import lint
errors and keep the file imports minimal.
- Line 475: Remove the leftover commented-out JSX referencing CarouselItem and
development_efficiency: either implement the CarouselItem usage inside the
carousel or delete the comment line entirely; locate the commented line that
reads "<CarouselItem className="bg-background-default"
card={development_efficiency[0]} />" near the carousel rendering and either
replace it with the proper CarouselItem component usage (ensuring props match
CarouselItem's signature) or remove the comment so no dead/commented JSX
remains.
- Line 279: The component is misnamed: rename the default-exported function
SiteHome to a clearer name like EnterprisePage (update the function declaration
and the export default to EnterprisePage) and then update any
references/imports/usages of SiteHome elsewhere in the repo to the new name
(search for SiteHome and replace with EnterprisePage); ensure file-level
React/Next conventions remain valid after renaming (e.g., default export matches
the function name) and run type checks to catch any missed references.

In `@apps/site/src/components/animation.tsx`:
- Around line 32-33: Remove the debug console statements in the Rive component
props: eliminate the onLoad: () => console.log("Rive loaded successfully") and
onLoadError: (e) => console.error("Rive load error:", e) calls; either remove
the onLoad handler entirely and replace onLoadError with a call to your
observability API (e.g., captureException(e) / telemetry.report(e)) or no-op
handlers if you must keep the props (refer to the onLoad and onLoadError
properties in the animation component) so no debug console output is emitted in
production.
- Line 51: Remove the leftover dev comment after the cleanup return in the
animation component; specifically edit the cleanup returned by the effect (the
line containing "return () => rive?.pause();") to remove the trailing "// <-
this" comment so the file (apps/site/src/components/animation.tsx) only contains
the cleanup function with no inline debug note.
- Line 23: The isVisible state and its setter (isVisible / setVisible) are
redundant because useInView already exposes isInView; remove the useState
declaration and the effect that syncs isVisible with isInView, then update the
playback/useEffect logic that currently references isVisible to use isInView
directly (keep the useInView hook and any refs intact). Ensure no leftover
references to setVisible remain and remove any now-unused imports/variables.
- Line 59: Replace the verbose spread assignment {...{ style: style }} with a
direct prop assignment style={style} in the component (look for the JSX element
rendering the style prop in animation.tsx, e.g., within the Animation component
or the element that currently uses {...{ style: style }}), ensuring the prop
name remains "style" and the value remains the same variable.

In `@apps/site/src/components/enterprise/carousel-item.tsx`:
- Line 18: Remove the ineffective key prop from inside the CarouselItem
component: delete the internal prop key={card.title} on the <Card> rendered by
CarouselItem and ensure callers provide a key when rendering <CarouselItem> in a
list (e.g., key={card.title} at the place where CarouselItem is
mapped/instantiated). Update any tests or usages that assumed an internal key to
verify keys are applied by the parent renderers instead.

In `@apps/site/src/components/enterprise/form.tsx`:
- Around line 16-17: Replace the use of the `@ts-ignore` and direct `Tally`
reference in the `onLoad` handler with a type-safe access via the declared
global `Tally` on `window` (use optional chaining to safely call the embed
loader). Update the `onLoad` callback that currently calls `Tally.loadEmbeds()`
to call the `loadEmbeds` method through `window` (e.g., using optional chaining)
so TypeScript recognizes the global from `global.d.ts` and no `@ts-ignore` is
needed; ensure you reference `onLoad` and the `Tally` global when making this
change.

In `@apps/site/src/components/enterprise/switch-enterprise.tsx`:
- Around line 36-55: Duplicate JSX for the card (icon + title + description)
should be extracted into a small reusable component (e.g., ContentCard) and used
in place of the repeated blocks around the map calls; create a ContentCard
component that accepts props { box, idx } and renders the same structure
(Action, <i className={cn(..., box.icon)} />, title h3, and description p) and
then replace each occurrence (the map rendering over content[activeTab] and the
two other identical blocks) with <ContentCard box={box} idx={idx} /> (ensure the
key is applied to the outermost element inside ContentCard or to the map
wrapper, preserve existing classNames and imports like Action and cn).
- Line 9: The field currently typed as "content: Array<any>;" loses type
safety—define a dedicated interface (e.g., ContentBox with properties icon:
string, title: string, description: string) and replace the loose Array<any>
usage by typing the content field as ContentBox[][] (or ContentBox[] if it’s a
single-dimensional array) so the "content" property in switch-enterprise.tsx is
strongly typed and provides proper IDE autocompletion.

In `@apps/site/src/components/logo-parade.tsx`:
- Line 2: The import list in logo-parade.tsx includes an unused symbol useRef;
remove useRef from the import statement (leave useState) or if you intended to
use a ref, add its usage inside the LogoParade component (e.g., create and
reference a ref via useRef in the component). Update the import line that
currently reads import { useState, useRef } from "react" to only import what’s
used.
- Line 105: The component defines unused variables speeds, speed, and setSpeed
(in LogoParade) while the marquee animationDuration is hardcoded to "110s";
either remove the speeds object and the useState hook (speed, setSpeed) and
related unused imports, or wire them up by replacing the hardcoded "110s" with a
dynamic value derived from speeds[speed], ensure the useState default (e.g.,
"normal") is used, and update any controls or JSX that should call setSpeed so
the animationDuration updates when speed changes.

In `@apps/site/src/components/technology.tsx`:
- Line 10: The import list in components/technology.tsx includes an unused
symbol `useState`; remove `useState` from the import statement (i.e., only
import what is actually used) so the module no longer contains the unused import
and lints cleanly—look for the import line that currently reads `import {
useState } from "react";` and update it to import only the needed React symbols
or remove the line if none are required.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bef2f3c3-d71c-4633-9f91-e81a7e49db73

📥 Commits

Reviewing files that changed from the base of the PR and between 6f79795 and e0fc179.

⛔ Files ignored due to path filters (15)
  • apps/site/public/icons/technologies/mariadb.svg is excluded by !**/*.svg
  • apps/site/public/icons/technologies/mariadbdark.svg is excluded by !**/*.svg
  • apps/site/public/icons/technologies/mongodb copy.svg is excluded by !**/*.svg
  • apps/site/public/icons/technologies/mongodbsimple.svg is excluded by !**/*.svg
  • apps/site/public/icons/technologies/mssql.svg is excluded by !**/*.svg
  • apps/site/public/icons/technologies/mysql copy.svg is excluded by !**/*.svg
  • apps/site/public/icons/technologies/mysqlsimple.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/Illustrations/Diagrams/Code/Type3.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/enterprise_0.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/enterprise_0_light.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/enterprise_1.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/enterprise_1_light.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/enterprise_2.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/enterprise_2_light.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • apps/site/package.json
  • apps/site/public/animations/enterprise/build_fortify_grow.riv
  • apps/site/src/app/enterprise/page.tsx
  • apps/site/src/components/animation.tsx
  • apps/site/src/components/enterprise/carousel-item.tsx
  • apps/site/src/components/enterprise/footer-accordion.tsx
  • apps/site/src/components/enterprise/form.tsx
  • apps/site/src/components/enterprise/switch-enterprise.tsx
  • apps/site/src/components/homepage/card-section/card-section.tsx
  • apps/site/src/components/logo-parade.tsx
  • apps/site/src/components/technology.tsx
  • apps/site/src/types/global.d.ts
  • packages/eclipse/src/components/button.tsx

Copy link
Copy Markdown
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.

🧹 Nitpick comments (2)
apps/site/src/components/enterprise/scroll-carousel.tsx (2)

62-77: Consider disabling nav buttons at scroll boundaries.

Both left/right controls remain active even when already at the first/last item. Disabling at bounds would remove no-op clicks and improve interaction clarity.

Also applies to: 99-115

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/scroll-carousel.tsx` around lines 62 -
77, The left/right nav buttons in ScrollCarousel should be disabled when at the
start/end to prevent no-op clicks: track the current visible index or scroll
boundary inside the ScrollCarousel component (e.g., maintain a currentIndex or
isAtStart/isAtEnd state updated in your scroll/resize handlers) and use that
state to add disabled and aria-disabled attributes to the left/right buttons and
conditionally apply the hidden/disabled styles; update the onClick handlers that
call scrollByItem to be no-ops when the corresponding boundary state is true so
the buttons (the elements using onClick={() => scrollByItem(-1)} and onClick={()
=> scrollByItem(1)}) are visually and functionally disabled at bounds.

86-89: Use index-based composite keys for better carousel resilience.

While the carousel data arrays currently have unique titles, using key={item.title} relies on title uniqueness and can cause subtle bugs if the data changes. React best practices recommend index-based composite keys for lists: key={${item.title}-${index}} or unique IDs when available. This pattern is more robust and prevents accidental DOM reuse during updates.

Note: The same pattern appears redundantly in carousel-item.tsx line 19, which can be removed since the parent already keys each item.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/scroll-carousel.tsx` around lines 86 -
89, The carousel map currently uses key={item.title} which can break on title
collisions; update the items.map in ScrollCarousel (the items.map(...) render)
to use an index-based composite key such as `${item.title}-${index}` (capture
the index in the map callback) or a real unique id if available, and remove the
duplicate key prop in carousel-item.tsx (the key on the child component) since
the parent now provides the list key to avoid redundant/contradictory keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/site/src/components/enterprise/scroll-carousel.tsx`:
- Around line 62-77: The left/right nav buttons in ScrollCarousel should be
disabled when at the start/end to prevent no-op clicks: track the current
visible index or scroll boundary inside the ScrollCarousel component (e.g.,
maintain a currentIndex or isAtStart/isAtEnd state updated in your scroll/resize
handlers) and use that state to add disabled and aria-disabled attributes to the
left/right buttons and conditionally apply the hidden/disabled styles; update
the onClick handlers that call scrollByItem to be no-ops when the corresponding
boundary state is true so the buttons (the elements using onClick={() =>
scrollByItem(-1)} and onClick={() => scrollByItem(1)}) are visually and
functionally disabled at bounds.
- Around line 86-89: The carousel map currently uses key={item.title} which can
break on title collisions; update the items.map in ScrollCarousel (the
items.map(...) render) to use an index-based composite key such as
`${item.title}-${index}` (capture the index in the map callback) or a real
unique id if available, and remove the duplicate key prop in carousel-item.tsx
(the key on the child component) since the parent now provides the list key to
avoid redundant/contradictory keys.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d9cf1932-4a45-4a72-8fba-42f4614801a0

📥 Commits

Reviewing files that changed from the base of the PR and between 9bcd0f6 and 432fd34.

⛔ Files ignored due to path filters (5)
  • apps/site/public/illustrations/enterprise/bgf-light.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/bgf.svg is excluded by !**/*.svg
  • apps/site/public/illustrations/enterprise/enterprise_2_light.svg is excluded by !**/*.svg
  • apps/site/public/og/og-enterprise.png is excluded by !**/*.png
  • apps/site/public/og/og-index.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • apps/site/src/app/(index)/page.tsx
  • apps/site/src/app/enterprise/page.tsx
  • apps/site/src/components/enterprise/carousel-item.tsx
  • apps/site/src/components/enterprise/scroll-carousel.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/site/src/components/enterprise/carousel-item.tsx
  • apps/site/src/app/enterprise/page.tsx

Clean up the enterprise page follow-up items so the new landing experience is easier to maintain and behaves more predictably. This resolves remaining review feedback around copy, typing, embeds, animation cleanup, and carousel interactions.

Made-with: Cursor
Copy link
Copy Markdown
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: 3

🧹 Nitpick comments (1)
apps/site/src/app/enterprise/page.tsx (1)

64-107: Let TypeScript validate this section data instead of any.

card: any and db: any throw away the compiler right where the JSX depends on subtitle, icon, image, name, and url. Small local types here would catch bad data edits before they ship.

🧩 Example tightening
+type DatabaseCard = {
+  name: string;
+  icon: string;
+  url?: string;
+};
+
+type ComplexityCard = {
+  title: string;
+  subtitle: string;
+  icon: string;
+  image?: string;
+};
+
-const databases = {
+const databases: { title: string; list: DatabaseCard[] } = {
   title: "Supported Databases",
   list: [
     // ...
   ],
 };
 
-const complexities = [
+const complexities: ComplexityCard[] = [
   // ...
 ];
 
-          {complexities.map((card: any, index: number) => {
+          {complexities.map((card, index) => {
             const last = index === complexities.length - 1;
             return (
               // ...
             );
           })}
 
-                        {databases.list.map((db: any, idx: number) => (
+                        {databases.list.map((db, idx) => (
                           // ...
                         ))}

Also applies to: 110-131, 400-445

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/enterprise/page.tsx` around lines 64 - 107, The code uses
loose any types (e.g., card: any, db: any) which defeats compile-time checks for
fields like subtitle, icon, image, name, and url; define local interfaces such
as DatabaseItem { name: string; icon: string; url: string; subtitle?: string;
image?: string } and CardItem { title: string; subtitle?: string; image?: string
} and annotate the constants and map callbacks (specifically the databases
constant and the map callbacks that use db and card) with these types so
TypeScript validates the shape, then update any variable declarations/props that
currently use any to use the new interfaces to catch missing or mis-typed fields
at compile time.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/site/src/app/enterprise/page.tsx`:
- Around line 64-107: The databases.list entries all have placeholder url: "/"
which flows into the Technology component and causes every chip to link to the
homepage; update each object in databases.list (e.g., the PostgreSQL, MySQL,
MariaDB, SQLite, SQL Server, CockroachDB, PlanetScale, MongoDB entries) to
either provide the correct destination URL for that technology or remove the url
property entirely so Technology renders no link, and apply the same fix to the
other occurrences noted (lines 447-450) to avoid shipping placeholder links to
production.

In `@apps/site/src/components/enterprise/switch-enterprise.tsx`:
- Around line 12-15: The component currently assumes exactly two tabs but types
tabs and content as arbitrary arrays; update the contract and rendering to be
consistent: either change SwitchEnterpriseProps to require exactly two entries
(e.g., use a tuple type for tabs and a tuple/array-of-two for content) and keep
the existing mobile branches that index [0] and [1], or (preferred) make the
mobile rendering dynamic by iterating over tabs and content instead of
hard-coding indices—update the render logic that references tabs[0], tabs[1],
content[0], content[1] (and related mobile branches) to map over the
tabs/content arrays and render each section, and adjust any prop
validation/types accordingly so consumers can’t pass shorter arrays.
- Around line 41-50: The buttons in the SwitchEnterprise component (the mapped
Button instances using tabs, idx, activeTab and setActiveTab) lack accessible
state; update the Button JSX to expose its selected state by adding
aria-pressed={activeTab === idx} (or, if you prefer full tab semantics, wrap
with role="tablist" and give each Button role="tab" plus
aria-selected={activeTab === idx}), ensuring the onClick still calls
setActiveTab(idx) so ARIA reflects the activeTab state.

---

Nitpick comments:
In `@apps/site/src/app/enterprise/page.tsx`:
- Around line 64-107: The code uses loose any types (e.g., card: any, db: any)
which defeats compile-time checks for fields like subtitle, icon, image, name,
and url; define local interfaces such as DatabaseItem { name: string; icon:
string; url: string; subtitle?: string; image?: string } and CardItem { title:
string; subtitle?: string; image?: string } and annotate the constants and map
callbacks (specifically the databases constant and the map callbacks that use db
and card) with these types so TypeScript validates the shape, then update any
variable declarations/props that currently use any to use the new interfaces to
catch missing or mis-typed fields at compile time.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 940504c5-c3e3-408a-b3c5-dff0ce38104f

📥 Commits

Reviewing files that changed from the base of the PR and between 432fd34 and f7b739b.

📒 Files selected for processing (8)
  • apps/site/src/app/enterprise/page.tsx
  • apps/site/src/components/animation.tsx
  • apps/site/src/components/enterprise/carousel-item.tsx
  • apps/site/src/components/enterprise/form.tsx
  • apps/site/src/components/enterprise/scroll-carousel.tsx
  • apps/site/src/components/enterprise/switch-enterprise.tsx
  • apps/site/src/components/logo-parade.tsx
  • apps/site/src/components/technology.tsx
✅ Files skipped from review due to trivial changes (2)
  • apps/site/src/components/technology.tsx
  • apps/site/src/components/logo-parade.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/site/src/components/enterprise/form.tsx
  • apps/site/src/components/animation.tsx
  • apps/site/src/components/enterprise/scroll-carousel.tsx

Comment on lines +64 to +107
const databases = {
title: "Supported Databases",
list: [
{
name: "PostgreSQL",
icon: "/icons/companies/postgres.svg",
url: "/",
},
{
name: "MySQL",
icon: "/icons/technologies/mysqlsimple.svg",
url: "/",
},
{
name: "MariaDB",
icon: "/icons/technologies/mariadb.svg",
url: "/",
},
{
name: "SQLite",
icon: "/icons/companies/sqlite.svg",
url: "/",
},
{
name: "SQL Server",
icon: "/icons/companies/sqlserver.svg",
url: "/",
},
{
name: "CockroachDB",
icon: "/icons/companies/cockroachdb.svg",
url: "/",
},
{
name: "PlanetScale",
icon: "/icons/companies/planetscale.svg",
url: "/",
},
{
name: "MongoDB",
icon: "/icons/technologies/mongodbsimple.svg",
url: "/",
},
],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Replace the placeholder database destinations.

Every entry in databases.list currently uses url: "/", and that value is passed straight into Technology. That either sends every “Supported Databases” chip to the homepage or ships obvious placeholder data into production. Use real targets or omit url until they exist.

Also applies to: 447-450

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/enterprise/page.tsx` around lines 64 - 107, The
databases.list entries all have placeholder url: "/" which flows into the
Technology component and causes every chip to link to the homepage; update each
object in databases.list (e.g., the PostgreSQL, MySQL, MariaDB, SQLite, SQL
Server, CockroachDB, PlanetScale, MongoDB entries) to either provide the correct
destination URL for that technology or remove the url property entirely so
Technology renders no link, and apply the same fix to the other occurrences
noted (lines 447-450) to avoid shipping placeholder links to production.

Comment on lines +12 to +15
interface SwitchEnterpriseProps {
content: ContentBox[][];
tabs: { id: string; value: string }[];
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Make the prop contract match the hard-coded two-tab layout.

tabs and content are typed as arbitrary arrays, but the mobile branches index [0] and [1] directly. A shorter input will throw, and any third tab silently disappears on mobile. Either encode this as a fixed 2-tab API or render the mobile sections by iterating instead of hard-coding indices.

♻️ If this component is intentionally fixed to two tabs
+interface SwitchEnterpriseTab {
+  id: string;
+  value: string;
+}
+
 interface SwitchEnterpriseProps {
-  content: ContentBox[][];
-  tabs: { id: string; value: string }[];
+  content: [ContentBox[], ContentBox[]];
+  tabs: [SwitchEnterpriseTab, SwitchEnterpriseTab];
 }

Also applies to: 65-84

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/switch-enterprise.tsx` around lines 12 -
15, The component currently assumes exactly two tabs but types tabs and content
as arbitrary arrays; update the contract and rendering to be consistent: either
change SwitchEnterpriseProps to require exactly two entries (e.g., use a tuple
type for tabs and a tuple/array-of-two for content) and keep the existing mobile
branches that index [0] and [1], or (preferred) make the mobile rendering
dynamic by iterating over tabs and content instead of hard-coding indices—update
the render logic that references tabs[0], tabs[1], content[0], content[1] (and
related mobile branches) to map over the tabs/content arrays and render each
section, and adjust any prop validation/types accordingly so consumers can’t
pass shorter arrays.

Comment on lines +41 to +50
<div className="gap-6 mx-auto justify-center items-center hidden md:flex">
{tabs.map((tab, idx) => (
<Button
key={tab.id}
size="4xl"
variant={activeTab === idx ? "orm" : "default-stronger"}
onClick={() => setActiveTab(idx)}
>
{tab.value}
</Button>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Expose the active state on the switch buttons.

Right now the current tab is only communicated by variant, so assistive tech gets a row of identical buttons with no selected state. Add aria-pressed at minimum, or full tab semantics if you want this to behave like a tablist.

♿ Minimal fix
           <Button
             key={tab.id}
             size="4xl"
             variant={activeTab === idx ? "orm" : "default-stronger"}
+            aria-pressed={activeTab === idx}
             onClick={() => setActiveTab(idx)}
           >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="gap-6 mx-auto justify-center items-center hidden md:flex">
{tabs.map((tab, idx) => (
<Button
key={tab.id}
size="4xl"
variant={activeTab === idx ? "orm" : "default-stronger"}
onClick={() => setActiveTab(idx)}
>
{tab.value}
</Button>
<div className="gap-6 mx-auto justify-center items-center hidden md:flex">
{tabs.map((tab, idx) => (
<Button
key={tab.id}
size="4xl"
variant={activeTab === idx ? "orm" : "default-stronger"}
aria-pressed={activeTab === idx}
onClick={() => setActiveTab(idx)}
>
{tab.value}
</Button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/switch-enterprise.tsx` around lines 41 -
50, The buttons in the SwitchEnterprise component (the mapped Button instances
using tabs, idx, activeTab and setActiveTab) lack accessible state; update the
Button JSX to expose its selected state by adding aria-pressed={activeTab ===
idx} (or, if you prefer full tab semantics, wrap with role="tablist" and give
each Button role="tab" plus aria-selected={activeTab === idx}), ensuring the
onClick still calls setActiveTab(idx) so ARIA reflects the activeTab state.

Use the nearest snapped card as the current carousel position so repeated next clicks advance reliably instead of stopping after the first scroll.

Made-with: Cursor
Copy link
Copy Markdown
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.

🧹 Nitpick comments (3)
apps/site/src/components/enterprise/scroll-carousel.tsx (3)

37-40: Avoid shadowing the items prop inside scrollByItem.

Using items for both props and queried elements makes this block harder to reason about. A distinct name improves clarity.

♻️ Small clarity refactor
-    const items = container?.querySelectorAll<HTMLElement>("[data-carousel-item]");
+    const carouselItems = container?.querySelectorAll<HTMLElement>(
+      "[data-carousel-item]",
+    );

-    if (!container || !items?.length) {
+    if (!container || !carouselItems?.length) {
       return;
     }

-    const itemList = Array.from(items);
+    const itemList = Array.from(carouselItems);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/scroll-carousel.tsx` around lines 37 -
40, The function scrollByItem is shadowing the component prop items by declaring
a local variable named items from container?.querySelectorAll; rename the local
query result (for example to carouselElements or carouselItems) and update any
subsequent references in scrollByItem to use that new identifier so the prop
items remains unshadowed and the code is clearer; locate scrollByItem and
scrollRef to make the change.

71-87: Bounds state can become stale when content size changes without resize.

If card layout changes after mount (e.g., late-loading content/fonts), isAtStart/isAtEnd may be outdated until the user scrolls or resizes. Consider observing container size/content changes and re-running updateScrollBounds.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/scroll-carousel.tsx` around lines 71 -
87, The bounds update effect currently listens only for scroll and window
resize, so isAtStart/isAtEnd can become stale when content or fonts load; modify
the effect that references scrollRef and updateScrollBounds to also observe
size/content changes (e.g., create a ResizeObserver on scrollRef.current and/or
a MutationObserver for child changes) and call updateScrollBounds when
observations fire (debounce via requestAnimationFrame if needed), and ensure you
disconnect the observers in the effect cleanup along with removing the existing
scroll/resize listeners.

91-165: Consider extracting a shared nav button component.

Desktop and mobile controls duplicate the same button structure and behavior. A small shared component would reduce drift risk and simplify future style/logic updates.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/components/enterprise/scroll-carousel.tsx` around lines 91 -
165, The left/right buttons are duplicated for desktop and mobile; create a
small shared component (e.g., NavButton) that accepts props: direction
('left'|'right'), disabled (use isAtStart/isAtEnd), onClick (pass
scrollByItem(-1/1)), extraClassName (to keep differing layout classes), and
ariaLabel, and renders the same <button> structure with the correct icon class
("fa-chevron-left"/"fa-chevron-right") and cn usage; then replace the six
duplicated button instances with NavButton calls in both the desktop and mobile
controls so behavior (disabled, aria-disabled, onClick) and styling are
preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/site/src/components/enterprise/scroll-carousel.tsx`:
- Around line 37-40: The function scrollByItem is shadowing the component prop
items by declaring a local variable named items from
container?.querySelectorAll; rename the local query result (for example to
carouselElements or carouselItems) and update any subsequent references in
scrollByItem to use that new identifier so the prop items remains unshadowed and
the code is clearer; locate scrollByItem and scrollRef to make the change.
- Around line 71-87: The bounds update effect currently listens only for scroll
and window resize, so isAtStart/isAtEnd can become stale when content or fonts
load; modify the effect that references scrollRef and updateScrollBounds to also
observe size/content changes (e.g., create a ResizeObserver on scrollRef.current
and/or a MutationObserver for child changes) and call updateScrollBounds when
observations fire (debounce via requestAnimationFrame if needed), and ensure you
disconnect the observers in the effect cleanup along with removing the existing
scroll/resize listeners.
- Around line 91-165: The left/right buttons are duplicated for desktop and
mobile; create a small shared component (e.g., NavButton) that accepts props:
direction ('left'|'right'), disabled (use isAtStart/isAtEnd), onClick (pass
scrollByItem(-1/1)), extraClassName (to keep differing layout classes), and
ariaLabel, and renders the same <button> structure with the correct icon class
("fa-chevron-left"/"fa-chevron-right") and cn usage; then replace the six
duplicated button instances with NavButton calls in both the desktop and mobile
controls so behavior (disabled, aria-disabled, onClick) and styling are
preserved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fa819898-344d-494c-b219-9d93ab9c6d75

📥 Commits

Reviewing files that changed from the base of the PR and between f7b739b and 3b3bed3.

📒 Files selected for processing (1)
  • apps/site/src/components/enterprise/scroll-carousel.tsx

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