Skip to content

Website components shadcn#197

Open
aidenybai wants to merge 1 commit intomainfrom
cursor/website-components-shadcn-c93c
Open

Website components shadcn#197
aidenybai wants to merge 1 commit intomainfrom
cursor/website-components-shadcn-c93c

Conversation

@aidenybai
Copy link
Owner

@aidenybai aidenybai commented Feb 26, 2026

Migrate website interactive UI components to shadcn to standardize the component library and improve maintainability.


Open in Web Open in Cursor 


Summary by cubic

Migrated website UI to shadcn/Radix primitives for consistent styling, simpler code, and easier maintenance. Replaced custom elements across pages with shared components.

  • Refactors

    • Adopted Button, Card, Input, Select, Table, Tabs, Tooltip, ScrollArea, and Collapsible components.
    • Updated benchmark tooltip/charts/table, code/read blocks, install tabs, demo footer, GitHub/docs buttons, and editor picker pages to use these primitives.
    • Removed bespoke scrollbars and tooltip logic; rely on Radix behaviors and simplified motion.
  • Dependencies

    • Added @radix-ui/react: tabs, select, tooltip, scroll-area, collapsible, slot.
    • Updated pnpm lockfile.

Written for commit e8769ce. Summary will update on new commits.


Note

Medium Risk
Moderate UI refactor replacing custom dropdown/tooltip/scroll/interactive elements with new Radix-based primitives; risk is mainly styling/behavior regressions and focus/keyboard interaction changes, with no backend or data-flow impact.

Overview
Standardizes the website’s UI component layer by introducing shadcn-style primitives (Button, Card, Input, Select, Tabs, Table, Tooltip, ScrollArea) built on Radix + class-variance-authority.

Refactors multiple interactive surfaces (e.g., open-file editor picker, install tabs, benchmark tooltip/tables, code/copy controls, demo footer, GitHub/docs buttons, collapsibles, and scrollable areas) to use these shared components, removing bespoke dropdown/tooltip/scrollbar logic and aligning styling/behavior.

Adds required Radix dependencies in packages/website/package.json and updates pnpm-lock.yaml accordingly.

Written by Cursor Bugbot for commit e8769ce. This will update automatically on new commits. Configure here.

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
@cursor
Copy link

cursor bot commented Feb 26, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@vercel
Copy link
Contributor

vercel bot commented Feb 26, 2026

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

Project Deployment Actions Updated (UTC)
react-grab-website Ready Ready Preview, Comment Feb 26, 2026 2:28pm

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 26, 2026

Open in StackBlitz

@react-grab/cli

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/cli@197

grab

npm i https://pkg.pr.new/aidenybai/react-grab/grab@197

@react-grab/ami

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/ami@197

@react-grab/amp

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/amp@197

@react-grab/claude-code

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/claude-code@197

@react-grab/codex

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/codex@197

@react-grab/copilot

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/copilot@197

@react-grab/cursor

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/cursor@197

@react-grab/droid

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/droid@197

@react-grab/gemini

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/gemini@197

@react-grab/opencode

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/opencode@197

react-grab

npm i https://pkg.pr.new/aidenybai/react-grab@197

@react-grab/relay

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/relay@197

@react-grab/utils

npm i https://pkg.pr.new/aidenybai/react-grab/@react-grab/utils@197

commit: e8769ce

@aidenybai aidenybai marked this pull request as ready for review February 27, 2026 01:07
@pullfrog
Copy link
Contributor

pullfrog bot commented Feb 27, 2026

This run croaked 😵

The workflow encountered an error before any progress could be reported. Please check the workflow run logs for details.

Pullfrog  | View workflow run | Triggered by Pullfrogpullfrog.com𝕏

</span>
<Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
<TooltipTrigger asChild>
<Link href={href} rel="noreferrer" className={className}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing exit animations on tooltip content motion.div causes visual snap when tooltip closes instead of smooth animation out

Fix on Vercel


useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Enter" && !isDropdownOpen) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The Select dropdown doesn't close after selecting an editor because handleEditorChange no longer calls setIsEditorSelectOpen(false)

Fix on Vercel

