Portal shapes
Custom frame-like shapes that teleport children between each other, inspired by Portal.
import {
createShapeId,
TLContent,
TLShapePartial,
TLRichText,
TLTextShapeProps,
Tldraw,
} from 'tldraw'
import 'tldraw/tldraw.css'
import companionCube from './companion-cube.json'
import { PortalShapeUtil } from './PortalShapeUtil'
// [1]
const shapeUtils = [PortalShapeUtil]
const tagline: TLRichText = {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{ type: 'text', text: "Now you're thinking with " },
{ type: 'text', marks: [{ type: 'strike' }], text: 'portals' },
{ type: 'text', text: ' frames' },
],
},
],
}
export default function PortalShapesExample() {
return (
<div className="tldraw__editor">
<Tldraw
shapeUtils={shapeUtils}
onMount={(editor) => {
// [2]
const blueId = createShapeId('blue-portal')
const orangeId = createShapeId('orange-portal')
const portalShapes = [
{
id: blueId,
type: 'portal',
x: 100,
y: 150,
props: { w: 200, h: 300, color: 'blue' },
},
{
id: orangeId,
type: 'portal',
x: 500,
y: 150,
props: { w: 200, h: 300, color: 'orange' },
},
] as const
editor.createShapes(portalShapes as unknown as TLShapePartial[])
// [3]
editor.createShape({
type: 'text',
x: 100,
y: 500,
props: {
size: 'l',
richText: tagline,
} satisfies Partial<TLTextShapeProps>,
})
// [4]
editor.putContentOntoCurrentPage(companionCube as unknown as TLContent, {
point: { x: 300, y: 20 },
})
editor.selectNone()
editor.zoomToFit({ animation: { duration: 0 } })
editor.zoomOut(undefined, { animation: { duration: 0 } })
}}
/>
</div>
)
}
/*
[1]
Register the custom PortalShapeUtil. This array is defined outside of the
component so it stays referentially stable across renders.
[2]
Create a pair of linked portals — one blue, one orange. They find each
other by color, so only one of each should exist on a page.
[3]
Add the Portal tagline as a text shape.
[4]
Load the companion cube from a snapshot and place it on the canvas
for the user to drag into the portals.
*/
This example shows how to extend BaseFrameLikeShapeUtil to create custom shapes that behave like frames — they accept children via drag-and-drop and clip their contents. Two portal shapes (blue and orange) are linked: dragging a shape into one teleports it into the other.
Is this page helpful?
Prev
Drag and drop shapeNext
Attach shapes together (bindings)