@byline/ui 2.6.0 → 2.7.0

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.
@@ -2,11 +2,23 @@ import type React from 'react';
2
2
  interface ShimmerProps {
3
3
  className?: string;
4
4
  width?: string | number;
5
+ /**
6
+ * Height of the bar. For the single-bar variants (`rectangular`,
7
+ * `circular`, and single-line `text`) this sizes the bar itself. For the
8
+ * multi-line text variant (`variant="text"` with `lines > 1`) it sizes the
9
+ * container that holds the lines — use `lineHeight` to size each line.
10
+ */
5
11
  height?: string | number;
12
+ /**
13
+ * Height of each line in the multi-line text variant (`variant="text"`
14
+ * with `lines > 1`). Falls back to the `.text` class height (1rem) when
15
+ * omitted. Ignored by the single-bar variants — use `height` there.
16
+ */
17
+ lineHeight?: string | number;
6
18
  borderRadius?: string;
7
19
  variant?: 'text' | 'rectangular' | 'circular';
8
20
  lines?: number;
9
21
  children?: React.ReactNode;
10
22
  }
11
- export declare function Shimmer({ className, width, height, borderRadius, variant, lines, children, ...other }: ShimmerProps): React.JSX.Element;
23
+ export declare function Shimmer({ className, width, height, lineHeight, borderRadius, variant, lines, children, ...other }: ShimmerProps): React.JSX.Element;
12
24
  export {};
@@ -1,12 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import classnames from "classnames";
3
3
  import shimmer_module from "./shimmer.module.js";
