asChild
Prop Issue in Astro with shadcn/uiWhen integrating shadcn/ui components with Astro, you might encounter issues with the asChild
prop not working as expected. This is a common problem that occurs due to how Astro handles React components and prop forwarding.
When using shadcn/ui components like PopoverTrigger
with the asChild
prop in Astro, you might find that the prop doesn’t work as intended.
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="capitalize justify-between"
>
{value
? frameworks.find((framework) => framework.value === value)?.label
: `${title}`}
<ChevronsUpDown className="opacity-50" />
</Button>
</PopoverTrigger>
I guess it happens because Astro inserts its own nodes while rendering nested components, and the button passes its props to a temporary child.
Instead of relying on the asChild
prop, you can directly apply the button styling to the PopoverTrigger
component:
<PopoverTrigger className={cn(buttonVariants({ variant: "outline" }))}>
{value
? frameworks.find((framework) => framework.value === value)?.label
: `${title}`}
<ChevronsUpDown className="size-4 opacity-50" />
</PopoverTrigger>
asChild
prop: We eliminate the problematic prop entirelyPopoverTrigger
Here’s a complete example of a working Combobox component in Astro:
import { useState } from "react"
import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { ChevronsUpDown, Check } from "lucide-react"
const frameworks = [
{ value: "next.js", label: "Next.js" },
{ value: "sveltekit", label: "SvelteKit" },
{ value: "nuxt.js", label: "Nuxt.js" },
{ value: "remix", label: "Remix" },
{ value: "astro", label: "Astro" },
]
export default function ComboboxDemo({ title = "Select framework..." }) {
const [open, setOpen] = useState(false)
const [value, setValue] = useState("")
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger
className={cn(
buttonVariants({ variant: "outline" }),
"capitalize justify-between"
)}
role="combobox"
aria-expanded={open}
>
{value
? frameworks.find((framework) => framework.value === value)?.label
: title}
<ChevronsUpDown className="size-4 opacity-50" />
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
{/* Your popover content here */}
</PopoverContent>
</Popover>
)
}