Closed neo773 closed 1 year ago
You can make a couple of things:
Portal
component in popover (Maybe you have z-index
issues)modal={false}
on Dialog (The overlay will no be rendered)Dialog.Content
with Dialog.Overlay
(You can not set modal={false}
because the overlay will not be rendered)You can make a couple of things:
- Not render the
Portal
component in popover (Maybe you havez-index
issues)- Set
modal={false}
on Dialog (The overlay will no be rendered)- Wrap
Dialog.Content
withDialog.Overlay
(You can not setmodal={false}
because the overlay will not be rendered)
The 3rd option worked, Thanks.
could you post the working code
I am having the same issue.
<FormField
control={form.control}
name="timezone"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Timezone</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
role="combobox"
className={cn(
"w-[200px] justify-between",
!field.value && "text-muted-foreground"
)}
>
{field.value
? TimeZones.find((timezone) => timezone === field.value)
: "Select timezone"}
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search timezone..." />
<CommandEmpty>No timezone found.</CommandEmpty>
<ScrollArea className="h-60">
<CommandGroup>
{TimeZones.map((timezone) => (
<CommandItem
value={timezone}
key={timezone}
onSelect={() => {
form.setValue("timezone", timezone);
}}
>
<CheckIcon
className={cn(
"mr-2 h-4 w-4",
timezone === field.value
? "opacity-100"
: "opacity-0"
)}
/>
{timezone}
</CommandItem>
))}
</CommandGroup>
</ScrollArea>
</Command>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
In order to make the ScrollArea
work inside of a Dialog
, I ended up having to add a container
prop to my PopoverContent
, like so:
interface PopoverContentProps {
container?: HTMLElement
}
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> & PopoverContentProps
>(({ className, container, align = 'center', sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal container={container}>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
...
Then I wrapped all <CommandItem />
's inside of a ScrollArea
with a className
of h-[300px]
so that the search will remain at the top while I can scroll through all of the options.
Finally, in the component where I define the Dialog
that wraps everything, I defined a dialogRef
, like so:
const dialogRef = React.useRef<HTMLDivElement>(null)
return (
<Dialog defaultOpen>
<DialogContent
ref={dialogRef}
...
I also had to add the dialogRef
to my ComboBox
props.
interface ComboboxProps {
// All my other props are defined above here...
dialogRef?: React.RefObject<HTMLElement>
}
const Combobox: FC<ComboboxProps> = ({
dialogRef,
...
Lastly, add your dialogRef
to the PopoverContent
inside of the ComboBox
:
<PopoverContent
container={dialogRef?.current === null ? undefined : dialogRef?.current}
className="w-[350px] p-0"
>
So now you should be able to use your ComboBox
and the ScrollArea
should do its magic:
<Combobox dialogRef={dialogRef} />
Hope this helps!
I am having the same issue.
@KaramveerSinghSidhu Instead of ScrollArea, use the CommandList component like so:
<Command>
<CommandInput placeholder="Search language..." />
<CommandList>
<CommandEmpty>No language found.</CommandEmpty>
<CommandGroup>
{countryOptions.map((country) => {
console.log("COUNTRY>>>>", country)
return (
<CommandItem
value={country.label}
key={country.value}
onSelect={() => {
form.setValue("country", country.value)
}}
>
<CheckIcon
className={cn(
"mr-2 h-4 w-4",
country.value === field.value
? "opacity-100"
: "opacity-0"
)}
/>
{country.label}
</CommandItem>
)
})}
</CommandGroup>
</CommandList>
</Command>
@desiboli still not working.
<FormField
control={form.control}
name="timezone"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Timezone</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
role="combobox"
className={cn(
"w-[200px] justify-between",
!field.value && "text-muted-foreground"
)}
>
{field.value
? TimeZones.find((timezone) => timezone === field.value)
: "Select timezone"}
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search language..." />
<CommandList>
<CommandEmpty>No language found.</CommandEmpty>
<CommandGroup>
{TimeZones.map((timezone) => {
return (
<CommandItem
value={timezone}
key={timezone}
onSelect={() => {
form.setValue("timezone", timezone);
}}
>
<CheckIcon
className={cn(
"mr-2 h-4 w-4",
timezone === field.value
? "opacity-100"
: "opacity-0"
)}
/>
{timezone}
</CommandItem>
);
})}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
@KaramveerSinghSidhu That's weird it works for me, see video.
https://github.com/shadcn-ui/ui/assets/6296494/fdf647fe-5f0a-4e19-b163-37d43bbb3a77
Could you setup a sandbox where you can reproduce this ?
Set modal={true}
in popover like this
<Popover open={open} modal={true}>
✔
Thanks 😎
Isn't there a straightforward way to show a scroll bar on a Dialog
if it contains too much content or is too big for the screen to fit?
PS: I am not using popover just pure input fields in the dialog
I had this issue with the DropdownMenu component. In the end I managed to get this working by simply setting max-h- and overflow-scroll as tailwind classes on the DropdownMenuContent element, also tried it with the PopOverContent and it works, so i would assume this would also work on dialog and commandList
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="px-4">
{itemId > 0 ? 'Selected: ' + itemId : 'Select Range Item'}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="max-h-80 overflow-scroll">
{rangeItems.map((item) => (
<DropdownMenuItem
className={'text-sm' + (item.id == itemId ? ' bg-gray-200' : '')}
onClick={() => {
setItemId(item.id);
}}
>
{item.id + ' | ' + item.allocation}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
I was trying to use Shadcnui's ScrollArea, but with popover and dialog it wasn't working, it didn't generate the vertical bar, what helped me was indicating the ref in the Scroll within the ComandList, maybe it will work for someone else, remembering that they didn't want the bar system scrolling. I tested it with Popover and it doesn't work, but with Dialog it works fine. my code modification:
React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
<ScrollArea ref={ref}>
<CommandPrimitive.List
ref={ref}
className={cn('h-[400px] overflow-hidden overflow-x-hidden', className)}
{...props}
/>
<ScrollBar orientation='vertical'/>
</ScrollArea>
));
I was able to get the ScrollArea to work with the Dialog by setting a max height to the DialogContent component and then using the ScrollArea component nested within.
<Dialog
open={isOpen}
onOpenChange={setIsOpen}
>
<DialogContent className='h-full max-h-[96%] p-4'>
<ScrollArea className='p-4'>
<DialogHeader>
<DialogTitle asChild>
<h2>{title}</h2>
</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
{children}
<DialogFooter className=''>
<div className='flex justify-center gap-x-2'>
<DialogClose asChild>
<Button
variant='outline'
className='w-full'
>
Cancel
</Button>
</DialogClose>
<Button
className='w-full'
>
confirm
</Button>
</div>
</DialogFooter>
</ScrollArea>
</DialogContent>
</Dialog>
You can make a couple of things:
- Not render the
Portal
component in popover (Maybe you havez-index
issues)- Set
modal={false}
on Dialog (The overlay will no be rendered)- Wrap
Dialog.Content
withDialog.Overlay
(You can not setmodal={false}
because the overlay will not be rendered)
@joaom00 The third one solves the problem for me but I still have another issue when I press tab to jumb to the next input the focus move to the dialog instade of the next input the second one solves this but I need the overlay
Would be nice if the dialog content would be scrollable by default since that is what's expected. Takes quite a bit of extra frustration to figure out how to make it work:
<!-- -->
<Dialog.Root>
<Dialog.Trigger>
<slot name="OpenButton" />
</Dialog.Trigger>
<Dialog.Content class="!p-0">
<!-- scroll area needed to make Dialog's content scrollable -->
<ScrollArea>
<Dialog.Header>
<div class="stickyDialogBars top-0">
<Dialog.Title>
<slot name="Title" />
</Dialog.Title>
</div>
<div class="p-4">
<Dialog.Description>
<slot name="Content" />
</Dialog.Description>
</div>
</Dialog.Header>
<div class="stickyDialogBars bottom-0">
<Dialog.Close class="">
<Button>Back</Button>
</Dialog.Close>
</div>
</ScrollArea>
<!-- -->
</Dialog.Content>
</Dialog.Root>
<style lang="sass">
.stickyDialogBars
@apply sticky flex place-content-center py-4
@apply bg-background bg-opacity-90
// hide close icon on top right corner for m
</style>
It seems this issue also happens with custom scroll components. In my case, I was not using the ScrollArea
component but @7hourspg's solution worked regardless.
<Popover modal={true}>
<PopoverTrigger>Open</PopoverTrigger>
<PopoverContent
className="flex flex-col gap-4 w-60 h-60 overflow-y-scroll p-2"
align="start"
>
{content.map((c) => (
<button key={c.id} className="w-full">
{c.title}
</button>
))}
</PopoverContent>
</Popover>
Set
modal={true}
in popover like this<Popover open={open} modal={true}>
✔ Thanks 😎
This makes another side-effect. Dialog closes and reopens when you click outside of popover.
Set
modal={true}
in popover like this<Popover open={open} modal={true}>
✔ Thanks 😎This makes another side-effect. Dialog closes and reopens when you click outside of popover.
works fine for me
`
{!disabled && (
<PopoverContent
className={cn('p-0', isAccountSetupPage && 'w-[--radix-popover-trigger-width]')}
align="start"
>
<Command>
<CommandInput placeholder="Search Timezone" className="h-9" />
{isLoading ? (
<div className="flex items-center justify-center p-4">
<Loader />
</div>
) : (
<>
<CommandEmpty>No Result found.</CommandEmpty>
<CommandGroup>
<CommandList className="h-48">
{filteredData.map((filteredData) => (
<CommandItem
key={filteredData.label}
value={filteredData.label}
onSelect={() => handleSelectTimezone(filteredData.label)}
className=" cursor-pointer text-sm "
>
<Check
className={cn(
'absolute right-2 mr-2 h-4 w-4',
defaultValue === filteredData.label ? 'opacity-100 ' : 'opacity-0 '
)}
/>
{filteredData.label}
</CommandItem>
))}
</CommandList>
</CommandGroup>
</>
)}
</Command>
</PopoverContent>
)}
</Popover>`
setting modal to true in Popover works for me thanks!
Set
modal={true}
in popover like this<Popover open={open} modal={true}>
✔ Thanks 😎
This works thanks
When using
ScrollArea
insideDialog
gesture scrolling doesn't work only way to navigate is by grabbing the scroll indicatorhttps://github.com/shadcn/ui/assets/62795688/ea1abc45-19f7-4969-812e-5b376e1a3f9a
To reproduce this bug
index.ts
ComboBox.ts