Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import * as React from "react";
import * as React from "react"

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

const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
);
}
);
Input.displayName = "Input";
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-1",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
)}
{...props}
/>
)
}

export { Input };
export { Input }
79 changes: 55 additions & 24 deletions components/ui/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,61 @@
import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
"use client"

import { cn } from "@/lib/utils";
import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"

const TooltipProvider = TooltipPrimitive.Provider;
import { cn } from "@/lib/utils"

const Tooltip = TooltipPrimitive.Root;

const TooltipTrigger = TooltipPrimitive.Trigger;

const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-tooltip-content-transform-origin]",
className
)}
function TooltipProvider({
delayDuration = 0,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
{...props}
/>
</TooltipPrimitive.Portal>
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
)
}

function Tooltip({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return (
<TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
)
}
Comment on lines +21 to +29
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify this pattern matches the latest shadcn/ui implementation.

The Tooltip component embeds its own TooltipProvider, creating a new provider per tooltip instance. This differs from the typical Radix UI pattern where a single TooltipProvider wraps the application root and multiple tooltips share it.

Implications:

  • Users cannot share provider configuration across multiple tooltips
  • Performance overhead with many tooltip instances (each creates a new React context provider)
  • Users cannot wrap TooltipProvider at a higher level to configure all tooltips globally

Action required:
Please verify this matches the latest shadcn/ui tooltip implementation. If this is indeed the new pattern, consider documenting it for users migrating from older versions.


🌐 Web query:

Latest shadcn/ui tooltip component implementation pattern TooltipProvider usage

💡 Result:

Short answer — wrap your Tooltip(s) with TooltipProvider at a high level (usually near App/layout) and use the Tooltip + TooltipTrigger + TooltipContent primitives for each tooltip. Example (official pattern):

import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"

function App() {
return (



Hover me


Tooltip text





)
}

Notes:

  • TooltipProvider gives global defaults (timing/behavior) for nested tooltips; place it near your app root or layout. [1][2]
  • Use TooltipTrigger asChild when you want the trigger to be the child element without extra wrapper. [1]

Sources: official shadcn/ui docs. [1] UI docs (latest site) (ui.shadcn.com) [2] v3 docs / examples. (v3.shadcn.com)

Citations:



Fix: Remove embedded TooltipProvider and align with official shadcn/ui pattern.

The current implementation wraps each Tooltip instance with its own TooltipProvider, which deviates from the official shadcn/ui pattern where TooltipProvider should be placed near your app root or layout and multiple tooltips share it.

Issues with current pattern:

  • Creates unnecessary React context overhead (one provider per tooltip instead of one shared provider)
  • Prevents users from configuring provider behavior globally via a single TooltipProvider
  • Does not match the official usage pattern where a single TooltipProvider wraps multiple Tooltip + TooltipTrigger + TooltipContent instances

Remove the embedded TooltipProvider from the Tooltip component and expect users to place TooltipProvider at a high level in their application tree (or document this custom pattern with an explicit reason if this deviation is intentional).

🤖 Prompt for AI Agents
components/ui/tooltip.tsx around lines 21 to 29: the Tooltip component currently
wraps each instance in its own TooltipProvider which creates per-tooltip context
overhead and deviates from the shadcn/ui pattern; remove the embedded
TooltipProvider and have Tooltip simply forward props to TooltipPrimitive.Root
so that a single TooltipProvider can be placed at the app root or layout and
shared by all Tooltip instances; update any docs/comments to instruct consumers
to wrap their app/layout with TooltipProvider if they need global tooltip
configuration.


function TooltipTrigger({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}

function TooltipContent({
className,
sideOffset = 0,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
sideOffset={sideOffset}
className={cn(
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
className
)}
{...props}
>
{children}
<TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
)
}

export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }