Skip to content

Commit 6712bc2

Browse files
authored
chore(popover): update to svelte 5 runes apis (#2016)
1 parent f670a94 commit 6712bc2

File tree

7 files changed

+515
-460
lines changed

7 files changed

+515
-460
lines changed

.changeset/hungry-things-retire.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
"@stackoverflow/stacks-svelte": minor
3+
---
4+
5+
Migrate `Popover`, `PopoverReference`, `PopoverContent`, and `PopoverCloseButton` components to use Svelte 5 runes API
6+
7+
BREAKING CHANGES:
8+
9+
**Popover component:**
10+
- Slot props (`let:visible`, `let:open`, `let:close`) are not available anymore. Snippet parameters should be used instead: `{#snippet children({ visible, open, close })}...{/snippet}`
11+
- `on:open` and `on:close` events are not available anymore. The new callback props should be used instead: `onopen`, `onclose`.
12+
13+
**PopoverCloseButton component:**
14+
- `on:click` event forwarding is not available anymore. The new callback prop should be used instead: `onclick`.
15+
16+
**Migration examples:**
17+
18+
```svelte
19+
<!-- Before (Svelte 4 API) -->
20+
<Popover
21+
id="my-popover"
22+
on:open={() => console.log('opened')}
23+
on:close={() => console.log('closed')}
24+
let:visible
25+
let:close
26+
>
27+
<PopoverReference>
28+
<button>Trigger</button>
29+
</PopoverReference>
30+
<PopoverContent>
31+
<p>Content here</p>
32+
<PopoverCloseButton on:click={handleClick} />
33+
</PopoverContent>
34+
<p>Visible: {visible}</p>
35+
</Popover>
36+
37+
<!-- After (Svelte 5 API) -->
38+
<Popover
39+
id="my-popover"
40+
onopen={() => console.log('opened')}
41+
onclose={() => console.log('closed')}
42+
>
43+
{#snippet children({ visible, close })}
44+
<PopoverReference>
45+
<button>Trigger</button>
46+
</PopoverReference>
47+
<PopoverContent>
48+
<p>Content here</p>
49+
<PopoverCloseButton onclick={handleClick} />
50+
</PopoverContent>
51+
<p>Visible: {visible}</p>
52+
{/snippet}
53+
</Popover>
54+
```
55+

packages/stacks-svelte/src/components/Popover/Popover.stories.svelte

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
</script>
4747

4848
<script lang="ts">
49-
let visible = false;
50-
let lastEvent: string;
49+
let visible = $state(false);
50+
let lastEvent = $state("");
5151
5252
const onToggle = (e: Event) => {
5353
const target = e.target as HTMLInputElement;
@@ -152,12 +152,13 @@
152152
<div class="hmn3 d-flex flex__center">
153153
<Popover id="inline" placement="top">
154154
<p class="ws3">
155-
This is is a paragraph <PopoverReference
156-
><span role="button" class="s-link"
155+
This is is a paragraph <PopoverReference>
156+
<span role="button" class="s-link"
157157
>containing a button styled as a link that wraps across
158158
two lines</span
159-
></PopoverReference
160-
>. It shows the benefit of using floating ui inline middleware.
159+
>
160+
</PopoverReference>. It shows the benefit of using floating ui
161+
inline middleware.
161162
</p>
162163
<PopoverContent>Here I am</PopoverContent>
163164
</Popover>
@@ -170,7 +171,9 @@
170171
<PopoverReference>
171172
<Button weight="filled">Trigger</Button>
172173
</PopoverReference>
173-
<PopoverContent>Here I am<PopoverCloseButton /></PopoverContent>
174+
<PopoverContent>
175+
Here I am<PopoverCloseButton />
176+
</PopoverContent>
174177
</Popover>
175178
</div>
176179
</Story>
@@ -182,27 +185,28 @@
182185
placement="right"
183186
dismissible={false}
184187
trapFocus={true}
185-
let:close
186188
>
187-
<PopoverReference>
188-
<Button weight="filled">Trigger</Button>
189-
</PopoverReference>
190-
<PopoverContent>
191-
<p class="d-flex fd-column g16">
192-
The focus is now trapped in the popover.
193-
<TextInput size="sm" id="name" label="Name"></TextInput>
194-
<TextInput size="sm" id="surname" label="Surname"
195-
></TextInput>
196-
<Button
197-
type="submit"
198-
weight="filled"
199-
onclick={() => close()}
200-
>
201-
Submit
202-
</Button>
203-
<PopoverCloseButton />
204-
</p>
205-
</PopoverContent>
189+
{#snippet children({ close })}
190+
<PopoverReference>
191+
<Button weight="filled">Trigger</Button>
192+
</PopoverReference>
193+
<PopoverContent>
194+
<p class="d-flex fd-column g16">
195+
The focus is now trapped in the popover.
196+
<TextInput size="sm" id="name" label="Name"></TextInput>
197+
<TextInput size="sm" id="surname" label="Surname"
198+
></TextInput>
199+
<Button
200+
type="submit"
201+
weight="filled"
202+
onclick={() => close()}
203+
>
204+
Submit
205+
</Button>
206+
<PopoverCloseButton />
207+
</p>
208+
</PopoverContent>
209+
{/snippet}
206210
</Popover>
207211
</div>
208212
</Story>
@@ -224,7 +228,7 @@
224228
id="popover-visibility-control"
225229
type="checkbox"
226230
checked={visible}
227-
on:click={onToggle}
231+
onclick={onToggle}
228232
/>
229233
</div>
230234
</div>
@@ -241,7 +245,9 @@
241245
</button>
242246
<Popover id="external-reference" placement="bottom">
243247
<PopoverReference elementId="external-reference-element" />
244-
<PopoverContent>Here I am<PopoverCloseButton /></PopoverContent>
248+
<PopoverContent>
249+
Here I am<PopoverCloseButton />
250+
</PopoverContent>
245251
</Popover>
246252
</div>
247253
</Story>
@@ -251,15 +257,16 @@
251257
<Popover
252258
id="events"
253259
placement="right"
254-
on:open={() => (lastEvent = "opened")}
255-
on:close={() => (lastEvent = "closed")}
256-
let:visible
260+
onopen={() => (lastEvent = "opened")}
261+
onclose={() => (lastEvent = "closed")}
257262
>
258-
<PopoverReference>
259-
<Button weight="filled">Trigger</Button>
260-
</PopoverReference>
261-
<PopoverContent>Here I am</PopoverContent>
262-
<p class="mt12">Visible: {visible}</p>
263+
{#snippet children({ visible })}
264+
<PopoverReference>
265+
<Button weight="filled">Trigger</Button>
266+
</PopoverReference>
267+
<PopoverContent>Here I am</PopoverContent>
268+
<p class="mt12">Visible: {visible}</p>
269+
{/snippet}
263270
</Popover>
264271
<p>Last Event: {lastEvent}</p>
265272
</div>

0 commit comments

Comments
 (0)