4
- function Shimmer({ className, width = '100%', height = '1rem', borderRadius, variant = 'rectangular', lines = 1, children, ...other }) {
5
- const shimmerStyle = {
6
- width: 'number' == typeof width ? `${width}px` : width,
7
- height: 'number' == typeof height ? `${height}px` : height,
8
- borderRadius: borderRadius
9
- };
4
+ const toCssSize = (value)=>'number' == typeof value ? `${value}px` : value;
5
+ function Shimmer({ className, width = '100%', height, lineHeight, borderRadius, variant = 'rectangular', lines = 1, children, ...other }) {
10
6
  const getVariantClass = ()=>{
11
7
  switch(variant){
12
8
  case 'text':
@@ -17,20 +13,33 @@ function Shimmer({ className, width = '100%', height = '1rem', borderRadius, var
17
13
  return shimmer_module.rectangular;
18
14
  }
19
15
  };
20
- if ('text' === variant && lines > 1) return /*#__PURE__*/ jsx("div", {
21
- className: classnames(shimmer_module.shimmerContainer, className),
22
- ...other,
23
- children: Array.from({
24
- length: lines
25
- }, (_, index)=>/*#__PURE__*/ jsx("div", {
26
- className: classnames(shimmer_module.shimmer, shimmer_module.text),
27
- style: {
28
- ...shimmerStyle,
29
- width: index === lines - 1 ? '75%' : '100%',
30
- marginBottom: index === lines - 1 ? 0 : '0.5rem'
31
- }
32
- }, `shimmer-line-${index}`))
33
- });
16
+ if ('text' === variant && lines > 1) {
17
+ const resolvedLineHeight = toCssSize(lineHeight);
18
+ return /*#__PURE__*/ jsx("div", {
19
+ className: classnames(shimmer_module.shimmerContainer, className),
20
+ style: {
21
+ width: toCssSize(width),
22
+ height: toCssSize(height)
23
+ },
24
+ ...other,
25
+ children: Array.from({
26
+ length: lines
27
+ }, (_, index)=>/*#__PURE__*/ jsx("div", {
28
+ className: classnames(shimmer_module.shimmer, shimmer_module.text),
29
+ style: {
30
+ width: index === lines - 1 ? '75%' : '100%',
31
+ height: resolvedLineHeight,
32
+ borderRadius,
33
+ marginBottom: index === lines - 1 ? 0 : '0.5rem'
34
+ }
35
+ }, `shimmer-line-${index}`))
36
+ });
37
+ }
38
+ const shimmerStyle = {
39
+ width: toCssSize(width),
40
+ height: toCssSize(height) ?? '1rem',
41
+ borderRadius
42
+ };
34
43
  return /*#__PURE__*/ jsx("div", {
35
44
  className: classnames(shimmer_module.shimmer, getVariantClass(), className),
36
45
  style: shimmerStyle,
@@ -2,8 +2,8 @@
2
2
 
3
3
  @layer byline-components {
4
4
  :is(.shimmer-hQj5gn, .byline-shimmer) {
5
- background-color: #f0f0f0;
6
- background-image: linear-gradient(90deg, #0000, #fff9, #0000);
5
+ background-color: var(--surface-shimmer);
6
+ background-image: linear-gradient(90deg, #0000, #ffffffb3, #0000);
7
7
  background-size: 200% 100%;
8
8
  animation: 1.5s infinite shimmer-hQj5gn;
9
9
  position: relative;
@@ -11,13 +11,13 @@
11
11
  }
12
12
 
13
13
  :is(:is(.dark, [data-theme="dark"]) .shimmer-hQj5gn, :is(.dark, [data-theme="dark"]) .byline-shimmer) {
14
- background-color: #141414;
15
- background-image: linear-gradient(90deg, #0000, #ffffff03, #0000);
14
+ background-image: linear-gradient(90deg, #0000, #ffffff0a, #0000);
16
15
  }
17
16
 
18
17
  :is(.shimmerContainer-YqBAXa, .byline-shimmer-container) {
19
18
  flex-direction: column;
20
19
  display: flex;
20
+ overflow: hidden;
21
21
  }
22
22
 
23
23
  :is(.rectangular-qx6oTl, .byline-shimmer-rectangular) {
@@ -1314,6 +1314,7 @@
1314
1314
  --surface-subtle: var(--canvas-50);
1315
1315
  --surface-subtle-hover: var(--canvas-100);
1316
1316
  --surface-subtle-active: var(--canvas-200);
1317
+ --surface-shimmer: var(--canvas-100);
1317
1318
  --surface-panel-scrollbar: var(--gray-50);
1318
1319
  --surface-panel-scrollbar-thumb: var(--primary-100);
1319
1320
  }
@@ -1336,6 +1337,7 @@
1336
1337
  --surface-subtle: var(--canvas-800);
1337
1338
  --surface-subtle-hover: var(--canvas-700);
1338
1339
  --surface-subtle-active: var(--canvas-600);
1340
+ --surface-shimmer: oklch(from var(--canvas-base) calc(l * .45) c h);
1339
1341
  --surface-panel-scrollbar: var(--canvas-700);
1340
1342
  --surface-panel-scrollbar-thumb: var(--primary-400);
1341
1343
  }
@@ -1358,6 +1360,7 @@
1358
1360
  --surface-subtle: var(--canvas-50);
1359
1361
  --surface-subtle-hover: var(--canvas-100);
1360
1362
  --surface-subtle-active: var(--canvas-200);
1363
+ --surface-shimmer: var(--canvas-100);
1361
1364
  --surface-panel-scrollbar: var(--gray-50);
1362
1365
  --surface-panel-scrollbar-thumb: var(--primary-100);
1363
1366
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": false,
4
4
  "type": "module",
5
5
  "license": "MPL-2.0",
6
- "version": "2.6.0",
6
+ "version": "2.7.0",
7
7
  "engines": {
8
8
  "node": ">=20.9.0"
9
9
  },
@@ -62,7 +62,7 @@
62
62
  "npm-run-all": "^4.1.5",
63
63
  "react-day-picker": "^10.0.1",
64
64
  "zod": "^4.4.3",
65
- "@byline/core": "2.6.0"
65
+ "@byline/core": "2.7.0"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "react": "^19.0.0",
@@ -15,8 +15,8 @@
15
15
  :global(.byline-shimmer) {
16
16
  position: relative;
17
17
  overflow: hidden;
18
- background-color: #f0f0f0;
19
- background-image: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
18
+ background-color: var(--surface-shimmer);
19
+ background-image: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent);
20
20
  background-size: 200% 100%;
21
21
  animation: shimmer 1.5s infinite;
22
22
  }
@@ -25,8 +25,9 @@
25
25
  :global([data-theme="dark"]) {
26
26
  .shimmer,
27
27
  :global(.byline-shimmer) {
28
- background-color: #141414;
29
- background-image: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.01), transparent);
28
+ /* base colour comes from --surface-shimmer; only the white sheen is
29
+ toned down here so it doesn't glare against the dark bar */
30
+ background-image: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.04), transparent);
30
31
  }
31
32
  }
32
33
 
@@ -34,6 +35,9 @@
34
35
  :global(.byline-shimmer-container) {
35
36
  display: flex;
36
37
  flex-direction: column;
38
+ /* When a container `height` is set, crop overflowing lines cleanly
39
+ rather than letting them spill past the skeleton's bounds. */
40
+ overflow: hidden;
37
41
  }
38
42
 
39
43
  .rectangular,
@@ -7,29 +7,39 @@ import styles from './shimmer.module.css'
7
7
  interface ShimmerProps {
8
8
  className?: string
9
9
  width?: string | number
10
+ /**
11
+ * Height of the bar. For the single-bar variants (`rectangular`,
12
+ * `circular`, and single-line `text`) this sizes the bar itself. For the
13
+ * multi-line text variant (`variant="text"` with `lines > 1`) it sizes the
14
+ * container that holds the lines — use `lineHeight` to size each line.
15
+ */
10
16
  height?: string | number
17
+ /**
18
+ * Height of each line in the multi-line text variant (`variant="text"`
19
+ * with `lines > 1`). Falls back to the `.text` class height (1rem) when
20
+ * omitted. Ignored by the single-bar variants — use `height` there.
21
+ */
22
+ lineHeight?: string | number
11
23
  borderRadius?: string
12
24
  variant?: 'text' | 'rectangular' | 'circular'
13
25
  lines?: number
14
26
  children?: React.ReactNode
15
27
  }
16
28
 
29
+ const toCssSize = (value: string | number | undefined): string | undefined =>
30
+ typeof value === 'number' ? `${value}px` : value
31
+
17
32
  export function Shimmer({
18
33
  className,
19
34
  width = '100%',
20
- height = '1rem',
35
+ height,
36
+ lineHeight,
21
37
  borderRadius,
22
38
  variant = 'rectangular',
23
39
  lines = 1,
24
40
  children,
25
41
  ...other
26
42
  }: ShimmerProps): React.JSX.Element {
27
- const shimmerStyle = {
28
- width: typeof width === 'number' ? `${width}px` : width,
29
- height: typeof height === 'number' ? `${height}px` : height,
30
- borderRadius: borderRadius,
31
- }
32
-
33
43
  const getVariantClass = () => {
34
44
  switch (variant) {
35
45
  case 'text':
@@ -42,15 +52,24 @@ export function Shimmer({
42
52
  }
43
53
 
44
54
  if (variant === 'text' && lines > 1) {
55
+ // `height` sizes the container; each line is sized by `lineHeight`
56
+ // (undefined falls through to the `.text` class height). `height` is
57
+ // deliberately not spread onto the lines so it can't distort them.
58
+ const resolvedLineHeight = toCssSize(lineHeight)
45
59
  return (
46
- <div className={cx(styles.shimmerContainer, className)} {...other}>
60
+ <div
61
+ className={cx(styles.shimmerContainer, className)}
62
+ style={{ width: toCssSize(width), height: toCssSize(height) }}
63
+ {...other}
64
+ >
47
65
  {Array.from({ length: lines }, (_, index) => (
48
66
  <div
49
67
  key={`shimmer-line-${index}`}
50
68
  className={cx(styles.shimmer, styles.text)}
51
69
  style={{
52
- ...shimmerStyle,
53
70
  width: index === lines - 1 ? '75%' : '100%',
71
+ height: resolvedLineHeight,
72
+ borderRadius,
54
73
  marginBottom: index === lines - 1 ? 0 : '0.5rem',
55
74
  }}
56
75
  />
@@ -59,6 +78,12 @@ export function Shimmer({
59
78
  )
60
79
  }
61
80
 
81
+ const shimmerStyle = {
82
+ width: toCssSize(width),
83
+ height: toCssSize(height) ?? '1rem',
84
+ borderRadius,
85
+ }
86
+
62
87
  return (
63
88
  <div
64
89
  className={cx(styles.shimmer, getVariantClass(), className)}
@@ -39,12 +39,16 @@
39
39
  --surface-subtle-hover: var(--canvas-100);
40
40
  --surface-subtle-active: var(--canvas-200);
41
41
 
42
+ /* Shimmer / skeleton placeholder bar — sits a step darker than the
43
+ panel so loading lines read clearly on a light surface. */
44
+ --surface-shimmer: var(--canvas-100);
45
+
42
46
  /* Panel scrollers */
43
47
  --surface-panel-scrollbar: var(--gray-50);
44
48
  --surface-panel-scrollbar-thumb: var(--primary-100);
45
49
  }
46
50
 
47
- /* 🌙 Dark via `.dark` class or [data-theme="dark"] attribute.
51
+ /* 🌙 Dark via `.dark` class or [data-theme="dark"] attribute.
48
52
  * We rely on the consuming application to detect a user's
49
53
  * preferred color scheme - either by header or cookie, and to set
50
54
  * a root html class accordingly (for now), which unfortunately means
@@ -83,6 +87,11 @@
83
87
  --surface-subtle-hover: var(--canvas-700);
84
88
  --surface-subtle-active: var(--canvas-600);
85
89
 
90
+ /* Shimmer / skeleton placeholder bar — lifted just above the panel so
91
+ loading lines are visible without glaring on a dark surface. Sits
92
+ between canvas-800 (panel) and canvas-700 (hover). */
93
+ --surface-shimmer: oklch(from var(--canvas-base) calc(l * 0.45) c h);
94
+
86
95
  /* Panel scrollers */
87
96
  --surface-panel-scrollbar: var(--canvas-700);
88
97
  --surface-panel-scrollbar-thumb: var(--primary-400);
@@ -125,6 +134,9 @@
125
134
  --surface-subtle-hover: var(--canvas-100);
126
135
  --surface-subtle-active: var(--canvas-200);
127
136
 
137
+ /* Shimmer / skeleton placeholder bar */
138
+ --surface-shimmer: var(--canvas-100);
139
+
128
140
  /* Panel scrollers */
129
141
  --surface-panel-scrollbar: var(--gray-50);
130
142
  --surface-panel-scrollbar-thumb: var(--primary-100);