@carissa-io/theme-default 0.3.12 → 0.3.14

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/DESIGN.md CHANGED
@@ -270,6 +270,16 @@ The close button is a plain "x" in `--c-muted`, `--c-text` on hover, with the us
270
270
  components, and it is the same in both modes (it dims whatever mode the page is in). The box fades in and rises 0.5rem in `$transition-duration`; with reduced motion it
271
271
  just appears.
272
272
 
273
+ **Scroll edges (Modal and Drawer).** The body scrolls between the header and the footer, so a long body used to be cut flush against the title and the buttons with nothing
274
+ to show where the scroll area ends. The theme draws that edge: a **1px `--c-disabled-border` line** under the header and over the footer (the footer line exists only
275
+ when there is a footer), plus a fixed 0.5rem gap between each line and the header or footer content (the components' default, left as it is). The line is the quiet
276
+ neutral border, not `--c-muted` (the Divider's 5.74:1 line would compete with the content and with the box border): on `--c-background` it is **1.48:1 in light**
277
+ (`#d4d4d4` on `#fff`) and **1.91:1 in dark** (`#404040` on `#0a0a0a`). It is a decorative separator (the scroll position and the content are exposed by the scrollable region
278
+ itself), so the 3:1 non-text minimum does not apply; the test only requires it to be distinguishable from the background (above 1.1:1) and records the two ratios,
279
+ in the same spirit as the Progress track (a faint guide, 1.3:1). It is a custom property, so dark mode needs no extra rule. The unscrolled layout is the same as before:
280
+ the header keeps 1.25rem above and 0.5rem below its content, and the body keeps the remaining 0.75rem (1.25rem less the 0.5rem gap) on each side, so the distance
281
+ between the title and the content is still 1.25rem, now with the line inside it; a body without a header or without a footer keeps the whole 1.25rem on that side.
282
+
273
283
  ## Toast
274
284
  From [components-toast](components/components-toast): the fixed region of toasts (24rem wide, 1rem from the edges, 0.75rem between toasts, above the page content) and its six
275
285
  placements. The look of each toast is the Alert's (see above), so its colors, roles and contrast are the Alert's in both modes. The action is a bold, underlined
@@ -359,6 +369,7 @@ and `--c-text` for the current page (`aria-current="page"`). The content collaps
359
369
  From [components-drawer](components/components-drawer): `Drawer`, the Modal's box as a panel on an edge of the screen (`start`, `end`, `top`, `bottom`; `sm` 20rem, `md` 28rem, `lg` 40rem). It is `--c-background` with `--c-text` (17.93:1 / 18.16:1), a 1px `--c-muted` border
360
370
  (the edge that still reads in dark), square, with the Modal's layered shadow and the same padding (1.5rem by 1.25rem) and close button (`--c-muted`, `--c-text` on hover). The **backdrop** is `rgb(0 0 0 / 0.5)` in both modes, with the shadow the only literal color of the block.
361
371
  The panel slides in over `$transition-duration`; with reduced motion it just appears.
372
+ The header and footer lines and the 0.5rem gaps are the Modal's (see [Modal](#modal), scroll edges): 1px `--c-disabled-border`, 1.48:1 light and 1.91:1 dark on `--c-background`.
362
373
 
363
374
  ## Menu
364
375
  From [components-menu](components/components-menu): `Menu`, `MenuItem`, `MenuSeparator` and `MenuLabel`. The panel is the Popover's (`--c-background`, a 1px `--c-muted` border, flat). Items are `--c-text` with 0.625rem of block and 0.75rem of side padding, and hover and keyboard focus share a `--c-surface-active`
@@ -428,6 +439,18 @@ From [components-faq](components/components-faq): `Faq`. It is the Accordion (th
428
439
  ## Carousel
429
440
  From [components-carousel](components/components-carousel): `Carousel`. The arrows and the pause / play button are the secondary button's: square, 2.75rem, a 1px `--c-muted` border (5.74:1 / 7.85:1 on the background), a `--c-surface-active` hover and a `--c-text` glyph (17.93:1 / 18.16:1; 14.23:1 / 13.88:1 on the hover). The glyphs (corner, bars, triangle) are drawn with borders in `currentColor`, so they follow the mode and need no new colour. Disabled arrows are at half opacity (exempt). The dots are 0.625rem circles in `--c-muted` (5.74:1 / 7.85:1 on the background, 5.27:1 / 7.11:1 on `--c-surface`, above the 3:1 minimum for graphics) and the current one is `--c-primary` (21:1 / 19.8:1) and 1.5rem long. Colour is not the only cue: the current dot is a bar against circles, and it also carries `aria-current`; the lightness gap between the two colours is 3.66:1 in light and 2.52:1 in dark (below 3:1 there, which the shape makes up for). The keyboard ring is the theme's 1px `--c-focus` outline offset by 2px (21:1 / 19.8:1). Transitions run at 0.2s and stop under `prefers-reduced-motion`.
430
441
 
442
+ ## Visually hidden
443
+ From [components-visually-hidden](components/components-visually-hidden): `VisuallyHidden`. The hidden state is the clip pattern and has no look. The revealed state (`focusable`, a skip link) is `--c-text` on `--c-background` (17.93:1 / 18.16:1) with a 0.75rem 1rem padding at the top-left corner; it is only shown while it has keyboard focus, so the browser's focus indicator still marks it and the pair stays well above 4.5:1 in both modes. No new colour.
444
+
445
+ ## Live region
446
+ From [components-live-region](components/components-live-region): `LiveRegion`. Hidden regions have no look (they are announced, not seen). The visible variant is a square box: `--c-text` on `--c-surface` (16.44:1 / 16.44:1) with a 1px `--c-muted` border (5.27:1 / 7.11:1 on the surface, above the 3:1 non-text minimum), 0.75rem 1rem padding; an empty region takes no space.
447
+
448
+ ## Theme switch
449
+ From [components-theme-switch](components/components-theme-switch): `ThemeSwitch`. A segmented control built like the stepper and tabs: square, a 1px `--c-muted` border (5.74:1 / 7.85:1 on the background) and 2.75rem options with 1.25rem icons (`currentColor`, so `--c-text` at 17.93:1 / 18.16:1 on the background). The current option is filled `--c-primary` with an `--c-on-primary` icon (21:1 / 21:1) and a 2px `--c-on-primary` underline, so it is told apart by shape as well as by colour; it also carries `aria-checked`. Hover is a `--c-surface-active` fill (`--c-text` 14.23:1 / 13.88:1). The keyboard ring is the theme's 1px `--c-focus` outline offset by 2px (21:1 / 19.8:1 on the background). The text labels stay visually hidden (the icons are the visible cue). The `cycle` variant is one bordered button of the same height showing the current mode icon (`--c-text` on `--c-background`, same hover and ring).
450
+
451
+ ## Icon
452
+ From [components-icon](components/components-icon): `Icon`. No colour of its own: the stroke is `currentColor`, so an icon has the contrast of the text it sits in (17.93:1 / 18.16:1 for `--c-text`, 5.74:1 / 7.85:1 for `--c-muted`, both above the 3:1 non-text minimum). Sizes are pinned in rem (1, 1.25, 1.5 and 2rem) so they do not drift with the font size around them. A decorative icon is `aria-hidden`; a lone one needs a `label`.
453
+
431
454
  ## Keyboard focus (all controls)
432
455
  One rule keeps the controls coherent: **an outlined control thickens its own border from 1px to 2px, black** (text fields,
433
456
  select, combobox, date picker, textarea, upload, empty checkbox, off switch, radio, secondary and ghost buttons); **a filled
package/README.md CHANGED
@@ -142,7 +142,7 @@ it: check the names against the theme's `scss/_tokens.scss` before you switch.
142
142
 
143
143
  ## What it configures
144
144
  `components-input`, `-button`, `-checkbox`, `-switch`, `-radio-group`, `-slider`, `-popover`, `-listbox`, `-select`,
145
- `-combobox`, `-upload`, `-calendar`, `-date-picker`, `-search`, `-typography`, `-card`, `-alert`, `-spinner`, `-modal`, `-toast`, `-divider`, `-badge`, `-tag`, `-link`, `-avatar`, `-skeleton`, `-progress`, `-tooltip`, `-prose`, `-tabs`, `-accordion`, `-breadcrumb`, `-pagination`, `-stepper`, `-sidebar`, `-navbar`, `-drawer`, `-menu`, `-table`, `-list`, `-description-list`, `-stat`, `-empty-state`, `-timeline`, `-tree`, `-code`, `-field`, `-number-input`, `-otp-input`, `-phone`, `-tag-input`, `-time-picker`, `-date-range`, `-rating`, `-color-picker`, `-async-autocomplete`, `-section`, `-faq` and `-carousel`. `components-email`, `-password`, `-url` and `-textarea`
145
+ `-combobox`, `-upload`, `-calendar`, `-date-picker`, `-search`, `-typography`, `-card`, `-alert`, `-spinner`, `-modal`, `-toast`, `-divider`, `-badge`, `-tag`, `-link`, `-avatar`, `-skeleton`, `-progress`, `-tooltip`, `-prose`, `-tabs`, `-accordion`, `-breadcrumb`, `-pagination`, `-stepper`, `-sidebar`, `-navbar`, `-drawer`, `-menu`, `-table`, `-list`, `-description-list`, `-stat`, `-empty-state`, `-timeline`, `-tree`, `-code`, `-field`, `-number-input`, `-otp-input`, `-phone`, `-tag-input`, `-time-picker`, `-date-range`, `-rating`, `-color-picker`, `-async-autocomplete`, `-section`, `-faq`, `-carousel`, `-visually-hidden`, `-live-region`, `-theme-switch` and `-icon`. `components-email`, `-password`, `-url` and `-textarea`
146
146
  are styled through the input.
147
147
 
148
148
  The checkbox's mixed state (`indeterminate`, from the next `components-checkbox` release, class `c-checkbox--indeterminate`) is the checked box with a 10px dash in `--c-on-primary`; on an older checkbox the rule is simply unused.
package/dist/index.css CHANGED
@@ -1651,7 +1651,8 @@
1651
1651
  gap: 1rem;
1652
1652
  align-items: flex-start;
1653
1653
  justify-content: space-between;
1654
- padding: 1.25rem 1.5rem 0;
1654
+ padding: 1.25rem 1.5rem 0.5rem;
1655
+ border-bottom: 1px solid var(--c-disabled-border);
1655
1656
  }
1656
1657
 
1657
1658
  .c-modal__heading {
@@ -1692,9 +1693,17 @@
1692
1693
  .c-modal__body {
1693
1694
  flex: 1 1 auto;
1694
1695
  min-height: 0;
1695
- padding: 1.25rem 1.5rem;
1696
+ padding-inline: 1.5rem;
1697
+ padding-top: max(0px, 1.25rem - 0.5rem);
1698
+ padding-bottom: max(0px, 1.25rem - 0.5rem);
1696
1699
  overflow-y: auto;
1697
1700
  }
1701
+ .c-modal__body:first-child {
1702
+ padding-top: 1.25rem;
1703
+ }
1704
+ .c-modal__body:last-child {
1705
+ padding-bottom: 1.25rem;
1706
+ }
1698
1707
 
1699
1708
  .c-modal__footer {
1700
1709
  display: flex;
@@ -1702,7 +1711,8 @@
1702
1711
  flex-wrap: wrap;
1703
1712
  gap: 1rem;
1704
1713
  justify-content: flex-end;
1705
- padding: 0 1.5rem 1.25rem;
1714
+ padding: 0.5rem 1.5rem 1.25rem;
1715
+ border-top: 1px solid var(--c-disabled-border);
1706
1716
  }
1707
1717
 
1708
1718
  @keyframes c-toast-enter {
@@ -3563,7 +3573,8 @@ hr.c-divider {
3563
3573
  gap: 1rem;
3564
3574
  align-items: flex-start;
3565
3575
  justify-content: space-between;
3566
- padding: 1.25rem 1.5rem 0;
3576
+ padding: 1.25rem 1.5rem 0.5rem;
3577
+ border-bottom: 1px solid var(--c-disabled-border);
3567
3578
  }
3568
3579
 
3569
3580
  .c-drawer__heading {
@@ -3604,9 +3615,17 @@ hr.c-divider {
3604
3615
  .c-drawer__body {
3605
3616
  flex: 1 1 auto;
3606
3617
  min-height: 0;
3607
- padding: 1.25rem 1.5rem;
3618
+ padding-inline: 1.5rem;
3619
+ padding-top: max(0px, 1.25rem - 0.5rem);
3620
+ padding-bottom: max(0px, 1.25rem - 0.5rem);
3608
3621
  overflow-y: auto;
3609
3622
  }
3623
+ .c-drawer__body:first-child {
3624
+ padding-top: 1.25rem;
3625
+ }
3626
+ .c-drawer__body:last-child {
3627
+ padding-bottom: 1.25rem;
3628
+ }
3610
3629
 
3611
3630
  .c-drawer__footer {
3612
3631
  display: flex;
@@ -3614,7 +3633,8 @@ hr.c-divider {
3614
3633
  flex-wrap: wrap;
3615
3634
  gap: 1rem;
3616
3635
  justify-content: flex-end;
3617
- padding: 0 1.5rem 1.25rem;
3636
+ padding: 0.5rem 1.5rem 1.25rem;
3637
+ border-top: 1px solid var(--c-disabled-border);
3618
3638
  }
3619
3639
 
3620
3640
  .c-menu {
@@ -5282,3 +5302,157 @@ ol.c-list {
5282
5302
  transition: none;
5283
5303
  }
5284
5304
  }
5305
+ .c-visually-hidden {
5306
+ position: absolute;
5307
+ width: 1px;
5308
+ height: 1px;
5309
+ padding: 0;
5310
+ margin: -1px;
5311
+ overflow: hidden;
5312
+ white-space: nowrap;
5313
+ border: 0;
5314
+ clip-path: inset(50%);
5315
+ }
5316
+
5317
+ .c-visually-hidden--focusable:focus,
5318
+ .c-visually-hidden--focusable:focus-within {
5319
+ position: fixed;
5320
+ top: 0.5rem;
5321
+ left: 0.5rem;
5322
+ z-index: 1000;
5323
+ width: auto;
5324
+ height: auto;
5325
+ padding: 0.75rem 1rem;
5326
+ margin: 0;
5327
+ overflow: visible;
5328
+ color: var(--c-text);
5329
+ white-space: normal;
5330
+ background: var(--c-background);
5331
+ clip-path: none;
5332
+ }
5333
+
5334
+ .c-live-region--hidden {
5335
+ position: absolute;
5336
+ width: 1px;
5337
+ height: 1px;
5338
+ padding: 0;
5339
+ margin: -1px;
5340
+ overflow: hidden;
5341
+ white-space: nowrap;
5342
+ border: 0;
5343
+ clip-path: inset(50%);
5344
+ }
5345
+
5346
+ .c-live-region:not(.c-live-region--hidden) {
5347
+ padding: 0.75rem 1rem;
5348
+ color: var(--c-text);
5349
+ background: var(--c-surface);
5350
+ border: 1px solid var(--c-muted);
5351
+ border-radius: 0;
5352
+ }
5353
+ .c-live-region:not(.c-live-region--hidden):empty {
5354
+ display: none;
5355
+ }
5356
+
5357
+ .c-theme-switch {
5358
+ box-sizing: border-box;
5359
+ display: inline-flex;
5360
+ align-items: center;
5361
+ gap: 0;
5362
+ padding: 0;
5363
+ color: var(--c-text);
5364
+ vertical-align: middle;
5365
+ background: var(--c-background);
5366
+ border: 1px solid var(--c-muted);
5367
+ border-radius: 0;
5368
+ }
5369
+
5370
+ .c-theme-switch__option,
5371
+ button.c-theme-switch {
5372
+ font: inherit;
5373
+ color: inherit;
5374
+ cursor: pointer;
5375
+ background: transparent;
5376
+ border: 0;
5377
+ transition: background-color 0.2s;
5378
+ }
5379
+ @media (prefers-reduced-motion: reduce) {
5380
+ .c-theme-switch__option,
5381
+ button.c-theme-switch {
5382
+ transition: none;
5383
+ }
5384
+ }
5385
+ .c-theme-switch__option:hover,
5386
+ button.c-theme-switch:hover {
5387
+ background: var(--c-surface-active);
5388
+ }
5389
+ .c-theme-switch__option:focus-visible,
5390
+ button.c-theme-switch:focus-visible {
5391
+ outline: 1px solid var(--c-focus);
5392
+ outline-offset: 2px;
5393
+ }
5394
+
5395
+ .c-theme-switch__option {
5396
+ display: inline-flex;
5397
+ align-items: center;
5398
+ gap: 0.5rem;
5399
+ padding: 0.75rem 0.875rem;
5400
+ border-radius: 0;
5401
+ }
5402
+
5403
+ .c-theme-switch__option--current,
5404
+ .c-theme-switch__option--current:hover {
5405
+ color: var(--c-on-primary);
5406
+ background: var(--c-primary);
5407
+ box-shadow: inset 0 -2px 0 var(--c-on-primary);
5408
+ }
5409
+
5410
+ .c-theme-switch--cycle {
5411
+ padding: 0.75rem 0.875rem;
5412
+ }
5413
+
5414
+ .c-theme-switch__icon {
5415
+ display: inline-flex;
5416
+ flex: none;
5417
+ width: 1.25rem;
5418
+ height: 1.25rem;
5419
+ }
5420
+
5421
+ .c-theme-switch__label {
5422
+ position: absolute;
5423
+ width: 1px;
5424
+ height: 1px;
5425
+ padding: 0;
5426
+ margin: -1px;
5427
+ overflow: hidden;
5428
+ white-space: nowrap;
5429
+ border: 0;
5430
+ clip-path: inset(50%);
5431
+ }
5432
+
5433
+ .c-icon {
5434
+ flex-shrink: 0;
5435
+ width: 1.25rem;
5436
+ height: 1.25rem;
5437
+ vertical-align: -0.2em;
5438
+ }
5439
+
5440
+ .c-icon--sm {
5441
+ width: 1rem;
5442
+ height: 1rem;
5443
+ }
5444
+
5445
+ .c-icon--md {
5446
+ width: 1.25rem;
5447
+ height: 1.25rem;
5448
+ }
5449
+
5450
+ .c-icon--lg {
5451
+ width: 1.5rem;
5452
+ height: 1.5rem;
5453
+ }
5454
+
5455
+ .c-icon--xl {
5456
+ width: 2rem;
5457
+ height: 2rem;
5458
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carissa-io/theme-default",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "Carissa UI: the default theme (Swiss minimalism) as SCSS variable overrides of the Carissa components, with a compiled CSS build",
5
5
  "type": "module",
6
6
  "style": "dist/index.css",
@@ -56,7 +56,7 @@
56
56
  "@carissa-io/components-card": "^0.1.0",
57
57
  "@carissa-io/components-alert": "^0.1.0",
58
58
  "@carissa-io/components-spinner": "^0.1.0",
59
- "@carissa-io/components-modal": "^0.1.0",
59
+ "@carissa-io/components-modal": "^0.1.2",
60
60
  "@carissa-io/components-toast": "^0.1.0",
61
61
  "@carissa-io/components-divider": "^0.1.0",
62
62
  "@carissa-io/components-badge": "^0.1.0",
@@ -74,7 +74,7 @@
74
74
  "@carissa-io/components-stepper": "^0.1.0",
75
75
  "@carissa-io/components-sidebar": "^0.1.0",
76
76
  "@carissa-io/components-navbar": "^0.1.0",
77
- "@carissa-io/components-drawer": "^0.1.0",
77
+ "@carissa-io/components-drawer": "^0.1.2",
78
78
  "@carissa-io/components-menu": "^0.1.0",
79
79
  "@carissa-io/components-table": "^0.1.0",
80
80
  "@carissa-io/components-list": "^0.1.0",
@@ -96,7 +96,11 @@
96
96
  "@carissa-io/components-async-autocomplete": "^0.1.0",
97
97
  "@carissa-io/components-section": "^0.1.0",
98
98
  "@carissa-io/components-faq": "^0.1.0",
99
- "@carissa-io/components-carousel": "^0.1.0"
99
+ "@carissa-io/components-carousel": "^0.1.0",
100
+ "@carissa-io/components-visually-hidden": "^0.1.0",
101
+ "@carissa-io/components-live-region": "^0.1.0",
102
+ "@carissa-io/components-theme-switch": "^0.1.0",
103
+ "@carissa-io/components-icon": "^0.1.0"
100
104
  },
101
105
  "peerDependenciesMeta": {
102
106
  "@carissa-io/components-input": {
@@ -287,6 +291,18 @@
287
291
  },
288
292
  "@carissa-io/components-carousel": {
289
293
  "optional": true
294
+ },
295
+ "@carissa-io/components-visually-hidden": {
296
+ "optional": true
297
+ },
298
+ "@carissa-io/components-live-region": {
299
+ "optional": true
300
+ },
301
+ "@carissa-io/components-theme-switch": {
302
+ "optional": true
303
+ },
304
+ "@carissa-io/components-icon": {
305
+ "optional": true
290
306
  }
291
307
  },
292
308
  "devDependencies": {
@@ -308,16 +324,18 @@
308
324
  "@carissa-io/components-date-range": "^0.1.0",
309
325
  "@carissa-io/components-description-list": "^0.1.0",
310
326
  "@carissa-io/components-divider": "^0.1.0",
311
- "@carissa-io/components-drawer": "^0.1.0",
327
+ "@carissa-io/components-drawer": "^0.1.2",
312
328
  "@carissa-io/components-empty-state": "^0.1.0",
313
329
  "@carissa-io/components-faq": "^0.1.0",
314
330
  "@carissa-io/components-field": "^0.1.0",
331
+ "@carissa-io/components-icon": "^0.1.0",
315
332
  "@carissa-io/components-input": "^0.2.1",
316
333
  "@carissa-io/components-link": "^0.1.0",
317
334
  "@carissa-io/components-list": "^0.1.0",
318
335
  "@carissa-io/components-listbox": "^0.1.1",
336
+ "@carissa-io/components-live-region": "^0.1.0",
319
337
  "@carissa-io/components-menu": "^0.1.0",
320
- "@carissa-io/components-modal": "^0.1.0",
338
+ "@carissa-io/components-modal": "^0.1.2",
321
339
  "@carissa-io/components-navbar": "^0.1.0",
322
340
  "@carissa-io/components-number-input": "^0.1.0",
323
341
  "@carissa-io/components-otp-input": "^0.1.0",
@@ -342,6 +360,7 @@
342
360
  "@carissa-io/components-tabs": "^0.1.0",
343
361
  "@carissa-io/components-tag": "^0.1.0",
344
362
  "@carissa-io/components-tag-input": "^0.1.0",
363
+ "@carissa-io/components-theme-switch": "^0.1.0",
345
364
  "@carissa-io/components-time-picker": "^0.1.0",
346
365
  "@carissa-io/components-timeline": "^0.1.0",
347
366
  "@carissa-io/components-toast": "^0.1.0",
@@ -349,6 +368,7 @@
349
368
  "@carissa-io/components-tree": "^0.1.0",
350
369
  "@carissa-io/components-typography": "^0.1.0",
351
370
  "@carissa-io/components-upload": "^0.1.1",
371
+ "@carissa-io/components-visually-hidden": "^0.1.0",
352
372
  "sass-embedded": "^1.105.1",
353
373
  "vitest": "^4.1.11"
354
374
  },
package/scss/index.scss CHANGED
@@ -655,7 +655,8 @@
655
655
  // Modal: a box on the page background with a 1px muted border (the edge that still reads in dark, where a shadow is almost
656
656
  // invisible), the theme radius, and the same 1.5rem / 1.25rem padding as Card. The backdrop is the one literal color: black
657
657
  // at 50%, the same in both modes. Its index forwards the typography styles, already loaded and configured above, so this
658
- // block goes after the Typography one (and after Card, which forwards it too).
658
+ // block goes after the Typography one (and after Card, which forwards it too). The scroll edges: a 1px --c-disabled-border line
659
+ // under the header and over the footer (the clip edge of the scrolling body), with the component's default 0.5rem gaps.
659
660
  @use '@carissa-io/components-modal/scss' as modal with (
660
661
  $c-modal-background: $var-background,
661
662
  $c-modal-color: $var-text,
@@ -666,6 +667,10 @@
666
667
  $c-modal-padding-x: 1.5rem,
667
668
  $c-modal-padding-y: 1.25rem,
668
669
  $c-modal-gap: 1rem,
670
+ $c-modal-header-divider-width: 1px,
671
+ $c-modal-header-divider-color: $var-disabled-border,
672
+ $c-modal-footer-divider-width: 1px,
673
+ $c-modal-footer-divider-color: $var-disabled-border,
669
674
  $c-modal-margin: 1rem,
670
675
  $c-modal-width-sm: 24rem,
671
676
  $c-modal-width-md: 32rem,
@@ -1141,7 +1146,7 @@
1141
1146
  // Drawer: the Modal's box as a panel on the edge: --c-background with --c-text, a 1px --c-muted border (the edge that still
1142
1147
  // reads in dark), the same padding and the same close button. The backdrop is the one literal color, black at 50% in both
1143
1148
  // modes, and so is the shadow. Its index forwards the typography styles, already loaded and configured above: this block
1144
- // goes after the Typography one.
1149
+ // goes after the Typography one. The scroll edges are the Modal's: 1px --c-disabled-border lines, default 0.5rem gaps.
1145
1150
  @use '@carissa-io/components-drawer/scss' as drawer with (
1146
1151
  $c-drawer-background: $var-background,
1147
1152
  $c-drawer-color: $var-text,
@@ -1152,6 +1157,10 @@
1152
1157
  $c-drawer-padding-x: 1.5rem,
1153
1158
  $c-drawer-padding-y: 1.25rem,
1154
1159
  $c-drawer-gap: 1rem,
1160
+ $c-drawer-header-divider-width: 1px,
1161
+ $c-drawer-header-divider-color: $var-disabled-border,
1162
+ $c-drawer-footer-divider-width: 1px,
1163
+ $c-drawer-footer-divider-color: $var-disabled-border,
1155
1164
  $c-drawer-size-sm: 20rem,
1156
1165
  $c-drawer-size-md: 28rem,
1157
1166
  $c-drawer-size-lg: 40rem,
@@ -1660,3 +1669,59 @@
1660
1669
  $c-carousel-focus-outline: $focus-width solid $var-focus,
1661
1670
  $c-carousel-focus-outline-offset: 2px
1662
1671
  );
1672
+
1673
+ // Visually hidden: the hidden state is the clip pattern and has no look. The revealed (focusable) state, a skip link, is
1674
+ // --c-text on --c-background (17.93:1 / 18.16:1) with comfortable padding; the browser's focus ring still marks it. No
1675
+ // component stylesheet is forwarded here, so the order does not matter.
1676
+ @use '@carissa-io/components-visually-hidden/scss' as visually-hidden with (
1677
+ $c-visually-hidden-focus-top: 0.5rem,
1678
+ $c-visually-hidden-focus-left: 0.5rem,
1679
+ $c-visually-hidden-focus-padding: 0.75rem 1rem,
1680
+ $c-visually-hidden-focus-background: $var-background,
1681
+ $c-visually-hidden-focus-color: $var-text
1682
+ );
1683
+
1684
+ // Live region: only the visible variant has a look, a square box like the theme's alerts and cards: --c-text on
1685
+ // --c-surface (16.44:1 / 16.44:1) with a 1px --c-muted border (5.27:1 / 7.11:1 on the surface, above the 3:1 minimum). An empty
1686
+ // region takes no space (the component hides it).
1687
+ @use '@carissa-io/components-live-region/scss' as live-region with (
1688
+ $c-live-region-visible-padding: 0.75rem 1rem,
1689
+ $c-live-region-visible-radius: $radius,
1690
+ $c-live-region-visible-color: $var-text,
1691
+ $c-live-region-visible-background: $var-surface,
1692
+ $c-live-region-visible-border: 1px solid $var-muted
1693
+ );
1694
+
1695
+ // Theme switch: a segmented control like the stepper and tabs: a square box with a 1px --c-muted border (5.74:1 / 7.85:1 on the
1696
+ // background) and 2.75rem options. The current option is filled --c-primary with --c-on-primary (21:1 / 21:1) and a 2px
1697
+ // --c-on-primary underline, so it is told apart by shape as well as by colour. Hover is --c-surface-active (--c-text 14.23:1 /
1698
+ // 13.88:1) and the keyboard ring is the theme's 1px --c-focus outline offset by 2px (21:1 / 19.8:1). The labels stay visually hidden.
1699
+ @use '@carissa-io/components-theme-switch/scss' as theme-switch with (
1700
+ $c-theme-switch-gap: 0,
1701
+ $c-theme-switch-padding: 0,
1702
+ $c-theme-switch-radius: $radius,
1703
+ $c-theme-switch-option-radius: $radius,
1704
+ $c-theme-switch-icon-size: 1.25rem,
1705
+ $c-theme-switch-option-padding: 0.75rem 0.875rem,
1706
+ $c-theme-switch-option-gap: 0.5rem,
1707
+ $c-theme-switch-show-label: false,
1708
+ $c-theme-switch-color: $var-text,
1709
+ $c-theme-switch-background: $var-background,
1710
+ $c-theme-switch-border: 1px solid $var-muted,
1711
+ $c-theme-switch-hover-background: $var-surface-active,
1712
+ $c-theme-switch-current-color: $var-on-primary,
1713
+ $c-theme-switch-current-background: $var-primary,
1714
+ $c-theme-switch-current-marker: inset 0 -2px 0 $var-on-primary,
1715
+ $c-theme-switch-focus-outline: $focus-width solid $var-focus,
1716
+ $c-theme-switch-focus-offset: 2px,
1717
+ $c-theme-switch-transition: $transition-duration
1718
+ );
1719
+
1720
+ // Icon: pinned sizes (1, 1.25, 1.5 and 2rem) so a glyph does not change with the font size around it; the colour is the
1721
+ // text colour of the parent (currentColor), so it follows both modes with no colour of its own.
1722
+ @use '@carissa-io/components-icon/scss' as icon with (
1723
+ $c-icon-size-sm: 1rem,
1724
+ $c-icon-size-md: 1.25rem,
1725
+ $c-icon-size-lg: 1.5rem,
1726
+ $c-icon-size-xl: 2rem
1727
+ );