@reliability-design/web 1.4.9 → 1.4.10
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 +155 -2
- package/custom-elements.json +18600 -0
- package/dist/components/rel-accordion/README.md +9 -2
- package/dist/components/rel-alert/README.md +4 -7
- package/dist/components/rel-autocomplete/README.md +209 -209
- package/dist/components/rel-avatar/README.md +228 -118
- package/dist/components/rel-breadcrumb/README.md +1 -0
- package/dist/components/rel-button/README.md +9 -9
- package/dist/components/rel-calendar/README.md +111 -109
- package/dist/components/rel-cardmedia/README.md +1 -1
- package/dist/components/rel-carousel/README.md +187 -187
- package/dist/components/rel-checkbox/README.md +159 -147
- package/dist/components/rel-chip/README.md +141 -138
- package/dist/components/rel-container/README.md +1 -1
- package/dist/components/rel-date-picker/README.md +221 -206
- package/dist/components/rel-drawer/README.md +4 -4
- package/dist/components/rel-kbd/README.md +188 -141
- package/dist/components/rel-layout/README.md +34 -34
- package/dist/components/rel-menu/README.md +17 -10
- package/dist/components/rel-menubar/README.md +218 -218
- package/dist/components/rel-otp/README.md +4 -8
- package/dist/components/rel-pagination/README.md +141 -100
- package/dist/components/rel-popover/README.md +220 -203
- package/dist/components/rel-radio/README.md +142 -131
- package/dist/components/rel-range-picker/README.md +194 -171
- package/dist/components/rel-resizable/README.md +220 -199
- package/dist/components/rel-segmented-button/README.md +158 -157
- package/dist/components/rel-select/README.md +20 -17
- package/dist/components/rel-sheet/README.md +3 -2
- package/dist/components/rel-signature-pad/README.md +161 -0
- package/dist/components/rel-slider/README.md +140 -131
- package/dist/components/rel-snackbar/README.md +170 -168
- package/dist/components/rel-split-button/README.md +129 -0
- package/dist/components/rel-stepper/README.md +171 -171
- package/dist/components/rel-switch/README.md +122 -117
- package/dist/components/rel-tab/README.md +184 -174
- package/dist/components/rel-textfield/README.md +21 -28
- package/dist/components/rel-time-picker/README.md +188 -170
- package/dist/components/rel-toast/README.md +20 -11
- package/dist/components/rel-tooltip/README.md +5 -4
- package/dist/components/rel-tree/README.md +157 -0
- package/dist/components/rel-upload/README.md +8 -5
- package/dist/index.d.mts +1602 -624
- package/dist/index.d.ts +1602 -624
- package/dist/index.js +11755 -6673
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10955 -5880
- package/dist/index.mjs.map +1 -1
- package/dist/styles/motion.css +31 -0
- package/dist/styles/motion.tokens.json +38 -0
- package/dist/styles/vars.css +88 -64
- package/dist/{vars-DXX6QOAG.css → vars-E22LYFMV.css} +88 -64
- package/package.json +60 -37
- package/dist/styles/focus-ring.ts +0 -84
|
@@ -1,203 +1,220 @@
|
|
|
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,
|
|
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="small" 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="large" 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"
|
|
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
|
|
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 `
|
|
81
|
-
// Default-true booleans are switched off via the property:
|
|
82
|
-
popover.closeOnOutsideClick = false;
|
|
83
|
-
popover.closeOnEscape = false;
|
|
84
|
-
</script>
|
|
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
|
-
|
|
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, radius, shadow, S/M/L padding; no border) 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="small" 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="large" 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" side-offset="16" align-offset="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 trap-focus>
|
|
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 `default-open` instead.
|
|
81
|
+
// Default-true booleans are switched off via the property:
|
|
82
|
+
popover.closeOnOutsideClick = false;
|
|
83
|
+
popover.closeOnEscape = false;
|
|
84
|
+
</script>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Deprecated aliases
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<!-- Lowercase-joined attribute spellings → kebab-case (since 1.5.0; still work, log a one-time
|
|
91
|
+
console notice, removed in 3.0) -->
|
|
92
|
+
<rel-popover defaultopen sideoffset="16" alignoffset="8" trapfocus closeonescape="false" closeonoutsideclick="false">…</rel-popover>
|
|
93
|
+
<!-- canonical -->
|
|
94
|
+
<rel-popover default-open side-offset="16" align-offset="8" trap-focus close-on-escape="false" close-on-outside-click="false">…</rel-popover>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
<!-- readme-gen:start -->
|
|
98
|
+
|
|
99
|
+
<!-- Generated from rel-popover.ts, rel-popover-content.ts — do not edit; run readme-generate.mjs -->
|
|
100
|
+
|
|
101
|
+
## Elements
|
|
102
|
+
|
|
103
|
+
| Element | Class | Source |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| `<rel-popover>` | `RelPopover` | `rel-popover.ts` |
|
|
106
|
+
| `<rel-popover-content>` | `RelPopoverContent` | `rel-popover-content.ts` |
|
|
107
|
+
|
|
108
|
+
## API
|
|
109
|
+
|
|
110
|
+
### `<rel-popover>`
|
|
111
|
+
|
|
112
|
+
#### Attributes / Properties
|
|
113
|
+
|
|
114
|
+
| Property | Attribute | Type | Default | Description |
|
|
115
|
+
| --- | --- | --- | --- | --- |
|
|
116
|
+
| `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. |
|
|
117
|
+
| `defaultOpen` | `default-open` | `boolean` | `false` | Initial state in uncontrolled mode (attribute `default-open`); ignored when `open` is set. The `defaultopen` attribute spelling is deprecated (still works; removal targeted for 3.0). |
|
|
118
|
+
| `disabled` | `disabled` | `boolean` | `false` | Blocks trigger interaction and dims the host to 60% opacity; does not close an already-open panel. Reflected. |
|
|
119
|
+
| `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. |
|
|
120
|
+
| `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. |
|
|
121
|
+
| `sideOffset` | `side-offset` | `number` | `8` | Gap between trigger and panel in pixels (attribute `side-offset`, default 8). With `arrow` the effective gap is at least 13px. The `sideoffset` attribute spelling is deprecated (still works; removal targeted for 3.0). |
|
|
122
|
+
| `alignOffset` | `align-offset` | `number` | `0` | Extra shift along the alignment axis in pixels (attribute `align-offset`, default 0); positive moves right / down. The `alignoffset` attribute spelling is deprecated (still works; removal targeted for 3.0). |
|
|
123
|
+
| `trapFocus` | `trap-focus` | `boolean` | `false` | Keep Tab / Shift+Tab cycling inside the panel while open (attribute `trap-focus`); use for forms. The `trapfocus` attribute spelling is deprecated (still works; removal targeted for 3.0). |
|
|
124
|
+
| `closeOnEscape` | `close-on-escape` | `boolean` | `true` | Close on Escape (attribute `close-on-escape`, default true; switch off with `close-on-escape="false"` or `el.closeOnEscape = false`). The `closeonescape` attribute spelling is deprecated (still works; removal targeted for 3.0). |
|
|
125
|
+
| `closeOnOutsideClick` | `close-on-outside-click` | `boolean` | `true` | Close on a pointer-down outside the trigger and panel (attribute `close-on-outside-click`, default true; switch off with `close-on-outside-click="false"` or the property). Also lets another popover's opening dismiss this one. The `closeonoutsideclick` attribute spelling is deprecated (still works; removal targeted for 3.0). |
|
|
126
|
+
| `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. |
|
|
127
|
+
| `hasPopup` | `has-popup` | `"dialog" \| "menu" \| "listbox" \| "tree" \| "grid" \| "true"` | `"dialog"` | New in 1.5.0. Value written to the trigger's `aria-haspopup` (attribute `has-popup`): `dialog` (default) for a panel of content, or `menu`, `listbox`, `tree`, `grid` or `true` when the panel holds that widget. A panel holding a `rel-menu` takes `menu`. |
|
|
128
|
+
|
|
129
|
+
### Events
|
|
130
|
+
|
|
131
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
132
|
+
| --- | --- | --- | --- |
|
|
133
|
+
| `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. |
|
|
134
|
+
|
|
135
|
+
### Slots
|
|
136
|
+
|
|
137
|
+
| Slot | Description |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| (default) | The trigger: the first slotted element toggles the panel on pointer down / Enter / Space and receives `aria-haspopup` (from `has-popup`), `aria-expanded` and `aria-controls` (a bare `<div>` / `<span>` also gets `tabindex="0"` and `role="button"`). |
|
|
140
|
+
| `content` | The panel body, usually a `<rel-popover-content>`; rendered inside the fixed, top-layer wrapper only while open. |
|
|
141
|
+
|
|
142
|
+
### CSS Parts
|
|
143
|
+
|
|
144
|
+
| Part | Description |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `arrow` | The 14×14 chevron box rendered on the panel edge facing the trigger when `arrow` is set (absent otherwise). |
|
|
147
|
+
|
|
148
|
+
### Tokens / CSS Variables
|
|
149
|
+
|
|
150
|
+
#### Component hooks
|
|
151
|
+
|
|
152
|
+
Set these on the host (or an ancestor) to customise the element without touching design tokens.
|
|
153
|
+
|
|
154
|
+
| Custom property | Default | Description |
|
|
155
|
+
| --- | --- | --- |
|
|
156
|
+
| `--rel-popover-arrow-bg` | `var(--rel-bg-neutral)` | Fill of the `arrow` chevron (default `--rel-bg-neutral`, matching `<rel-popover-content>`). |
|
|
157
|
+
| `--rel-popover-arrow-border` | `transparent` | **Deprecated.** Stroke of the `arrow` chevron's two slanted edges. The panel no longer draws a border — overlapping surfaces are separated by shadow — so this defaults to `transparent` and the chevron has no edge. Set it to restore a stroke. |
|
|
158
|
+
|
|
159
|
+
### `<rel-popover-content>`
|
|
160
|
+
|
|
161
|
+
#### Attributes / Properties
|
|
162
|
+
|
|
163
|
+
| Property | Attribute | Type | Default | Description |
|
|
164
|
+
| --- | --- | --- | --- | --- |
|
|
165
|
+
| `ariaLabel` | `aria-label` | `string` | `""` | Accessible name applied to the inner `role="dialog"` box (attribute `aria-label`); describe what the panel is for. |
|
|
166
|
+
| `size` | `size` | `"small" \| "medium" \| "large" \| "sm" \| "md" \| "lg"` | `"medium"` | Figma Size axis: panel padding 12px (`small`), 16px (`medium`, default) or 20px (`large`). `sm` / `md` / `lg` are alternative spellings and stay supported — they are normalised to the full words, not deprecated. Reflected. |
|
|
167
|
+
|
|
168
|
+
#### Methods
|
|
169
|
+
|
|
170
|
+
| Method | Signature | Description |
|
|
171
|
+
| --- | --- | --- |
|
|
172
|
+
| `focus` | `focus(options?: FocusOptions)` | Focuses the `role="dialog"` box rather than the host (which is not focusable). rel-popover lands focus here when the panel has nothing focusable, so a screen reader announces the dialog by its `aria-label`. |
|
|
173
|
+
|
|
174
|
+
### Events
|
|
175
|
+
|
|
176
|
+
| Event | Detail | Bubbles / composed | Description |
|
|
177
|
+
| --- | --- | --- | --- |
|
|
178
|
+
| — | — | — | This element emits no custom events. |
|
|
179
|
+
|
|
180
|
+
### Slots
|
|
181
|
+
|
|
182
|
+
| Slot | Description |
|
|
183
|
+
| --- | --- |
|
|
184
|
+
| (default) | The panel content (headings, paragraphs, form controls, buttons). |
|
|
185
|
+
|
|
186
|
+
### CSS Parts
|
|
187
|
+
|
|
188
|
+
| Part | Description |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `content` | The padded `role="dialog"` box that carries the surface, shadow and size padding. |
|
|
191
|
+
|
|
192
|
+
<!-- readme-gen:end -->
|
|
193
|
+
|
|
194
|
+
## Accessibility
|
|
195
|
+
|
|
196
|
+
- 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.
|
|
197
|
+
- `<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.
|
|
198
|
+
- On open, focus moves to the first focusable element inside the panel — found through slots and nested shadow roots, so a `<rel-button>` inside `<rel-popover-content>` counts. When there is none, the panel itself takes focus so it is announced: `<rel-popover-content>` focuses its `role="dialog"` box (named by its `aria-label`), and any other panel element falls back to the panel wrapper. On close, focus that was inside the popover returns to the trigger's own control (a `<rel-button>`'s inner `<button>`); a close while focus is elsewhere on the page leaves it there.
|
|
199
|
+
- With `trap-focus`, 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.
|
|
200
|
+
- 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.
|
|
201
|
+
|
|
202
|
+
| Key | Action |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| `Enter` / `Space` (on the trigger) | Toggle the panel |
|
|
205
|
+
| `Escape` (anywhere, while open) | Close (unless `closeOnEscape` is switched off) |
|
|
206
|
+
| `Tab` / `Shift+Tab` | Move through the panel's focusable elements; with `trap-focus` the order wraps at both ends |
|
|
207
|
+
|
|
208
|
+
## Notes / Edge Cases
|
|
209
|
+
|
|
210
|
+
- **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.
|
|
211
|
+
- **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.
|
|
212
|
+
- **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.
|
|
213
|
+
- **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.
|
|
214
|
+
- **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 `default-open` for an uncontrolled popover that starts open.
|
|
215
|
+
- **Default-true booleans** (`closeOnEscape`, `closeOnOutsideClick`): since 1.5.0 the attribute value `"false"` turns them off (`close-on-escape="false"`), as does setting the property. A bare attribute or `=""` still means true.
|
|
216
|
+
- **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.
|
|
217
|
+
- **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(side-offset, 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.
|
|
218
|
+
- **`<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).
|
|
219
|
+
- **`disabled`** blocks the trigger and dims the host but does not close a panel that is already open — set `open = false` first if needed.
|
|
220
|
+
- The `size` values on `<rel-popover-content>` are `small` / `medium` / `large`. The short spellings `sm` / `md` / `lg` are alternative spellings and keep working — they are normalised to the full words before the attribute reflects, so `rel-popover-content[size="medium"]` matches whichever spelling was written.
|