<div className="relative">
<ScrollArea
className={cn(
"overflow-y-auto rounded-md [scrollbar-width:none] [&_[data-slot='scroll-area-scrollbar']]:opacity-0 [&_[data-slot='scroll-area-scrollbar']]:transition-opacity hover:[&_[data-slot='scroll-area-scrollbar']]:opacity-100",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"overflow-y-auto rounded-md [scrollbar-width:none] [&_[data-slot='scroll-area-scrollbar']]:opacity-0 [&_[data-slot='scroll-area-scrollbar']]:transition-opacity hover:[&_[data-slot='scroll-area-scrollbar']]:opacity-100",
"overflow-y-auto rounded-md [scrollbar-width:none] [&_[data-slot=scroll-area-scrollbar]]:opacity-0 [&_[data-slot=scroll-area-scrollbar]]:transition-opacity hover:[&_[data-slot=scroll-area-scrollbar]]:opacity-100",

CSS selector with quoted attribute values inside Tailwind arbitrary bracket notation may be incorrectly parsed due to complex nested bracket and quote handling

Fix on Vercel

>
{children}
</motion.div>
<CollapsiblePrimitive.Content forceMount asChild>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<CollapsiblePrimitive.Content forceMount asChild>
<CollapsiblePrimitive.Content asChild>

The CollapsiblePrimitive.Content component has forceMount prop that conflicts with AnimatePresence conditional rendering, causing potential animation issues

Fix on Vercel

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

7 issues found across 24 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/website/components/ui/collapsible.tsx">

<violation number="1" location="packages/website/components/ui/collapsible.tsx:65">
P2: Avoid animating `height` in this transition; it causes layout/repaint work and violates the project animation guideline to animate compositor-friendly properties only.</violation>
</file>

<file name="packages/website/components/ui/button.tsx">

<violation number="1" location="packages/website/components/ui/button.tsx:9">
P2: The shared button primitive is missing `touch-action: manipulation`, which is required by the project interaction guidelines and can cause suboptimal touch behavior (e.g., double-tap zoom delays).</violation>
</file>

<file name="packages/website/components/blocks/read-tool-call-block.tsx">

<violation number="1" location="packages/website/components/blocks/read-tool-call-block.tsx:46">
P2: The new Button classes override shadcn size constraints and can reduce the interactive hit target below accessibility minimums.</violation>
</file>

<file name="packages/website/components/ui/card.tsx">

<violation number="1" location="packages/website/components/ui/card.tsx:1">
P2: Remove the unnecessary `"use client"` directive from this presentational component to avoid forcing an avoidable client boundary and hydration cost.</violation>
</file>

<file name="packages/website/components/ui/tooltip.tsx">

<violation number="1" location="packages/website/components/ui/tooltip.tsx:8">
P2: Default tooltip delay is disabled (`delayDuration = 0`), which breaks the required "delay first tooltip" interaction behavior.</violation>

<violation number="2" location="packages/website/components/ui/tooltip.tsx:24">
P2: Wrapping every `Tooltip` in an inner `TooltipProvider` overrides outer provider settings and breaks group-level tooltip timing behavior.</violation>
</file>

<file name="packages/website/app/open-file/page.tsx">

<violation number="1" location="packages/website/app/open-file/page.tsx:119">
P2: Pressing Enter on the editor Select trigger can unexpectedly call `handleOpen()` and navigate away before the Select opens, due to the global Enter handler relying only on `isEditorSelectOpen`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment on lines +65 to +67
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

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

P2: Avoid animating height in this transition; it causes layout/repaint work and violates the project animation guideline to animate compositor-friendly properties only.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/website/components/ui/collapsible.tsx, line 65:

<comment>Avoid animating `height` in this transition; it causes layout/repaint work and violates the project animation guideline to animate compositor-friendly properties only.</comment>

<file context>
@@ -31,44 +33,47 @@ export const Collapsible = ({
-          </motion.div>
+          <CollapsiblePrimitive.Content forceMount asChild>
+            <motion.div
+              initial={{ opacity: 0, height: 0 }}
+              animate={{ opacity: 1, height: "auto" }}
+              exit={{ opacity: 0, height: 0 }}
</file context>
Suggested change
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
Fix with Cubic

import { cn } from "@/utils/cn";

const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,background-color,border-color,box-shadow,transform,opacity] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-background aria-invalid:border-destructive",
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

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

P2: The shared button primitive is missing touch-action: manipulation, which is required by the project interaction guidelines and can cause suboptimal touch behavior (e.g., double-tap zoom delays).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/website/components/ui/button.tsx, line 9:

<comment>The shared button primitive is missing `touch-action: manipulation`, which is required by the project interaction guidelines and can cause suboptimal touch behavior (e.g., double-tap zoom delays).</comment>

<file context>
@@ -0,0 +1,65 @@
+import { cn } from "@/utils/cn";
+
+const buttonVariants = cva(
+  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,background-color,border-color,box-shadow,transform,opacity] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-background aria-invalid:border-destructive",
+  {
+    variants: {
</file context>
Fix with Cubic

className="max-w-full break-all text-left transition-colors duration-300"
variant="ghost"
size="sm"
className="h-auto max-w-full break-all px-0 py-0 text-left font-normal transition-colors duration-300 hover:bg-transparent"
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

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

P2: The new Button classes override shadcn size constraints and can reduce the interactive hit target below accessibility minimums.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/website/components/blocks/read-tool-call-block.tsx, line 46:

<comment>The new Button classes override shadcn size constraints and can reduce the interactive hit target below accessibility minimums.</comment>

<file context>
@@ -38,15 +39,17 @@ export const ReadToolCallBlock = ({
-        className="max-w-full break-all text-left transition-colors duration-300"
+        variant="ghost"
+        size="sm"
+        className="h-auto max-w-full break-all px-0 py-0 text-left font-normal transition-colors duration-300 hover:bg-transparent"
         style={{
           color: isClicked ? "#ffffff" : "#5b5b5b",
</file context>
Fix with Cubic

@@ -0,0 +1,91 @@
"use client";
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

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

P2: Remove the unnecessary "use client" directive from this presentational component to avoid forcing an avoidable client boundary and hydration cost.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/website/components/ui/card.tsx, line 1:

<comment>Remove the unnecessary `"use client"` directive from this presentational component to avoid forcing an avoidable client boundary and hydration cost.</comment>

<file context>
@@ -0,0 +1,91 @@
+"use client";
+
+import type { HTMLAttributes, ReactElement } from "react";
</file context>
Fix with Cubic

import { cn } from "@/utils/cn";

export const TooltipProvider = ({
delayDuration = 0,
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

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

P2: Default tooltip delay is disabled (delayDuration = 0), which breaks the required "delay first tooltip" interaction behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/website/components/ui/tooltip.tsx, line 8:

<comment>Default tooltip delay is disabled (`delayDuration = 0`), which breaks the required "delay first tooltip" interaction behavior.</comment>

<file context>
@@ -0,0 +1,59 @@
+import { cn } from "@/utils/cn";
+
+export const TooltipProvider = ({
+  delayDuration = 0,
+  ...props
+}: ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>): ReactElement => {
</file context>
Fix with Cubic

...props
}: ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>): ReactElement => {
return (
<TooltipProvider>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

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

P2: Wrapping every Tooltip in an inner TooltipProvider overrides outer provider settings and breaks group-level tooltip timing behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/website/components/ui/tooltip.tsx, line 24:

<comment>Wrapping every `Tooltip` in an inner `TooltipProvider` overrides outer provider settings and breaks group-level tooltip timing behavior.</comment>

<file context>
@@ -0,0 +1,59 @@
+  ...props
+}: ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>): ReactElement => {
+  return (
+    <TooltipProvider>
+      <TooltipPrimitive.Root data-slot="tooltip" {...props} />
+    </TooltipProvider>
</file context>
Fix with Cubic

useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Enter" && !isDropdownOpen) {
if (event.key === "Enter" && !isEditorSelectOpen) {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 27, 2026

Choose a reason for hiding this comment

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

P2: Pressing Enter on the editor Select trigger can unexpectedly call handleOpen() and navigate away before the Select opens, due to the global Enter handler relying only on isEditorSelectOpen.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/website/app/open-file/page.tsx, line 119:

<comment>Pressing Enter on the editor Select trigger can unexpectedly call `handleOpen()` and navigate away before the Select opens, due to the global Enter handler relying only on `isEditorSelectOpen`.</comment>

<file context>
@@ -115,31 +116,30 @@ const OpenFileContent = () => {
   useEffect(() => {
     const handleKeyDown = (event: KeyboardEvent) => {
-      if (event.key === "Enter" && !isDropdownOpen) {
+      if (event.key === "Enter" && !isEditorSelectOpen) {
         handleOpen();
       }
</file context>
Fix with Cubic

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

)}
>
<SelectValue placeholder="Select editor" />
</SelectTrigger>
Copy link

Choose a reason for hiding this comment

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

Duplicate editor icon in Select trigger

Medium Severity

The SelectTrigger contains an explicit icon (selectedEditor?.icon) alongside a SelectValue. Since each SelectItem wraps its full children (including the icon and name) inside SelectPrimitive.ItemText, and SelectValue renders the ItemText content of the selected item, the editor icon appears twice in the trigger — once from the explicit span and once from the SelectValue rendering.

Additional Locations (1)

Fix in Cursor Fix in Web

<thead>
<tr className="border-b border-[#2a2a2a]">
<th className="text-left py-2 px-4 text-xs font-medium text-neutral-500 uppercase tracking-wider">
<Table className="max-w-2xl border-collapse text-sm">
Copy link

Choose a reason for hiding this comment

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

Table wrapper div breaks flex centering layout

Medium Severity

The Table component introduces a wrapper div with w-full around the <table>. When placed inside the parent div with flex justify-center, this w-full wrapper stretches to the full container width, defeating the centering. Previously the <table> (with max-w-2xl) was the direct flex item and got centered; now it's left-aligned inside the full-width wrapper. The benchmark summary table loses its centered layout on wider viewports.

Additional Locations (1)

Fix in Cursor Fix in Web

>
{parameter}
</button>
</Button>
Copy link

Choose a reason for hiding this comment

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

Button base whitespace-nowrap prevents file path wrapping

Medium Severity

The Button base class includes whitespace-nowrap, which overrides the break-all class on the ReadToolCallBlock button. The old plain <button> had no whitespace-nowrap, so long file paths wrapped naturally. Now white-space: nowrap suppresses all line breaks, making word-break: break-all ineffective, so file path parameter text will overflow its container instead of wrapping.

Additional Locations (1)

Fix in Cursor Fix in Web

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