Portal Gun
When an element requires rendering outside of the usual component hierarchy, challenges related to stacking contents and z-index can interfere with the desired intention or look of an application1. Portal Gun enables server-side portal functionality for Astro projects, allowing a component to render an element somewhere else in the document.
Installing the integration
npx astro add @inox-tools/portal-gun
pnpm astro add @inox-tools/portal-gun
yarn astro add @inox-tools/portal-gun
How to use
Use a <portal-gate>
element with a to
attribute to send all children to the target portal:
<portal-gate to="group"> <dialog> <p>Dialog</p> </dialog></portal-gate>
Target Portal
You can define output portals anywhere on the page. They are replaced with every element teleported to it.
Use a <portal-landzone>
element with a name
attribute:
<portal-landzone name="group"></portal-landzone>
ID boundary portals
Any element with an id
has two implicit portals targets:
start:#<id>
: the children of the source portals are prepended to the children of the target elementend:#<id>
: the children of the source portals are append to the children of the target element
Given the following document:
<div id="element-id"> <p>Hello</p></div>
<portal-gate to="start:#element-id"> <p>Before</p></portal-gate><portal-gate to="end:#element-id"> <p>After</p></portal-gate>
The HTML sent to the client will be:
<div id="element-id"> <p>Before</p> <p>Hello</p> <p>After</p></div>
Global portals
The <head>
and <body>
elements have implicit portals for prepending and appending:
start:head
: targets the start of the<head>
elementend:head
: targets the end of the<head>
element, right before</head>
start:body
: targets the start of the<body>
elementend:body
: targets the end of the<body>
element, right before</body>
Caveats
Enabling portals disables response streaming. The entire document has to be generated in order for the elements in the portals to be teleported to the appropriate place. After that, the updated document is sent to the client.