@realmorg/ui 2.0.0-alpha.2 → 2.0.0-alpha.3

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.
Files changed (64) hide show
  1. package/components/accordion.html +18 -0
  2. package/components/alert-dialog.html +40 -0
  3. package/components/alert.html +14 -0
  4. package/components/aspect-ratio.html +6 -0
  5. package/components/attachment.html +14 -0
  6. package/components/avatar.html +22 -0
  7. package/components/badge.html +6 -0
  8. package/components/breadcrumb.html +30 -0
  9. package/components/bubble.html +10 -0
  10. package/components/button-group.html +14 -0
  11. package/components/button.html +6 -0
  12. package/components/calendar.html +6 -0
  13. package/components/card.html +30 -0
  14. package/components/carousel.html +22 -0
  15. package/components/chart.html +6 -0
  16. package/components/checkbox.html +6 -0
  17. package/components/code-block.html +6 -0
  18. package/components/collapsible.html +14 -0
  19. package/components/combobox.html +13 -0
  20. package/components/command.html +12 -0
  21. package/components/context-menu.html +14 -0
  22. package/components/dialog.html +49 -3
  23. package/components/direction.html +6 -0
  24. package/components/drawer.html +46 -3
  25. package/components/dropdown-menu.html +49 -0
  26. package/components/empty.html +26 -0
  27. package/components/field.html +26 -0
  28. package/components/hover-card.html +17 -0
  29. package/components/input-group.html +16 -0
  30. package/components/input-otp.html +12 -0
  31. package/components/input.html +12 -0
  32. package/components/item.html +38 -0
  33. package/components/kbd.html +10 -0
  34. package/components/label.html +6 -0
  35. package/components/marker.html +6 -0
  36. package/components/menubar.html +21 -0
  37. package/components/message-scroller.html +6 -0
  38. package/components/message.html +18 -0
  39. package/components/navigation-menu.html +29 -0
  40. package/components/pagination.html +6 -0
  41. package/components/popover.html +31 -0
  42. package/components/progress.html +6 -0
  43. package/components/radio-group.html +6 -0
  44. package/components/resizable.html +14 -0
  45. package/components/scroll-area.html +6 -0
  46. package/components/select.html +12 -0
  47. package/components/separator.html +6 -0
  48. package/components/sheet.html +30 -0
  49. package/components/sidebar.html +52 -2
  50. package/components/skeleton.html +6 -0
  51. package/components/slider.html +28 -1
  52. package/components/spinner.html +6 -0
  53. package/components/switch.html +6 -0
  54. package/components/table.html +6 -0
  55. package/components/tabs.html +18 -0
  56. package/components/textarea.html +12 -0
  57. package/components/toaster.html +6 -0
  58. package/components/toggle-group.html +6 -0
  59. package/components/toggle.html +6 -0
  60. package/components/tooltip.html +17 -0
  61. package/dist/theme.css +13 -0
  62. package/dist/ui.html +988 -9
  63. package/package.json +3 -3
  64. package/theme.css +13 -0
@@ -72,6 +72,12 @@
72
72
  </script>
73
73
 
74
74
  <style>
75
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
76
+ touch-action does not reach shadow content in iOS Safari. */
77
+ :host,
78
+ * {
79
+ touch-action: manipulation;
80
+ }
75
81
  :host {
76
82
  display: flex;
77
83
  flex-direction: column;
@@ -103,6 +109,12 @@
103
109
  font-size: var(--text-sm);
104
110
  outline: none;
105
111
  }
112
+ /* iOS Safari zooms in on a focused field whose text is under 16px. */
113
+ @media (pointer: coarse) {
114
+ input {
115
+ font-size: var(--text-base);
116
+ }
117
+ }
106
118
  input::placeholder {
107
119
  color: var(--muted-foreground);
108
120
  }
@@ -10,6 +10,12 @@
10
10
  </script>
11
11
 
12
12
  <style>
13
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
14
+ touch-action does not reach shadow content in iOS Safari. */
15
+ :host,
16
+ * {
17
+ touch-action: manipulation;
18
+ }
13
19
  :host {
14
20
  display: contents;
15
21
  }
