ionbase-ui 0.13.1 → 0.17.0
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/README.md +62 -45
- package/dist/components/Popover.d.ts +47 -0
- package/dist/components/Popover.d.ts.map +1 -0
- package/dist/components/Popover.js +71 -0
- package/dist/components/Popover.js.map +1 -0
- package/dist/components/Toast.d.ts +57 -0
- package/dist/components/Toast.d.ts.map +1 -0
- package/dist/components/Toast.js +81 -0
- package/dist/components/Toast.js.map +1 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/meta/Alert.json +248 -0
- package/dist/meta/Avatar.json +97 -0
- package/dist/meta/AvatarGroup.json +82 -0
- package/dist/meta/Badge.json +83 -0
- package/dist/meta/Button.json +518 -0
- package/dist/meta/Checkbox.json +113 -0
- package/dist/meta/Divider.json +30 -0
- package/dist/meta/FullCard.json +97 -0
- package/dist/meta/Header.json +91 -0
- package/dist/meta/Icon.json +35 -0
- package/dist/meta/Input.json +558 -0
- package/dist/meta/Link.json +239 -0
- package/dist/meta/Logo.json +46 -0
- package/dist/meta/LogoMark.json +41 -0
- package/dist/meta/Menu.json +50 -0
- package/dist/meta/MenuItem.json +75 -0
- package/dist/meta/Modal.json +241 -0
- package/dist/meta/NavItem.json +76 -0
- package/dist/meta/PhoneInput.json +472 -0
- package/dist/meta/Popover.json +124 -0
- package/dist/meta/Radio.json +104 -0
- package/dist/meta/RadioGroup.json +126 -0
- package/dist/meta/ScrollProgress.json +63 -0
- package/dist/meta/Select.json +195 -0
- package/dist/meta/TabItem.json +15 -0
- package/dist/meta/Table.json +135 -0
- package/dist/meta/TableBody.json +43 -0
- package/dist/meta/TableCell.json +105 -0
- package/dist/meta/TableHead.json +43 -0
- package/dist/meta/TableRow.json +56 -0
- package/dist/meta/Tabs.json +186 -0
- package/dist/meta/Toast.json +105 -0
- package/dist/meta/ToastProvider.json +75 -0
- package/dist/meta/Toggle.json +102 -0
- package/dist/meta/Tooltip.json +78 -0
- package/dist/meta/components.json +4757 -0
- package/dist/meta/index.json +479 -0
- package/dist/styles/index.css +2 -0
- package/dist/styles/popover.css +185 -0
- package/dist/styles/toast.css +216 -0
- package/dist/styles/tokens/base.css +26 -26
- package/dist/styles/tokens/theme-dark.css +11 -11
- package/dist/tokens/index.d.ts +9 -9
- package/dist/tokens/index.js +9 -9
- package/dist/tokens/index.js.map +1 -1
- package/package.json +12 -6
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
{
|
|
2
|
+
"package": "ionbase-ui",
|
|
3
|
+
"version": "0.17.0",
|
|
4
|
+
"usage": "Pick a component here, then read dist/meta/<Name>.json for its full contract.",
|
|
5
|
+
"hooks": [
|
|
6
|
+
"useToast"
|
|
7
|
+
],
|
|
8
|
+
"components": {
|
|
9
|
+
"Alert": {
|
|
10
|
+
"summary": "A persistent, in-page status message. Intent picks the ARIA role for you.",
|
|
11
|
+
"status": "stable",
|
|
12
|
+
"variants": {
|
|
13
|
+
"intent": [
|
|
14
|
+
"neutral",
|
|
15
|
+
"primary",
|
|
16
|
+
"success",
|
|
17
|
+
"warning",
|
|
18
|
+
"error",
|
|
19
|
+
"information"
|
|
20
|
+
],
|
|
21
|
+
"emphasis": [
|
|
22
|
+
"subtle",
|
|
23
|
+
"solid"
|
|
24
|
+
],
|
|
25
|
+
"layout": [
|
|
26
|
+
"inline",
|
|
27
|
+
"banner"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"detail": "dist/meta/Alert.json",
|
|
31
|
+
"hasIntent": true
|
|
32
|
+
},
|
|
33
|
+
"Avatar": {
|
|
34
|
+
"summary": "Avatar picks its content the way Figma's `Type` variant does, but by",
|
|
35
|
+
"variants": {
|
|
36
|
+
"size": [
|
|
37
|
+
"mini",
|
|
38
|
+
"sm",
|
|
39
|
+
"md",
|
|
40
|
+
"lg"
|
|
41
|
+
],
|
|
42
|
+
"shape": [
|
|
43
|
+
"circle",
|
|
44
|
+
"square"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"detail": "dist/meta/Avatar.json",
|
|
48
|
+
"hasIntent": false
|
|
49
|
+
},
|
|
50
|
+
"AvatarGroup": {
|
|
51
|
+
"summary": "AvatarGroup overlaps its children by a quarter of the avatar size, matching",
|
|
52
|
+
"variants": {
|
|
53
|
+
"size": [
|
|
54
|
+
"mini",
|
|
55
|
+
"sm",
|
|
56
|
+
"md",
|
|
57
|
+
"lg"
|
|
58
|
+
],
|
|
59
|
+
"shape": [
|
|
60
|
+
"circle",
|
|
61
|
+
"square"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"detail": "dist/meta/AvatarGroup.json",
|
|
65
|
+
"hasIntent": false
|
|
66
|
+
},
|
|
67
|
+
"Badge": {
|
|
68
|
+
"summary": "Badge is presentational — no role, no interaction. React Aria has nothing to",
|
|
69
|
+
"variants": {
|
|
70
|
+
"intent": [
|
|
71
|
+
"neutral",
|
|
72
|
+
"primary",
|
|
73
|
+
"success",
|
|
74
|
+
"warning",
|
|
75
|
+
"error",
|
|
76
|
+
"information"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"detail": "dist/meta/Badge.json",
|
|
80
|
+
"hasIntent": false
|
|
81
|
+
},
|
|
82
|
+
"Button": {
|
|
83
|
+
"summary": "Triggers an action in place. Never navigates.",
|
|
84
|
+
"status": "stable",
|
|
85
|
+
"variants": {
|
|
86
|
+
"variant": [
|
|
87
|
+
"success",
|
|
88
|
+
"primary-brand",
|
|
89
|
+
"primary-neutral",
|
|
90
|
+
"primary-soft",
|
|
91
|
+
"secondary",
|
|
92
|
+
"tertiary",
|
|
93
|
+
"destructive"
|
|
94
|
+
],
|
|
95
|
+
"size": [
|
|
96
|
+
"sm",
|
|
97
|
+
"md",
|
|
98
|
+
"lg",
|
|
99
|
+
"xl"
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
"detail": "dist/meta/Button.json",
|
|
103
|
+
"hasIntent": true
|
|
104
|
+
},
|
|
105
|
+
"Checkbox": {
|
|
106
|
+
"summary": "Checkbox wraps a native `<input type=\"checkbox\">` and hides it.",
|
|
107
|
+
"variants": {
|
|
108
|
+
"size": [
|
|
109
|
+
"sm",
|
|
110
|
+
"md",
|
|
111
|
+
"lg"
|
|
112
|
+
],
|
|
113
|
+
"intent": [
|
|
114
|
+
"neutral",
|
|
115
|
+
"brand",
|
|
116
|
+
"danger"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
"detail": "dist/meta/Checkbox.json",
|
|
120
|
+
"hasIntent": false
|
|
121
|
+
},
|
|
122
|
+
"Divider": {
|
|
123
|
+
"summary": "A single `<hr>`, matching Figma's `Border` (70:22153).",
|
|
124
|
+
"variants": {
|
|
125
|
+
"orientation": [
|
|
126
|
+
"horizontal",
|
|
127
|
+
"vertical"
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
"detail": "dist/meta/Divider.json",
|
|
131
|
+
"hasIntent": false
|
|
132
|
+
},
|
|
133
|
+
"FullCard": {
|
|
134
|
+
"summary": "Full Card — the full-bleed case study row from Figma `Full Card` (592:857).",
|
|
135
|
+
"variants": {
|
|
136
|
+
"alignment": [
|
|
137
|
+
"right",
|
|
138
|
+
"left"
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
"detail": "dist/meta/FullCard.json",
|
|
142
|
+
"hasIntent": false
|
|
143
|
+
},
|
|
144
|
+
"Header": {
|
|
145
|
+
"summary": "Header renders Figma's four Device variants — Desktop, Tablet,",
|
|
146
|
+
"variants": {},
|
|
147
|
+
"detail": "dist/meta/Header.json",
|
|
148
|
+
"hasIntent": false
|
|
149
|
+
},
|
|
150
|
+
"Icon": {
|
|
151
|
+
"summary": "Wrapper that applies the design system's icon sizing and accessibility",
|
|
152
|
+
"variants": {},
|
|
153
|
+
"detail": "dist/meta/Icon.json",
|
|
154
|
+
"hasIntent": false
|
|
155
|
+
},
|
|
156
|
+
"Input": {
|
|
157
|
+
"summary": "A single-line text field, together with its label, helper text and error message.",
|
|
158
|
+
"status": "stable",
|
|
159
|
+
"variants": {
|
|
160
|
+
"size": [
|
|
161
|
+
"sm",
|
|
162
|
+
"md",
|
|
163
|
+
"lg"
|
|
164
|
+
],
|
|
165
|
+
"autoCapitalize": [
|
|
166
|
+
"none",
|
|
167
|
+
"off",
|
|
168
|
+
"on",
|
|
169
|
+
"sentences",
|
|
170
|
+
"words",
|
|
171
|
+
"characters"
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
"detail": "dist/meta/Input.json",
|
|
175
|
+
"hasIntent": true
|
|
176
|
+
},
|
|
177
|
+
"Link": {
|
|
178
|
+
"summary": "Link — Figma `Link` (774:1516).",
|
|
179
|
+
"variants": {
|
|
180
|
+
"variant": [
|
|
181
|
+
"inline",
|
|
182
|
+
"standalone"
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
"detail": "dist/meta/Link.json",
|
|
186
|
+
"hasIntent": false
|
|
187
|
+
},
|
|
188
|
+
"Logo": {
|
|
189
|
+
"summary": "The full lockup: mark + wordmark, matching Figma's `Logo-Ionbase`",
|
|
190
|
+
"variants": {
|
|
191
|
+
"size": [
|
|
192
|
+
"sm",
|
|
193
|
+
"lg"
|
|
194
|
+
],
|
|
195
|
+
"wordmark": [
|
|
196
|
+
"text",
|
|
197
|
+
"vector"
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
"detail": "dist/meta/Logo.json",
|
|
201
|
+
"hasIntent": false
|
|
202
|
+
},
|
|
203
|
+
"LogoMark": {
|
|
204
|
+
"summary": "The bare icon glyph, no wordmark — what `Header` actually uses.",
|
|
205
|
+
"variants": {
|
|
206
|
+
"size": [
|
|
207
|
+
"sm",
|
|
208
|
+
"lg"
|
|
209
|
+
]
|
|
210
|
+
},
|
|
211
|
+
"detail": "dist/meta/LogoMark.json",
|
|
212
|
+
"hasIntent": false
|
|
213
|
+
},
|
|
214
|
+
"Menu": {
|
|
215
|
+
"summary": "Menu is the list surface, not a popover.",
|
|
216
|
+
"variants": {},
|
|
217
|
+
"detail": "dist/meta/Menu.json",
|
|
218
|
+
"hasIntent": false
|
|
219
|
+
},
|
|
220
|
+
"MenuItem": {
|
|
221
|
+
"summary": null,
|
|
222
|
+
"variants": {},
|
|
223
|
+
"detail": "dist/meta/MenuItem.json",
|
|
224
|
+
"hasIntent": false
|
|
225
|
+
},
|
|
226
|
+
"Modal": {
|
|
227
|
+
"summary": "A focus-trapping dialog. Renders nothing when closed and portals when open.",
|
|
228
|
+
"status": "stable",
|
|
229
|
+
"variants": {
|
|
230
|
+
"size": [
|
|
231
|
+
"sm",
|
|
232
|
+
"md",
|
|
233
|
+
"lg",
|
|
234
|
+
"fullscreen"
|
|
235
|
+
],
|
|
236
|
+
"align": [
|
|
237
|
+
"left",
|
|
238
|
+
"center"
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
"detail": "dist/meta/Modal.json",
|
|
242
|
+
"hasIntent": true
|
|
243
|
+
},
|
|
244
|
+
"NavItem": {
|
|
245
|
+
"summary": "Nav Item renders an `<a>` when given `href`, a `<button>` otherwise —",
|
|
246
|
+
"variants": {},
|
|
247
|
+
"detail": "dist/meta/NavItem.json",
|
|
248
|
+
"hasIntent": false
|
|
249
|
+
},
|
|
250
|
+
"PhoneInput": {
|
|
251
|
+
"summary": "PhoneInput — Figma `Input/Phone` (80:372).",
|
|
252
|
+
"variants": {
|
|
253
|
+
"autoCapitalize": [
|
|
254
|
+
"none",
|
|
255
|
+
"off",
|
|
256
|
+
"on",
|
|
257
|
+
"sentences",
|
|
258
|
+
"words",
|
|
259
|
+
"characters"
|
|
260
|
+
],
|
|
261
|
+
"size": [
|
|
262
|
+
"sm",
|
|
263
|
+
"md",
|
|
264
|
+
"lg"
|
|
265
|
+
]
|
|
266
|
+
},
|
|
267
|
+
"detail": "dist/meta/PhoneInput.json",
|
|
268
|
+
"hasIntent": false
|
|
269
|
+
},
|
|
270
|
+
"Popover": {
|
|
271
|
+
"summary": "Popover — Figma `Popover` (825:1853).",
|
|
272
|
+
"variants": {
|
|
273
|
+
"placement": [
|
|
274
|
+
"right",
|
|
275
|
+
"left",
|
|
276
|
+
"top",
|
|
277
|
+
"bottom"
|
|
278
|
+
],
|
|
279
|
+
"size": [
|
|
280
|
+
"sm",
|
|
281
|
+
"md",
|
|
282
|
+
"lg"
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
"detail": "dist/meta/Popover.json",
|
|
286
|
+
"hasIntent": false
|
|
287
|
+
},
|
|
288
|
+
"Radio": {
|
|
289
|
+
"summary": null,
|
|
290
|
+
"variants": {
|
|
291
|
+
"size": [
|
|
292
|
+
"sm",
|
|
293
|
+
"md",
|
|
294
|
+
"lg"
|
|
295
|
+
],
|
|
296
|
+
"intent": [
|
|
297
|
+
"neutral",
|
|
298
|
+
"brand",
|
|
299
|
+
"danger"
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
"detail": "dist/meta/Radio.json",
|
|
303
|
+
"hasIntent": false
|
|
304
|
+
},
|
|
305
|
+
"RadioGroup": {
|
|
306
|
+
"summary": "Renders a `<fieldset>` with a `<legend>` rather than a div with",
|
|
307
|
+
"variants": {
|
|
308
|
+
"size": [
|
|
309
|
+
"sm",
|
|
310
|
+
"md",
|
|
311
|
+
"lg"
|
|
312
|
+
],
|
|
313
|
+
"intent": [
|
|
314
|
+
"neutral",
|
|
315
|
+
"brand",
|
|
316
|
+
"danger"
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
"detail": "dist/meta/RadioGroup.json",
|
|
320
|
+
"hasIntent": false
|
|
321
|
+
},
|
|
322
|
+
"ScrollProgress": {
|
|
323
|
+
"summary": "The compact rail is the disclosure trigger. It is a real `<button>`, so a",
|
|
324
|
+
"variants": {},
|
|
325
|
+
"detail": "dist/meta/ScrollProgress.json",
|
|
326
|
+
"hasIntent": false
|
|
327
|
+
},
|
|
328
|
+
"Select": {
|
|
329
|
+
"summary": "A dropdown over a native <select>, with the same label and error wiring as Input.",
|
|
330
|
+
"status": "stable",
|
|
331
|
+
"variants": {
|
|
332
|
+
"size": [
|
|
333
|
+
"sm",
|
|
334
|
+
"md",
|
|
335
|
+
"lg"
|
|
336
|
+
]
|
|
337
|
+
},
|
|
338
|
+
"detail": "dist/meta/Select.json",
|
|
339
|
+
"hasIntent": true
|
|
340
|
+
},
|
|
341
|
+
"TabItem": {
|
|
342
|
+
"summary": null,
|
|
343
|
+
"variants": {},
|
|
344
|
+
"detail": "dist/meta/TabItem.json",
|
|
345
|
+
"hasIntent": false
|
|
346
|
+
},
|
|
347
|
+
"Table": {
|
|
348
|
+
"summary": "A data table. Table owns the scroll container and density; rows and cells are composed.",
|
|
349
|
+
"status": "stable",
|
|
350
|
+
"variants": {
|
|
351
|
+
"density": [
|
|
352
|
+
"compact",
|
|
353
|
+
"default",
|
|
354
|
+
"relaxed"
|
|
355
|
+
]
|
|
356
|
+
},
|
|
357
|
+
"detail": "dist/meta/Table.json",
|
|
358
|
+
"hasIntent": true
|
|
359
|
+
},
|
|
360
|
+
"TableBody": {
|
|
361
|
+
"summary": null,
|
|
362
|
+
"variants": {},
|
|
363
|
+
"detail": "dist/meta/TableBody.json",
|
|
364
|
+
"hasIntent": false
|
|
365
|
+
},
|
|
366
|
+
"TableCell": {
|
|
367
|
+
"summary": "One component covers Figma's `Table Cell` + `Cell Text`: the two are never",
|
|
368
|
+
"variants": {
|
|
369
|
+
"scope": [
|
|
370
|
+
"row",
|
|
371
|
+
"rowgroup",
|
|
372
|
+
"col",
|
|
373
|
+
"colgroup"
|
|
374
|
+
],
|
|
375
|
+
"align": [
|
|
376
|
+
"center",
|
|
377
|
+
"leading",
|
|
378
|
+
"trailing"
|
|
379
|
+
],
|
|
380
|
+
"variant": [
|
|
381
|
+
"link",
|
|
382
|
+
"default"
|
|
383
|
+
]
|
|
384
|
+
},
|
|
385
|
+
"detail": "dist/meta/TableCell.json",
|
|
386
|
+
"hasIntent": false
|
|
387
|
+
},
|
|
388
|
+
"TableHead": {
|
|
389
|
+
"summary": null,
|
|
390
|
+
"variants": {},
|
|
391
|
+
"detail": "dist/meta/TableHead.json",
|
|
392
|
+
"hasIntent": false
|
|
393
|
+
},
|
|
394
|
+
"TableRow": {
|
|
395
|
+
"summary": "A plain `<tr>`. Hover is CSS-only (`:hover` plus a `data-hovered` escape",
|
|
396
|
+
"variants": {},
|
|
397
|
+
"detail": "dist/meta/TableRow.json",
|
|
398
|
+
"hasIntent": false
|
|
399
|
+
},
|
|
400
|
+
"Tabs": {
|
|
401
|
+
"summary": null,
|
|
402
|
+
"variants": {
|
|
403
|
+
"type": [
|
|
404
|
+
"pill",
|
|
405
|
+
"underline"
|
|
406
|
+
],
|
|
407
|
+
"size": [
|
|
408
|
+
"sm",
|
|
409
|
+
"md",
|
|
410
|
+
"lg"
|
|
411
|
+
],
|
|
412
|
+
"orientation": [
|
|
413
|
+
"horizontal",
|
|
414
|
+
"vertical"
|
|
415
|
+
]
|
|
416
|
+
},
|
|
417
|
+
"detail": "dist/meta/Tabs.json",
|
|
418
|
+
"hasIntent": false
|
|
419
|
+
},
|
|
420
|
+
"Toast": {
|
|
421
|
+
"summary": "Toast — Figma `Toast` (820:1655).",
|
|
422
|
+
"variants": {
|
|
423
|
+
"intent": [
|
|
424
|
+
"neutral",
|
|
425
|
+
"primary",
|
|
426
|
+
"success",
|
|
427
|
+
"warning",
|
|
428
|
+
"error",
|
|
429
|
+
"information"
|
|
430
|
+
]
|
|
431
|
+
},
|
|
432
|
+
"detail": "dist/meta/Toast.json",
|
|
433
|
+
"hasIntent": false
|
|
434
|
+
},
|
|
435
|
+
"ToastProvider": {
|
|
436
|
+
"summary": "Renders the queue and supplies `useToast`.",
|
|
437
|
+
"variants": {
|
|
438
|
+
"placement": [
|
|
439
|
+
"top-left",
|
|
440
|
+
"top-right",
|
|
441
|
+
"bottom-left",
|
|
442
|
+
"bottom-right"
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
"detail": "dist/meta/ToastProvider.json",
|
|
446
|
+
"hasIntent": false
|
|
447
|
+
},
|
|
448
|
+
"Toggle": {
|
|
449
|
+
"summary": "Toggle is a checkbox with `role=\"switch\"`.",
|
|
450
|
+
"variants": {
|
|
451
|
+
"size": [
|
|
452
|
+
"sm",
|
|
453
|
+
"md",
|
|
454
|
+
"lg"
|
|
455
|
+
],
|
|
456
|
+
"intent": [
|
|
457
|
+
"neutral",
|
|
458
|
+
"brand",
|
|
459
|
+
"danger"
|
|
460
|
+
]
|
|
461
|
+
},
|
|
462
|
+
"detail": "dist/meta/Toggle.json",
|
|
463
|
+
"hasIntent": false
|
|
464
|
+
},
|
|
465
|
+
"Tooltip": {
|
|
466
|
+
"summary": "Tooltip — Figma `Tooltip` (801:1568).",
|
|
467
|
+
"variants": {
|
|
468
|
+
"placement": [
|
|
469
|
+
"right",
|
|
470
|
+
"left",
|
|
471
|
+
"top",
|
|
472
|
+
"bottom"
|
|
473
|
+
]
|
|
474
|
+
},
|
|
475
|
+
"detail": "dist/meta/Tooltip.json",
|
|
476
|
+
"hasIntent": false
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
package/dist/styles/index.css
CHANGED
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
@import url('./divider.css');
|
|
46
46
|
@import url('./link.css');
|
|
47
47
|
@import url('./modal.css');
|
|
48
|
+
@import url('./popover.css');
|
|
48
49
|
@import url('./tooltip.css');
|
|
50
|
+
@import url('./toast.css');
|
|
49
51
|
@import url('./nav-item.css');
|
|
50
52
|
@import url('./scroll-progress.css');
|
|
51
53
|
@import url('./full-card.css');
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Popover
|
|
3
|
+
*
|
|
4
|
+
* Measured from Figma `Popover` (825:1853). Placement x Size.
|
|
5
|
+
*
|
|
6
|
+
* IT SITS BETWEEN TOOLTIP AND MODAL
|
|
7
|
+
*
|
|
8
|
+
* A tooltip is a hint that cannot hold focusable content; a modal is a task
|
|
9
|
+
* that takes over the page. A popover holds interactive content but stays
|
|
10
|
+
* attached to the control that opened it — no visible scrim, anchored to its
|
|
11
|
+
* trigger, and `surface/raised` rather than Modal's `surface/overlay`.
|
|
12
|
+
*/
|
|
13
|
+
.ion-popover {
|
|
14
|
+
--ion-popover-width: 320px;
|
|
15
|
+
|
|
16
|
+
position: absolute;
|
|
17
|
+
z-index: 1150;
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* Between Modal (1000) and Toast (1200). A popover opened from a control
|
|
21
|
+
* inside a dialog has to sit above the dialog, and a toast confirming what
|
|
22
|
+
* the popover did has to sit above both.
|
|
23
|
+
*/
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: var(--spacing-12);
|
|
27
|
+
width: var(--ion-popover-width);
|
|
28
|
+
max-width: calc(100vw - var(--spacing-16) * 2);
|
|
29
|
+
padding: var(--spacing-16);
|
|
30
|
+
background-color: var(--surface-raised);
|
|
31
|
+
|
|
32
|
+
/* For dark mode, where surface/raised is neutral.800 against a near-black
|
|
33
|
+
* page and the shadow alone does not separate them. Same as Toast. */
|
|
34
|
+
border: var(--border-width-default) solid var(--border-subtle);
|
|
35
|
+
border-radius: var(--radius-md);
|
|
36
|
+
box-shadow: var(--ion-shadow-shadow-lg);
|
|
37
|
+
font-family: var(--font-family-sans);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.ion-popover--sm {
|
|
41
|
+
--ion-popover-width: 280px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.ion-popover--lg {
|
|
45
|
+
--ion-popover-width: 400px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* The underlay listens, it does not paint.
|
|
50
|
+
*
|
|
51
|
+
* Modal's scrim is visible because a modal replaces the page. This one is
|
|
52
|
+
* transparent: it exists only so a click anywhere outside closes the popover,
|
|
53
|
+
* while everything behind stays legible.
|
|
54
|
+
*/
|
|
55
|
+
.ion-popover__underlay {
|
|
56
|
+
position: fixed;
|
|
57
|
+
inset: 0;
|
|
58
|
+
z-index: 1140;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* The arrow, as a rotated square rather than a border triangle.
|
|
63
|
+
*
|
|
64
|
+
* Tooltip uses borders because it has no outline to match. This panel has a
|
|
65
|
+
* 1px border, so the caret needs two of its edges drawn — a rotated square
|
|
66
|
+
* with a border on two sides is the only shape that produces a continuous
|
|
67
|
+
* outline where it meets the panel. React Aria positions it along the edge;
|
|
68
|
+
* these rules only decide which side it sits on and which edges are drawn.
|
|
69
|
+
*/
|
|
70
|
+
.ion-popover__arrow {
|
|
71
|
+
position: absolute;
|
|
72
|
+
width: 12px;
|
|
73
|
+
height: 12px;
|
|
74
|
+
background-color: var(--surface-raised);
|
|
75
|
+
border: var(--border-width-default) solid var(--border-subtle);
|
|
76
|
+
transform: rotate(45deg);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/*
|
|
80
|
+
* `--top` means the popover is ABOVE the trigger, so the caret hangs off the
|
|
81
|
+
* bottom edge. These follow the RESOLVED placement: react-aria flips on
|
|
82
|
+
* collision, and an arrow left on the requested side points away from the
|
|
83
|
+
* trigger entirely.
|
|
84
|
+
*
|
|
85
|
+
* The half-width negative offset centres the rotated square on the edge, and
|
|
86
|
+
* clearing two borders leaves the seam continuous with the panel.
|
|
87
|
+
*/
|
|
88
|
+
.ion-popover--top .ion-popover__arrow {
|
|
89
|
+
bottom: -7px;
|
|
90
|
+
border-top: none;
|
|
91
|
+
border-left: none;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.ion-popover--bottom .ion-popover__arrow {
|
|
95
|
+
top: -7px;
|
|
96
|
+
border-bottom: none;
|
|
97
|
+
border-right: none;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.ion-popover--left .ion-popover__arrow {
|
|
101
|
+
right: -7px;
|
|
102
|
+
border-bottom: none;
|
|
103
|
+
border-left: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.ion-popover--right .ion-popover__arrow {
|
|
107
|
+
left: -7px;
|
|
108
|
+
border-top: none;
|
|
109
|
+
border-right: none;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.ion-popover__header {
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: flex-start;
|
|
115
|
+
gap: var(--spacing-12);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.ion-popover__title {
|
|
119
|
+
margin: 0;
|
|
120
|
+
flex: 1 1 auto;
|
|
121
|
+
min-width: 0;
|
|
122
|
+
color: var(--text-default);
|
|
123
|
+
font-size: var(--type-body);
|
|
124
|
+
line-height: var(--type-body-line-height);
|
|
125
|
+
font-weight: var(--font-weight-medium);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* 32px around a 20px glyph — WCAG 2.2 SC 2.5.8 asks 24x24 minimum. Same
|
|
130
|
+
* reasoning as Modal's close, Alert's dismiss and Toast's.
|
|
131
|
+
*/
|
|
132
|
+
.ion-popover__close {
|
|
133
|
+
display: inline-flex;
|
|
134
|
+
align-items: center;
|
|
135
|
+
justify-content: center;
|
|
136
|
+
flex-shrink: 0;
|
|
137
|
+
width: var(--spacing-32);
|
|
138
|
+
height: var(--spacing-32);
|
|
139
|
+
padding: 0;
|
|
140
|
+
background: none;
|
|
141
|
+
border: none;
|
|
142
|
+
border-radius: var(--radius-sm);
|
|
143
|
+
color: var(--icon-secondary);
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
transition: background-color var(--ion-duration-base) var(--ion-ease-out);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.ion-popover__close svg {
|
|
149
|
+
width: var(--icon-size-md);
|
|
150
|
+
height: var(--icon-size-md);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@media (hover: hover) {
|
|
154
|
+
.ion-popover__close:hover {
|
|
155
|
+
background-color: var(--surface-hover);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.ion-popover__close:focus-visible {
|
|
160
|
+
outline: var(--border-width-thick) solid var(--ring-focus);
|
|
161
|
+
outline-offset: 2px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/*
|
|
165
|
+
* The body is the only part that scrolls, capped against the viewport. A
|
|
166
|
+
* popover anchored near an edge would otherwise run off it — Figma panels hug
|
|
167
|
+
* because a Figma frame has no viewport to overflow.
|
|
168
|
+
*/
|
|
169
|
+
.ion-popover__body {
|
|
170
|
+
max-height: 60vh;
|
|
171
|
+
overflow-y: auto;
|
|
172
|
+
color: var(--text-secondary);
|
|
173
|
+
font-size: var(--type-body-sm);
|
|
174
|
+
line-height: var(--type-body-sm-line-height);
|
|
175
|
+
font-weight: var(--font-weight-regular);
|
|
176
|
+
overflow-wrap: anywhere;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.ion-popover__footer {
|
|
180
|
+
display: flex;
|
|
181
|
+
align-items: center;
|
|
182
|
+
justify-content: flex-end;
|
|
183
|
+
gap: var(--spacing-8);
|
|
184
|
+
flex-shrink: 0;
|
|
185
|
+
}
|