Skip to content

Commit 6de743b

Browse files
committed
docs(portal): add floating portal examples
1 parent 65ecd20 commit 6de743b

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

docs/src/pages/components/Portal.svx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,15 @@ Use the `tag` prop to specify a custom HTML element. By default, Portal uses a `
2828
Wrap `Modal` in a `Portal` to escape parent containers with `overflow: hidden` or z-index stacking contexts. This ensures the modal appears above all content and isn't clipped by parent boundaries.
2929

3030
<FileSource src="/framed/Portal/ModalPortal" />
31+
32+
## Floating portal
33+
34+
The `FloatingPortal` component automatically positions content relative to a reference element using [Floating UI](https://floating-ui.com/). This is useful for dropdowns, popovers, and tooltips.
35+
36+
<FileSource src="/framed/Portal/FloatingPortal" />
37+
38+
## Floating portal placement
39+
40+
Control the placement of the floating portal using the `placement` prop.
41+
42+
<FileSource src="/framed/Portal/FloatingPortalPlacement" />
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script>
2+
import { Button, FloatingPortal } from "carbon-components-svelte";
3+
4+
let buttonRef = null;
5+
let showPortal = false;
6+
</script>
7+
8+
<Button bind:this={buttonRef} on:click={() => (showPortal = !showPortal)}>
9+
Toggle Floating Portal
10+
</Button>
11+
12+
{#if showPortal && buttonRef}
13+
<FloatingPortal reference={buttonRef} placement="bottom" offset={8}>
14+
<div style="padding: 1rem; background: var(--cds-layer-01); border: 1px solid var(--cds-border-subtle-01); box-shadow: var(--cds-shadow-03); border-radius: 4px; min-width: 200px;">
15+
<p style="margin: 0 0 0.5rem 0;">Floating portal content</p>
16+
<p style="margin: 0; font-size: 0.875rem; color: var(--cds-text-secondary);">
17+
This content is positioned relative to the button above.
18+
</p>
19+
</div>
20+
</FloatingPortal>
21+
{/if}
22+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<script>
2+
import { Button, FloatingPortal } from "carbon-components-svelte";
3+
4+
let buttonRefs = {};
5+
let openPlacements = {};
6+
7+
const placements = [
8+
"top",
9+
"top-start",
10+
"top-end",
11+
"right",
12+
"right-start",
13+
"right-end",
14+
"bottom",
15+
"bottom-start",
16+
"bottom-end",
17+
"left",
18+
"left-start",
19+
"left-end",
20+
];
21+
22+
function togglePlacement(placement) {
23+
openPlacements[placement] = !openPlacements[placement];
24+
openPlacements = { ...openPlacements };
25+
}
26+
</script>
27+
28+
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 2rem; padding: 4rem;">
29+
{#each placements as placement}
30+
<div style="display: flex; justify-content: center; align-items: center;">
31+
<Button
32+
bind:this={buttonRefs[placement]}
33+
on:click={() => togglePlacement(placement)}
34+
>
35+
{placement}
36+
</Button>
37+
{#if openPlacements[placement] && buttonRefs[placement]}
38+
<FloatingPortal
39+
reference={buttonRefs[placement]}
40+
placement={placement}
41+
offset={8}
42+
>
43+
<div
44+
style="padding: 0.75rem; background: var(--cds-layer-01); border: 1px solid var(--cds-border-subtle-01); box-shadow: var(--cds-shadow-03); border-radius: 4px; white-space: nowrap;"
45+
>
46+
{placement}
47+
</div>
48+
</FloatingPortal>
49+
{/if}
50+
</div>
51+
{/each}
52+
</div>
53+

0 commit comments

Comments
 (0)