@@ -20,6 +26,10 @@
20
26
 
21
27
  <custom-element name="ui-context-menu-trigger">
22
28
  <style>
29
+ :host,
30
+ * {
31
+ touch-action: manipulation;
32
+ }
23
33
  :host {
24
34
  display: block;
25
35
  }
@@ -48,6 +58,10 @@
48
58
  </script>
49
59
 
50
60
  <style>
61
+ :host,
62
+ * {
63
+ touch-action: manipulation;
64
+ }
51
65
  :host {
52
66
  position: fixed;
53
67
  box-sizing: border-box;
@@ -74,12 +74,21 @@
74
74
  observe(() => {
75
75
  const dialog = refs.dialog;
76
76
  if (!dialog || props.open === dialog.open) return;
77
- if (props.open) dialog.showModal();
78
- else dialog.close();
77
+ if (!props.open) return dialog.close();
78
+ dialog.showModal();
79
+ // Left to the browser, focus lands on the first button (often close) with a focus ring after a
80
+ // tap, and Firefox and WebKit ignore autofocus on slotted content.
81
+ (host.querySelector("[autofocus]") ?? dialog).focus();
79
82
  });
80
83
  </script>
81
84
 
82
85
  <style>
86
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
87
+ touch-action does not reach shadow content in iOS Safari. */
88
+ :host,
89
+ * {
90
+ touch-action: manipulation;
91
+ }
83
92
  :host {
84
93
  display: contents;
85
94
  }
@@ -87,7 +96,10 @@
87
96
  box-sizing: border-box;
88
97
  width: 100%;
89
98
  max-width: min(calc(var(--spacing) * 128), calc(100% - calc(var(--spacing) * 8)));
90
- max-height: calc(100% - calc(var(--spacing) * 8));
99
+ /* Without an explicit height, a dialog pinned to both edges of the screen can stretch to
100
+ full height. svh stays the same while a phone's address bar shows and hides. */
101
+ height: fit-content;
102
+ max-height: calc(100svh - calc(var(--spacing) * 8));
91
103
  padding: calc(var(--spacing) * 6);
92
104
  border: 1px solid var(--border);
93
105
  border-radius: var(--radius-lg);
@@ -96,8 +108,13 @@
96
108
  box-shadow: var(--shadow-lg);
97
109
  overflow: auto;
98
110
  }
111
+ dialog:focus {
112
+ outline: none;
113
+ }
99
114
  dialog[open] {
100
115
  display: grid;
116
+ /* Safari stretches a grid overlay to its max-height unless the rows are packed at the start. */
117
+ align-content: start;
101
118
  gap: calc(var(--spacing) * 4);
102
119
  animation: zoom 0.2s ease-out;
103
120
  }
@@ -116,7 +133,11 @@
116
133
  display: flex;
117
134
  flex-direction: column;
118
135
  }
136
+ [part="body"] {
137
+ display: contents;
138
+ }
119
139
  :host(:is(:state(attr-side-is-left), :state(attr-side-is-right))) [part="body"] {
140
+ display: block;
120
141
  flex: 1;
121
142
  }
