Closed 5starkarma closed 4 months ago
Hey @5starkarma,
Thanks for bringing it up. I will look more into this over the weekend. It looks like you would need to add a custom portal host to bottom of your modal screen. Example:
<PortalHost name='invite-employee-portal' />
Then, you would need to add a portalHostName
prop to your SelectContent
component. Pass the name of your custom portal host (ex: "invite-employee-portal") to the SelectPrimitive.Portal
through its hostName
prop. Something like:
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & { portalHost?: string }
>(({ className, children, position = 'popper', portalHost, ...props }, ref) => {
const { open } = SelectPrimitive.useRootContext();
return (
<SelectPrimitive.Portal hostName={portalHost} >
<SelectPrimitive.Overlay style={Platform.OS !== 'web' ? StyleSheet.absoluteFill : undefined}>
<Animated.View entering={FadeIn} exiting={FadeOut}>
<SelectPrimitive.Content
ref={ref}
className={cn(
'relative z-50 max-h-96 min-w-[8rem] rounded-md border border-border bg-popover shadow-md shadow-foreground/10 py-2 px-1 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',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
open
? 'web:zoom-in-95 web:animate-in web:fade-in-0'
: 'web:zoom-out-95 web:animate-out web:fade-out-0',
className
)}
position={position}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
'p-1',
position === 'popper' &&
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</Animated.View>
</SelectPrimitive.Overlay>
</SelectPrimitive.Portal>
);
});
SelectContent.displayName = SelectPrimitive.Content.displayName;
When you use that select, it should look something like:
<SelectContent portalHost='invite-employee-portal' >
@5starkarma Until I update the documentation, you can use the following commits as guidelines to fixing this issue.
useModalPortalRoot
which will be needed in the component with the presentation: "modal"
screen options.portalHost
props to the components that use a portal: https://github.com/mrzachnugent/react-native-reusables/commit/a055dbe5c921297ea217263a2cef0615e7155a2f. modal.tsx
screen as a model for your implementation https://github.com/mrzachnugent/react-native-reusables/commit/31acef5540d1e1914386d9e905e29d53d06cba95.
const { sideOffset, ...rootProps } = useModalPortalRoot();
View
, pass it the rootProps
, and add a custom portal host as its last child
<View {...rootProps}>
{/* your existing JSX */}
<PortalHost name='invite-employee-portal' />
</View>
SelectContent
component: sideOffset={sideOffset}
and portalHost='invite-employee-portal'
@mrzachnugent Thank you for the prompt response. Before I got the response I switched it to a normal stack page but I will keep this in mind for the future. Thanks again!
Should this work with a Select
in a Dialog
? I think I've added the extra port here (have on in my root _layout
file too) and it does enable the select - which is progress - but seems the nested portals are the wrong z index or something related? I did try change them to no avail
For example
const { sideOffset, ...rootProps } = useModalPortalRoot();
const contentInsets = {
top: insets.top,
bottom: insets.bottom + Math.abs(sideOffset),
left: 16,
right: 16,
};
return (
<Dialog open={adding} onOpenChange={() => setAdding(false)}>
<DialogContent className="sm:max-w-[425px] native:w-[385px] z-50 bg-lime-900">
<FormProvider {...methods}>
<TextController name="firstName" label="First Name" />
<TextController name="lastName" label="Last Name" />
<MultilineTextController
name="metadata"
label="Metadata"
placeholder="random"
numberOfLines={4}
/>
<Select>
<SelectTrigger>
<SelectValue
className="text-foreground text-sm native:text-lg"
placeholder="Select a role"
/>
</SelectTrigger>
<View {...rootProps}>
<SelectContent
insets={contentInsets}
sideOffset={sideOffset}
className="w-full z-40 bg-cyan-500"
portalHost="modal-example"
>
<SelectGroup>
<SelectLabel>Roles</SelectLabel>
<SelectItem label="Staff" value="staff">
Staff
</SelectItem>
<SelectItem label="Manager" value="manager">
Manager
</SelectItem>
<SelectItem label="Admin" value="admin">
Admin
</SelectItem>
</SelectGroup>
</SelectContent>
<PortalHost name="modal-example" />
</View>
</Select>
</FormProvider>
<DialogFooter>
<Button onPress={methods.handleSubmit(onSubmit)}>
<Text>Save</Text>
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
If i move the custom portal outside of Dialog
, its also (more) wrong:
I am facing the same issue even with the new components and examples.
Should this work with a
Select
in aDialog
? I think I've added the extra port here (have on in my root_layout
file too) and it does enable the select - which is progress - but seems the nested portals are the wrong z index or something related? I did try change them to no avail
I had the same problem in the web version, I solved it in a palliative way by adding the container
attribute in SelectContent
.
To use it, I created a div inside the dialog and assigned the div's ref
to the container
property.
const divRef = useRef<HTMLDivElement>(null);
...
return (
<Dialog>
<DialogContent>
<div ref={divRef}>
<Select>
<SelectContent container={divRef.current}>
</SelectContent>
</Select>
</div>
</DialogContent>
</Dialog>
)
One important thing is to make sure the ref
is not null. To do this, the div has to be added to the DOM first.
{isDivLoaded && (
<SelectContent container={divRef.current}>
</SelectContent>
)}
Describe the bug As title states. The dropdown does not open if inside modal.
Expected behavior Expect the
Select
to open.Screenshots
Platform (please complete the following information):