@soxa-ui/theme-base 0.0.0-stage → 0.3.0-beta.1

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 (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +399 -2
  3. package/dist/setup/index.d.ts +31 -0
  4. package/dist/setup/index.js +4 -0
  5. package/dist/setup/plugins/index.d.ts +3 -0
  6. package/dist/setup/plugins/table-head.plugin.d.ts +44 -0
  7. package/dist/setup/plugins/table-head.plugin.js +86 -0
  8. package/dist/setup/plugins/tabs-view.plugin.d.ts +32 -0
  9. package/dist/setup/plugins/tabs-view.plugin.js +100 -0
  10. package/dist/setup/plugins/toasts-front.plugin.d.ts +63 -0
  11. package/dist/setup/plugins/toasts-front.plugin.js +131 -0
  12. package/dist/setup/plugins/transitions.d.ts +43 -0
  13. package/dist/setup/plugins/transitions.js +75 -0
  14. package/package.json +55 -4
  15. package/src/anchored.css +75 -0
  16. package/src/caption.css +71 -0
  17. package/src/components/accordion.css +96 -0
  18. package/src/components/button.css +139 -0
  19. package/src/components/calendar.css +594 -0
  20. package/src/components/check-box.css +121 -0
  21. package/src/components/date-input.css +224 -0
  22. package/src/components/date-picker.css +208 -0
  23. package/src/components/dialog.css +95 -0
  24. package/src/components/drag-and-drop.css +18 -0
  25. package/src/components/drawer.css +171 -0
  26. package/src/components/field.css +440 -0
  27. package/src/components/icon.css +61 -0
  28. package/src/components/input.css +189 -0
  29. package/src/components/label.css +160 -0
  30. package/src/components/list-box.css +165 -0
  31. package/src/components/menu.css +224 -0
  32. package/src/components/number-input.css +183 -0
  33. package/src/components/pagination.css +164 -0
  34. package/src/components/popover.css +164 -0
  35. package/src/components/progress-linear.css +88 -0
  36. package/src/components/progress-spinner.css +127 -0
  37. package/src/components/radio-group.css +130 -0
  38. package/src/components/rating.css +141 -0
  39. package/src/components/scroller.css +136 -0
  40. package/src/components/select.css +233 -0
  41. package/src/components/skeleton.css +33 -0
  42. package/src/components/slider.css +482 -0
  43. package/src/components/switch.css +142 -0
  44. package/src/components/table.css +1513 -0
  45. package/src/components/tabs.css +166 -0
  46. package/src/components/tags.css +371 -0
  47. package/src/components/textarea.css +179 -0
  48. package/src/components/toasts.css +447 -0
  49. package/src/components/tooltip.css +59 -0
  50. package/src/direction.css +30 -0
  51. package/src/disabled.css +26 -0
  52. package/src/group.css +90 -0
  53. package/src/index.css +97 -0
  54. package/src/modal.css +183 -0
  55. package/src/place.css +30 -0
  56. package/src/required.css +40 -0
  57. package/src/reset.css +172 -0
  58. package/src/swipe.css +71 -0
  59. package/src/target.css +46 -0
  60. package/theme-contract.json +3373 -0
  61. package/theme-variables.json +336 -0
@@ -0,0 +1,594 @@
1
+ /* ─── Calendar ────────────────────────────────────────────────
2
+ * The grids of the shown months, one pair of paging buttons for all of them
3
+ * and the footer, if one is passed.
4
+ *
5
+ * .so-calendar root — a column: the row of months and the footer
6
+ * .so-calendar__months the row of months
7
+ * .so-calendar__month a month, one per grid
8
+ * .so-calendar__heading heading row — root of the picker Popover
9
+ * .so-calendar__title month title — a button, trigger of the picker
10
+ * .so-calendar__title-text text: the grid name and the live region
11
+ * .so-calendar__prev "back" button (Button) — first month only
12
+ * .so-calendar__next "forward" button (Button) — same place
13
+ * .so-calendar__grid the grid — `table`
14
+ * .so-calendar__weekdays row of weekdays (`thead > tr`)
15
+ * .so-calendar__weekday a weekday (`th`)
16
+ * .so-calendar__week a week (`tbody > tr`)
17
+ * .so-calendar__filler filler — a day of the adjacent month (`td`)
18
+ * .so-calendar-item a day — Calendar.Item (`td`)
19
+ * __day day tile: the number or the slot content
20
+ * .so-calendar__footer footer — row of actions under the grids, if passed
21
+ *
22
+ * Geometry is one variable per size, the side of the day tile
23
+ * (`--so-calendar-day`): the height of Button of the same size (`button.css`)
24
+ * — the paging buttons stand in the heading row level with the tiles of the
25
+ * outer columns and are square with the same side. The cell is wider than the
26
+ * tile by a bleed for the focus ring on every side (`--so-calendar-bleed`):
27
+ * the ring of a day fits its cell and does not lie on its neighbours, and the
28
+ * ring of a paging button fits the calendar box, so a scrolling panel around
29
+ * it does not clip it. The column (`--so-calendar-column`) is the cell, but
30
+ * not narrower than two and a half label fonts: on large sizes the labels
31
+ * outgrow the cell, and the calendar widens instead of clipping them; the
32
+ * tile stays centred in a wider column, `--so-calendar-inset` from its edge.
33
+ * Everything else counts from the cell and the column: the weekday row, the
34
+ * month height, the gap between months (half a cell), the place of the
35
+ * paging buttons, the footer edges. Slot content larger than the tile gets
36
+ * its size from the consumer — through the same variable on the calendar.
37
+ *
38
+ * The root is a column: the row of months, the footer below. The width
39
+ * follows the months, not the container: the paging buttons stand at the end
40
+ * of the root and must land over the last columns. Months that do not fit
41
+ * the width wrap, and the first line is spread to the edges: the arrows stay
42
+ * over the last columns of the last month of the line. The footer does not
43
+ * set the width (`contain: inline-size`): buttons wider than a month wrap to
44
+ * a second line in it instead of widening the calendar.
45
+ *
46
+ * Paging buttons — one pair for the whole calendar, right at the end of the
47
+ * heading row, over the two last columns, as in the Android calendar. In the
48
+ * DOM the pair stands at the first month, right after its title (Tab goes
49
+ * title, "back", "forward", grid), so the buttons are taken out of the flow
50
+ * and placed from the end of the root: the month block and the root of the
51
+ * title popover are not positioned. A square with the tile side: the button
52
+ * holds one icon, and the Button scale padding is removed.
53
+ *
54
+ * A month keeps the height of six weeks for any month: the calendar does not
55
+ * jump when paging, and rows of neighbouring grids stay level. The month
56
+ * title is a button as high as a tile; a name longer than the row is cut with
57
+ * an ellipsis instead of wrapping — a second line would shift the grid. The
58
+ * end padding of the heading row is two cells, for the paging buttons, the
59
+ * same for all months.
60
+ *
61
+ * The grid is a table of seven columns of one cell each; the column width is
62
+ * set by the first row, and the day content does not widen it. A weekday
63
+ * label is clipped by its column without an ellipsis: on a short name an
64
+ * ellipsis would leave one letter. A day is a cell and carries focus (one Tab
65
+ * stop for all grids); the tile inside is centred in the cell, within the
66
+ * ring bleed, as a centred column: the number or whatever the consumer put in
67
+ * the slot. A selectable day gets the hand cursor; an unavailable day takes
68
+ * focus but is not selected, a disabled one takes neither.
69
+ *
70
+ * Font — the day scale (`--so-calendar-day-font-size-<size>`): the number in
71
+ * a cell is the font of the place at `normal`, 2px a size around it. The
72
+ * weekday labels and the tiles of the month and year picker take the same
73
+ * font: they stand on the place of the day grid. The month title is the
74
+ * Button font of the same size, a line as high as the cell: only a block
75
+ * keeps the ellipsis on a long name. A three-letter short weekday name fits
76
+ * the column (the `weekdayLabelWidth` rule of the core) — narrow the column
77
+ * or enlarge the labels only together with the «дни недели» check of the
78
+ * calendar browser spec.
79
+ *
80
+ * A disabled calendar fades by its root as a whole (`disabled.css`), a
81
+ * disabled day by its cell, with the tile; a day in a disabled calendar does
82
+ * not fade a second time.
83
+ *
84
+ * The month and year picker is a popover of the title inside the calendar
85
+ * (`contained`, `edge="top"`): it does not go to `body` but covers the
86
+ * calendar — its positioned ancestor — with a backdrop over the whole
87
+ * calendar, and the choice is made in a card at its top edge.
88
+ *
89
+ * .so-popover__panel popover panel — backdrop over the whole calendar
90
+ * .so-popover__handle gesture strip, if enabled (`swipe`)
91
+ * .so-popover__content layout in the backdrop — exactly the card
92
+ * .so-calendar__picker the card: the list and the header
93
+ * .so-calendar__picker-list list of months or years — ListBox
94
+ * .so-list-box__list list node: tiles in a grid
95
+ * .so-calendar__picker-header header: year and arrows (after the list in the DOM)
96
+ * .so-calendar__picker-heading year or range of years — level button
97
+ * .so-calendar__picker-prev "back" arrow (Button)
98
+ * .so-calendar__picker-next "forward" arrow (Button)
99
+ *
100
+ * The backdrop is the panel itself: it is stretched over the whole calendar,
101
+ * and a press on the backdrop is a press inside the popover, on which the
102
+ * calendar code closes the panel and returns focus to the title. The card is
103
+ * one full-width cell of the panel grid, at the top edge, as high as its
104
+ * content: the last weeks of the month show under it. The gesture strip is
105
+ * in the same cell, at the bottom edge of the card and over it: the panel is
106
+ * pressed to the top edge and is pulled from below; the card keeps a padding
107
+ * under it, and the strip does not cover the list. The header stands after
108
+ * the list in the DOM — focus lands on the list on opening — and flex order
109
+ * puts it on top. The list is 4 columns by 3 rows, cells share the card width
110
+ * evenly, a row is a quarter higher than a day cell; a tile fills its cell,
111
+ * the label is centred, wraps only between words when wider than the tile,
112
+ * and a word wider than the tile itself is cut with an ellipsis.
113
+ *
114
+ * The panel selector goes through the root of the title popover, a direct
115
+ * child of the month: a day slot may hold a foreign popover, and it lies in a
116
+ * grid cell. Between the root and the panel — a descendant, not a child: the
117
+ * adapter may keep a `contained` panel in its boxless nodes (`Teleport` in
118
+ * React). The weight is above the panel rules at an anchor and in a container
119
+ * (`anchored.css`, `components/popover.css`): they come later, and an equal
120
+ * weight would lose by order.
121
+ *
122
+ * The bleed and the font scale are variables of the document root; the
123
+ * defaults are the numbers of the oren theme, a theme sets its own on the
124
+ * document root.
125
+ *
126
+ * Look — colours of selection, hover, range band and preview, the "today"
127
+ * frame, the struck-out unavailable day, the weight of titles and labels,
128
+ * tabular figures, the focus ring, the button view, mirrored arrows in RTL,
129
+ * the forced colours view, the backdrop veil, surface, edge and shadow of the
130
+ * card, its entry, return when released and exit when swiped — is drawn by
131
+ * the theme. */
132
+
133
+ :root {
134
+ --so-calendar-bleed: 0.25rem;
135
+
136
+ /* The days are the font of the place at `normal`, and every step counts
137
+ * from it: 2px smaller at `sm`, 2px, 4px and 6px larger at `lg`, `xl` and
138
+ * `2xl` — 14 / 16 / 18 / 20 / 22px at a 16px place, 12 / 14 / 16 / 18 /
139
+ * 20px at 14px. `em` resolves where the variable is read: on the day cell,
140
+ * on the weekday labels and on the tiles of the month and year picker, each
141
+ * against a parent that takes the font of the calendar, that is of the
142
+ * place. */
143
+ --so-calendar-day-font-size-sm: calc(1em - 0.125rem);
144
+ --so-calendar-day-line-height-sm: calc(1.25 / 0.875);
145
+ --so-calendar-day-font-size-normal: 1em;
146
+ --so-calendar-day-line-height-normal: 1.5;
147
+ --so-calendar-day-font-size-lg: calc(1em + 0.125rem);
148
+ --so-calendar-day-line-height-lg: calc(1.75 / 1.125);
149
+ --so-calendar-day-font-size-xl: calc(1em + 0.25rem);
150
+ --so-calendar-day-line-height-xl: calc(1.75 / 1.25);
151
+ --so-calendar-day-font-size-2xl: calc(1em + 0.375rem);
152
+ --so-calendar-day-line-height-2xl: calc(2 / 1.375);
153
+ }
154
+
155
+ /* No modifier means `normal`: the core always writes `--size-*`, but the block
156
+ * must look like the default without it as well. The paging buttons and the
157
+ * picker count from the root. */
158
+ .so-calendar {
159
+ --so-calendar-day: var(--so-button-height-normal);
160
+ --so-calendar-cell: calc(var(--so-calendar-day) + 2 * var(--so-calendar-bleed));
161
+ --so-calendar-head: var(--so-calendar-day);
162
+ --so-calendar-column: max(
163
+ var(--so-calendar-cell),
164
+ 2.5 * var(--so-calendar-day-font-size-normal)
165
+ );
166
+ --so-calendar-inset: calc((var(--so-calendar-column) - var(--so-calendar-day)) / 2);
167
+ --so-calendar-gap: calc(var(--so-calendar-cell) / 2);
168
+ position: relative;
169
+ display: flex;
170
+ flex-direction: column;
171
+ gap: calc(2 * var(--so-calendar-bleed));
172
+ width: fit-content;
173
+ max-width: 100%;
174
+ }
175
+
176
+ .so-calendar .so-calendar__title {
177
+ line-height: var(--so-calendar-cell);
178
+ }
179
+
180
+ .so-calendar .so-calendar__weekday,
181
+ .so-calendar .so-calendar-item,
182
+ .so-calendar .so-calendar__picker-list > .so-list-box__list > .so-list-box-item > .so-button {
183
+ font-size: var(--so-calendar-day-font-size-normal);
184
+ line-height: var(--so-calendar-day-line-height-normal);
185
+ }
186
+
187
+ .so-calendar--size-sm {
188
+ --so-calendar-day: var(--so-button-height-sm);
189
+ --so-calendar-column: max(var(--so-calendar-cell), 2.5 * var(--so-calendar-day-font-size-sm));
190
+ }
191
+
192
+ .so-calendar--size-sm .so-calendar__title {
193
+ font-size: var(--so-button-font-size-sm);
194
+ line-height: var(--so-calendar-cell);
195
+ }
196
+
197
+ .so-calendar--size-sm .so-calendar__weekday,
198
+ .so-calendar--size-sm .so-calendar-item,
199
+ .so-calendar--size-sm
200
+ .so-calendar__picker-list
201
+ > .so-list-box__list
202
+ > .so-list-box-item
203
+ > .so-button {
204
+ font-size: var(--so-calendar-day-font-size-sm);
205
+ line-height: var(--so-calendar-day-line-height-sm);
206
+ }
207
+
208
+ .so-calendar--size-normal {
209
+ --so-calendar-day: var(--so-button-height-normal);
210
+ --so-calendar-column: max(
211
+ var(--so-calendar-cell),
212
+ 2.5 * var(--so-calendar-day-font-size-normal)
213
+ );
214
+ }
215
+
216
+ .so-calendar--size-normal .so-calendar__title {
217
+ line-height: var(--so-calendar-cell);
218
+ }
219
+
220
+ .so-calendar--size-normal .so-calendar__weekday,
221
+ .so-calendar--size-normal .so-calendar-item,
222
+ .so-calendar--size-normal
223
+ .so-calendar__picker-list
224
+ > .so-list-box__list
225
+ > .so-list-box-item
226
+ > .so-button {
227
+ font-size: var(--so-calendar-day-font-size-normal);
228
+ line-height: var(--so-calendar-day-line-height-normal);
229
+ }
230
+
231
+ .so-calendar--size-lg {
232
+ --so-calendar-day: var(--so-button-height-lg);
233
+ --so-calendar-column: max(var(--so-calendar-cell), 2.5 * var(--so-calendar-day-font-size-lg));
234
+ }
235
+
236
+ .so-calendar--size-lg .so-calendar__title {
237
+ font-size: var(--so-button-font-size-lg);
238
+ line-height: var(--so-calendar-cell);
239
+ }
240
+
241
+ .so-calendar--size-lg .so-calendar__weekday,
242
+ .so-calendar--size-lg .so-calendar-item,
243
+ .so-calendar--size-lg
244
+ .so-calendar__picker-list
245
+ > .so-list-box__list
246
+ > .so-list-box-item
247
+ > .so-button {
248
+ font-size: var(--so-calendar-day-font-size-lg);
249
+ line-height: var(--so-calendar-day-line-height-lg);
250
+ }
251
+
252
+ .so-calendar--size-xl {
253
+ --so-calendar-day: var(--so-button-height-xl);
254
+ --so-calendar-column: max(var(--so-calendar-cell), 2.5 * var(--so-calendar-day-font-size-xl));
255
+ }
256
+
257
+ .so-calendar--size-xl .so-calendar__title {
258
+ font-size: var(--so-button-font-size-xl);
259
+ line-height: var(--so-calendar-cell);
260
+ }
261
+
262
+ .so-calendar--size-xl .so-calendar__weekday,
263
+ .so-calendar--size-xl .so-calendar-item,
264
+ .so-calendar--size-xl
265
+ .so-calendar__picker-list
266
+ > .so-list-box__list
267
+ > .so-list-box-item
268
+ > .so-button {
269
+ font-size: var(--so-calendar-day-font-size-xl);
270
+ line-height: var(--so-calendar-day-line-height-xl);
271
+ }
272
+
273
+ .so-calendar--size-2xl {
274
+ --so-calendar-day: var(--so-button-height-2xl);
275
+ --so-calendar-column: max(var(--so-calendar-cell), 2.5 * var(--so-calendar-day-font-size-2xl));
276
+ }
277
+
278
+ .so-calendar--size-2xl .so-calendar__title {
279
+ font-size: var(--so-button-font-size-2xl);
280
+ line-height: var(--so-calendar-cell);
281
+ }
282
+
283
+ .so-calendar--size-2xl .so-calendar__weekday,
284
+ .so-calendar--size-2xl .so-calendar-item,
285
+ .so-calendar--size-2xl
286
+ .so-calendar__picker-list
287
+ > .so-list-box__list
288
+ > .so-list-box-item
289
+ > .so-button {
290
+ font-size: var(--so-calendar-day-font-size-2xl);
291
+ line-height: var(--so-calendar-day-line-height-2xl);
292
+ }
293
+
294
+ /* A disabled calendar fades by its root as a whole — titles, weekdays, days,
295
+ * paging buttons and the footer. Days and buttons are disabled with it and do
296
+ * not fade a second time under the faded root. */
297
+ .so-calendar[data-disabled='true'] {
298
+ opacity: var(--so-disabled-opacity);
299
+ }
300
+
301
+ .so-calendar[data-disabled='true'] > * {
302
+ --so-disabled-opacity: 1;
303
+ }
304
+
305
+ /* Months — in a row, in their own node: a footer in the same row would add
306
+ * its width to the row, and the paging buttons would hang past the last
307
+ * column. While the months fit, there is no free space, and the gap between
308
+ * them is exactly `--so-calendar-gap`. */
309
+ .so-calendar__months {
310
+ display: flex;
311
+ flex-wrap: wrap;
312
+ justify-content: space-between;
313
+ gap: var(--so-calendar-gap);
314
+ }
315
+
316
+ /* "Back" — over the sixth column, "forward" — over the seventh, level with
317
+ * their tiles; two bleeds between the buttons, as between the tiles of
318
+ * neighbouring days. */
319
+ .so-calendar__prev,
320
+ .so-calendar__next {
321
+ position: absolute;
322
+ inset-block-start: var(--so-calendar-bleed);
323
+ inline-size: var(--so-calendar-day);
324
+ block-size: var(--so-calendar-day);
325
+ padding-inline: 0;
326
+ }
327
+
328
+ .so-calendar__prev {
329
+ inset-inline-end: calc(var(--so-calendar-column) + var(--so-calendar-inset));
330
+ }
331
+
332
+ .so-calendar__next {
333
+ inset-inline-end: var(--so-calendar-inset);
334
+ }
335
+
336
+ /* Weeks are pressed to the top, the room for six weeks is under the last. */
337
+ .so-calendar__month {
338
+ display: flex;
339
+ flex-direction: column;
340
+ min-block-size: calc(
341
+ var(--so-calendar-cell) + var(--so-calendar-head) + 6 * var(--so-calendar-cell)
342
+ );
343
+ }
344
+
345
+ /* The heading row is the popover root: inline in Popover, here it takes the
346
+ * whole row and puts the title button at the start of the month, level with
347
+ * the tile of the first column. It must not be positioned: the paging buttons
348
+ * and the picker stand from the calendar root. */
349
+ .so-calendar__month > .so-calendar__heading {
350
+ display: flex;
351
+ align-items: center;
352
+ justify-content: flex-start;
353
+ block-size: var(--so-calendar-cell);
354
+ padding-inline-start: var(--so-calendar-inset);
355
+ padding-inline-end: calc(2 * var(--so-calendar-column));
356
+ }
357
+
358
+ .so-calendar__title {
359
+ min-width: 0;
360
+ max-width: 100%;
361
+ block-size: var(--so-calendar-day);
362
+ }
363
+
364
+ .so-calendar__title-text {
365
+ overflow: hidden;
366
+ text-overflow: ellipsis;
367
+ white-space: nowrap;
368
+ }
369
+
370
+ .so-calendar__grid {
371
+ table-layout: fixed;
372
+ border-collapse: collapse;
373
+ inline-size: calc(7 * var(--so-calendar-column));
374
+ }
375
+
376
+ .so-calendar__weekdays {
377
+ block-size: var(--so-calendar-head);
378
+ }
379
+
380
+ .so-calendar__weekday {
381
+ padding: 0;
382
+ text-align: center;
383
+ vertical-align: middle;
384
+ overflow: hidden;
385
+ white-space: nowrap;
386
+ inline-size: var(--so-calendar-column);
387
+ }
388
+
389
+ /* The height is set on the row: a filler has no content, and without it the
390
+ * row would shrink to the days in it. */
391
+ .so-calendar__week {
392
+ block-size: var(--so-calendar-cell);
393
+ }
394
+
395
+ /* A filler only holds a place in the week: a number would repeat a date that
396
+ * stands in the neighbouring grid. */
397
+ .so-calendar__filler {
398
+ padding: 0;
399
+ }
400
+
401
+ /* The content is at the end of the line, like dialog buttons, the edges level
402
+ * with the tiles of the outer columns. */
403
+ .so-calendar__footer {
404
+ display: flex;
405
+ flex-wrap: wrap;
406
+ align-items: center;
407
+ justify-content: flex-end;
408
+ contain: inline-size;
409
+ gap: calc(2 * var(--so-calendar-bleed));
410
+ padding-inline: var(--so-calendar-inset);
411
+ }
412
+
413
+ /* The cell is positioned: the theme draws the range band on it, and the tile
414
+ * — positioned too and after it in the DOM — stands on top. */
415
+ .so-calendar-item {
416
+ position: relative;
417
+ padding: 0;
418
+ text-align: center;
419
+ vertical-align: middle;
420
+ -webkit-user-select: none;
421
+ user-select: none;
422
+ inline-size: var(--so-calendar-column);
423
+ block-size: var(--so-calendar-cell);
424
+ }
425
+
426
+ /* Not narrower and not lower than a tile; larger slot content widens the
427
+ * tile. */
428
+ .so-calendar-item__day {
429
+ position: relative;
430
+ display: flex;
431
+ flex-direction: column;
432
+ align-items: center;
433
+ justify-content: center;
434
+ margin-inline: auto;
435
+ inline-size: fit-content;
436
+ min-inline-size: var(--so-calendar-day);
437
+ min-block-size: var(--so-calendar-day);
438
+ }
439
+
440
+ .so-calendar-item:not([data-disabled='true'], [data-unavailable='true']) {
441
+ cursor: pointer;
442
+ }
443
+
444
+ .so-calendar-item[data-disabled='true'] {
445
+ opacity: var(--so-disabled-opacity);
446
+ }
447
+
448
+ .so-calendar-item[data-disabled='true'] > * {
449
+ --so-disabled-opacity: 1;
450
+ }
451
+
452
+ /* The picker covers the whole calendar instead of following its content
453
+ * height, as a panel with the `top` edge does; it has no padding of its own.
454
+ * The card and the strip are in one grid cell, at the top.
455
+ *
456
+ * The card and the strip follow the pointer while the backdrop stays: moving
457
+ * with the card, it would stick out of the calendar. The gesture plugin
458
+ * writes the offset to the panel itself (`--so-swipe-offset`), and the card
459
+ * and the strip are not layers and inherit it (`swipe.css`). */
460
+ .so-calendar__month > .so-calendar__heading .so-popover__panel[data-contained='true'] {
461
+ display: grid;
462
+ align-content: flex-start;
463
+ inset: 0;
464
+ padding: 0;
465
+ translate: none;
466
+ }
467
+
468
+ /* The layout in the backdrop is exactly the card: the full backdrop width,
469
+ * without the popover padding and without scrolling — the card fits the
470
+ * calendar at any size. */
471
+ .so-calendar__month
472
+ > .so-calendar__heading
473
+ .so-popover__panel[data-contained='true']
474
+ > .so-popover__content {
475
+ grid-area: 1 / 1;
476
+ width: auto;
477
+ padding: 0;
478
+ overflow: visible;
479
+ translate: 0 var(--so-swipe-offset);
480
+ }
481
+
482
+ /* The card keeps the rhythm of two bleeds, like neighbouring days: the
483
+ * padding, the gap between the header and the list, the gap between tiles.
484
+ * The padding also holds the focus ring of the list. */
485
+ .so-calendar__picker {
486
+ display: flex;
487
+ flex-direction: column;
488
+ gap: calc(2 * var(--so-calendar-bleed));
489
+ padding: calc(2 * var(--so-calendar-bleed));
490
+ }
491
+
492
+ /* The header is like the calendar heading row: the year or range of years at
493
+ * the start, the arrows right at the end; the logical auto margin of the year
494
+ * button takes the rest of the line. */
495
+ .so-calendar__picker-header {
496
+ display: flex;
497
+ flex-shrink: 0;
498
+ align-items: center;
499
+ order: -9999;
500
+ gap: calc(2 * var(--so-calendar-bleed));
501
+ block-size: var(--so-calendar-day);
502
+ }
503
+
504
+ .so-calendar__picker-heading {
505
+ min-width: 0;
506
+ block-size: var(--so-calendar-day);
507
+ margin-inline-end: auto;
508
+ }
509
+
510
+ .so-calendar__picker-prev,
511
+ .so-calendar__picker-next {
512
+ flex-shrink: 0;
513
+ inline-size: var(--so-calendar-day);
514
+ block-size: var(--so-calendar-day);
515
+ padding-inline: 0;
516
+ }
517
+
518
+ /* The tiles are children of the list node, not of the ListBox root: the root
519
+ * is a frame around the header, list and footer, and it only has to drop the
520
+ * padding and width of the list. */
521
+ .so-calendar__picker > .so-calendar__picker-list {
522
+ min-width: 0;
523
+ max-width: none;
524
+ padding: 0;
525
+ }
526
+
527
+ .so-calendar__picker > .so-calendar__picker-list > .so-list-box__list {
528
+ display: grid;
529
+ grid-template-columns: repeat(4, minmax(0, 1fr));
530
+ grid-template-rows: repeat(3, minmax(calc(1.25 * var(--so-calendar-cell)), 1fr));
531
+ gap: calc(2 * var(--so-calendar-bleed));
532
+ }
533
+
534
+ /* The strip is a direct child of the panel: that is how the gesture plugin
535
+ * finds it. */
536
+ .so-calendar__month
537
+ > .so-calendar__heading
538
+ .so-popover__panel[data-contained='true']
539
+ > .so-popover__handle {
540
+ position: static;
541
+ z-index: 1;
542
+ grid-area: 1 / 1;
543
+ align-self: flex-end;
544
+ translate: 0 var(--so-swipe-offset);
545
+ }
546
+
547
+ .so-calendar__month
548
+ > .so-calendar__heading
549
+ .so-popover__panel[data-contained='true']:has(> .so-popover__handle)
550
+ .so-calendar__picker {
551
+ padding-block-end: var(--so-target-size);
552
+ }
553
+
554
+ /* A tile is a row over the whole cell, not a button of its own size in the
555
+ * middle of it. The label is centred: vertically by the button, horizontally
556
+ * by the text alignment that the ListBox row keeps at the start. A tile
557
+ * picks a month or a year, a press does something at once: the hand cursor,
558
+ * the default one on a disabled tile. */
559
+ .so-calendar__picker-list > .so-list-box__list > .so-list-box-item {
560
+ display: flex;
561
+ }
562
+
563
+ .so-calendar__picker-list > .so-list-box__list > .so-list-box-item > .so-button {
564
+ flex: 1;
565
+ min-width: 0;
566
+ height: auto;
567
+ padding-inline: 0;
568
+ }
569
+
570
+ .so-calendar__picker-list
571
+ > .so-list-box__list
572
+ > .so-list-box-item
573
+ > .so-button:not([data-disabled='true']) {
574
+ cursor: pointer;
575
+ }
576
+
577
+ .so-calendar__picker-list > .so-list-box__list > .so-list-box-item > .so-button > .so-button__text {
578
+ text-align: center;
579
+ }
580
+
581
+ /* Wrapping (`data-content-fit='wrap'` of the row, set by the calendar) — only
582
+ * between words: a label of several words (`vi-VN` "Tháng 10", a `th-TH` year
583
+ * with the era) would lose its number to an ellipsis. A word wider than the
584
+ * tile has nowhere to wrap, and the text area cuts it with the button
585
+ * ellipsis on the label line that did not fit instead of letting it out, as
586
+ * a wrapping ListBox row does. */
587
+ .so-calendar__picker-list
588
+ > .so-list-box__list
589
+ > .so-list-box-item[data-content-fit='wrap']
590
+ > .so-button
591
+ > .so-button__text {
592
+ overflow: hidden;
593
+ overflow-wrap: normal;
594
+ }