@brightspot/ui 5.4.2 → 5.4.3-pr.192

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 (89) hide show
  1. package/dist/components/badge/Badge.d.ts +19 -0
  2. package/dist/components/badge/Badge.d.ts.map +1 -1
  3. package/dist/components/badge/Badge.js +16 -1
  4. package/dist/components/badge/Badge.js.map +1 -1
  5. package/dist/custom-elements.json +18 -0
  6. package/dist/storybook/assets/{ActionBar.stories-BJcrfF0X.js → ActionBar.stories-BwKZ8jTT.js} +1 -1
  7. package/dist/storybook/assets/{ActionItem.stories-xLR-VN2Q.js → ActionItem.stories-Df3verWG.js} +1 -1
  8. package/dist/storybook/assets/{Avatar.stories-Cj5Q2yEp.js → Avatar.stories-Bghlkr3H.js} +1 -1
  9. package/dist/storybook/assets/{AvatarGroup.stories-DLWAQHFa.js → AvatarGroup.stories-CzeWxUTU.js} +1 -1
  10. package/dist/storybook/assets/{Badge.stories-DGSKAf9D.js → Badge.stories-BT5lSPGT.js} +56 -7
  11. package/dist/storybook/assets/{Banner.stories-BZ3LLa4I.js → Banner.stories-BjFdFSa4.js} +1 -1
  12. package/dist/storybook/assets/{Button-ffu9dnxC.js → Button-D180UbjB.js} +1 -1
  13. package/dist/storybook/assets/{Button.stories-DB-uDcVu.js → Button.stories-CrSX4UIL.js} +1 -1
  14. package/dist/storybook/assets/{ButtonGroup.stories-eGya8Uts.js → ButtonGroup.stories-BFObAokB.js} +1 -1
  15. package/dist/storybook/assets/{Card.stories-B_hhKmQB.js → Card.stories-DuSjN2D2.js} +1 -1
  16. package/dist/storybook/assets/{Celebrate.stories-DqKwiwly.js → Celebrate.stories-BWO2srfl.js} +1 -1
  17. package/dist/storybook/assets/{Checkbox.stories-Bly8OVzf.js → Checkbox.stories-BMfILOzR.js} +1 -1
  18. package/dist/storybook/assets/{CircularProgress.stories-BZUNNkMK.js → CircularProgress.stories-Dc8zPUpU.js} +1 -1
  19. package/dist/storybook/assets/{ClipboardMixin.stories-D2XMhwIg.js → ClipboardMixin.stories-CAjaKg7r.js} +1 -1
  20. package/dist/storybook/assets/{Color-6BZIO3FS-BPcC43iH.js → Color-6BZIO3FS-BtiyepW3.js} +1 -1
  21. package/dist/storybook/assets/{Colors.stories-DveV04we.js → Colors.stories-Dw2fTxL_.js} +1 -1
  22. package/dist/storybook/assets/{CombinedEffects.stories-Dl_MhHhl.js → CombinedEffects.stories-B5sQuyyD.js} +1 -1
  23. package/dist/storybook/assets/{ComponentStatesMixin-CmZnizKN.js → ComponentStatesMixin-iTkOii8_.js} +1 -1
  24. package/dist/storybook/assets/{ComponentStatesMixin.stories-BrAFoGDu.js → ComponentStatesMixin.stories-Bf1PGTh8.js} +1 -1
  25. package/dist/storybook/assets/{CopyToClipboard.stories-CiKbtpBJ.js → CopyToClipboard.stories-DyDVRVId.js} +1 -1
  26. package/dist/storybook/assets/{Debounce.stories-BQ7W_yTX.js → Debounce.stories-_1QyhRvo.js} +1 -1
  27. package/dist/storybook/assets/{DocsRenderer-LL677BLK-DiDzi0rZ.js → DocsRenderer-LL677BLK-mX98SSbE.js} +3 -3
  28. package/dist/storybook/assets/{Dropdown.stories-LYd0-ypG.js → Dropdown.stories-CauEwIiv.js} +1 -1
  29. package/dist/storybook/assets/{EmptyState.stories-DjKyE0h3.js → EmptyState.stories-C-UcFH2P.js} +1 -1
  30. package/dist/storybook/assets/{EscaAvatar.stories-D3v91UKv.js → EscaAvatar.stories-CrL2Tdi3.js} +1 -1
  31. package/dist/storybook/assets/{Events.stories-CTe5eZa6.js → Events.stories-ClUoOf2J.js} +1 -1
  32. package/dist/storybook/assets/{Heading.stories-DKt-wgRB.js → Heading.stories-CqDURuaf.js} +1 -1
  33. package/dist/storybook/assets/{HueRipple.stories-B3SVSdL8.js → HueRipple.stories-DJQOCvrv.js} +1 -1
  34. package/dist/storybook/assets/{Icon.stories-B5tDsd--.js → Icon.stories-WOCYLVIC.js} +1 -1
  35. package/dist/storybook/assets/{IconButton.stories-DOV4zFAP.js → IconButton.stories-uIuDW2Jc.js} +1 -1
  36. package/dist/storybook/assets/{LinearProgress.stories-ai3UD-xw.js → LinearProgress.stories-CQZWZ94q.js} +1 -1
  37. package/dist/storybook/assets/{Message.stories-CzqIe49h.js → Message.stories-DqD-EjEb.js} +1 -1
  38. package/dist/storybook/assets/{OnFindMixin.stories-CUaE6pX1.js → OnFindMixin.stories-DYrj1tfl.js} +1 -1
  39. package/dist/storybook/assets/{Pagination.stories-CXCbChNW.js → Pagination.stories-IvkB8_RP.js} +1 -1
  40. package/dist/storybook/assets/{Popover.stories-DyptvVL3.js → Popover.stories-yeJxuJ_x.js} +1 -1
  41. package/dist/storybook/assets/{ReadyMixin-BUpBkgED.js → ReadyMixin-B0XVzdH2.js} +1 -1
  42. package/dist/storybook/assets/{RovingTabindexMixin.stories-DzEH38Tn.js → RovingTabindexMixin.stories-JKJXpQ1a.js} +1 -1
  43. package/dist/storybook/assets/{Rtc.stories-DxQWkudF.js → Rtc.stories-DfWQtLoI.js} +1 -1
  44. package/dist/storybook/assets/{ScrollShadow.stories-DbMdNLKA.js → ScrollShadow.stories-DD_jQZ5k.js} +1 -1
  45. package/dist/storybook/assets/{Switch.stories-CvSwuR0Z.js → Switch.stories-BC35M81K.js} +1 -1
  46. package/dist/storybook/assets/{Tab.stories-CI6m8NXD.js → Tab.stories-Cy-KbsOG.js} +1 -1
  47. package/dist/storybook/assets/{Tabs.stories-BMat3ubI.js → Tabs.stories-CvhLvl1p.js} +1 -1
  48. package/dist/storybook/assets/{Throttle.stories-PEUZoXfI.js → Throttle.stories-nU7jf9yB.js} +1 -1
  49. package/dist/storybook/assets/{Tooltip.stories-kDJ5PbGO.js → Tooltip.stories-BT6j1z87.js} +1 -1
  50. package/dist/storybook/assets/{Upload.stories-Bb5KBlh7.js → Upload.stories-DaF5wY54.js} +1 -1
  51. package/dist/storybook/assets/{UploadItem.stories-VZVWc52f.js → UploadItem.stories-CC8wtYPQ.js} +1 -1
  52. package/dist/storybook/assets/{Welcome.stories-BgzaFbT1.js → Welcome.stories-DAp73cbU.js} +1 -1
  53. package/dist/storybook/assets/{Widget.stories-Bbczy09Q.js → Widget.stories-Ce_Ni_Rc.js} +1 -1
  54. package/dist/storybook/assets/{WithTooltip-65CFNBJE-BoKgPPcr.js → WithTooltip-65CFNBJE-Bkacmhfv.js} +1 -1
  55. package/dist/storybook/assets/{blocks-j0yzxuDk.js → blocks-CBDAfSKn.js} +5 -5
  56. package/dist/storybook/assets/{formatter-EIJCOSYU-B5-4vV2C.js → formatter-EIJCOSYU-BVbGt3s2.js} +1 -1
  57. package/dist/storybook/assets/if-defined-B4TUfCpr.js +1 -0
  58. package/dist/storybook/assets/iframe-Bsa4H6Fe.css +1 -0
  59. package/dist/storybook/assets/{iframe-DUmd7GbF.js → iframe-Dvs8mbFG.js} +4 -4
  60. package/dist/storybook/assets/{index-ACSvfrQi.js → index-DPIbqAS7.js} +1 -1
  61. package/dist/storybook/assets/{onFind-t_5Bmfio.js → onFind-DLwO1HNO.js} +1 -1
  62. package/dist/storybook/assets/{onFind.stories-CQWcRPFY.js → onFind.stories-Dq-zkOGi.js} +1 -1
  63. package/dist/storybook/assets/{onRemove.stories-B9_DDB2B.js → onRemove.stories-gd3ki21J.js} +1 -1
  64. package/dist/storybook/assets/{onVisible.stories-G0qjGum_.js → onVisible.stories-5WTX6gRk.js} +1 -1
  65. package/dist/storybook/assets/{style-map-D_jXmlQ4.js → style-map-K0t_tOsq.js} +1 -1
  66. package/dist/storybook/assets/{syntaxhighlighter-ED5Y7EFY-7_fYNYDB.js → syntaxhighlighter-ED5Y7EFY-AnjtyXja.js} +1 -1
  67. package/dist/storybook/iframe.html +2 -2
  68. package/dist/storybook/index.json +1 -1
  69. package/dist/storybook/project.json +1 -1
  70. package/dist/tailwind-plugin-badge.js +118 -2
  71. package/dist/tailwind-plugin-badge.js.map +1 -1
  72. package/dist/tailwind-plugin-badge.ts +134 -2
  73. package/docs/components/Badge.md +12 -10
  74. package/package.json +1 -1
  75. package/src/legacy/tool-ui/src/DashboardWidget.css +1 -1
  76. package/src/legacy/tool-ui/src/Entry.ts +1 -0
  77. package/src/legacy/tool-ui/src/main/webapp/dist/{v4.6fa2ceb9bc8a86731790.js → v4.ebbbe25f838d4265081e.js} +2 -2
  78. package/src/legacy/tool-ui/src/main/webapp/dist/v4.fda8a624070bce61ac0d.css +3 -0
  79. package/src/legacy/tool-ui/src/main/webapp/dist/{v5.b7af407a8c1506dbc92f.js → v5.0c31b1ef75a387820deb.js} +2 -2
  80. package/src/legacy/tool-ui/src/main/webapp/dist/v5.e927095bfd14d91c35b3.css +5 -0
  81. package/src/legacy/tool-ui/src/main/webapp/v4/Entry.less +2 -2
  82. package/dist/storybook/assets/if-defined-DBQP12ek.js +0 -1
  83. package/dist/storybook/assets/iframe-Ce3XRnL4.css +0 -1
  84. package/src/legacy/tool-ui/src/main/webapp/dist/v4.361bbdb193ac4bca44d7.css +0 -3
  85. package/src/legacy/tool-ui/src/main/webapp/dist/v5.553c18f29cb4a71c3577.css +0 -5
  86. /package/src/legacy/tool-ui/src/main/webapp/dist/{v4.6fa2ceb9bc8a86731790.js.LICENSE.txt → v4.ebbbe25f838d4265081e.js.LICENSE.txt} +0 -0
  87. /package/src/legacy/tool-ui/src/main/webapp/dist/{v5.b7af407a8c1506dbc92f.js.LICENSE.txt → v5.0c31b1ef75a387820deb.js.LICENSE.txt} +0 -0
  88. /package/src/legacy/tool-ui/src/main/webapp/v4/{Downloads.css → Downloads.less} +0 -0
  89. /package/src/legacy/tool-ui/src/main/webapp/v4/{Utils.css → Utils.less} +0 -0