122
143
  :host(:state(attr-side-is-right)) dialog {
@@ -185,6 +206,7 @@
185
206
  <dialog
186
207
  ref="dialog"
187
208
  part="dialog"
209
+ tabindex="-1"
188
210
  _aria-label="#dialog.label"
189
211
  _aria-description="#dialog.description"
190
212
  onclose="closed()"
@@ -201,6 +223,10 @@
201
223
 
202
224
  <custom-element name="ui-dialog-trigger" slot="trigger">
203
225
  <style>
226
+ :host,
227
+ * {
228
+ touch-action: manipulation;
229
+ }
204
230
  :host,
205
231
  span {
206
232
  display: contents;
@@ -216,6 +242,10 @@
216
242
  </script>
217
243
 
218
244
  <style>
245
+ :host,
246
+ * {
247
+ touch-action: manipulation;
248
+ }
219
249
  :host,
220
250
  span {
221
251
  display: contents;
@@ -227,6 +257,10 @@
227
257
 
228
258
  <custom-element name="ui-dialog-header" slot="header">
229
259
  <style>
260
+ :host,
261
+ * {
262
+ touch-action: manipulation;
263
+ }
230
264
  :host {
231
265
  display: grid;
232
266
  gap: calc(var(--spacing) * 2);
@@ -238,6 +272,10 @@
238
272
 
239
273
  <custom-element name="ui-dialog-title">
240
274
  <style>
275
+ :host,
276
+ * {
277
+ touch-action: manipulation;
278
+ }
241
279
  :host {
242
280
  display: block;
243
281
  }
@@ -254,6 +292,10 @@
254
292
 
255
293
  <custom-element name="ui-dialog-description">
256
294
  <style>
295
+ :host,
296
+ * {
297
+ touch-action: manipulation;
298
+ }
257
299
  :host {
258
300
  display: block;
259
301
  }
@@ -269,6 +311,10 @@
269
311
 
270
312
  <custom-element name="ui-dialog-footer" slot="footer">
271
313
  <style>
314
+ :host,
315
+ * {
316
+ touch-action: manipulation;
317
+ }
272
318
  :host {
273
319
  display: flex;
274
320
  flex-wrap: wrap;
@@ -8,6 +8,12 @@
8
8
  </script>
9
9
 
10
10
  <style>
11
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
12
+ touch-action does not reach shadow content in iOS Safari. */
13
+ :host,
14
+ * {
15
+ touch-action: manipulation;
16
+ }
11
17
  :host {
12
18
  display: contents;
13
19
  }
@@ -64,20 +64,33 @@
64
64
  observe(() => {
65
65
  const dialog = refs.dialog;
66
66
  if (!dialog || props.open === dialog.open) return;
67
- if (props.open) dialog.showModal();
68
- else dialog.close();
67
+ if (!props.open) return dialog.close();
68
+ dialog.showModal();
69
+ // Left to the browser, focus lands on the first button (often close) with a focus ring after a
70
+ // tap, and Firefox and WebKit ignore autofocus on slotted content.
71
+ (host.querySelector("[autofocus]") ?? dialog).focus();
69
72
  });
70
73
  </script>
71
74
 
72
75
  <style>
76
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
77
+ touch-action does not reach shadow content in iOS Safari. */
78
+ :host,
79
+ * {
80
+ touch-action: manipulation;
81
+ }
73
82
  :host {
74
83
  display: contents;
75
84
  }
85
+ dialog:focus {
86
+ outline: none;
87
+ }
76
88
  dialog {
77
89
  box-sizing: border-box;
78
90
  width: 100%;
79
91
  max-width: none;
80
- max-height: 80dvh;
92
+ height: fit-content;
93
+ max-height: 80svh;
81
94
  margin: auto 0 0;
82
95
  padding: calc(var(--spacing) * 4) calc(var(--spacing) * 6) calc(var(--spacing) * 6);
83
96
  border: 1px solid var(--border);
@@ -103,9 +116,14 @@
103
116
  }
104
117
  dialog[open] {
105
118
  display: grid;
119
+ /* Safari stretches a grid overlay to its max-height unless the rows are packed at the start. */
120
+ align-content: start;
106
121
  gap: calc(var(--spacing) * 4);
107
122
  animation: slide 0.25s ease-out;
108
123
  }
124
+ [part="body"] {
125
+ display: contents;
126
+ }
109
127
  dialog::backdrop {
110
128
  background: rgb(0 0 0 / 0.5);
111
129
  }
@@ -138,6 +156,7 @@
138
156
  <dialog
139
157
  ref="dialog"
140
158
  part="dialog"
159
+ tabindex="-1"
141
160
  _aria-label="#drawer.label"
142
161
  _aria-description="#drawer.description"
143
162
  onclose="closed()"
@@ -151,6 +170,10 @@
151
170
 
152
171
  <custom-element name="ui-drawer-trigger" slot="trigger">
153
172
  <style>
173
+ :host,
174
+ * {
175
+ touch-action: manipulation;
176
+ }
154
177
  :host,
155
178
  span {
156
179
  display: contents;
@@ -162,6 +185,10 @@
162
185
 
163
186
  <custom-element name="ui-drawer-close">
164
187
  <style>
188
+ :host,
189
+ * {
190
+ touch-action: manipulation;
191
+ }
165
192
  :host,
166
193
  span {
167
194
  display: contents;
@@ -173,6 +200,10 @@
173
200
 
174
201
  <custom-element name="ui-drawer-header" slot="header">
175
202
  <style>
203
+ :host,
204
+ * {
205
+ touch-action: manipulation;
206
+ }
176
207
  :host {
177
208
  display: grid;
178
209
  gap: calc(var(--spacing) * 1.5);
@@ -184,6 +215,10 @@
184
215
 
185
216
  <custom-element name="ui-drawer-title">
186
217
  <style>
218
+ :host,
219
+ * {
220
+ touch-action: manipulation;
221
+ }
187
222
  :host {
188
223
  display: block;
189
224
  }
@@ -199,6 +234,10 @@
199
234
 
200
235
  <custom-element name="ui-drawer-description">
201
236
  <style>
237
+ :host,
238
+ * {
239
+ touch-action: manipulation;
240
+ }
202
241
  :host {
203
242
  display: block;
204
243
  }
@@ -214,6 +253,10 @@
214
253
 
215
254
  <custom-element name="ui-drawer-footer" slot="footer">
216
255
  <style>
256
+ :host,
257
+ * {
258
+ touch-action: manipulation;
259
+ }
217
260
  :host {
218
261
  display: grid;
219
262
  gap: calc(var(--spacing) * 2);
@@ -19,6 +19,12 @@
19
19
  </script>
20
20
 
21
21
  <style>
22
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
23
+ touch-action does not reach shadow content in iOS Safari. */
24
+ :host,
25
+ * {
26
+ touch-action: manipulation;
27
+ }
22
28
  :host {
23
29
  display: contents;
24
30
  }
@@ -29,6 +35,10 @@
29
35
 
30
36
  <custom-element name="ui-dropdown-menu-trigger">
31
37
  <style>
38
+ :host,
39
+ * {
40
+ touch-action: manipulation;
41
+ }
32
42
  :host {
33
43
  display: inline-block;
34
44
  vertical-align: middle;
@@ -62,6 +72,10 @@
62
72
  </script>
63
73
 
64
74
  <style>
75
+ :host,
76
+ * {
77
+ touch-action: manipulation;
78
+ }
65
79
  :host {
66
80
  box-sizing: border-box;
67
81
  min-width: calc(var(--spacing) * 32);
@@ -73,6 +87,9 @@
73
87
  color: var(--popover-foreground);
74
88
  box-shadow: var(--shadow-md);
75
89
  inset: auto;
90
+ height: fit-content;
91
+ max-height: calc(100svh - calc(var(--spacing) * 8));
92
+ overflow-y: auto;
76
93
  position-area: bottom span-right;
77
94
  position-try-fallbacks: flip-block, flip-inline;
78
95
  }
@@ -123,6 +140,10 @@
123
140
  </script>
124
141
 
125
142
  <style>
143
+ :host,
144
+ * {
145
+ touch-action: manipulation;
146
+ }
126
147
  :host {
127
148
  display: flex;
128
149
  align-items: center;
@@ -190,6 +211,10 @@
190
211
  </script>
191
212
 
192
213
  <style>
214
+ :host,
215
+ * {
216
+ touch-action: manipulation;
217
+ }
193
218
  :host {
194
219
  display: flex;
195
220
  align-items: center;
@@ -245,6 +270,10 @@
245
270
  </script>
246
271
 
247
272
  <style>
273
+ :host,
274
+ * {
275
+ touch-action: manipulation;
276
+ }
248
277
  :host {
249
278
  display: block;
250
279
  }
@@ -285,6 +314,10 @@
285
314
  </script>
286
315
 
287
316
  <style>
317
+ :host,
318
+ * {
319
+ touch-action: manipulation;
320
+ }
288
321
  :host {
289
322
  display: flex;
290
323
  align-items: center;
@@ -326,6 +359,10 @@
326
359
 
327
360
  <custom-element name="ui-menu-label">
328
361
  <style>
362
+ :host,
363
+ * {
364
+ touch-action: manipulation;
365
+ }
329
366
  :host {
330
367
  display: block;
331
368
  padding: calc(var(--spacing) * 1.5) calc(var(--spacing) * 2);
@@ -339,6 +376,10 @@
339
376
 
340
377
  <custom-element name="ui-menu-group" role="group">
341
378
  <style>
379
+ :host,
380
+ * {
381
+ touch-action: manipulation;
382
+ }
342
383
  :host {
343
384
  display: block;
344
385
  }
@@ -349,6 +390,10 @@
349
390
 
350
391
  <custom-element name="ui-menu-separator" role="separator">
351
392
  <style>
393
+ :host,
394
+ * {
395
+ touch-action: manipulation;
396
+ }
352
397
  :host {
353
398
  display: block;
354
399
  height: 1px;
@@ -360,6 +405,10 @@
360
405
 
361
406
  <custom-element name="ui-menu-shortcut">
362
407
  <style>
408
+ :host,
409
+ * {
410
+ touch-action: manipulation;
411
+ }
363
412
  :host {
364
413
  margin-inline-start: auto;
365
414
  font-size: var(--text-xs);
@@ -1,5 +1,11 @@
1
1
  <custom-element name="ui-empty">
2
2
  <style>
3
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
4
+ touch-action does not reach shadow content in iOS Safari. */
5
+ :host,
6
+ * {
7
+ touch-action: manipulation;
8
+ }
3
9
  :host {
4
10
  display: flex;
5
11
  flex-direction: column;
@@ -20,6 +26,10 @@
20
26
 
21
27
  <custom-element name="ui-empty-header">
22
28
  <style>
29
+ :host,
30
+ * {
31
+ touch-action: manipulation;
32
+ }
23
33
  :host {
24
34
  display: flex;
25
35
  flex-direction: column;
@@ -34,6 +44,10 @@
34
44
 
35
45
  <custom-element name="ui-empty-media">
36
46
  <style>
47
+ :host,
48
+ * {
49
+ touch-action: manipulation;
50
+ }
37
51
  :host {
38
52
  display: flex;
39
53
  flex-shrink: 0;
@@ -63,6 +77,10 @@
63
77
  </script>
64
78
 
65
79
  <style>
80
+ :host,
81
+ * {
82
+ touch-action: manipulation;
83
+ }
66
84
  :host {
67
85
  display: block;
68
86
  }
@@ -79,6 +97,10 @@
79
97
 
80
98
  <custom-element name="ui-empty-description">
81
99
  <style>
100
+ :host,
101
+ * {
102
+ touch-action: manipulation;
103
+ }
82
104
  :host {
83
105
  display: block;
84
106
  font-size: var(--text-sm);
@@ -91,6 +113,10 @@
91
113
 
92
114
  <custom-element name="ui-empty-content">
93
115
  <style>
116
+ :host,
117
+ * {
118
+ touch-action: manipulation;
119
+ }
94
120
  :host {
95
121
  display: flex;
96
122
  flex-direction: column;
@@ -8,6 +8,12 @@
8
8
  </script>
9
9
 
10
10
  <style>
11
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
12
+ touch-action does not reach shadow content in iOS Safari. */
13
+ :host,
14
+ * {
15
+ touch-action: manipulation;
16
+ }
11
17
  :host {
12
18
  display: flex;
13
19
  flex-direction: column;
@@ -41,6 +47,10 @@
41
47
 
42
48
  <custom-element name="ui-field-content">
43
49
  <style>
50
+ :host,
51
+ * {
52
+ touch-action: manipulation;
53
+ }
44
54
  :host {
45
55
  display: flex;
46
56
  flex: 1;
@@ -55,6 +65,10 @@
55
65
 
56
66
  <custom-element name="ui-field-description">
57
67
  <style>
68
+ :host,
69
+ * {
70
+ touch-action: manipulation;
71
+ }
58
72
  :host {
59
73
  display: block;
60
74
  font-size: var(--text-sm);
@@ -68,6 +82,10 @@
68
82
 
69
83
  <custom-element name="ui-field-group">
70
84
  <style>
85
+ :host,
86
+ * {
87
+ touch-action: manipulation;
88
+ }
71
89
  :host {
72
90
  display: flex;
73
91
  flex-direction: column;
@@ -87,6 +105,10 @@
87
105
  </script>
88
106
 
89
107
  <style>
108
+ :host,
109
+ * {
110
+ touch-action: manipulation;
111
+ }
90
112
  :host {
91
113
  display: flex;
92
114
  flex-direction: column;
@@ -103,6 +125,10 @@
103
125
 
104
126
  <custom-element name="ui-field-legend" slot="legend">
105
127
  <style>
128
+ :host,
129
+ * {
130
+ touch-action: manipulation;
131
+ }
106
132
  :host {
107
133
  display: block;
108
134
  font-size: var(--text-base);
@@ -31,6 +31,12 @@
31
31
  </script>
32
32
 
33
33
  <style>
34
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
35
+ touch-action does not reach shadow content in iOS Safari. */
36
+ :host,
37
+ * {
38
+ touch-action: manipulation;
39
+ }
34
40
  :host {
35
41
  display: contents;
36
42
  }
@@ -41,6 +47,10 @@
41
47
 
42
48
  <custom-element name="ui-hover-card-trigger">
43
49
  <style>
50
+ :host,
51
+ * {
52
+ touch-action: manipulation;
53
+ }
44
54
  :host {
45
55
  display: inline-block;
46
56
  }
@@ -59,6 +69,10 @@
59
69
  </script>
60
70
 
61
71
  <style>
72
+ :host,
73
+ * {
74
+ touch-action: manipulation;
75
+ }
62
76
  :host {
63
77
  box-sizing: border-box;
64
78
  width: calc(var(--spacing) * 64);
@@ -70,6 +84,9 @@
70
84
  color: var(--popover-foreground);
71
85
  box-shadow: var(--shadow-md);
72
86
  inset: auto;
87
+ height: fit-content;
88
+ max-height: calc(100svh - calc(var(--spacing) * 8));
89
+ overflow-y: auto;
73
90
  position-area: bottom;
74
91
  position-try-fallbacks: flip-block, flip-inline;
75
92
  }
@@ -11,6 +11,12 @@
11
11
  </script>
12
12
 
13
13
  <style>
14
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
15
+ touch-action does not reach shadow content in iOS Safari. */
16
+ :host,
17
+ * {
18
+ touch-action: manipulation;
19
+ }
14
20
  :host {
15
21
  display: flex;
16
22
  align-items: center;
@@ -38,6 +44,12 @@
38
44
  font-size: var(--text-sm);
39
45
  outline: none;
40
46
  }
47
+ /* iOS Safari zooms in on a focused field whose text is under 16px. */
48
+ @media (pointer: coarse) {
49
+ input {
50
+ font-size: var(--text-base);
51
+ }
52
+ }
41
53
  input::placeholder {
42
54
  color: var(--muted-foreground);
43
55
  }
@@ -49,6 +61,10 @@
49
61
 
50
62
  <custom-element name="ui-input-group-addon">
51
63
  <style>
64
+ :host,
65
+ * {
66
+ touch-action: manipulation;
67
+ }
52
68
  :host {
53
69
  display: flex;
54
70
  order: -1;
@@ -77,6 +77,12 @@
77
77
  </script>
78
78
 
79
79
  <style>
80
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
81
+ touch-action does not reach shadow content in iOS Safari. */
82
+ :host,
83
+ * {
84
+ touch-action: manipulation;
85
+ }
80
86
  :host {
81
87
  display: inline-flex;
82
88
  }
@@ -97,6 +103,12 @@
97
103
  text-align: center;
98
104
  outline: none;
99
105
  }
106
+ /* iOS Safari zooms in on a focused field whose text is under 16px. */
107
+ @media (pointer: coarse) {
108
+ input {
109
+ font-size: var(--text-base);
110
+ }
111
+ }
100
112
  input:first-child,
101
113
  input[data-gap] {
102
114
  margin-left: 0;