@salemcobalt/ui 0.2.0-rc.14 → 0.2.0-rc.16

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/dist/styles.css CHANGED
@@ -1,4 +1,4 @@
1
- /* @salemcobalt/ui 0.2.0-rc.14 — requires @salemcobalt/tokens/css. */
1
+ /* @salemcobalt/ui 0.2.0-rc.16 — requires @salemcobalt/tokens/css. */
2
2
  @layer sc {
3
3
  /* ---- base.css ---- */
4
4
  /* Shared: focus ring, reduced motion. Component files follow. */
@@ -73,6 +73,16 @@
73
73
  line-height: var(--sc-font-line-height-tight);
74
74
  letter-spacing: var(--sc-font-tracking-tight);
75
75
  }
76
+ /* Overline: a section label. 12px uppercase mono with wide tracking; muted unless a tone is set. */
77
+ .sc-heading[data-size='overline'] {
78
+ font-family: var(--sc-font-family-mono);
79
+ font-size: var(--sc-font-size-xs);
80
+ font-weight: var(--sc-font-weight-medium);
81
+ line-height: var(--sc-font-line-height-snug);
82
+ letter-spacing: var(--sc-font-tracking-wider);
83
+ text-transform: uppercase;
84
+ text-wrap: wrap;
85
+ }
76
86
  .sc-heading[data-truncate] {
77
87
  overflow: hidden;
78
88
  text-overflow: ellipsis;
@@ -117,6 +127,9 @@
117
127
  .sc-text[data-numeric] {
118
128
  font-variant-numeric: tabular-nums;
119
129
  }
130
+ .sc-text[data-family='mono'] {
131
+ font-family: var(--sc-font-family-mono);
132
+ }
120
133
  .sc-text[data-truncate=''] {
121
134
  overflow: hidden;
122
135
  text-overflow: ellipsis;
@@ -367,6 +380,13 @@
367
380
  .sc-button[data-loading] > .sc-button__shortcut {
368
381
  opacity: 0;
369
382
  }
383
+ /* No hint where there is no fine pointer (phones, tablets without a trackpad): touch users rarely have the keys,
384
+ and the hint costs width. A tablet with a trackpad (any-pointer: fine) keeps it. `aria-keyshortcuts` stays. */
385
+ @media not all and (any-pointer: fine) {
386
+ .sc-button__shortcut {
387
+ display: none;
388
+ }
389
+ }
370
390
  @keyframes sc-spin {
371
391
  to {
372
392
  rotate: 1turn;
@@ -627,6 +647,26 @@
627
647
  border-color: var(--sc-color-accent-default);
628
648
  box-shadow: inset 0 0 0 1px var(--sc-color-accent-default);
629
649
  }
650
+ /* Plain: a quiet row. No surface or shadow; interactive hover is a wash (no border or elevation, so a long list
651
+ does not flicker); selected is the accent wash with a 1px accent border (3:1, the selection cue). */
652
+ .sc-card[data-variant='plain'] {
653
+ background: transparent;
654
+ border-color: transparent;
655
+ }
656
+ .sc-card[data-variant='plain'][data-interactive]:hover {
657
+ background: var(--sc-color-surface-hover);
658
+ border-color: transparent;
659
+ box-shadow: none;
660
+ }
661
+ .sc-card[data-variant='plain'][data-interactive]:active {
662
+ background: var(--sc-color-surface-active);
663
+ }
664
+ .sc-card[data-variant='plain'][data-selected],
665
+ .sc-card[data-variant='plain'][data-selected]:hover {
666
+ background: var(--sc-color-accent-wash);
667
+ border-color: var(--sc-color-accent-border);
668
+ box-shadow: none;
669
+ }
630
670
  @media (prefers-reduced-motion: reduce) {
631
671
  .sc-card {
632
672
  transition: none;
@@ -2032,6 +2072,37 @@
2032
2072
  .sc-priority-nav__ellipsis {
2033
2073
  display: none;
2034
2074
  }
2075
+ /* Item badge (`badge`): a count pill or a dot after the label, in accent. Decorative (aria-hidden); the link's
2076
+ name carries `badgeLabel`. "More" shows the collapsed items' badges summed. No transition or animation. */
2077
+ .sc-priority-nav__badge {
2078
+ display: inline-grid;
2079
+ place-items: center;
2080
+ flex: none;
2081
+ box-sizing: border-box;
2082
+ border-radius: var(--sc-radius-full);
2083
+ background: var(--sc-color-accent-default);
2084
+ color: var(--sc-color-text-on-accent);
2085
+ pointer-events: none;
2086
+ }
2087
+ .sc-priority-nav__badge[data-kind='count'] {
2088
+ min-inline-size: var(--sc-size-icon-md);
2089
+ block-size: var(--sc-size-icon-md);
2090
+ padding-inline: var(--sc-spacing-3xs);
2091
+ font-size: var(--sc-font-size-xs);
2092
+ font-weight: var(--sc-font-weight-semibold);
2093
+ font-variant-numeric: tabular-nums;
2094
+ line-height: 1;
2095
+ }
2096
+ .sc-priority-nav__badge[data-kind='dot'] {
2097
+ inline-size: 8px;
2098
+ block-size: 8px;
2099
+ }
2100
+ .sc-priority-nav__panel .sc-priority-nav__badge {
2101
+ margin-inline-start: auto;
2102
+ }
2103
+ .sc-priority-nav__toggle {
2104
+ position: relative;
2105
+ }
2035
2106
  @container sc-priority-nav (inline-size <= 400px) {
2036
2107
  .sc-priority-nav__toggle {
2037
2108
  justify-content: center;
@@ -2044,6 +2115,17 @@
2044
2115
  .sc-priority-nav__chevron {
2045
2116
  display: none;
2046
2117
  }
2118
+ /* Icon-only: the badge sits on the toggle's inline-end corner, ringed like IconButton's dot. */
2119
+ .sc-priority-nav__toggle > .sc-priority-nav__badge {
2120
+ position: absolute;
2121
+ inset-block-start: 0;
2122
+ inset-inline-end: 0;
2123
+ box-shadow: 0 0 0 var(--sc-border-width-focus) var(--sc-color-surface-default);
2124
+ }
2125
+ .sc-priority-nav__toggle > .sc-priority-nav__badge[data-kind='dot'] {
2126
+ inset-block-start: var(--sc-spacing-2xs);
2127
+ inset-inline-end: var(--sc-spacing-2xs);
2128
+ }
2047
2129
  /* Visually hidden, still part of the accessible name ("More, 3 links"). */
2048
2130
  .sc-priority-nav__toggle-label {
2049
2131
  position: absolute;
@@ -5296,4 +5378,283 @@
5296
5378
  }
5297
5379
  }
5298
5380
 
5381
+ /* ---- score.css ---- */
5382
+ /* ---- Score ----------------------------------------------------------------- */
5383
+ /* A number on a tinted tile, or inside a ring. Tone sets the tint (--_bg), the number (--_fg) and the solid used
5384
+ for the ring arc and the selected tile (--_solid, --_on-solid). */
5385
+ .sc-score {
5386
+ --_bg: var(--sc-color-accent-subtle);
5387
+ --_fg: var(--sc-color-accent-text);
5388
+ --_solid: var(--sc-color-accent-default);
5389
+ --_on-solid: var(--sc-color-text-on-accent);
5390
+ --_s: var(--sc-size-score-sm);
5391
+ position: relative;
5392
+ display: inline-grid;
5393
+ place-items: center;
5394
+ flex: none;
5395
+ box-sizing: border-box;
5396
+ inline-size: var(--_s);
5397
+ block-size: var(--_s);
5398
+ border-radius: var(--sc-radius-lg);
5399
+ background: var(--_bg);
5400
+ color: var(--_fg);
5401
+ font-family: var(--sc-font-family-sans);
5402
+ font-size: var(--sc-font-size-sm);
5403
+ font-weight: var(--sc-font-weight-semibold);
5404
+ font-variant-numeric: tabular-nums;
5405
+ line-height: 1;
5406
+ vertical-align: middle;
5407
+ transition:
5408
+ background-color var(--sc-duration-fast) var(--sc-ease-standard),
5409
+ color var(--sc-duration-fast) var(--sc-ease-standard);
5410
+ }
5411
+ .sc-score[data-size='md'] {
5412
+ --_s: var(--sc-size-score-md);
5413
+ border-radius: var(--sc-radius-xl);
5414
+ font-size: var(--sc-font-size-lg);
5415
+ }
5416
+ .sc-score[data-tone='neutral'] {
5417
+ /* surface.active, so the tile still shows on a hovered row (surface.hover). Selected turns accent. */
5418
+ --_bg: var(--sc-color-surface-active);
5419
+ --_fg: var(--sc-color-text-muted);
5420
+ --_solid: var(--sc-color-text-muted);
5421
+ }
5422
+ .sc-score[data-tone='success'] {
5423
+ --_bg: var(--sc-color-success-subtle);
5424
+ --_fg: var(--sc-color-success-text);
5425
+ --_solid: var(--sc-color-success-solid);
5426
+ --_on-solid: var(--sc-color-text-on-status);
5427
+ }
5428
+ .sc-score[data-tone='warning'] {
5429
+ --_bg: var(--sc-color-warning-subtle);
5430
+ --_fg: var(--sc-color-warning-text);
5431
+ --_solid: var(--sc-color-warning-solid);
5432
+ --_on-solid: var(--sc-color-text-on-status);
5433
+ }
5434
+ .sc-score[data-tone='danger'] {
5435
+ --_bg: var(--sc-color-danger-subtle);
5436
+ --_fg: var(--sc-color-danger-text);
5437
+ --_solid: var(--sc-color-danger-solid);
5438
+ --_on-solid: var(--sc-color-text-on-status);
5439
+ }
5440
+ /* Not scored (`value={null}`): no tone, a muted dash on the neutral tile or inside an empty ring. --_solid stays
5441
+ accent, so a selected row still turns the tile solid accent, as neutral does. */
5442
+ .sc-score[data-unscored] {
5443
+ --_bg: var(--sc-color-surface-active);
5444
+ --_fg: var(--sc-color-text-muted);
5445
+ }
5446
+ .sc-score__body {
5447
+ display: grid;
5448
+ justify-items: center;
5449
+ gap: var(--sc-spacing-3xs);
5450
+ }
5451
+ .sc-score__caption {
5452
+ font-family: var(--sc-font-family-mono);
5453
+ font-size: var(--sc-font-size-xs);
5454
+ font-weight: var(--sc-font-weight-medium);
5455
+ letter-spacing: var(--sc-font-tracking-wide);
5456
+ text-transform: uppercase;
5457
+ color: var(--sc-color-text-muted);
5458
+ }
5459
+ /* Selected: the tile goes solid in its tone (neutral goes accent), inside a selected row or on `selected`. */
5460
+ .sc-score[data-variant='tile'][data-selected],
5461
+ .sc-card[data-selected] .sc-score[data-variant='tile'],
5462
+ [aria-pressed='true'] .sc-score[data-variant='tile'],
5463
+ [aria-selected='true'] .sc-score[data-variant='tile'] {
5464
+ background: var(--_solid);
5465
+ color: var(--_on-solid);
5466
+ }
5467
+ .sc-score[data-variant='tile'][data-tone='neutral'][data-selected],
5468
+ .sc-card[data-selected] .sc-score[data-variant='tile'][data-tone='neutral'],
5469
+ [aria-pressed='true'] .sc-score[data-variant='tile'][data-tone='neutral'],
5470
+ [aria-selected='true'] .sc-score[data-variant='tile'][data-tone='neutral'] {
5471
+ background: var(--sc-color-accent-default);
5472
+ color: var(--sc-color-text-on-accent);
5473
+ }
5474
+ .sc-score[data-variant='tile'][data-selected] .sc-score__caption,
5475
+ .sc-card[data-selected] .sc-score[data-variant='tile'] .sc-score__caption,
5476
+ [aria-pressed='true'] .sc-score[data-variant='tile'] .sc-score__caption,
5477
+ [aria-selected='true'] .sc-score[data-variant='tile'] .sc-score__caption {
5478
+ color: inherit;
5479
+ }
5480
+ /* Ring: the number in the tone's text colour over a donut. The SVG is drawn for the 64px ring token with a 6px
5481
+ stroke (r = 29 in Score.tsx); the arc length comes from --sc-score-fill (0–100, set inline). */
5482
+ .sc-score[data-variant='ring'] {
5483
+ --_s: var(--sc-size-score-ring);
5484
+ border-radius: var(--sc-radius-full);
5485
+ background: transparent;
5486
+ font-size: var(--sc-font-size-lg);
5487
+ }
5488
+ .sc-score__ring {
5489
+ position: absolute;
5490
+ inset: 0;
5491
+ inline-size: 100%;
5492
+ block-size: 100%;
5493
+ rotate: -90deg;
5494
+ overflow: visible;
5495
+ }
5496
+ .sc-score__track,
5497
+ .sc-score__arc {
5498
+ fill: none;
5499
+ stroke-width: var(--sc-size-score-ring-stroke);
5500
+ }
5501
+ .sc-score__track {
5502
+ stroke: var(--sc-color-surface-active);
5503
+ }
5504
+ .sc-score__arc {
5505
+ stroke: var(--_solid);
5506
+ stroke-linecap: round;
5507
+ stroke-dasharray: 100;
5508
+ stroke-dashoffset: calc(100 - var(--sc-score-fill, 0));
5509
+ /* Moves only when the value changes; the first render draws it in place. */
5510
+ transition: stroke-dashoffset var(--sc-duration-slow) var(--sc-ease-enter);
5511
+ }
5512
+ .sc-score[data-variant='ring'] .sc-score__body {
5513
+ position: relative;
5514
+ }
5515
+ @media (prefers-reduced-motion: reduce) {
5516
+ .sc-score,
5517
+ .sc-score__arc {
5518
+ transition: none;
5519
+ }
5520
+ }
5521
+
5522
+ /* ---- reason-list.css ---- */
5523
+ /* ---- ReasonList ------------------------------------------------------------ */
5524
+ /* Marker shape per tone: for = filled square, against = bar, gap = hollow circle. Markers use the tone's solid,
5525
+ 3:1 on every surface; the shape carries the meaning on its own (WCAG 1.4.1). */
5526
+ .sc-reason-list {
5527
+ --_m: 9px;
5528
+ --_marker: var(--sc-color-success-solid);
5529
+ display: grid;
5530
+ gap: var(--sc-spacing-xs);
5531
+ margin: 0;
5532
+ padding: 0;
5533
+ list-style: none;
5534
+ font-family: var(--sc-font-family-sans);
5535
+ font-size: var(--sc-font-size-sm);
5536
+ line-height: var(--sc-font-line-height-ui);
5537
+ color: var(--sc-color-text-muted);
5538
+ }
5539
+ .sc-reason-list[data-size='sm'] {
5540
+ --_m: 7px;
5541
+ gap: var(--sc-spacing-2xs);
5542
+ font-size: var(--sc-font-size-xs);
5543
+ }
5544
+ .sc-reason-list[data-divider] {
5545
+ padding-block-start: var(--sc-spacing-xs);
5546
+ border-block-start: var(--sc-border-width-hairline) dashed var(--sc-color-border-default);
5547
+ }
5548
+ .sc-reason-list[data-tone='against'] {
5549
+ --_marker: var(--sc-color-danger-solid);
5550
+ }
5551
+ .sc-reason-list[data-tone='gap'] {
5552
+ --_marker: var(--sc-color-warning-solid);
5553
+ }
5554
+ .sc-reason-list__item {
5555
+ position: relative;
5556
+ padding-inline-start: calc(var(--_m) + var(--sc-spacing-xs));
5557
+ }
5558
+ /* Centred on the first line: half the line box less half the marker. */
5559
+ .sc-reason-list__item::before {
5560
+ content: '';
5561
+ position: absolute;
5562
+ inset-inline-start: 0;
5563
+ inset-block-start: 0.45em;
5564
+ inset-block-start: calc((1lh - var(--_m)) / 2);
5565
+ box-sizing: border-box;
5566
+ inline-size: var(--_m);
5567
+ block-size: var(--_m);
5568
+ border-radius: var(--sc-radius-xs);
5569
+ background: var(--_marker);
5570
+ }
5571
+ .sc-reason-list[data-tone='against'] > .sc-reason-list__item::before {
5572
+ inset-block-start: 0.6em;
5573
+ inset-block-start: calc((1lh - var(--_m) / 3) / 2);
5574
+ block-size: calc(var(--_m) / 3);
5575
+ border-radius: var(--sc-radius-full);
5576
+ }
5577
+ .sc-reason-list[data-tone='gap'] > .sc-reason-list__item::before {
5578
+ background: transparent;
5579
+ border: var(--sc-border-width-focus) solid var(--_marker);
5580
+ border-radius: var(--sc-radius-full);
5581
+ }
5582
+ .sc-reason-list__item :where(strong, b) {
5583
+ font-weight: var(--sc-font-weight-semibold);
5584
+ color: var(--sc-color-text-default);
5585
+ }
5586
+
5587
+ /* ---- word-diff.css ---- */
5588
+ /* ---- WordDiff -------------------------------------------------------------- */
5589
+ /* Strike-through and underline carry the meaning; the tint only groups the words. Both lines are 3:1 on their tint
5590
+ (diff.*-stroke on diff.*-wash) in light and dark. */
5591
+ .sc-word-diff {
5592
+ margin: 0;
5593
+ font-family: var(--sc-font-family-sans);
5594
+ font-size: var(--sc-font-size-sm);
5595
+ line-height: var(--sc-font-line-height-normal);
5596
+ color: var(--sc-color-text-default);
5597
+ white-space: pre-wrap;
5598
+ overflow-wrap: anywhere;
5599
+ }
5600
+ .sc-word-diff[data-size='md'] {
5601
+ font-size: var(--sc-font-size-md);
5602
+ }
5603
+ p.sc-word-diff,
5604
+ div.sc-word-diff {
5605
+ max-inline-size: var(--sc-font-measure);
5606
+ }
5607
+ .sc-word-diff__added,
5608
+ .sc-word-diff__removed {
5609
+ padding-inline: var(--sc-spacing-3xs);
5610
+ border-radius: var(--sc-radius-xs);
5611
+ text-decoration-thickness: var(--sc-border-width-focus);
5612
+ box-decoration-break: clone;
5613
+ -webkit-box-decoration-break: clone;
5614
+ }
5615
+ .sc-word-diff__added {
5616
+ background: var(--sc-color-diff-added-wash);
5617
+ color: var(--sc-color-text-default);
5618
+ text-decoration-line: underline;
5619
+ text-decoration-color: var(--sc-color-diff-added-stroke);
5620
+ text-underline-offset: 0.2em;
5621
+ }
5622
+ .sc-word-diff__removed {
5623
+ background: var(--sc-color-diff-removed-wash);
5624
+ color: var(--sc-color-text-muted);
5625
+ text-decoration-line: line-through;
5626
+ text-decoration-color: var(--sc-color-diff-removed-stroke);
5627
+ }
5628
+
5629
+ /* ---- quote.css ---- */
5630
+ /* ---- Quote ----------------------------------------------------------------- */
5631
+ /* Label and words on one line, on the accent wash with the accent border (both from the plain Card selected
5632
+ state), so an echoed instruction reads as "yours" next to what changed. */
5633
+ .sc-quote {
5634
+ box-sizing: border-box;
5635
+ margin: 0;
5636
+ padding: var(--sc-spacing-xs) var(--sc-spacing-sm);
5637
+ border: var(--sc-border-width-hairline) solid var(--sc-color-accent-border);
5638
+ border-radius: var(--sc-radius-lg);
5639
+ background: var(--sc-color-accent-wash);
5640
+ font-family: var(--sc-font-family-sans);
5641
+ font-size: var(--sc-font-size-sm);
5642
+ line-height: var(--sc-font-line-height-ui);
5643
+ color: var(--sc-color-text-muted);
5644
+ }
5645
+ .sc-quote__label {
5646
+ display: inline;
5647
+ margin-inline-end: var(--sc-spacing-xs);
5648
+ font-family: var(--sc-font-family-mono);
5649
+ font-size: var(--sc-font-size-xs);
5650
+ font-weight: var(--sc-font-weight-medium);
5651
+ letter-spacing: var(--sc-font-tracking-wider);
5652
+ text-transform: uppercase;
5653
+ color: var(--sc-color-accent-text);
5654
+ }
5655
+ .sc-quote__text {
5656
+ display: inline;
5657
+ margin: 0;
5658
+ }
5659
+
5299
5660
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salemcobalt/ui",
3
- "version": "0.2.0-rc.14",
4
- "description": "React components for the Salem Cobalt design system: Button, IconButton, Icon set, BroomIcon, Badge, Card, Stack, Inline, Kbd, Dialog, FullScreenFlow, Tooltip, Menu, Popover, PriorityNav, Toolbar, Banner, Spinner, Progress, Tabs, Input, Textarea, Select, FileInput, Checkbox, Switch, Heading, Text, Table, Stat, Chip, Disclosure, EmptyState, Skeleton.",
3
+ "version": "0.2.0-rc.16",
4
+ "description": "React components for the Salem Cobalt design system: Button, IconButton, Icon set, BroomIcon, Badge, Card, Stack, Inline, Kbd, Dialog, FullScreenFlow, Tooltip, Menu, Popover, PriorityNav, Toolbar, Banner, Spinner, Progress, Tabs, Input, Textarea, Select, FileInput, Checkbox, Switch, Heading, Text, Table, Stat, Chip, Disclosure, EmptyState, Skeleton, Score, ReasonList, WordDiff, Quote.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -33,7 +33,7 @@
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",
35
35
  "react-dom": "^19.0.0",
36
- "@salemcobalt/tokens": "^0.2.0-rc.14"
36
+ "@salemcobalt/tokens": "^0.2.0-rc.16"
37
37
  },
38
38
  "dependencies": {
39
39
  "@base-ui/react": "^1.9.0",
@@ -57,7 +57,7 @@
57
57
  "tsup": "^9.0.0",
58
58
  "typescript": "^5.9.3",
59
59
  "vitest": "^5.0.5",
60
- "@salemcobalt/tokens": "^0.2.0-rc.14"
60
+ "@salemcobalt/tokens": "^0.2.0-rc.16"
61
61
  },
62
62
  "publishConfig": {
63
63
  "access": "public"