Skip to content
Merged
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
44 changes: 27 additions & 17 deletions packages/components/src/ui/select.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Popover } from '@radix-ui/react-popover';
import * as PopoverPrimitive from '@radix-ui/react-popover';
Comment on lines 1 to +2
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix Radix Popover import/usage (compile breaker).

@radix-ui/react-popover does not export a Popover named component. Use PopoverPrimitive.Root and drop the duplicate import.

- import { Popover } from '@radix-ui/react-popover';
+ // (remove)

 import * as PopoverPrimitive from '@radix-ui/react-popover';
@@
-    <Popover open={popoverState.isOpen} onOpenChange={popoverState.setOpen}>
+    <PopoverPrimitive.Root open={popoverState.isOpen} onOpenChange={popoverState.setOpen}>
@@
-    </Popover>
+    </PopoverPrimitive.Root>

Also applies to: 108-108, 222-222

πŸ€– Prompt for AI Agents
In packages/components/src/ui/select.tsx around lines 1-2 (also occurrences at
108 and 222), the code imports a non-existent named Popover from
'@radix-ui/react-popover' and duplicates the import; replace both imports with a
single "import * as PopoverPrimitive from '@radix-ui/react-popover';", then
update all JSX usages of <Popover> to <PopoverPrimitive.Root> (and corresponding
closing tags) and use other primitives from PopoverPrimitive (Trigger, Content,
etc.) as needed; remove the duplicate import lines.

import { Check as DefaultCheckIcon, ChevronDown as DefaultChevronIcon } from 'lucide-react';
import * as React from 'react';
import { useOverlayTriggerState } from 'react-stately';
import { PopoverContent, PopoverTrigger } from './popover';
import { PopoverTrigger } from './popover';
import { cn } from './utils';

export interface SelectOption {
Expand Down Expand Up @@ -52,11 +53,7 @@ export function Select({
const triggerRef = React.useRef<HTMLButtonElement>(null);
const popoverRef = React.useRef<HTMLDivElement>(null);
const selectedItemRef = React.useRef<HTMLButtonElement>(null);
const [menuWidth, setMenuWidth] = React.useState<number | undefined>(undefined);

React.useEffect(() => {
if (triggerRef.current) setMenuWidth(triggerRef.current.offsetWidth);
}, []);
// No need for JavaScript width measurement - Radix provides --radix-popover-trigger-width CSS variable

// Scroll to selected item when dropdown opens
React.useEffect(() => {
Expand Down Expand Up @@ -130,15 +127,27 @@ export function Select({
<ChevronIcon className="w-4 h-4 opacity-50" />
</Trigger>
</PopoverTrigger>
<PopoverContent
ref={popoverRef}
className={cn('z-50 p-0 shadow-md border-0', contentClassName)}
// biome-ignore lint/a11y/useSemanticElements: using <div> for PopoverContent to ensure keyboard accessibility and focus management
role="listbox"
id={listboxId}
style={{ width: menuWidth ? `${menuWidth}px` : undefined }}
>
<div className="bg-white p-1.5 rounded-md focus:outline-none sm:text-sm">
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={popoverRef}
align="start"
sideOffset={4}
className={cn(
'z-50 rounded-md border bg-popover text-popover-foreground shadow-md outline-none',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-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',
'p-0 shadow-md border-0',
contentClassName
)}
// biome-ignore lint/a11y/useSemanticElements: using <div> for PopoverContent to ensure keyboard accessibility and focus management
role="listbox"
id={listboxId}
style={{ width: 'var(--radix-popover-trigger-width)' }}
data-slot="popover-content"
>
<div className="bg-white p-1.5 rounded-md focus:outline-none sm:text-sm w-full">
<div className="px-1.5 pb-1.5">
<SearchInput
type="text"
Expand Down Expand Up @@ -168,7 +177,7 @@ export function Select({
className="w-full h-9 rounded-md bg-white px-2 text-sm leading-none focus:ring-0 focus:outline-none border-0"
/>
</div>
<ul className="max-h-[200px] overflow-y-auto rounded-md">
<ul className="max-h-[200px] overflow-y-auto rounded-md w-full">
{filtered.length === 0 && <li className="px-3 py-2 text-sm text-gray-500">No results.</li>}
{filtered.map((option) => {
const isSelected = option.value === value;
Expand Down Expand Up @@ -208,7 +217,8 @@ export function Select({
})}
</ul>
</div>
</PopoverContent>
</PopoverPrimitive.Content>
</PopoverPrimitive.Portal>
</Popover>
);
}