@@ -1 +1 @@
1
- {"generatedAt":1784580333470,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":true,"hasStorybookEslint":true,"refCount":0,"knownPackages":{"testPackages":{"@storybook/addon-vitest":"10.2.12","@vitest/browser-playwright":"4.0.18","playwright":"1.58.2","vitest":"4.0.18"},"stylingPackages":{"tailwindcss":"^3.4.13","autoprefixer":"10.4.21"}},"hasRouterPackage":false,"packageManager":{"type":"yarn","agent":"yarn","nodeLinker":"undefined"},"preview":{"usesGlobals":true},"framework":{"name":"@storybook/web-components-vite","options":{}},"builder":"@storybook/builder-vite","renderer":"@storybook/web-components","portableStoriesFileCount":0,"applicationFileCount":6,"storybookVersion":"10.2.12","storybookVersionSpecifier":"10.2.12","language":"typescript","storybookPackages":{"@storybook/addon-themes":{"version":"10.2.12"},"@storybook/web-components-vite":{"version":"10.2.12"},"@wc-toolkit/storybook-helpers":{"version":"10.0.0"},"eslint-plugin-storybook":{"version":"10.0.7"},"storybook":{}},"addons":{"@storybook/addon-docs":{"version":"10.2.12"},"@storybook/addon-vitest":{"version":"10.2.12"}},"packageJsonType":"module"}
1
+ {"generatedAt":1784655174620,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":true,"hasStorybookEslint":true,"refCount":0,"knownPackages":{"testPackages":{"@storybook/addon-vitest":"10.2.12","@vitest/browser-playwright":"4.0.18","playwright":"1.58.2","vitest":"4.0.18"},"stylingPackages":{"tailwindcss":"^3.4.13","autoprefixer":"10.4.21"}},"hasRouterPackage":false,"packageManager":{"type":"yarn","agent":"yarn","nodeLinker":"undefined"},"preview":{"usesGlobals":true},"framework":{"name":"@storybook/web-components-vite","options":{}},"builder":"@storybook/builder-vite","renderer":"@storybook/web-components","portableStoriesFileCount":0,"applicationFileCount":6,"storybookVersion":"10.2.12","storybookVersionSpecifier":"10.2.12","language":"typescript","storybookPackages":{"@storybook/addon-themes":{"version":"10.2.12"},"@storybook/web-components-vite":{"version":"10.2.12"},"@wc-toolkit/storybook-helpers":{"version":"10.0.0"},"eslint-plugin-storybook":{"version":"10.0.7"},"storybook":{}},"addons":{"@storybook/addon-docs":{"version":"10.2.12"},"@storybook/addon-vitest":{"version":"10.2.12"}},"packageJsonType":"module"}
@@ -1,6 +1,6 @@
1
1
  import plugin from 'tailwindcss/plugin';
2
2
  const className = '.btu-badge';
3
- module.exports = plugin(function ({ addComponents, theme, e, matchUtilities, addUtilities }) {
3
+ module.exports = plugin(function ({ addBase, addComponents, theme, e, matchUtilities, addUtilities }) {
4
4
  const sizes = theme('badgeSize');
5
5
  const colors = theme('colors');
6
6
  const fontSizes = theme('fontSize');
@@ -31,18 +31,53 @@ module.exports = plugin(function ({ addComponents, theme, e, matchUtilities, add
31
31
  }, {});
32
32
  if (colors) {
33
33
  const badgeColors = [];
34
+ // The `busy` activity renders as a text shimmer: a lighter glint sweeps
35
+ // across the label while the pill fill stays put. The gradient + text
36
+ // clip live on the per-color compound (`.btu-badge-<color>.btu-badge-
37
+ // activity-busy`), NOT the bare `.btu-badge-activity-busy` — so the class
38
+ // can never clip a non-existent background to invisible glyphs on its own.
39
+ // Dark mode swaps the glint for a lighter, highly saturated version of the
40
+ // badge's OWN background (pale dark-mode text has no lightness headroom, so
41
+ // it pops via saturation); chroma is bumped past the gamut edge on purpose
42
+ // and the browser maps it back to the most saturated in-gamut value.
43
+ const lightGlint = 'oklch(from currentColor calc(l + 0.38) calc(c * 0.5) h)';
44
+ const darkGlint = (bg) => `oklch(from ${bg} calc(l + 0.35) calc(c + 0.1) h)`;
45
+ const darkBusyMedia = {};
34
46
  for (const key in colors) {
47
+ const fill = `var(--badge-color-background, oklch(var(--btu-theme-${key}-50)))`;
48
+ const busySel = `${className}-${e(key)}${className}-activity-busy`;
49
+ // layer 0 (gradient) clips to the glyphs; layer 1 (solid fill) is the
50
+ // pill — its own layer so the two-value background-clip sticks (Chrome
51
+ // truncates the clip list to the number of background layers).
52
+ const busyGradient = (glint) => `linear-gradient(100deg, currentColor 0 40%, ${glint} 50%, currentColor 60% 100%), linear-gradient(${fill}, ${fill})`;
35
53
  badgeColors.push({
36
54
  [`${className}-${e(key)}`]: {
37
55
  '--icon-size': iconSizes['xs'],
38
- backgroundColor: `var(--badge-color-background, oklch(var(--btu-theme-${key}-50)))`,
56
+ backgroundColor: fill,
39
57
  color: `var(--badge-color-foreground, oklch(var(--btu-theme-${key}-700)))`,
40
58
  textDecoration: 'underline',
41
59
  textDecorationColor: `var(--badge-color-background, oklch(var(--btu-theme-${key}-50)))`,
42
60
  },
61
+ [busySel]: {
62
+ backgroundImage: busyGradient(lightGlint),
63
+ backgroundSize: '300% 100%, 100% 100%',
64
+ backgroundRepeat: 'no-repeat',
65
+ backgroundClip: 'text, border-box',
66
+ WebkitBackgroundClip: 'text, border-box',
67
+ WebkitTextFillColor: 'transparent',
68
+ },
69
+ // Dark mode (explicit .is-dark): swap in the saturated background glint.
70
+ [`.is-dark ${busySel}`]: {
71
+ backgroundImage: busyGradient(darkGlint(fill)),
72
+ },
43
73
  });
74
+ darkBusyMedia[`:root:not([data-theme*='"appearance":"light"']):not(.is-dark) ${busySel}`] = {
75
+ backgroundImage: busyGradient(darkGlint(fill)),
76
+ };
44
77
  }
45
78
  addComponents(badgeColors);
79
+ // Dark mode via system preference (unless the CMS forced light).
80
+ addComponents({ '@media (prefers-color-scheme: dark)': darkBusyMedia });
46
81
  }
47
82
  if (sizes && fontSizes) {
48
83
  const badgeSizes = [];
@@ -74,6 +109,87 @@ module.exports = plugin(function ({ addComponents, theme, e, matchUtilities, add
74
109
  }
75
110
  addComponents(badgeSizes);
76
111
  }
112
+ // ─── Attention: activity="busy" (shimmer) + activity="live" (ping dot) ──
113
+ // Classes are intent-named (`btu-badge-activity-<state>`); the effect each
114
+ // maps to is decided here, and the timing/scale literals are internal (no
115
+ // effect-named public knobs, so the visual can change without a breaking
116
+ // API change). `busy` keeps the text at its full foreground colour and
117
+ // sweeps a lighter glint through it — `color` is left intact so
118
+ // `currentColor` still resolves for the child `<btu-icon>` SVG stroke; the
119
+ // gradient + clip that reveal the glint live on the per-color compound above.
120
+ addComponents({
121
+ // Bare class carries only the (color-agnostic) animation; the gradient
122
+ // and text-clip are on the per-color compound, so this alone is a no-op.
123
+ '.btu-badge-activity-busy': {
124
+ animation: 'btu-badge-shimmer 2.2s linear infinite',
125
+ },
126
+ // Only the label text shimmers — keep child icons at their normal
127
+ // colour (reset the inherited transparent text-fill so glyph-font icons
128
+ // don't disappear; SVG icons are unaffected either way).
129
+ '.btu-badge-activity-busy :is(btu-icon, svg)': {
130
+ WebkitTextFillColor: 'currentColor',
131
+ },
132
+ // Solid dot (::before) plus a clone (::after) that starts at the dot's
133
+ // size and scales up + fades out — a ping rippling from the centre.
134
+ // flex-start anchors the dot at the padding edge where the ::after ping
135
+ // is positioned; without it, the size rules' justify-content:center +
136
+ // min-width would recenter short content and offset the ping from the dot.
137
+ '.btu-badge-activity-live': {
138
+ position: 'relative',
139
+ justifyContent: 'flex-start',
140
+ },
141
+ '.btu-badge-activity-live::after': {
142
+ content: "''",
143
+ position: 'absolute',
144
+ // Overlay the leading dot: its left edge sits at the badge's
145
+ // padding-inline-start, vertically centred.
146
+ insetInlineStart: 'var(--badge-px)',
147
+ top: '50%',
148
+ marginTop: 'calc(var(--badge-dot-size, 6px) / -2)',
149
+ width: 'var(--badge-dot-size, 6px)',
150
+ height: 'var(--badge-dot-size, 6px)',
151
+ borderRadius: '9999px',
152
+ backgroundColor: 'currentColor',
153
+ transformOrigin: 'center',
154
+ pointerEvents: 'none',
155
+ animation: 'btu-badge-dot-ping 1.6s ease-out infinite',
156
+ },
157
+ // ── Reduced motion: settle to the resting state, no looping ──
158
+ // animation-fill-mode: forwards holds the final keyframe (ping: opacity 0
159
+ // / invisible; shimmer: band off the glyphs) instead of reverting to the
160
+ // base — otherwise the ping ::after snaps back to a static opaque dot.
161
+ '@media (prefers-reduced-motion: reduce)': {
162
+ '.btu-badge-activity-live::after': {
163
+ animationIterationCount: '1',
164
+ animationDuration: '0.01ms',
165
+ animationFillMode: 'forwards',
166
+ },
167
+ '.btu-badge-activity-busy': {
168
+ animationIterationCount: '1',
169
+ animationDuration: '0.01ms',
170
+ animationFillMode: 'forwards',
171
+ },
172
+ },
173
+ });
174
+ // Keyframes must be registered via addBase (not addComponents).
175
+ addBase({
176
+ '@keyframes btu-badge-shimmer': {
177
+ // Continuous sweep of layer 0 across the glyphs; layer 1 fill stays put.
178
+ // background-position MUST stay within [0%, 100%]: a 300%-wide no-repeat
179
+ // gradient only fully covers the element in that range, and the text is
180
+ // painted solely by this layer — any position outside it exposes bare
181
+ // glyphs (transparent text-fill) and wipes the label. Within [0%,100%]
182
+ // the highlight band still travels fully across and off both edges, so
183
+ // the ends read as a natural rest without ever uncovering the text.
184
+ '0%': { backgroundPosition: '100% 0, 0 0' },
185
+ '100%': { backgroundPosition: '0% 0, 0 0' },
186
+ },
187
+ '@keyframes btu-badge-dot-ping': {
188
+ // Start exactly at the dot's size, scale out and fade, then rest.
189
+ '0%': { transform: 'scale(1)', opacity: '0.6' },
190
+ '70%, 100%': { transform: 'scale(3)', opacity: '0' },
191
+ },
192
+ });
77
193
  }, {
78
194
  theme: {
79
195
  badgeSize: {
@@ -1 +1 @@
1
- {"version":3,"file":"tailwind-plugin-badge.js","sourceRoot":"","sources":["../src/tailwind-plugin-badge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tailwind-plugin-badge.js","sourceRoot":"","sources":["../src/tailwind-plugin-badge.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,17 @@ declare let module: any
17
17
  * Base -> btu-badge-lg btu-badge-purple
18
18
  * Dot -> btu-badge-lg btu-badge-primary before:size-2 before:rounded-lg before:bg-[currentColor] before:[content:'']
19
19
  * Close -> btu-badge-lg btu-badge-error after:btu-icon after:btu-icon-x
20
+ *
21
+ * Attention (draw the eye). Classes are named by intent, not by effect, so the
22
+ * visual can change without touching callers (see the `activity` attribute):
23
+ *
24
+ * btu-badge-activity-busy - In-progress. A glint of the badge's own foreground
25
+ * color sweeps across the label text (gradient clipped
26
+ * to the glyphs; pill fill preserved; icons/dot unaffected).
27
+ * Combine with a btu-badge-<color> class — that compound
28
+ * carries the gradient; the bare class alone is a no-op.
29
+ * btu-badge-activity-live - Live/active. A ring ripples outward from the leading
30
+ * dot (implies btu-badge-dot).
20
31
  */
21
32
 
22
33
  type Size = {
@@ -29,7 +40,7 @@ type Size = {
29
40
  const className = '.btu-badge'
30
41
 
31
42
  module.exports = plugin(
32
- function ({ addComponents, theme, e, matchUtilities, addUtilities }) {
43
+ function ({ addBase, addComponents, theme, e, matchUtilities, addUtilities }) {
33
44
  const sizes = theme('badgeSize')
34
45
  const colors: [CSSRuleObject] = theme('colors')
35
46
  const fontSizes: Record<string, CSSRuleObject> = theme('fontSize')
@@ -73,18 +84,54 @@ module.exports = plugin(
73
84
 
74
85
  if (colors) {
75
86
  const badgeColors: CSSRuleObject[] = []
87
+ // The `busy` activity renders as a text shimmer: a lighter glint sweeps
88
+ // across the label while the pill fill stays put. The gradient + text
89
+ // clip live on the per-color compound (`.btu-badge-<color>.btu-badge-
90
+ // activity-busy`), NOT the bare `.btu-badge-activity-busy` — so the class
91
+ // can never clip a non-existent background to invisible glyphs on its own.
92
+ // Dark mode swaps the glint for a lighter, highly saturated version of the
93
+ // badge's OWN background (pale dark-mode text has no lightness headroom, so
94
+ // it pops via saturation); chroma is bumped past the gamut edge on purpose
95
+ // and the browser maps it back to the most saturated in-gamut value.
96
+ const lightGlint = 'oklch(from currentColor calc(l + 0.38) calc(c * 0.5) h)'
97
+ const darkGlint = (bg: string) => `oklch(from ${bg} calc(l + 0.35) calc(c + 0.1) h)`
98
+ const darkBusyMedia: CSSRuleObject = {}
76
99
  for (const key in colors) {
100
+ const fill = `var(--badge-color-background, oklch(var(--btu-theme-${key}-50)))`
101
+ const busySel = `${className}-${e(key)}${className}-activity-busy`
102
+ // layer 0 (gradient) clips to the glyphs; layer 1 (solid fill) is the
103
+ // pill — its own layer so the two-value background-clip sticks (Chrome
104
+ // truncates the clip list to the number of background layers).
105
+ const busyGradient = (glint: string) =>
106
+ `linear-gradient(100deg, currentColor 0 40%, ${glint} 50%, currentColor 60% 100%), linear-gradient(${fill}, ${fill})`
77
107
  badgeColors.push({
78
108
  [`${className}-${e(key)}`]: {
79
109
  '--icon-size': iconSizes['xs'],
80
- backgroundColor: `var(--badge-color-background, oklch(var(--btu-theme-${key}-50)))`,
110
+ backgroundColor: fill,
81
111
  color: `var(--badge-color-foreground, oklch(var(--btu-theme-${key}-700)))`,
82
112
  textDecoration: 'underline',
83
113
  textDecorationColor: `var(--badge-color-background, oklch(var(--btu-theme-${key}-50)))`,
84
114
  },
115
+ [busySel]: {
116
+ backgroundImage: busyGradient(lightGlint),
117
+ backgroundSize: '300% 100%, 100% 100%',
118
+ backgroundRepeat: 'no-repeat',
119
+ backgroundClip: 'text, border-box',
120
+ WebkitBackgroundClip: 'text, border-box',
121
+ WebkitTextFillColor: 'transparent',
122
+ },
123
+ // Dark mode (explicit .is-dark): swap in the saturated background glint.
124
+ [`.is-dark ${busySel}`]: {
125
+ backgroundImage: busyGradient(darkGlint(fill)),
126
+ },
85
127
  })
128
+ darkBusyMedia[`:root:not([data-theme*='"appearance":"light"']):not(.is-dark) ${busySel}`] = {
129
+ backgroundImage: busyGradient(darkGlint(fill)),
130
+ }
86
131
  }
87
132
  addComponents(badgeColors)
133
+ // Dark mode via system preference (unless the CMS forced light).
134
+ addComponents({ '@media (prefers-color-scheme: dark)': darkBusyMedia })
88
135
  }
89
136
 
90
137
  if (sizes && fontSizes) {
@@ -119,6 +166,91 @@ module.exports = plugin(
119
166
  }
120
167
  addComponents(badgeSizes)
121
168
  }
169
+
170
+ // ─── Attention: activity="busy" (shimmer) + activity="live" (ping dot) ──
171
+ // Classes are intent-named (`btu-badge-activity-<state>`); the effect each
172
+ // maps to is decided here, and the timing/scale literals are internal (no
173
+ // effect-named public knobs, so the visual can change without a breaking
174
+ // API change). `busy` keeps the text at its full foreground colour and
175
+ // sweeps a lighter glint through it — `color` is left intact so
176
+ // `currentColor` still resolves for the child `<btu-icon>` SVG stroke; the
177
+ // gradient + clip that reveal the glint live on the per-color compound above.
178
+ addComponents({
179
+ // Bare class carries only the (color-agnostic) animation; the gradient
180
+ // and text-clip are on the per-color compound, so this alone is a no-op.
181
+ '.btu-badge-activity-busy': {
182
+ animation: 'btu-badge-shimmer 2.2s linear infinite',
183
+ },
184
+ // Only the label text shimmers — keep child icons at their normal
185
+ // colour (reset the inherited transparent text-fill so glyph-font icons
186
+ // don't disappear; SVG icons are unaffected either way).
187
+ '.btu-badge-activity-busy :is(btu-icon, svg)': {
188
+ WebkitTextFillColor: 'currentColor',
189
+ },
190
+
191
+ // Solid dot (::before) plus a clone (::after) that starts at the dot's
192
+ // size and scales up + fades out — a ping rippling from the centre.
193
+ // flex-start anchors the dot at the padding edge where the ::after ping
194
+ // is positioned; without it, the size rules' justify-content:center +
195
+ // min-width would recenter short content and offset the ping from the dot.
196
+ '.btu-badge-activity-live': {
197
+ position: 'relative',
198
+ justifyContent: 'flex-start',
199
+ },
200
+ '.btu-badge-activity-live::after': {
201
+ content: "''",
202
+ position: 'absolute',
203
+ // Overlay the leading dot: its left edge sits at the badge's
204
+ // padding-inline-start, vertically centred.
205
+ insetInlineStart: 'var(--badge-px)',
206
+ top: '50%',
207
+ marginTop: 'calc(var(--badge-dot-size, 6px) / -2)',
208
+ width: 'var(--badge-dot-size, 6px)',
209
+ height: 'var(--badge-dot-size, 6px)',
210
+ borderRadius: '9999px',
211
+ backgroundColor: 'currentColor',
212
+ transformOrigin: 'center',
213
+ pointerEvents: 'none',
214
+ animation: 'btu-badge-dot-ping 1.6s ease-out infinite',
215
+ },
216
+
217
+ // ── Reduced motion: settle to the resting state, no looping ──
218
+ // animation-fill-mode: forwards holds the final keyframe (ping: opacity 0
219
+ // / invisible; shimmer: band off the glyphs) instead of reverting to the
220
+ // base — otherwise the ping ::after snaps back to a static opaque dot.
221
+ '@media (prefers-reduced-motion: reduce)': {
222
+ '.btu-badge-activity-live::after': {
223
+ animationIterationCount: '1',
224
+ animationDuration: '0.01ms',
225
+ animationFillMode: 'forwards',
226
+ },
227
+ '.btu-badge-activity-busy': {
228
+ animationIterationCount: '1',
229
+ animationDuration: '0.01ms',
230
+ animationFillMode: 'forwards',
231
+ },
232
+ },
233
+ })
234
+
235
+ // Keyframes must be registered via addBase (not addComponents).
236
+ addBase({
237
+ '@keyframes btu-badge-shimmer': {
238
+ // Continuous sweep of layer 0 across the glyphs; layer 1 fill stays put.
239
+ // background-position MUST stay within [0%, 100%]: a 300%-wide no-repeat
240
+ // gradient only fully covers the element in that range, and the text is
241
+ // painted solely by this layer — any position outside it exposes bare
242
+ // glyphs (transparent text-fill) and wipes the label. Within [0%,100%]
243
+ // the highlight band still travels fully across and off both edges, so
244
+ // the ends read as a natural rest without ever uncovering the text.
245
+ '0%': { backgroundPosition: '100% 0, 0 0' },
246
+ '100%': { backgroundPosition: '0% 0, 0 0' },
247
+ },
248
+ '@keyframes btu-badge-dot-ping': {
249
+ // Start exactly at the dot's size, scale out and fade, then rest.
250
+ '0%': { transform: 'scale(1)', opacity: '0.6' },
251
+ '70%, 100%': { transform: 'scale(3)', opacity: '0' },
252
+ },
253
+ })
122
254
  },
123
255
  {
124
256
  theme: {
@@ -17,11 +17,12 @@
17
17
 
18
18
  ### Fields
19
19
 
20
- | Name | Privacy | Type | Default | Description | Inherited From |
21
- | --------- | ------- | ---------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
22
- | `variant` | | `'info' \| 'primary' \| 'error' \| 'success' \| 'warning'` | `'info'` | Style of the badge.&#xA;- 'info': Informational (default)&#xA;- 'primary': Primary action or emphasis&#xA;- 'error': Error or danger state&#xA;- 'success': Success or completion state&#xA;- 'warning': Warning or caution state | |
23
- | `dot` | | `boolean` | `false` | Should a dot be displayed before the label? | |
24
- | `size` | | `'sm' \| 'md' \| 'lg'` | `'sm'` | Size variant.&#xA;- 'sm': Small (default)&#xA;- 'md': Medium&#xA;- 'lg': Large | |
20
+ | Name | Privacy | Type | Default | Description | Inherited From |
21
+ | ---------- | ------- | ---------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
22
+ | `variant` | | `'info' \| 'primary' \| 'error' \| 'success' \| 'warning'` | `'info'` | Style of the badge.&#xA;- 'info': Informational (default)&#xA;- 'primary': Primary action or emphasis&#xA;- 'error': Error or danger state&#xA;- 'success': Success or completion state&#xA;- 'warning': Warning or caution state | |
23
+ | `dot` | | `boolean` | `false` | Should a dot be displayed before the label? | |
24
+ | `size` | | `'sm' \| 'md' \| 'lg'` | `'sm'` | Size variant.&#xA;- 'sm': Small (default)&#xA;- 'md': Medium&#xA;- 'lg': Large | |
25
+ | `activity` | | `'busy' \| 'live' \| undefined` | | Attention state that draws the eye to the badge. Names the \*intent\*; the&#xA;component owns the visual treatment (so it can change without callers).&#xA;- 'busy': an in-progress state — a glint shimmers across the label text&#xA;- 'live': a live/active state — a ring ripples out from the leading dot&#xA; (implies \`dot\`) | |
25
26
 
26
27
  ### Methods
27
28
 
@@ -37,11 +38,12 @@
37
38
 
38
39
  ### Attributes
39
40
 
40
- | Name | Field | Inherited From |
41
- | --------- | ------- | -------------- |
42
- | `variant` | variant | |
43
- | `dot` | dot | |
44
- | `size` | size | |
41
+ | Name | Field | Inherited From |
42
+ | ---------- | -------- | -------------- |
43
+ | `variant` | variant | |
44
+ | `dot` | dot | |
45
+ | `size` | size | |
46
+ | `activity` | activity | |
45
47
 
46
48
  ### CSS Properties
47
49
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspot/ui",
3
- "version": "5.4.2",
3
+ "version": "5.4.3-pr.192",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "description": "A UI library for building Brightspot CMS components.",
@@ -230,7 +230,7 @@ button.DashboardWidget-maximize {
230
230
  .DashboardWidget-filters {
231
231
  --Input-focusBackground: var(--color-gray2);
232
232
 
233
- @apply relative flex w-full items-center gap-2 overflow-auto overscroll-x-contain px-[--margin] py-4 transition-opacity [grid-column:fullbleed-start/fullbleed-end];
233
+ @apply btu-scrollshadow-25 flex w-full items-center gap-2 overflow-auto overscroll-x-contain px-[--margin] py-4 transition-opacity [grid-column:fullbleed-start/fullbleed-end] before:absolute before:row-start-2 before:content-[--whitespace] after:absolute after:row-start-2 after:content-[--whitespace];
234
234
 
235
235
  form {
236
236
  @apply flex w-full min-w-max items-center justify-end gap-2 transition-opacity;
@@ -844,6 +844,7 @@ onFind(
844
844
  '.Popup[name="AddEmbeddedContent"] .frame',
845
845
  '.Popup[name^="conversation-"] .frame',
846
846
  '.Popup[name^="_copy"] > .Popup-content > .frame',
847
+ '.Popup[name="DateStringCalendarFrame"] .frame',
847
848
  ],
848
849
  (frame: HTMLElement) => {
849
850
  const config = { attributeFilter: ['class'] }