Documentation Index
Fetch the complete documentation index at: https://copylabs.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Portal
Portal is a utility component for rendering children into a different part of the React tree, typically at the root of the application. In React Native, it uses Modal to achieve this.
Import
import { Portal, PortalProvider, usePortal, ManagedPortal } from 'radix-native-ui';
Basic Usage
import { Portal, Flex, Text } from 'radix-native-ui';
<Portal>
<Flex position="absolute" top={0} left={0}>
<Text>This renders at the root level</Text>
</Flex>
</Portal>
Portal Components
Portal
The main portal component that renders children into a Modal.
Portal.Provider (PortalProvider)
Provider component that manages multiple portals. Wrap your app with this to enable programmatic portal management.
usePortal
Hook to programmatically add, remove, and update portals.
ManagedPortal
A managed portal that automatically handles cleanup when the component unmounts or visibility changes.
Portal.FlatList
A FlatList that renders its items in a portal.
Props
Portal
Portal.Provider
ManagedPortal
usePortal Hook
The usePortal hook returns methods for managing portals:
const { addPortal, removePortal, updatePortal } = usePortal();
// Add a portal
addPortal('my-portal', <View><Text>Content</Text></View>);
// Remove a portal
removePortal('my-portal');
// Update a portal's content
updatePortal('my-portal', <View><Text>New Content</Text></View>);
Examples
Basic Portal
<Portal>
<Flex position="absolute" bottom={5} left={5} right={5}>
<Card>
<Text>This appears at the bottom of the screen</Text>
</Card>
</Flex>
</Portal>
Modal Overlay
function ModalOverlay({ visible, children }) {
if (!visible) return null;
return (
<Portal visible={visible}>
<Flex
flex={1}
backgroundColor="rgba(0, 0, 0, 0.5)"
justify="center"
align="center"
>
<Card>
{children}
</Card>
</Flex>
</Portal>
);
}
Controlled Portal
function ControlledModal({ open, onClose, children }) {
return (
<Portal
visible={open}
animationType="slide"
onRequestClose={onClose}
>
<Flex flex={1} justify="center" align="center">
<Card>
{children}
<Button onPress={onClose}>Close</Button>
</Card>
</Flex>
</Portal>
);
}
Transparent Overlay
<Portal transparent animationType="fade">
<Flex
flex={1}
backgroundColor="rgba(0, 0, 0, 0.5)"
justify="center"
align="center"
>
<Card>
<Text>Semi-transparent overlay</Text>
</Card>
</Flex>
</Portal>
Using Portal.Provider with ManagedPortal
import { PortalProvider, ManagedPortal, usePortal } from 'radix-native-ui';
function MyComponent() {
const [showModal, setShowModal] = useState(false);
return (
<PortalProvider>
<Button onPress={() => setShowModal(true)}>Open Modal</Button>
<ManagedPortal name="modal" visible={showModal}>
<Flex
flex={1}
backgroundColor="rgba(0, 0, 0, 0.5)"
justify="center"
align="center"
>
<Card>
<Text>Modal Content</Text>
<Button onPress={() => setShowModal(false)}>Close</Button>
</Card>
</Flex>
</ManagedPortal>
</PortalProvider>
);
}
Programmatic Portal with usePortal
import { PortalProvider, usePortal } from 'radix-native-ui';
function ToastLikeNotification({ message, onDismiss }) {
const { addPortal, removePortal } = usePortal();
const portalId = 'notification-toast';
useEffect(() => {
addPortal(portalId, (
<Flex
position="absolute"
bottom={5}
left={5}
right={5}
>
<Card>
<Text>{message}</Text>
</Card>
</Flex>
));
// Auto-remove after duration
const timer = setTimeout(() => {
removePortal(portalId);
onDismiss?.();
}, 3000);
return () => clearTimeout(timer);
}, []);
return null;
}
function App() {
return (
<PortalProvider>
<ToastLikeNotification message="Hello from Portal!" />
</PortalProvider>
);
}
function DropdownMenu({ trigger, children, open }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
return (
<>
<Flex
onLayout={(e) => {
setPosition({
x: e.nativeEvent.layout.x,
y: e.nativeEvent.layout.y + e.nativeEvent.layout.height
});
}}
>
{trigger}
</Flex>
{open && (
<Portal>
<Card
position="absolute"
top={position.y}
left={position.x}
>
{children}
</Card>
</Portal>
)}
</>
);
}
function Tooltip({ content, children }) {
const [visible, setVisible] = useState(false);
const [position, setPosition] = useState({ x: 0, y: 0 });
return (
<>
<Flex
onLongPress={() => setVisible(true)}
onPressOut={() => setVisible(false)}
onLayout={(e) => {
setPosition({
x: e.nativeEvent.layout.x,
y: e.nativeEvent.layout.y - 10
});
}}
>
{children}
</Flex>
{visible && (
<Portal>
<Card
size={1}
position="absolute"
top={position.y}
left={position.x}
>
<Text size={1}>{content}</Text>
</Card>
</Portal>
)}
</>
);
}