@reliability-design/web 1.4.5 → 1.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +211 -49
- package/dist/components/rel-accordion/README.md +132 -132
- package/dist/components/rel-alert/README.md +145 -141
- package/dist/components/rel-autocomplete/README.md +156 -61
- package/dist/components/rel-avatar/README.md +116 -130
- package/dist/components/rel-badge/README.md +98 -93
- package/dist/components/rel-breadcrumb/README.md +96 -102
- package/dist/components/rel-button/README.md +160 -130
- package/dist/components/rel-calendar/README.md +109 -109
- package/dist/components/rel-card/README.md +75 -94
- package/dist/components/rel-cardmedia/README.md +100 -127
- package/dist/components/rel-carousel/README.md +184 -166
- package/dist/components/rel-checkbox/README.md +93 -75
- package/dist/components/rel-chip/README.md +132 -121
- package/dist/components/rel-container/README.md +107 -99
- package/dist/components/rel-date-picker/README.md +200 -289
- package/dist/components/rel-divider/README.md +78 -100
- package/dist/components/rel-drawer/README.md +187 -200
- package/dist/components/rel-kbd/README.md +141 -151
- package/dist/components/rel-menu/README.md +178 -151
- package/dist/components/rel-menubar/README.md +218 -329
- package/dist/components/rel-otp/README.md +170 -440
- package/dist/components/rel-pagination/README.md +100 -424
- package/dist/components/rel-popover/README.md +203 -568
- package/dist/components/rel-progress/README.md +88 -110
- package/dist/components/rel-radio/README.md +131 -135
- package/dist/components/rel-range-picker/README.md +162 -0
- package/dist/components/rel-resizable/README.md +199 -140
- package/dist/components/rel-segmented-button/README.md +155 -141
- package/dist/components/rel-select/README.md +154 -93
- package/dist/components/rel-sheet/README.md +168 -224
- package/dist/components/rel-skeleton/README.md +103 -0
- package/dist/components/rel-slider/README.md +130 -135
- package/dist/components/rel-snackbar/README.md +162 -134
- package/dist/components/rel-stepper/README.md +158 -160
- package/dist/components/rel-switch/README.md +108 -102
- package/dist/components/rel-tab/README.md +171 -163
- package/dist/components/rel-textfield/README.md +159 -69
- package/dist/components/rel-time-picker/README.md +122 -157
- package/dist/components/rel-toast/README.md +157 -148
- package/dist/components/rel-tooltip/README.md +108 -103
- package/dist/components/rel-upload/README.md +220 -0
- package/dist/index.d.mts +1387 -350
- package/dist/index.d.ts +1387 -350
- package/dist/index.js +5863 -3600
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5864 -3592
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +877 -866
- package/dist/{vars-XNMTSRVN.css → vars-JHTUGNRG.css} +877 -866
- package/package.json +4 -3
- package/dist/components/rel-accordion/rel-accordion.ts +0 -336
- package/dist/components/rel-alert/rel-alert.ts +0 -305
- package/dist/components/rel-autocomplete/rel-autocomplete.ts +0 -689
- package/dist/components/rel-avatar/rel-avatar.ts +0 -142
- package/dist/components/rel-badge/rel-badge.ts +0 -170
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +0 -106
- package/dist/components/rel-button/rel-button.ts +0 -560
- package/dist/components/rel-calendar/index.ts +0 -1
- package/dist/components/rel-calendar/rel-calendar.ts +0 -519
- package/dist/components/rel-card/rel-card.ts +0 -88
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +0 -88
- package/dist/components/rel-carousel/index.ts +0 -1
- package/dist/components/rel-carousel/rel-carousel.ts +0 -700
- package/dist/components/rel-chart/README.md +0 -286
- package/dist/components/rel-chart/index.ts +0 -1
- package/dist/components/rel-chart/rel-chart.ts +0 -754
- package/dist/components/rel-checkbox/rel-checkbox.ts +0 -382
- package/dist/components/rel-chip/rel-chip.ts +0 -472
- package/dist/components/rel-container/rel-container.ts +0 -95
- package/dist/components/rel-date-picker/date-format.test.ts +0 -43
- package/dist/components/rel-date-picker/date-format.ts +0 -47
- package/dist/components/rel-date-picker/index.ts +0 -1
- package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1237
- package/dist/components/rel-divider/rel-divider.ts +0 -54
- package/dist/components/rel-drawer/index.ts +0 -1
- package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
- package/dist/components/rel-drawer/rel-drawer.ts +0 -604
- package/dist/components/rel-kbd/rel-kbd.ts +0 -188
- package/dist/components/rel-layout/rel-layout.ts +0 -49
- package/dist/components/rel-menu/rel-menu.ts +0 -535
- package/dist/components/rel-menubar/index.ts +0 -2
- package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
- package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
- package/dist/components/rel-menubar/rel-menubar.ts +0 -777
- package/dist/components/rel-nav-menu/README.md +0 -289
- package/dist/components/rel-nav-menu/index.ts +0 -3
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
- package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
- package/dist/components/rel-navbar/README.md +0 -126
- package/dist/components/rel-navbar/rel-navbar.ts +0 -105
- package/dist/components/rel-otp/index.ts +0 -1
- package/dist/components/rel-otp/rel-otp.ts +0 -517
- package/dist/components/rel-pagination/index.ts +0 -1
- package/dist/components/rel-pagination/rel-pagination.ts +0 -509
- package/dist/components/rel-popover/index.ts +0 -2
- package/dist/components/rel-popover/rel-popover-content.ts +0 -81
- package/dist/components/rel-popover/rel-popover.ts +0 -444
- package/dist/components/rel-progress/rel-progress.ts +0 -225
- package/dist/components/rel-radio/rel-radio.ts +0 -305
- package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1331
- package/dist/components/rel-resizable/index.ts +0 -3
- package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
- package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
- package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -213
- package/dist/components/rel-select/rel-select.ts +0 -1385
- package/dist/components/rel-sheet/rel-sheet.ts +0 -465
- package/dist/components/rel-sidebar/README.md +0 -209
- package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1185
- package/dist/components/rel-skeleton/rel-skeleton.ts +0 -134
- package/dist/components/rel-slider/rel-slider.ts +0 -670
- package/dist/components/rel-snackbar/rel-snackbar.ts +0 -325
- package/dist/components/rel-stepper/rel-stepper.ts +0 -565
- package/dist/components/rel-switch/rel-switch.ts +0 -197
- package/dist/components/rel-tab/rel-tab.ts +0 -264
- package/dist/components/rel-table/README.md +0 -178
- package/dist/components/rel-table/rel-table-body.ts +0 -22
- package/dist/components/rel-table/rel-table-caption.ts +0 -30
- package/dist/components/rel-table/rel-table-cell.ts +0 -43
- package/dist/components/rel-table/rel-table-footer.ts +0 -24
- package/dist/components/rel-table/rel-table-head.ts +0 -47
- package/dist/components/rel-table/rel-table-header.ts +0 -22
- package/dist/components/rel-table/rel-table-row.ts +0 -37
- package/dist/components/rel-table/rel-table.ts +0 -62
- package/dist/components/rel-textfield/rel-textfield.ts +0 -866
- package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1126
- package/dist/components/rel-toast/rel-toast.ts +0 -204
- package/dist/components/rel-tooltip/rel-tooltip.ts +0 -190
- package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
- package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar.ts +0 -446
- package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
- package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
- package/dist/components/rel-upload/rel-upload.ts +0 -943
|
@@ -1,568 +1,203 @@
|
|
|
1
|
-
# rel-popover
|
|
2
|
-
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
</rel-
|
|
20
|
-
</rel-popover>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<rel-popover
|
|
29
|
-
<button
|
|
30
|
-
<rel-popover-content>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
</rel-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
<rel-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<rel-
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
</rel-popover-content>
|
|
71
|
-
</rel-popover>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
- `
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
##
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
popover.addEventListener('rel-open-change', (e) => {
|
|
206
|
-
isOpen = e.detail.open;
|
|
207
|
-
popover.open = isOpen; // Update the attribute
|
|
208
|
-
});
|
|
209
|
-
</script>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
When `open` attribute is set, the component:
|
|
213
|
-
- Will NOT update its own state
|
|
214
|
-
- Emits `rel-open-change` events
|
|
215
|
-
- You must update the `open` attribute in response to events
|
|
216
|
-
|
|
217
|
-
## Positioning Behavior
|
|
218
|
-
|
|
219
|
-
The popover uses smart positioning with collision detection:
|
|
220
|
-
|
|
221
|
-
### Side Preference
|
|
222
|
-
Specify the preferred side with the `side` attribute:
|
|
223
|
-
- `"bottom"` (default) - Opens below trigger
|
|
224
|
-
- `"top"` - Opens above trigger
|
|
225
|
-
- `"right"` - Opens to the right
|
|
226
|
-
- `"left"` - Opens to the left
|
|
227
|
-
|
|
228
|
-
### Collision Detection
|
|
229
|
-
If the popover would overflow the viewport, it automatically flips to the opposite side:
|
|
230
|
-
- Bottom → Top (if more space above)
|
|
231
|
-
- Top → Bottom (if more space below)
|
|
232
|
-
- Right → Left (if more space on left)
|
|
233
|
-
- Left → Right (if more space on right)
|
|
234
|
-
|
|
235
|
-
### Alignment
|
|
236
|
-
Control how the popover aligns to its trigger:
|
|
237
|
-
|
|
238
|
-
For top/bottom sides:
|
|
239
|
-
- `"start"` - Aligns to left edge of trigger
|
|
240
|
-
- `"center"` (default) - Centers horizontally
|
|
241
|
-
- `"end"` - Aligns to right edge of trigger
|
|
242
|
-
|
|
243
|
-
For left/right sides:
|
|
244
|
-
- `"start"` - Aligns to top edge of trigger
|
|
245
|
-
- `"center"` (default) - Centers vertically
|
|
246
|
-
- `"end"` - Aligns to bottom edge of trigger
|
|
247
|
-
|
|
248
|
-
### Offsets
|
|
249
|
-
Fine-tune positioning with offsets:
|
|
250
|
-
- `sideOffset` - Distance from trigger (default: 8px)
|
|
251
|
-
- `alignOffset` - Shift along alignment axis (default: 0)
|
|
252
|
-
|
|
253
|
-
```html
|
|
254
|
-
<!-- 16px away from trigger, shifted 8px to the right -->
|
|
255
|
-
<rel-popover side="bottom" sideOffset="16" alignOffset="8">
|
|
256
|
-
<button slot="trigger">Custom Offset</button>
|
|
257
|
-
<rel-popover-content>Content</rel-popover-content>
|
|
258
|
-
</rel-popover>
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
### Dynamic Repositioning
|
|
262
|
-
The popover automatically repositions when:
|
|
263
|
-
- Window is resized
|
|
264
|
-
- Page is scrolled
|
|
265
|
-
- Popover content size changes
|
|
266
|
-
|
|
267
|
-
## Close Triggers
|
|
268
|
-
|
|
269
|
-
The popover can close in several ways:
|
|
270
|
-
|
|
271
|
-
1. **Click Outside** (default enabled)
|
|
272
|
-
- Click anywhere outside the popover
|
|
273
|
-
- Controlled by `closeOnOutsideClick` attribute
|
|
274
|
-
|
|
275
|
-
2. **Escape Key** (default enabled)
|
|
276
|
-
- Press Escape to close
|
|
277
|
-
- Controlled by `closeOnEscape` attribute
|
|
278
|
-
|
|
279
|
-
3. **Close Button**
|
|
280
|
-
- Add `data-popover-close` to any element
|
|
281
|
-
```html
|
|
282
|
-
<button data-popover-close>Close</button>
|
|
283
|
-
<button type="button" data-popover-close>Cancel</button>
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
4. **Programmatic**
|
|
287
|
-
```javascript
|
|
288
|
-
popover.open = false;
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
## Focus Management
|
|
292
|
-
|
|
293
|
-
### Default Behavior
|
|
294
|
-
When popover opens:
|
|
295
|
-
1. Saves currently focused element
|
|
296
|
-
2. Focuses first focusable element in popover
|
|
297
|
-
3. Returns focus to trigger when closed
|
|
298
|
-
|
|
299
|
-
### Focus Trap
|
|
300
|
-
Enable focus trapping for forms and modal-like behavior:
|
|
301
|
-
```html
|
|
302
|
-
<rel-popover trapFocus>
|
|
303
|
-
<button slot="trigger">Edit</button>
|
|
304
|
-
<rel-popover-content>
|
|
305
|
-
<form>
|
|
306
|
-
<input type="text" />
|
|
307
|
-
<button>Save</button>
|
|
308
|
-
<button data-popover-close>Cancel</button>
|
|
309
|
-
</form>
|
|
310
|
-
</rel-popover-content>
|
|
311
|
-
</rel-popover>
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
With `trapFocus` enabled:
|
|
315
|
-
- Tab cycles through focusable elements
|
|
316
|
-
- When reaching last element, Tab wraps to first
|
|
317
|
-
- Shift+Tab cycles backward
|
|
318
|
-
- Cannot tab out of the popover
|
|
319
|
-
|
|
320
|
-
## Keyboard Navigation
|
|
321
|
-
|
|
322
|
-
| Key | Action |
|
|
323
|
-
|-----|--------|
|
|
324
|
-
| `Click Trigger` | Toggle popover open/close |
|
|
325
|
-
| `Escape` | Close popover (if `closeOnEscape` is true) |
|
|
326
|
-
| `Tab` | Move to next focusable element |
|
|
327
|
-
| `Shift + Tab` | Move to previous focusable element |
|
|
328
|
-
| `Tab` (with `trapFocus`) | Cycle through elements, wrapping at edges |
|
|
329
|
-
|
|
330
|
-
## Accessibility
|
|
331
|
-
|
|
332
|
-
The component implements WCAG accessibility guidelines:
|
|
333
|
-
|
|
334
|
-
### ARIA Attributes
|
|
335
|
-
- Trigger has `aria-haspopup="dialog"`
|
|
336
|
-
- Trigger has `aria-expanded` reflecting open state
|
|
337
|
-
- Trigger has `aria-controls` pointing to content
|
|
338
|
-
- Content has `role="dialog"`
|
|
339
|
-
- Content can have `aria-label` for screen readers
|
|
340
|
-
|
|
341
|
-
### Focus Management
|
|
342
|
-
- Automatically focuses first focusable element
|
|
343
|
-
- Returns focus to trigger on close
|
|
344
|
-
- Optional focus trapping for modal behavior
|
|
345
|
-
|
|
346
|
-
### Keyboard Support
|
|
347
|
-
- Full keyboard navigation
|
|
348
|
-
- Escape key to close
|
|
349
|
-
- Tab navigation through content
|
|
350
|
-
|
|
351
|
-
### Best Practices
|
|
352
|
-
```html
|
|
353
|
-
<!-- Good: Descriptive trigger and labeled content -->
|
|
354
|
-
<rel-popover>
|
|
355
|
-
<button slot="trigger" aria-label="Open user settings">
|
|
356
|
-
<svg>...</svg>
|
|
357
|
-
</button>
|
|
358
|
-
<rel-popover-content aria-label="User settings">
|
|
359
|
-
<h3>Settings</h3>
|
|
360
|
-
<!-- ... -->
|
|
361
|
-
</rel-popover-content>
|
|
362
|
-
</rel-popover>
|
|
363
|
-
|
|
364
|
-
<!-- Good: Close button with clear label -->
|
|
365
|
-
<button type="button" data-popover-close aria-label="Close settings">
|
|
366
|
-
×
|
|
367
|
-
</button>
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
## Styling Tokens
|
|
371
|
-
|
|
372
|
-
The component uses design tokens from the Reliability Design System:
|
|
373
|
-
|
|
374
|
-
### Colors (rel-popover-content)
|
|
375
|
-
- `--rel-bg-surface` - Content background
|
|
376
|
-
- `--rel-border-default` - Border color
|
|
377
|
-
- `--rel-text-label` - Text color
|
|
378
|
-
- `--rel-text-placeholder` - Paragraph text color
|
|
379
|
-
|
|
380
|
-
### Typography
|
|
381
|
-
- `--rel-fonts-font-family` - Font family (Poppins)
|
|
382
|
-
- `--rel-fonts-weight-body-semibold` - Heading weight
|
|
383
|
-
- `--rel-body-sm-regular-font-size` - Base text size
|
|
384
|
-
- `--rel-body-md-regular-line-height` - Paragraph line height
|
|
385
|
-
|
|
386
|
-
### Spacing
|
|
387
|
-
- `--rel-spacing-md` (16px) - Content padding
|
|
388
|
-
- `--rel-spacing-xs` (8px) - Heading bottom margin
|
|
389
|
-
- `--rel-spacing-sm` (12px) - Paragraph bottom margin
|
|
390
|
-
|
|
391
|
-
### Borders & Effects
|
|
392
|
-
- `--rel-stroke-sm` (1px) - Border width
|
|
393
|
-
- `--rel-border-radius-sm` (8px) - Border radius
|
|
394
|
-
- `--rel-shadows-shadow-300` - Drop shadow
|
|
395
|
-
|
|
396
|
-
### Z-Index
|
|
397
|
-
- Popover content: `z-index: 1001`
|
|
398
|
-
|
|
399
|
-
### Custom Styling
|
|
400
|
-
Use CSS parts to style the component:
|
|
401
|
-
```css
|
|
402
|
-
/* Style the trigger wrapper */
|
|
403
|
-
rel-popover::part(trigger) {
|
|
404
|
-
display: block;
|
|
405
|
-
width: 100%;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/* Style the content wrapper */
|
|
409
|
-
rel-popover::part(content-wrapper) {
|
|
410
|
-
/* Custom styles */
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/* Style the content container */
|
|
414
|
-
rel-popover-content::part(content) {
|
|
415
|
-
max-width: 600px;
|
|
416
|
-
padding: 24px;
|
|
417
|
-
}
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
## Complete Example
|
|
421
|
-
|
|
422
|
-
```html
|
|
423
|
-
<!DOCTYPE html>
|
|
424
|
-
<html lang="en">
|
|
425
|
-
<head>
|
|
426
|
-
<meta charset="UTF-8">
|
|
427
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
428
|
-
<title>Popover Demo</title>
|
|
429
|
-
<script type="module" src="./dist/index.js"></script>
|
|
430
|
-
</head>
|
|
431
|
-
<body>
|
|
432
|
-
<div style="padding: 100px;">
|
|
433
|
-
<!-- Basic Popover -->
|
|
434
|
-
<rel-popover id="basic-popover">
|
|
435
|
-
<button slot="trigger">Open Popover</button>
|
|
436
|
-
<rel-popover-content aria-label="Information">
|
|
437
|
-
<h3>About Popovers</h3>
|
|
438
|
-
<p>Popovers are floating containers that display rich content anchored to a trigger element.</p>
|
|
439
|
-
<button data-popover-close>Got it</button>
|
|
440
|
-
</rel-popover-content>
|
|
441
|
-
</rel-popover>
|
|
442
|
-
|
|
443
|
-
<!-- Positioning Variations -->
|
|
444
|
-
<rel-popover side="top" align="start">
|
|
445
|
-
<button slot="trigger">Top Start</button>
|
|
446
|
-
<rel-popover-content>
|
|
447
|
-
<p>Positioned above, aligned to start</p>
|
|
448
|
-
</rel-popover-content>
|
|
449
|
-
</rel-popover>
|
|
450
|
-
|
|
451
|
-
<rel-popover side="right" align="center">
|
|
452
|
-
<button slot="trigger">Right Center</button>
|
|
453
|
-
<rel-popover-content>
|
|
454
|
-
<p>Positioned to the right, centered</p>
|
|
455
|
-
</rel-popover-content>
|
|
456
|
-
</rel-popover>
|
|
457
|
-
|
|
458
|
-
<!-- Form with Focus Trap -->
|
|
459
|
-
<rel-popover id="form-popover" trapFocus>
|
|
460
|
-
<button slot="trigger">Edit Profile</button>
|
|
461
|
-
<rel-popover-content aria-label="Edit profile form">
|
|
462
|
-
<h3>Edit Profile</h3>
|
|
463
|
-
<form id="profile-form">
|
|
464
|
-
<div style="margin-bottom: 12px;">
|
|
465
|
-
<label>
|
|
466
|
-
Name:<br>
|
|
467
|
-
<input type="text" name="name" value="John Doe" style="width: 100%;">
|
|
468
|
-
</label>
|
|
469
|
-
</div>
|
|
470
|
-
<div style="margin-bottom: 12px;">
|
|
471
|
-
<label>
|
|
472
|
-
Email:<br>
|
|
473
|
-
<input type="email" name="email" value="john@example.com" style="width: 100%;">
|
|
474
|
-
</label>
|
|
475
|
-
</div>
|
|
476
|
-
<div style="display: flex; gap: 8px;">
|
|
477
|
-
<button type="submit">Save</button>
|
|
478
|
-
<button type="button" data-popover-close>Cancel</button>
|
|
479
|
-
</div>
|
|
480
|
-
</form>
|
|
481
|
-
</rel-popover-content>
|
|
482
|
-
</rel-popover>
|
|
483
|
-
|
|
484
|
-
<!-- Controlled Mode -->
|
|
485
|
-
<div>
|
|
486
|
-
<button id="external-open">Open Controlled Popover</button>
|
|
487
|
-
<button id="external-close">Close Controlled Popover</button>
|
|
488
|
-
<p>State: <span id="state-display">closed</span></p>
|
|
489
|
-
|
|
490
|
-
<rel-popover id="controlled-popover">
|
|
491
|
-
<button slot="trigger">Controlled Trigger</button>
|
|
492
|
-
<rel-popover-content>
|
|
493
|
-
<h3>Controlled Popover</h3>
|
|
494
|
-
<p>This popover's state is controlled externally.</p>
|
|
495
|
-
<button data-popover-close>Close</button>
|
|
496
|
-
</rel-popover-content>
|
|
497
|
-
</rel-popover>
|
|
498
|
-
</div>
|
|
499
|
-
</div>
|
|
500
|
-
|
|
501
|
-
<script>
|
|
502
|
-
// Event logging
|
|
503
|
-
document.getElementById('basic-popover').addEventListener('rel-open-change', (e) => {
|
|
504
|
-
console.log('Basic popover:', e.detail.open ? 'opened' : 'closed');
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
// Form handling
|
|
508
|
-
document.getElementById('profile-form').addEventListener('submit', (e) => {
|
|
509
|
-
e.preventDefault();
|
|
510
|
-
const formData = new FormData(e.target);
|
|
511
|
-
console.log('Saved:', Object.fromEntries(formData));
|
|
512
|
-
document.getElementById('form-popover').open = false;
|
|
513
|
-
});
|
|
514
|
-
|
|
515
|
-
// Controlled mode
|
|
516
|
-
const controlledPopover = document.getElementById('controlled-popover');
|
|
517
|
-
const stateDisplay = document.getElementById('state-display');
|
|
518
|
-
|
|
519
|
-
let isOpen = false;
|
|
520
|
-
|
|
521
|
-
controlledPopover.addEventListener('rel-open-change', (e) => {
|
|
522
|
-
isOpen = e.detail.open;
|
|
523
|
-
controlledPopover.open = isOpen;
|
|
524
|
-
stateDisplay.textContent = isOpen ? 'open' : 'closed';
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
document.getElementById('external-open').addEventListener('click', () => {
|
|
528
|
-
isOpen = true;
|
|
529
|
-
controlledPopover.open = isOpen;
|
|
530
|
-
stateDisplay.textContent = 'open';
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
document.getElementById('external-close').addEventListener('click', () => {
|
|
534
|
-
isOpen = false;
|
|
535
|
-
controlledPopover.open = isOpen;
|
|
536
|
-
stateDisplay.textContent = 'closed';
|
|
537
|
-
});
|
|
538
|
-
</script>
|
|
539
|
-
</body>
|
|
540
|
-
</html>
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
## Browser Support
|
|
544
|
-
|
|
545
|
-
Compatible with all modern browsers supporting:
|
|
546
|
-
- Web Components (Custom Elements v1)
|
|
547
|
-
- Shadow DOM
|
|
548
|
-
- ES2020+ features
|
|
549
|
-
- ResizeObserver API
|
|
550
|
-
|
|
551
|
-
## Framework Integration
|
|
552
|
-
|
|
553
|
-
Works seamlessly with:
|
|
554
|
-
- Vanilla JavaScript
|
|
555
|
-
- Angular
|
|
556
|
-
- React (via wrapper)
|
|
557
|
-
- Vue
|
|
558
|
-
- Any framework supporting Web Components
|
|
559
|
-
|
|
560
|
-
## Comparison with Tooltip
|
|
561
|
-
|
|
562
|
-
While `rel-tooltip` is for brief labels on hover, `rel-popover` is for:
|
|
563
|
-
- **Rich interactive content** - Forms, menus, complex layouts
|
|
564
|
-
- **Explicit user action** - Click to open (not hover)
|
|
565
|
-
- **Focus management** - Can trap focus for forms
|
|
566
|
-
- **Controlled state** - External state management support
|
|
567
|
-
|
|
568
|
-
Use `rel-tooltip` for simple labels, use `rel-popover` for interactive content.
|
|
1
|
+
# rel-popover
|
|
2
|
+
|
|
3
|
+
A click-to-open floating panel anchored to a trigger, implementing the Figma "Popover" component (including its opt-in chevron). The folder registers two elements: `<rel-popover>` is the controller — its first child is the trigger, its `content` slot is the panel — and `<rel-popover-content>` is the optional styled surface (neutral background, border, radius, shadow, S/M/L padding) you drop into that slot. The panel is promoted to the browser top layer and positioned in viewport coordinates, so it renders correctly even inside a centred `<rel-modal>`. Use it for rich, interactive content that needs an explicit click — small forms, filters, menus, detail cards. For a short hover label use `<rel-tooltip>`; for a task that must be completed before continuing use `<rel-modal>`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<!-- Basic: first child = trigger, slot="content" = panel -->
|
|
9
|
+
<rel-popover>
|
|
10
|
+
<rel-button>Open</rel-button>
|
|
11
|
+
<rel-popover-content aria-label="About popovers">
|
|
12
|
+
<h3>Popover title</h3>
|
|
13
|
+
<p>Any HTML can go here.</p>
|
|
14
|
+
</rel-popover-content>
|
|
15
|
+
</rel-popover>
|
|
16
|
+
|
|
17
|
+
<!-- Panel padding (Figma Size S / M / L = 12 / 16 / 20px) -->
|
|
18
|
+
<rel-popover>
|
|
19
|
+
<rel-button variant="secondary">Compact</rel-button>
|
|
20
|
+
<rel-popover-content size="sm" aria-label="Compact panel"><p>12px padding</p></rel-popover-content>
|
|
21
|
+
</rel-popover>
|
|
22
|
+
<rel-popover>
|
|
23
|
+
<rel-button variant="secondary">Roomy</rel-button>
|
|
24
|
+
<rel-popover-content size="lg" aria-label="Roomy panel"><p>20px padding</p></rel-popover-content>
|
|
25
|
+
</rel-popover>
|
|
26
|
+
|
|
27
|
+
<!-- Positioning: side, alignment and pixel offsets -->
|
|
28
|
+
<rel-popover side="top" align="start">
|
|
29
|
+
<rel-button>Top / start</rel-button>
|
|
30
|
+
<rel-popover-content aria-label="Top start"><p>Above the trigger, left edges aligned.</p></rel-popover-content>
|
|
31
|
+
</rel-popover>
|
|
32
|
+
<rel-popover side="right" sideoffset="16" alignoffset="8">
|
|
33
|
+
<rel-button>Right, 16px away</rel-button>
|
|
34
|
+
<rel-popover-content aria-label="Right offset"><p>16px gap, shifted 8px down.</p></rel-popover-content>
|
|
35
|
+
</rel-popover>
|
|
36
|
+
|
|
37
|
+
<!-- Chevron pointing at the trigger -->
|
|
38
|
+
<rel-popover side="bottom" arrow>
|
|
39
|
+
<rel-button>With arrow</rel-button>
|
|
40
|
+
<rel-popover-content aria-label="Arrow demo"><p>The chevron follows the trigger centre.</p></rel-popover-content>
|
|
41
|
+
</rel-popover>
|
|
42
|
+
|
|
43
|
+
<!-- Any element can be the trigger or the panel -->
|
|
44
|
+
<rel-popover>
|
|
45
|
+
<span>Plain text trigger (made focusable automatically)</span>
|
|
46
|
+
<div slot="content" style="padding: 12px; background: var(--rel-bg-neutral); border: 1px solid var(--rel-border-default); border-radius: 8px;">
|
|
47
|
+
Unstyled custom panel
|
|
48
|
+
</div>
|
|
49
|
+
</rel-popover>
|
|
50
|
+
|
|
51
|
+
<!-- Form with focus trap: Tab cycles inside the panel until it closes -->
|
|
52
|
+
<rel-popover trapfocus>
|
|
53
|
+
<rel-button>Edit profile</rel-button>
|
|
54
|
+
<rel-popover-content aria-label="Edit profile">
|
|
55
|
+
<h3>Edit profile</h3>
|
|
56
|
+
<form>
|
|
57
|
+
<rel-textfield label="Name" value="Ada Lovelace"></rel-textfield>
|
|
58
|
+
<rel-textfield label="Email" type="email" value="ada@example.com"></rel-textfield>
|
|
59
|
+
<rel-button>Save</rel-button>
|
|
60
|
+
</form>
|
|
61
|
+
</rel-popover-content>
|
|
62
|
+
</rel-popover>
|
|
63
|
+
|
|
64
|
+
<!-- Controlled: you own `open` and apply every requested change -->
|
|
65
|
+
<rel-popover id="controlled" open>
|
|
66
|
+
<rel-button>Controlled trigger</rel-button>
|
|
67
|
+
<rel-popover-content aria-label="Controlled panel">
|
|
68
|
+
<p>State lives outside the component.</p>
|
|
69
|
+
<rel-button id="done" variant="secondary">Done</rel-button>
|
|
70
|
+
</rel-popover-content>
|
|
71
|
+
</rel-popover>
|
|
72
|
+
<script>
|
|
73
|
+
const popover = document.getElementById('controlled');
|
|
74
|
+
popover.addEventListener('rel-open-change', (e) => {
|
|
75
|
+
popover.open = e.detail.open; // nothing happens until you apply it
|
|
76
|
+
});
|
|
77
|
+
document.getElementById('done').addEventListener('click', () => {
|
|
78
|
+
popover.open = false;
|
|
79
|
+
});
|
|
80
|
+
// Uncontrolled instances: never set `open`; start open with `defaultopen` instead.
|
|
81
|
+
// Default-true booleans are switched off via the property:
|
|
82
|
+
popover.closeOnOutsideClick = false;
|
|
83
|
+
popover.closeOnEscape = false;
|
|
84
|
+
</script>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
<!-- readme-gen:start -->
|
|
88
|
+
|
|
89
|
+
<!-- Generated from rel-popover.ts, rel-popover-content.ts — do not edit; run readme-generate.mjs -->
|
|
90
|
+
|
|
91
|
+
## Elements
|
|
92
|
+
|
|
93
|
+
| Element | Class | Source |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| `<rel-popover>` | `RelPopover` | `rel-popover.ts` |
|
|
96
|
+
| `<rel-popover-content>` | `RelPopoverContent` | `rel-popover-content.ts` |
|
|
97
|
+
|
|
98
|
+
## API
|
|
99
|
+
|
|
100
|
+
### `<rel-popover>`
|
|
101
|
+
|
|
102
|
+
#### Attributes / Properties
|
|
103
|
+
|
|
104
|
+
| Property | Attribute | Type | Default | Description |
|
|
105
|
+
| --- | --- | --- | --- | --- |
|
|
106
|
+
| `open` | `open` | `boolean` | `undefined` | Controlled open state. Leave unset for uncontrolled mode; once set (true or false) the component only emits `rel-open-change` and you must update `open` yourself. Reflected. |
|
|
107
|
+
| `defaultOpen` | `defaultopen` | `boolean` | `false` | Initial state in uncontrolled mode (attribute `defaultopen`); ignored when `open` is set. |
|
|
108
|
+
| `disabled` | `disabled` | `boolean` | `false` | Blocks trigger interaction and dims the host to 60% opacity; does not close an already-open panel. Reflected. |
|
|
109
|
+
| `side` | `side` | `"top" \| "right" \| "bottom" \| "left"` | `"bottom"` | Which side of the trigger the panel opens on: `top`, `right`, `bottom` (default) or `left`. The panel is clamped 8px inside the viewport but never flips to another side. Reflected. |
|
|
110
|
+
| `align` | `align` | `"start" \| "center" \| "end"` | `"center"` | Alignment along the cross axis: `start` (left / top edge of the trigger), `center` (default) or `end` (right / bottom edge). Reflected. |
|
|
111
|
+
| `sideOffset` | `sideoffset` | `number` | `8` | Gap between trigger and panel in pixels (attribute `sideoffset`, default 8). With `arrow` the effective gap is at least 13px. |
|
|
112
|
+
| `alignOffset` | `alignoffset` | `number` | `0` | Extra shift along the alignment axis in pixels (attribute `alignoffset`, default 0); positive moves right / down. |
|
|
113
|
+
| `trapFocus` | `trapfocus` | `boolean` | `false` | Keep Tab / Shift+Tab cycling inside the panel while open (attribute `trapfocus`); use for forms. |
|
|
114
|
+
| `closeOnEscape` | `closeonescape` | `boolean` | `true` | Close on Escape (attribute `closeonescape`, default true; switch off via the property, e.g. `el.closeOnEscape = false`). |
|
|
115
|
+
| `closeOnOutsideClick` | `closeonoutsideclick` | `boolean` | `true` | Close on a pointer-down outside the trigger and panel (attribute `closeonoutsideclick`, default true; switch off via the property). Also lets another popover's opening dismiss this one. |
|
|
116
|
+
| `arrow` | `arrow` | `boolean` | `false` | Opt-in pointer (audit 23a): a 14×11 triangle on the panel edge that faces the trigger — the Figma Popover "Chevron" — following `side` and tracking the trigger's centre along the cross axis (clamped inside the panel). It is drawn with the panel's tokens (`--rel-popover-arrow-bg` / `--rel-popover-arrow-border`, defaulting to rel-popover-content's background and border). With the arrow on, the panel keeps at least the arrow's height plus 2px away from the trigger so the tip never overlaps it; larger `sideOffset` values still apply. Default off — existing popovers render exactly as before. Reflected. |
|
|
117
|
+
|
|
118
|
+
### Events
|
|
119
|
+
|
|
120
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
121
|
+
| --- | --- | --- | --- |
|
|
122
|
+
| `rel-open-change` | `{ open: next }` | bubbles / composed | Fired whenever the trigger, Escape, an outside click or another popover requests a state change. Detail: `{ open: boolean }` — the requested state; in controlled mode apply it to `open` yourself. |
|
|
123
|
+
|
|
124
|
+
### Slots
|
|
125
|
+
|
|
126
|
+
| Slot | Description |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| (default) | The trigger: the first slotted element toggles the panel on pointer down / Enter / Space and receives `aria-haspopup`, `aria-expanded` and `aria-controls` (a bare `<div>` / `<span>` also gets `tabindex="0"` and `role="button"`). |
|
|
129
|
+
| `content` | The panel body, usually a `<rel-popover-content>`; rendered inside the fixed, top-layer wrapper only while open. |
|
|
130
|
+
|
|
131
|
+
### CSS Parts
|
|
132
|
+
|
|
133
|
+
| Part | Description |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| `arrow` | The 14×14 chevron box rendered on the panel edge facing the trigger when `arrow` is set (absent otherwise). |
|
|
136
|
+
|
|
137
|
+
### Tokens / CSS Variables
|
|
138
|
+
|
|
139
|
+
#### Component hooks
|
|
140
|
+
|
|
141
|
+
Set these on the host (or an ancestor) to customise the element without touching design tokens.
|
|
142
|
+
|
|
143
|
+
| Custom property | Default | Description |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| `--rel-popover-arrow-bg` | `var(--rel-bg-neutral)` | Fill of the `arrow` chevron (default `--rel-bg-neutral`, matching `<rel-popover-content>`). |
|
|
146
|
+
| `--rel-popover-arrow-border` | `var(--rel-border-default)` | Stroke of the `arrow` chevron's two slanted edges (default `--rel-border-default`). |
|
|
147
|
+
|
|
148
|
+
### `<rel-popover-content>`
|
|
149
|
+
|
|
150
|
+
#### Attributes / Properties
|
|
151
|
+
|
|
152
|
+
| Property | Attribute | Type | Default | Description |
|
|
153
|
+
| --- | --- | --- | --- | --- |
|
|
154
|
+
| `ariaLabel` | `aria-label` | `string` | `""` | Accessible name applied to the inner `role="dialog"` box (attribute `aria-label`); describe what the panel is for. |
|
|
155
|
+
| `size` | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Figma Size axis (S/M/L): panel padding 12/16/20px. Reflected. |
|
|
156
|
+
|
|
157
|
+
### Events
|
|
158
|
+
|
|
159
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
160
|
+
| --- | --- | --- | --- |
|
|
161
|
+
| — | — | — | This element emits no custom events. |
|
|
162
|
+
|
|
163
|
+
### Slots
|
|
164
|
+
|
|
165
|
+
| Slot | Description |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| (default) | The panel content (headings, paragraphs, form controls, buttons). |
|
|
168
|
+
|
|
169
|
+
### CSS Parts
|
|
170
|
+
|
|
171
|
+
| Part | Description |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| `content` | The padded `role="dialog"` box that carries the surface, border, shadow and size padding. |
|
|
174
|
+
|
|
175
|
+
<!-- readme-gen:end -->
|
|
176
|
+
|
|
177
|
+
## Accessibility
|
|
178
|
+
|
|
179
|
+
- The trigger (first slotted element) is decorated with `aria-haspopup="dialog"`, `aria-expanded` (kept in sync with the open state) and `aria-controls` pointing at the panel wrapper. A trigger that is not natively focusable and contains nothing focusable (a bare `<div>` / `<span>`) also gets `tabindex="0"` and `role="button"`; native buttons and `<rel-button>` are left alone so they do not get a second Tab stop.
|
|
180
|
+
- `<rel-popover-content>` renders its box with `role="dialog"`; pass `aria-label` so the dialog has a name. A custom panel element should carry its own role and label.
|
|
181
|
+
- On open, focus moves to the first focusable element inside the panel (links, enabled buttons and inputs, positive `tabindex`), or to the panel wrapper when there is none. On close, focus returns to whatever was focused before opening (normally the trigger).
|
|
182
|
+
- With `trapfocus`, Tab from the last focusable element wraps to the first and Shift+Tab from the first wraps to the last, so keyboard focus cannot leave the panel while it is open. Without it, Tab leaves the panel normally and the panel stays open until an outside click or Escape.
|
|
183
|
+
- There are no screen-reader announcements beyond the `aria-expanded` change; put the important content first in the panel so it is read when focus lands.
|
|
184
|
+
|
|
185
|
+
| Key | Action |
|
|
186
|
+
| --- | --- |
|
|
187
|
+
| `Enter` / `Space` (on the trigger) | Toggle the panel |
|
|
188
|
+
| `Escape` (anywhere, while open) | Close (unless `closeOnEscape` is switched off) |
|
|
189
|
+
| `Tab` / `Shift+Tab` | Move through the panel's focusable elements; with `trapfocus` the order wraps at both ends |
|
|
190
|
+
|
|
191
|
+
## Notes / Edge Cases
|
|
192
|
+
|
|
193
|
+
- **Slots.** The trigger is the *default* slot's first element; the panel goes in `slot="content"`. There is no `trigger` slot. Only one element should be in the default slot — extra default-slot children render next to the trigger but never toggle the panel.
|
|
194
|
+
- **Top layer / inside a modal.** The panel wrapper is a native `popover="manual"` element shown with `showPopover()`, so a transformed or `overflow: hidden` ancestor (for example `<rel-modal>`'s centred panel) cannot clip it or break its `position: fixed` coordinates. Where the Popover API is unavailable it falls back to `position: fixed; z-index: 1001` and re-measures once to cancel any containing-block offset.
|
|
195
|
+
- **No collision flipping.** The panel always opens on the requested `side`; it is only clamped to stay 8px inside the viewport. Pick the side yourself for edge-of-screen triggers.
|
|
196
|
+
- **One open at a time.** Opening a popover light-dismisses every other open popover that honours `closeOnOutsideClick`, whether it was opened by pointer, keyboard or code. A popover nested inside another's panel keeps its parent open.
|
|
197
|
+
- **Controlled vs uncontrolled.** `open` is `undefined` until you set it; setting it (to `true` *or* `false`) switches the instance to controlled mode permanently, after which the component only emits `rel-open-change` and never changes its own state. Use `defaultopen` for an uncontrolled popover that starts open.
|
|
198
|
+
- **Default-true booleans** (`closeOnEscape`, `closeOnOutsideClick`) cannot be turned off with an attribute — a boolean attribute is true whenever present. Set the property instead.
|
|
199
|
+
- **Positioning updates** run on window resize and on scroll (capture phase). They do not run when the panel's own content changes size; toggle `open` or trigger a resize if you swap content while open.
|
|
200
|
+
- **Arrow.** `arrow` draws a 14×11 chevron on the panel edge facing the trigger, centred on the trigger and clamped 15px in from the panel corners; the trigger gap becomes `max(sideoffset, 13px)`. Colour it with `--rel-popover-arrow-bg` / `--rel-popover-arrow-border` (defaults match `<rel-popover-content>`); if you use a custom panel with a different surface, set both so the chevron blends in.
|
|
201
|
+
- **`<rel-popover-content>`** is `display: block; width: 100%; max-width: 400px`; override `max-width` on the element for wider panels. Slotted `h1`–`h6` get heading-sm type and `p` gets placeholder-tone body text with a bottom margin (none on the last paragraph).
|
|
202
|
+
- **`disabled`** blocks the trigger and dims the host but does not close a panel that is already open — set `open = false` first if needed.
|
|
203
|
+
- The `size` values on `<rel-popover-content>` are the short spellings `sm` / `md` / `lg`; there are no full-word aliases on this element.
|