radix-ui / themes

Radix Themes is an open-source component library optimized for fast development, easy maintenance, and accessibility. Maintained by @workos.

Home Page:https://radix-ui.com/themes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to stop propagation on SelectPrimitive.Trigger

singh-jay opened this issue · comments

I am trying to render a card with a select component inside it based on the shadcn-ui, which is placed relative to an input field on input focus to show the card to select the item, to close on click outside I have added a dom event to detect click and check if the node does not contain the children. but when I click on the select trigger it triggers the click outside, I tried the different options to prevent event propagation as suggested in [https://github.com/radix-ui/primitives/issues/1700], but no luck. If anyone has a solution, please share. I'm in the middle of a project and stuck with this issue for a long time.
Video -
Screencast from 14-04-24 05:09:54 PM IST.webm

Reproduction link - https://github.com/singh-jay/radix-demo-app
// page.tsx
`"use client";

import { ClickOutside } from "@/components/ui/click-outside";
import { Input } from "@/components/ui/input";
import { useState } from "react";
import { CardWithForm } from "./card";

export default function Home() {
const [open, setOpen] = useState(false);
return (


<ClickOutside
handleClickOutside={() => {
console.log("outside clicked");
setOpen(false);
}}
>

<Input placeholder="Select Value" onFocus={() => setOpen(true)} />
{open && }



);
}
// Card.tsximport * as React from "react";

import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";

export function CardWithForm() {
return (


Create project
Deploy your new project in one-click.





Name



Framework
<SelectTrigger id="framework" onChange={(e) => { e.preventDefault(); e.stopPropagation(); }} onClick={(e) => { e.preventDefault(); e.stopPropagation(); }} onSelect={(e) => { e.preventDefault(); e.stopPropagation(); }} ref={(ref) => { if (!ref) return; ref.addEventListener("click", (e) => { console.log("clicked"); e.preventDefault(); }); }} > <SelectValue placeholder="Select" /> </SelectTrigger> <SelectContent position="popper"> <SelectItem value="next">Next.js</SelectItem> <SelectItem value="sveltekit">SvelteKit</SelectItem> <SelectItem value="astro">Astro</SelectItem> <SelectItem value="nuxt">Nuxt.js</SelectItem> </SelectContent> </Select> </div> </div> </form> </CardContent> <CardFooter className="flex justify-between"> <Button variant="outline">Cancel</Button> <Button>Deploy</Button> </CardFooter> </Card> ); } ` // ClickOutside `import React, { ReactNode, useEffect, useRef } from 'react'; type ClickOutsideProps = { handleClickOutside: (e: MouseEvent) => void; children: ReactNode; className?: string; disable?: boolean; }; const ClickOutside = (props: ClickOutsideProps) => { const domNodeRef = useRef<HTMLDivElement | null>(null); const { className = '', disable = false, handleClickOutside, children } = props; useEffect(() => { const clickOutsideHandler = (e: MouseEvent) => { if ( !disable && domNodeRef.current && e.target && !domNodeRef.current.contains(e.target as Node) ) { handleClickOutside(e); } }; document.addEventListener('click', clickOutsideHandler, true); return () => { document.removeEventListener('click', clickOutsideHandler, true); }; }, []); return ( <div className={clickoutside ${className}} onClick={(e) => e.stopPropagation()} ref={domNodeRef} > {children} ); }; ClickOutside.displayName = 'ClickOutside'; export { ClickOutside };`

I'll have to close this because this is more of a self-inflicted issue, rather than a problem with Radix.

Select Trigger opens the menu on mousedown, and the click event itself lands on Select Content.

Select Content is portalled—that is, rendered outside of its containing element, which your component technically correctly interprets as an outside click.

Sounds like you are just trying to implement a Popover yourself, which exists as a primitive and avoids these issues:
https://www.radix-ui.com/primitives/docs/components/popover