storybook-vrhythm 0.2.0 → 0.3.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.
package/dist/index.d.ts CHANGED
@@ -1,15 +1,66 @@
1
- import { DecoratorFunction } from '@storybook/types';
1
+ import { DecoratorFunction, Renderer } from 'storybook/internal/types';
2
2
 
3
3
  interface StyleProps {
4
4
  color?: string;
5
5
  lineHeight?: string | number;
6
6
  offset?: string | number;
7
+ opacity?: number;
8
+ zIndex?: number;
9
+ columnWidth?: string | number;
10
+ columnColor?: string;
7
11
  }
8
12
  interface ConfigProps {
9
13
  hide?: boolean;
14
+ preset?: string;
15
+ container?: string;
10
16
  }
11
17
 
18
+ declare module 'storybook/internal/types' {
19
+ interface StorybookParameters {
20
+ /** Vertical rhythm overlay options (storybook-vrhythm). */
21
+ vrhythm?: StyleProps & ConfigProps;
22
+ }
23
+ }
24
+ declare module 'storybook/internal/csf' {
25
+ interface Globals {
26
+ /** Toolbar toggle for the vertical rhythm overlay (`'true'` | `'false'` or boolean). */
27
+ vrhythm?: string | boolean;
28
+ }
29
+ }
30
+
31
+ declare const presets: {
32
+ readonly '4px': {
33
+ readonly lineHeight: "4px";
34
+ readonly color: "rgba(0, 150, 255, 0.15)";
35
+ };
36
+ readonly '8px': {
37
+ readonly lineHeight: "8px";
38
+ readonly color: "rgba(0, 150, 255, 0.2)";
39
+ };
40
+ readonly '16px': {
41
+ readonly lineHeight: "16px";
42
+ readonly color: "rgba(204, 204, 204, 0.5)";
43
+ };
44
+ readonly '24px': {
45
+ readonly lineHeight: "24px";
46
+ readonly color: "rgba(204, 204, 204, 0.5)";
47
+ };
48
+ readonly material: {
49
+ readonly lineHeight: "4px";
50
+ readonly color: "rgba(244, 67, 54, 0.15)";
51
+ };
52
+ readonly tailwind: {
53
+ readonly lineHeight: "4px";
54
+ readonly color: "rgba(99, 102, 241, 0.15)";
55
+ };
56
+ readonly bootstrap: {
57
+ readonly lineHeight: "8px";
58
+ readonly color: "rgba(13, 110, 253, 0.2)";
59
+ };
60
+ };
61
+ type PresetName = keyof typeof presets;
62
+
12
63
  type VRhythmParams = StyleProps & ConfigProps;
13
- declare const withVRhythm: DecoratorFunction;
64
+ declare const withVRhythm: DecoratorFunction<Renderer>;
14
65
 
15
- export { type ConfigProps, type StyleProps, type VRhythmParams, withVRhythm };
66
+ export { type ConfigProps, type PresetName, type StyleProps, type VRhythmParams, presets, withVRhythm };
package/dist/index.js CHANGED
@@ -2,6 +2,8 @@
2
2
  var DEFAULT_COLOR = "rgb(204, 204, 204)";
3
3
  var DEFAULT_LINE_HEIGHT = "16px";
4
4
  var DEFAULT_OFFSET = 0;
5
+ var DEFAULT_OPACITY = 1;
6
+ var DEFAULT_Z_INDEX = 9999;
5
7
  var PARENT_SELECTOR = "body";
6
8
  var DIV_ID = "storybook-rhythm";
7
9
 
@@ -9,16 +11,37 @@ var DIV_ID = "storybook-rhythm";
9
11
  var getStyle = ({
10
12
  color = DEFAULT_COLOR,
11
13
  lineHeight = DEFAULT_LINE_HEIGHT,
12
- offset = DEFAULT_OFFSET
13
- }) => ({
14
- position: "absolute",
15
- top: offset,
16
- left: 0,
17
- right: 0,
18
- bottom: 0,
19
- background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,
20
- pointerEvents: "none"
21
- });
14
+ offset = DEFAULT_OFFSET,
15
+ opacity = DEFAULT_OPACITY,
16
+ zIndex = DEFAULT_Z_INDEX,
17
+ columnWidth,
18
+ columnColor
19
+ }) => {
20
+ const horizontal = `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`;
21
+ const background = columnWidth != null ? `${horizontal}, linear-gradient(90deg, ${columnColor ?? color} 1px, transparent 1px) left top / ${columnWidth} 1px` : horizontal;
22
+ return {
23
+ position: "absolute",
24
+ top: offset,
25
+ left: 0,
26
+ right: 0,
27
+ bottom: 0,
28
+ background,
29
+ pointerEvents: "none",
30
+ opacity,
31
+ zIndex
32
+ };
33
+ };
34
+
35
+ // src/presets.ts
36
+ var presets = {
37
+ "4px": { lineHeight: "4px", color: "rgba(0, 150, 255, 0.15)" },
38
+ "8px": { lineHeight: "8px", color: "rgba(0, 150, 255, 0.2)" },
39
+ "16px": { lineHeight: "16px", color: "rgba(204, 204, 204, 0.5)" },
40
+ "24px": { lineHeight: "24px", color: "rgba(204, 204, 204, 0.5)" },
41
+ material: { lineHeight: "4px", color: "rgba(244, 67, 54, 0.15)" },
42
+ tailwind: { lineHeight: "4px", color: "rgba(99, 102, 241, 0.15)" },
43
+ bootstrap: { lineHeight: "8px", color: "rgba(13, 110, 253, 0.2)" }
44
+ };
22
45
 
23
46
  // src/utils.ts
24
47
  function createElement() {
@@ -39,11 +62,11 @@ function removeElement() {
39
62
  element.remove();
40
63
  }
41
64
  }
42
- function injectStyle(style) {
65
+ function injectStyle(style, container) {
43
66
  const element = getOrCreateElement();
44
67
  Object.assign(element.style, style);
45
68
  if (!element.parentNode) {
46
- const parent = document.querySelector(PARENT_SELECTOR);
69
+ const parent = document.querySelector(container ?? PARENT_SELECTOR);
47
70
  if (parent) {
48
71
  parent.append(element);
49
72
  }
@@ -53,24 +76,33 @@ function injectStyle(style) {
53
76
  // src/index.ts
54
77
  var DEFAULT_PARAMS = {
55
78
  hide: false,
79
+ preset: "",
80
+ container: "",
56
81
  color: DEFAULT_COLOR,
57
82
  lineHeight: DEFAULT_LINE_HEIGHT,
58
- offset: DEFAULT_OFFSET
83
+ offset: DEFAULT_OFFSET,
84
+ opacity: DEFAULT_OPACITY,
85
+ zIndex: DEFAULT_Z_INDEX
59
86
  };
60
87
  var withVRhythm = (storyFn, context) => {
88
+ const raw = context.parameters?.vrhythm;
89
+ const presetStyles = raw?.preset && raw.preset in presets ? presets[raw.preset] : {};
61
90
  const params = {
62
91
  ...DEFAULT_PARAMS,
63
- ...context.parameters?.vrhythm
92
+ ...presetStyles,
93
+ ...raw
64
94
  };
65
- if (params.hide) {
95
+ const globalsVrhythm = context.globals?.vrhythm;
96
+ const isHidden = !!params.hide || globalsVrhythm === false || globalsVrhythm === "false";
97
+ if (isHidden) {
66
98
  removeElement();
67
99
  } else {
68
100
  const style = getStyle(params);
69
- injectStyle(style);
101
+ injectStyle(style, params.container || void 0);
70
102
  }
71
103
  return storyFn(context);
72
104
  };
73
105
 
74
- export { withVRhythm };
106
+ export { presets, withVRhythm };
75
107
  //# sourceMappingURL=index.js.map
76
108
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/utils.ts","../src/index.ts"],"names":[],"mappings":";AAAO,IAAM,aAAA,GAAgB,oBAAA;AACtB,IAAM,mBAAA,GAAsB,MAAA;AAC5B,IAAM,cAAA,GAAiB,CAAA;AACvB,IAAM,eAAA,GAAkB,MAAA;AACxB,IAAM,MAAA,GAAS,kBAAA;;;ACGf,IAAM,WAAW,CAAC;AAAA,EACvB,KAAA,GAAQ,aAAA;AAAA,EACR,UAAA,GAAa,mBAAA;AAAA,EACb,MAAA,GAAS;AACX,CAAA,MAA6B;AAAA,EAC3B,QAAA,EAAU,UAAA;AAAA,EACV,GAAA,EAAK,MAAA;AAAA,EACL,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO,CAAA;AAAA,EACP,MAAA,EAAQ,CAAA;AAAA,EACR,UAAA,EAAY,CAAA,gBAAA,EAAmB,KAAK,CAAA,sCAAA,EAAyC,UAAU,CAAA,CAAA;AAAA,EACvF,aAAA,EAAe;AACjB,CAAA,CAAA;;;AChBA,SAAS,aAAA,GAAgC;AACvC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,YAAA,CAAa,MAAM,MAAM,CAAA;AACjC,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,kBAAA,GAAqC;AAC5C,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC/C,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAO,aAAA,EAAc;AACvB;AAEO,SAAS,aAAA,GAAsB;AACpC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC9C,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,EACjB;AACF;AAEO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,MAAM,UAAU,kBAAA,EAAmB;AACnC,EAAA,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA;AAElC,EAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACvB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,eAAe,CAAA;AACrD,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,OAAO,OAAO,CAAA;AAAA,IACvB;AAAA,EACF;AACF;;;ACrBA,IAAM,cAAA,GAA0C;AAAA,EAC9C,IAAA,EAAM,KAAA;AAAA,EACN,KAAA,EAAO,aAAA;AAAA,EACP,UAAA,EAAY,mBAAA;AAAA,EACZ,MAAA,EAAQ;AACV,CAAA;AAEO,IAAM,WAAA,GAAiC,CAAC,OAAA,EAAS,OAAA,KAAY;AAClE,EAAA,MAAM,MAAA,GAAkC;AAAA,IACtC,GAAG,cAAA;AAAA,IACH,GAAI,QAAQ,UAAA,EAAwD;AAAA,GACtE;AAEA,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,MAAO;AACL,IAAA,MAAM,KAAA,GAAQ,SAAS,MAAM,CAAA;AAC7B,IAAA,WAAA,CAAY,KAAK,CAAA;AAAA,EACnB;AAEA,EAAA,OAAO,QAAQ,OAAO,CAAA;AACxB","file":"index.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_OFFSET = 0;\nexport const PARENT_SELECTOR = 'body';\nexport const DIV_ID = 'storybook-rhythm';\n","import { StyleObj, StyleProps } from './types';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n}: StyleProps): StyleObj => ({\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,\n pointerEvents: 'none',\n});\n","import { PARENT_SELECTOR, DIV_ID } from './constants';\nimport { StyleObj } from './types';\n\nfunction createElement(): HTMLDivElement {\n const element = document.createElement('div');\n element.setAttribute('id', DIV_ID);\n return element;\n}\n\nfunction getOrCreateElement(): HTMLDivElement {\n const existing = document.getElementById(DIV_ID) as HTMLDivElement | null;\n if (existing) {\n return existing;\n }\n return createElement();\n}\n\nexport function removeElement(): void {\n const element = document.getElementById(DIV_ID);\n if (element) {\n element.remove();\n }\n}\n\nexport function injectStyle(style: StyleObj): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import type { DecoratorFunction } from '@storybook/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: Required<VRhythmParams> = {\n hide: false,\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n};\n\nexport const withVRhythm: DecoratorFunction = (storyFn, context) => {\n const params: Required<VRhythmParams> = {\n ...DEFAULT_PARAMS,\n ...(context.parameters as { vrhythm?: VRhythmParams } | undefined)?.vrhythm,\n };\n\n if (params.hide) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style);\n }\n\n return storyFn(context);\n};\n\nexport type { StyleProps, ConfigProps } from './types';\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/presets.ts","../src/utils.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_OPACITY = 1;\nexport const DEFAULT_Z_INDEX = 9999;\nexport const PARENT_SELECTOR = 'body';\nexport const DIV_ID = 'storybook-rhythm';\n","import { StyleObj, StyleProps } from './types';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n opacity = DEFAULT_OPACITY,\n zIndex = DEFAULT_Z_INDEX,\n columnWidth,\n columnColor,\n}: StyleProps): StyleObj => {\n const horizontal = `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`;\n\n const background =\n columnWidth != null\n ? `${horizontal}, linear-gradient(90deg, ${columnColor ?? color} 1px, transparent 1px) left top / ${columnWidth} 1px`\n : horizontal;\n\n return {\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background,\n pointerEvents: 'none',\n opacity,\n zIndex,\n };\n};\n","import type { StyleProps } from './types';\n\nexport const presets = {\n '4px': { lineHeight: '4px', color: 'rgba(0, 150, 255, 0.15)' },\n '8px': { lineHeight: '8px', color: 'rgba(0, 150, 255, 0.2)' },\n '16px': { lineHeight: '16px', color: 'rgba(204, 204, 204, 0.5)' },\n '24px': { lineHeight: '24px', color: 'rgba(204, 204, 204, 0.5)' },\n material: { lineHeight: '4px', color: 'rgba(244, 67, 54, 0.15)' },\n tailwind: { lineHeight: '4px', color: 'rgba(99, 102, 241, 0.15)' },\n bootstrap: { lineHeight: '8px', color: 'rgba(13, 110, 253, 0.2)' },\n} as const satisfies Record<string, StyleProps>;\n\nexport type PresetName = keyof typeof presets;\n","import { PARENT_SELECTOR, DIV_ID } from './constants';\nimport { StyleObj } from './types';\n\nfunction createElement(): HTMLDivElement {\n const element = document.createElement('div');\n element.setAttribute('id', DIV_ID);\n return element;\n}\n\nfunction getOrCreateElement(): HTMLDivElement {\n const existing = document.getElementById(DIV_ID) as HTMLDivElement | null;\n if (existing) {\n return existing;\n }\n return createElement();\n}\n\nexport function removeElement(): void {\n const element = document.getElementById(DIV_ID);\n if (element) {\n element.remove();\n }\n}\n\nexport function injectStyle(style: StyleObj, container?: string): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(container ?? PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import './storybook-parameter-augmentation';\n\nimport type { DecoratorFunction, Renderer } from 'storybook/internal/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { presets, PresetName } from './presets';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: VRhythmParams = {\n hide: false,\n preset: '',\n container: '',\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n opacity: DEFAULT_OPACITY,\n zIndex: DEFAULT_Z_INDEX,\n};\n\nexport const withVRhythm: DecoratorFunction<Renderer> = (storyFn, context) => {\n const raw = (context.parameters as { vrhythm?: VRhythmParams } | undefined)\n ?.vrhythm;\n const presetStyles =\n raw?.preset && raw.preset in presets\n ? presets[raw.preset as PresetName]\n : {};\n const params: VRhythmParams = {\n ...DEFAULT_PARAMS,\n ...presetStyles,\n ...raw,\n };\n\n const globalsVrhythm = (\n context.globals as { vrhythm?: string | boolean } | undefined\n )?.vrhythm;\n const isHidden =\n !!params.hide || globalsVrhythm === false || globalsVrhythm === 'false';\n\n if (isHidden) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style, params.container || undefined);\n }\n\n return storyFn(context);\n};\n\nexport { presets } from './presets';\nexport type { PresetName } from './presets';\nexport type { StyleProps, ConfigProps } from './types';\n"]}
package/dist/preset.js CHANGED
@@ -1,11 +1 @@
1
- // src/preset.ts
2
- import { dirname, join } from "path";
3
- import { fileURLToPath } from "url";
4
- var dir = dirname(fileURLToPath(import.meta.url));
5
- function previewAnnotations(entry = []) {
6
- return [...entry, join(dir, "preview.js")];
7
- }
8
- export {
9
- previewAnnotations
10
- };
11
1
  //# sourceMappingURL=preset.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/preset.ts"],"sourcesContent":["import { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst dir = dirname(fileURLToPath(import.meta.url));\n\nexport function previewAnnotations(entry: string[] = []) {\n return [...entry, join(dir, 'preview.js')];\n}\n"],"mappings":";AAAA,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAE9B,IAAM,MAAM,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE3C,SAAS,mBAAmB,QAAkB,CAAC,GAAG;AACvD,SAAO,CAAC,GAAG,OAAO,KAAK,KAAK,YAAY,CAAC;AAC3C;","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/preview.d.ts CHANGED
@@ -1,5 +1,14 @@
1
- import { ProjectAnnotations, Renderer } from '@storybook/types';
1
+ import * as storybook_internal_csf from 'storybook/internal/csf';
2
+ import { VRhythmParams } from './index.js';
3
+ import 'storybook/internal/types';
2
4
 
3
- declare const preview: ProjectAnnotations<Renderer>;
5
+ declare const _default: storybook_internal_csf.PreviewAddon<{
6
+ parameters: {
7
+ vrhythm?: VRhythmParams;
8
+ };
9
+ globals: {
10
+ vrhythm?: string | boolean;
11
+ };
12
+ }>;
4
13
 
5
- export { preview as default };
14
+ export { _default as default };
package/dist/preview.js CHANGED
@@ -1,7 +1,13 @@
1
+ import { definePreviewAddon } from 'storybook/internal/csf';
2
+
3
+ // src/preview.ts
4
+
1
5
  // src/constants.ts
2
6
  var DEFAULT_COLOR = "rgb(204, 204, 204)";
3
7
  var DEFAULT_LINE_HEIGHT = "16px";
4
8
  var DEFAULT_OFFSET = 0;
9
+ var DEFAULT_OPACITY = 1;
10
+ var DEFAULT_Z_INDEX = 9999;
5
11
  var PARENT_SELECTOR = "body";
6
12
  var DIV_ID = "storybook-rhythm";
7
13
 
@@ -9,16 +15,37 @@ var DIV_ID = "storybook-rhythm";
9
15
  var getStyle = ({
10
16
  color = DEFAULT_COLOR,
11
17
  lineHeight = DEFAULT_LINE_HEIGHT,
12
- offset = DEFAULT_OFFSET
13
- }) => ({
14
- position: "absolute",
15
- top: offset,
16
- left: 0,
17
- right: 0,
18
- bottom: 0,
19
- background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,
20
- pointerEvents: "none"
21
- });
18
+ offset = DEFAULT_OFFSET,
19
+ opacity = DEFAULT_OPACITY,
20
+ zIndex = DEFAULT_Z_INDEX,
21
+ columnWidth,
22
+ columnColor
23
+ }) => {
24
+ const horizontal = `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`;
25
+ const background = columnWidth != null ? `${horizontal}, linear-gradient(90deg, ${columnColor ?? color} 1px, transparent 1px) left top / ${columnWidth} 1px` : horizontal;
26
+ return {
27
+ position: "absolute",
28
+ top: offset,
29
+ left: 0,
30
+ right: 0,
31
+ bottom: 0,
32
+ background,
33
+ pointerEvents: "none",
34
+ opacity,
35
+ zIndex
36
+ };
37
+ };
38
+
39
+ // src/presets.ts
40
+ var presets = {
41
+ "4px": { lineHeight: "4px", color: "rgba(0, 150, 255, 0.15)" },
42
+ "8px": { lineHeight: "8px", color: "rgba(0, 150, 255, 0.2)" },
43
+ "16px": { lineHeight: "16px", color: "rgba(204, 204, 204, 0.5)" },
44
+ "24px": { lineHeight: "24px", color: "rgba(204, 204, 204, 0.5)" },
45
+ material: { lineHeight: "4px", color: "rgba(244, 67, 54, 0.15)" },
46
+ tailwind: { lineHeight: "4px", color: "rgba(99, 102, 241, 0.15)" },
47
+ bootstrap: { lineHeight: "8px", color: "rgba(13, 110, 253, 0.2)" }
48
+ };
22
49
 
23
50
  // src/utils.ts
24
51
  function createElement() {
@@ -39,11 +66,11 @@ function removeElement() {
39
66
  element.remove();
40
67
  }
41
68
  }
42
- function injectStyle(style) {
69
+ function injectStyle(style, container) {
43
70
  const element = getOrCreateElement();
44
71
  Object.assign(element.style, style);
45
72
  if (!element.parentNode) {
46
- const parent = document.querySelector(PARENT_SELECTOR);
73
+ const parent = document.querySelector(container ?? PARENT_SELECTOR);
47
74
  if (parent) {
48
75
  parent.append(element);
49
76
  }
@@ -53,29 +80,54 @@ function injectStyle(style) {
53
80
  // src/index.ts
54
81
  var DEFAULT_PARAMS = {
55
82
  hide: false,
83
+ preset: "",
84
+ container: "",
56
85
  color: DEFAULT_COLOR,
57
86
  lineHeight: DEFAULT_LINE_HEIGHT,
58
- offset: DEFAULT_OFFSET
87
+ offset: DEFAULT_OFFSET,
88
+ opacity: DEFAULT_OPACITY,
89
+ zIndex: DEFAULT_Z_INDEX
59
90
  };
60
91
  var withVRhythm = (storyFn, context) => {
92
+ const raw = context.parameters?.vrhythm;
93
+ const presetStyles = raw?.preset && raw.preset in presets ? presets[raw.preset] : {};
61
94
  const params = {
62
95
  ...DEFAULT_PARAMS,
63
- ...context.parameters?.vrhythm
96
+ ...presetStyles,
97
+ ...raw
64
98
  };
65
- if (params.hide) {
99
+ const globalsVrhythm = context.globals?.vrhythm;
100
+ const isHidden = !!params.hide || globalsVrhythm === false || globalsVrhythm === "false";
101
+ if (isHidden) {
66
102
  removeElement();
67
103
  } else {
68
104
  const style = getStyle(params);
69
- injectStyle(style);
105
+ injectStyle(style, params.container || void 0);
70
106
  }
71
107
  return storyFn(context);
72
108
  };
73
109
 
74
110
  // src/preview.ts
75
- var preview = {
76
- decorators: [withVRhythm]
77
- };
78
- var preview_default = preview;
111
+ var preview_default = definePreviewAddon({
112
+ decorators: [withVRhythm],
113
+ globalTypes: {
114
+ vrhythm: {
115
+ description: "Toggle vertical rhythm grid overlay",
116
+ toolbar: {
117
+ title: "V-Rhythm",
118
+ icon: "grid",
119
+ items: [
120
+ { value: "true", title: "Show grid", icon: "eye" },
121
+ { value: "false", title: "Hide grid", icon: "eyeclose" }
122
+ ],
123
+ dynamicTitle: true
124
+ }
125
+ }
126
+ },
127
+ initialGlobals: {
128
+ vrhythm: "true"
129
+ }
130
+ });
79
131
 
80
132
  export { preview_default as default };
81
133
  //# sourceMappingURL=preview.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/utils.ts","../src/index.ts","../src/preview.ts"],"names":[],"mappings":";AAAO,IAAM,aAAA,GAAgB,oBAAA;AACtB,IAAM,mBAAA,GAAsB,MAAA;AAC5B,IAAM,cAAA,GAAiB,CAAA;AACvB,IAAM,eAAA,GAAkB,MAAA;AACxB,IAAM,MAAA,GAAS,kBAAA;;;ACGf,IAAM,WAAW,CAAC;AAAA,EACvB,KAAA,GAAQ,aAAA;AAAA,EACR,UAAA,GAAa,mBAAA;AAAA,EACb,MAAA,GAAS;AACX,CAAA,MAA6B;AAAA,EAC3B,QAAA,EAAU,UAAA;AAAA,EACV,GAAA,EAAK,MAAA;AAAA,EACL,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO,CAAA;AAAA,EACP,MAAA,EAAQ,CAAA;AAAA,EACR,UAAA,EAAY,CAAA,gBAAA,EAAmB,KAAK,CAAA,sCAAA,EAAyC,UAAU,CAAA,CAAA;AAAA,EACvF,aAAA,EAAe;AACjB,CAAA,CAAA;;;AChBA,SAAS,aAAA,GAAgC;AACvC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,YAAA,CAAa,MAAM,MAAM,CAAA;AACjC,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,kBAAA,GAAqC;AAC5C,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC/C,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAO,aAAA,EAAc;AACvB;AAEO,SAAS,aAAA,GAAsB;AACpC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAC9C,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,EACjB;AACF;AAEO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,MAAM,UAAU,kBAAA,EAAmB;AACnC,EAAA,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA;AAElC,EAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACvB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,eAAe,CAAA;AACrD,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,OAAO,OAAO,CAAA;AAAA,IACvB;AAAA,EACF;AACF;;;ACrBA,IAAM,cAAA,GAA0C;AAAA,EAC9C,IAAA,EAAM,KAAA;AAAA,EACN,KAAA,EAAO,aAAA;AAAA,EACP,UAAA,EAAY,mBAAA;AAAA,EACZ,MAAA,EAAQ;AACV,CAAA;AAEO,IAAM,WAAA,GAAiC,CAAC,OAAA,EAAS,OAAA,KAAY;AAClE,EAAA,MAAM,MAAA,GAAkC;AAAA,IACtC,GAAG,cAAA;AAAA,IACH,GAAI,QAAQ,UAAA,EAAwD;AAAA,GACtE;AAEA,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,MAAO;AACL,IAAA,MAAM,KAAA,GAAQ,SAAS,MAAM,CAAA;AAC7B,IAAA,WAAA,CAAY,KAAK,CAAA;AAAA,EACnB;AAEA,EAAA,OAAO,QAAQ,OAAO,CAAA;AACxB,CAAA;;;AC9BA,IAAM,OAAA,GAAwC;AAAA,EAC5C,UAAA,EAAY,CAAC,WAAW;AAC1B,CAAA;AAEA,IAAO,eAAA,GAAQ","file":"preview.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_OFFSET = 0;\nexport const PARENT_SELECTOR = 'body';\nexport const DIV_ID = 'storybook-rhythm';\n","import { StyleObj, StyleProps } from './types';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n}: StyleProps): StyleObj => ({\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background: `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`,\n pointerEvents: 'none',\n});\n","import { PARENT_SELECTOR, DIV_ID } from './constants';\nimport { StyleObj } from './types';\n\nfunction createElement(): HTMLDivElement {\n const element = document.createElement('div');\n element.setAttribute('id', DIV_ID);\n return element;\n}\n\nfunction getOrCreateElement(): HTMLDivElement {\n const existing = document.getElementById(DIV_ID) as HTMLDivElement | null;\n if (existing) {\n return existing;\n }\n return createElement();\n}\n\nexport function removeElement(): void {\n const element = document.getElementById(DIV_ID);\n if (element) {\n element.remove();\n }\n}\n\nexport function injectStyle(style: StyleObj): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import type { DecoratorFunction } from '@storybook/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: Required<VRhythmParams> = {\n hide: false,\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n};\n\nexport const withVRhythm: DecoratorFunction = (storyFn, context) => {\n const params: Required<VRhythmParams> = {\n ...DEFAULT_PARAMS,\n ...(context.parameters as { vrhythm?: VRhythmParams } | undefined)?.vrhythm,\n };\n\n if (params.hide) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style);\n }\n\n return storyFn(context);\n};\n\nexport type { StyleProps, ConfigProps } from './types';\n","import type { ProjectAnnotations, Renderer } from '@storybook/types';\n\nimport { withVRhythm } from './index';\n\nconst preview: ProjectAnnotations<Renderer> = {\n decorators: [withVRhythm],\n};\n\nexport default preview;\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/getStyle.ts","../src/presets.ts","../src/utils.ts","../src/index.ts","../src/preview.ts"],"names":[],"mappings":"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","file":"preview.js","sourcesContent":["export const DEFAULT_COLOR = 'rgb(204, 204, 204)';\nexport const DEFAULT_LINE_HEIGHT = '16px';\nexport const DEFAULT_OFFSET = 0;\nexport const DEFAULT_OPACITY = 1;\nexport const DEFAULT_Z_INDEX = 9999;\nexport const PARENT_SELECTOR = 'body';\nexport const DIV_ID = 'storybook-rhythm';\n","import { StyleObj, StyleProps } from './types';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport const getStyle = ({\n color = DEFAULT_COLOR,\n lineHeight = DEFAULT_LINE_HEIGHT,\n offset = DEFAULT_OFFSET,\n opacity = DEFAULT_OPACITY,\n zIndex = DEFAULT_Z_INDEX,\n columnWidth,\n columnColor,\n}: StyleProps): StyleObj => {\n const horizontal = `linear-gradient(${color} 1px, transparent 1px) left top / 1px ${lineHeight}`;\n\n const background =\n columnWidth != null\n ? `${horizontal}, linear-gradient(90deg, ${columnColor ?? color} 1px, transparent 1px) left top / ${columnWidth} 1px`\n : horizontal;\n\n return {\n position: 'absolute',\n top: offset,\n left: 0,\n right: 0,\n bottom: 0,\n background,\n pointerEvents: 'none',\n opacity,\n zIndex,\n };\n};\n","import type { StyleProps } from './types';\n\nexport const presets = {\n '4px': { lineHeight: '4px', color: 'rgba(0, 150, 255, 0.15)' },\n '8px': { lineHeight: '8px', color: 'rgba(0, 150, 255, 0.2)' },\n '16px': { lineHeight: '16px', color: 'rgba(204, 204, 204, 0.5)' },\n '24px': { lineHeight: '24px', color: 'rgba(204, 204, 204, 0.5)' },\n material: { lineHeight: '4px', color: 'rgba(244, 67, 54, 0.15)' },\n tailwind: { lineHeight: '4px', color: 'rgba(99, 102, 241, 0.15)' },\n bootstrap: { lineHeight: '8px', color: 'rgba(13, 110, 253, 0.2)' },\n} as const satisfies Record<string, StyleProps>;\n\nexport type PresetName = keyof typeof presets;\n","import { PARENT_SELECTOR, DIV_ID } from './constants';\nimport { StyleObj } from './types';\n\nfunction createElement(): HTMLDivElement {\n const element = document.createElement('div');\n element.setAttribute('id', DIV_ID);\n return element;\n}\n\nfunction getOrCreateElement(): HTMLDivElement {\n const existing = document.getElementById(DIV_ID) as HTMLDivElement | null;\n if (existing) {\n return existing;\n }\n return createElement();\n}\n\nexport function removeElement(): void {\n const element = document.getElementById(DIV_ID);\n if (element) {\n element.remove();\n }\n}\n\nexport function injectStyle(style: StyleObj, container?: string): void {\n const element = getOrCreateElement();\n Object.assign(element.style, style);\n\n if (!element.parentNode) {\n const parent = document.querySelector(container ?? PARENT_SELECTOR);\n if (parent) {\n parent.append(element);\n }\n }\n}\n","import './storybook-parameter-augmentation';\n\nimport type { DecoratorFunction, Renderer } from 'storybook/internal/types';\n\nimport { getStyle } from './getStyle';\nimport { StyleProps, ConfigProps } from './types';\nimport { presets, PresetName } from './presets';\nimport { injectStyle, removeElement } from './utils';\nimport {\n DEFAULT_COLOR,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_OFFSET,\n DEFAULT_OPACITY,\n DEFAULT_Z_INDEX,\n} from './constants';\n\nexport type VRhythmParams = StyleProps & ConfigProps;\n\nconst DEFAULT_PARAMS: VRhythmParams = {\n hide: false,\n preset: '',\n container: '',\n color: DEFAULT_COLOR,\n lineHeight: DEFAULT_LINE_HEIGHT,\n offset: DEFAULT_OFFSET,\n opacity: DEFAULT_OPACITY,\n zIndex: DEFAULT_Z_INDEX,\n};\n\nexport const withVRhythm: DecoratorFunction<Renderer> = (storyFn, context) => {\n const raw = (context.parameters as { vrhythm?: VRhythmParams } | undefined)\n ?.vrhythm;\n const presetStyles =\n raw?.preset && raw.preset in presets\n ? presets[raw.preset as PresetName]\n : {};\n const params: VRhythmParams = {\n ...DEFAULT_PARAMS,\n ...presetStyles,\n ...raw,\n };\n\n const globalsVrhythm = (\n context.globals as { vrhythm?: string | boolean } | undefined\n )?.vrhythm;\n const isHidden =\n !!params.hide || globalsVrhythm === false || globalsVrhythm === 'false';\n\n if (isHidden) {\n removeElement();\n } else {\n const style = getStyle(params);\n injectStyle(style, params.container || undefined);\n }\n\n return storyFn(context);\n};\n\nexport { presets } from './presets';\nexport type { PresetName } from './presets';\nexport type { StyleProps, ConfigProps } from './types';\n","import { definePreviewAddon } from 'storybook/internal/csf';\n\nimport { withVRhythm, type VRhythmParams } from './index';\n\nexport default definePreviewAddon<{\n parameters: { vrhythm?: VRhythmParams };\n globals: { vrhythm?: string | boolean };\n}>({\n decorators: [withVRhythm],\n globalTypes: {\n vrhythm: {\n description: 'Toggle vertical rhythm grid overlay',\n toolbar: {\n title: 'V-Rhythm',\n icon: 'grid',\n items: [\n { value: 'true', title: 'Show grid', icon: 'eye' },\n { value: 'false', title: 'Hide grid', icon: 'eyeclose' },\n ],\n dynamicTitle: true,\n },\n },\n },\n initialGlobals: {\n vrhythm: 'true',\n },\n});\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "storybook-vrhythm",
3
- "version": "0.2.0",
4
- "description": "Storybook decorator and preset addon for vertical rhythm baseline guides",
3
+ "version": "0.3.0",
4
+ "description": "Baseline grid overlay for Storybook — see your vertical rhythm while you build",
5
5
  "license": "MIT",
6
6
  "author": "jmlweb",
7
7
  "homepage": "https://github.com/jmlweb/storybook-vrhythm",
@@ -11,13 +11,18 @@
11
11
  },
12
12
  "keywords": [
13
13
  "storybook-addon",
14
- "style",
15
- "debug",
16
- "layout",
17
- "baseline",
18
- "vertical-rhythm",
19
14
  "storybook",
20
- "decorator"
15
+ "vertical-rhythm",
16
+ "baseline-grid",
17
+ "typography",
18
+ "layout",
19
+ "design-system",
20
+ "css-grid",
21
+ "decorator",
22
+ "debug",
23
+ "spacing",
24
+ "material-design",
25
+ "tailwind"
21
26
  ],
22
27
  "type": "module",
23
28
  "main": "./dist/index.js",
@@ -34,7 +39,10 @@
34
39
  "import": "./dist/preview.js",
35
40
  "default": "./dist/preview.js"
36
41
  },
37
- "./preset": "./dist/preset.js",
42
+ "./preset": {
43
+ "import": "./dist/preset.js",
44
+ "default": "./dist/preset.js"
45
+ },
38
46
  "./package.json": "./package.json"
39
47
  },
40
48
  "files": [
@@ -45,22 +53,29 @@
45
53
  "node": ">=20"
46
54
  },
47
55
  "peerDependencies": {
48
- "storybook": "^8.0.0 || ^9.0.0 || ^10.0.0"
56
+ "storybook": "^10.0.0 || ^11.0.0"
49
57
  },
50
58
  "storybook": {
51
- "displayName": "Vertical rhythm",
59
+ "displayName": "Vertical Rhythm Grid",
52
60
  "supportedFrameworks": [
53
61
  "react",
54
62
  "vue",
55
63
  "angular",
56
64
  "web-components",
57
- "ember",
58
- "html",
59
- "svelte",
60
- "preact",
61
- "react-native"
65
+ "html-vite",
66
+ "svelte"
62
67
  ]
63
68
  },
69
+ "scripts": {
70
+ "build": "tsup",
71
+ "dev": "tsup --watch",
72
+ "test": "vitest run",
73
+ "test:watch": "vitest",
74
+ "test:coverage": "vitest run --coverage",
75
+ "lint": "tsc --noEmit",
76
+ "format": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
77
+ "format:check": "prettier --check 'src/**/*.ts' 'test/**/*.ts'"
78
+ },
64
79
  "prettier": {
65
80
  "printWidth": 80,
66
81
  "semi": true,
@@ -68,24 +83,13 @@
68
83
  "trailingComma": "es5"
69
84
  },
70
85
  "devDependencies": {
71
- "@storybook/types": "^8.6.14",
72
86
  "@types/node": "^25.5.0",
73
87
  "@vitest/coverage-v8": "^4.1.2",
74
88
  "jsdom": "^29.0.1",
75
89
  "prettier": "^3.5.3",
76
- "storybook": "^8.6.18",
90
+ "storybook": "^10.0.0",
77
91
  "tsup": "^8.5.1",
78
92
  "typescript": "^5.9.3",
79
93
  "vitest": "^4.1.2"
80
- },
81
- "scripts": {
82
- "build": "tsup",
83
- "dev": "tsup --watch",
84
- "test": "vitest run",
85
- "test:watch": "vitest",
86
- "test:coverage": "vitest run --coverage",
87
- "lint": "tsc --noEmit",
88
- "format": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
89
- "format:check": "prettier --check 'src/**/*.ts' 'test/**/*.ts'"
90
94
  }
91
- }
95
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2019 JosÃĐ Manuel Lucas
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,151 +0,0 @@
1
- # 📐 storybook-vrhythm
2
-
3
- [![npm package][npm-badge]][npm]
4
- [![License: MIT][license-badge]][license]
5
- [![Bundle Size](https://img.shields.io/bundlephobia/minzip/storybook-vrhythm)](https://bundlephobia.com/package/storybook-vrhythm)
6
-
7
- **A Storybook decorator that overlays vertical rhythm guide lines on your stories.**
8
- Verify that your components align to a baseline grid — with zero effort.
9
-
10
- ![Vertical rhythm overlay example](storybook-vrhythm.jpg)
11
-
12
- ## âœĻ Features
13
-
14
- - ðŸŽŊ **Framework agnostic** — Works with React, Vue, Angular, Svelte, and any Storybook-supported framework
15
- - ðŸŽĻ **Fully customizable** — Color, line height, offset, and visibility per story
16
- - ðŸŠķ **Lightweight** — Pure CSS overlay using `linear-gradient` (no images, no canvas)
17
- - ðŸ–ąïļ **Non-intrusive** — Overlay doesn't interfere with pointer events
18
- - ⚡ **Zero config** — Works out of the box with sensible defaults
19
-
20
- ## ðŸ“Ķ Installation
21
-
22
- <details open>
23
- <summary><strong>pnpm</strong></summary>
24
-
25
- ```bash
26
- pnpm add -D storybook-vrhythm
27
- ```
28
-
29
- </details>
30
-
31
- <details>
32
- <summary><strong>npm</strong></summary>
33
-
34
- ```bash
35
- npm install --save-dev storybook-vrhythm
36
- ```
37
-
38
- </details>
39
-
40
- <details>
41
- <summary><strong>yarn</strong></summary>
42
-
43
- ```bash
44
- yarn add -D storybook-vrhythm
45
- ```
46
-
47
- </details>
48
-
49
- ## 🚀 Usage
50
-
51
- This package is a **Storybook preset addon**: you can register it in `main` (recommended) or add the decorator manually in `preview`.
52
-
53
- **Requirements:** Node.js 18+ and Storybook 8 or newer (see `peerDependencies` in `package.json`).
54
-
55
- ### Register as an addon (recommended)
56
-
57
- Add the package to `addons` in `.storybook/main.ts` (or `main.js`). Storybook loads the preset and applies the vertical rhythm decorator in the preview iframe.
58
-
59
- ```typescript
60
- import type { StorybookConfig } from '@storybook/react-vite'; // or your framework package
61
-
62
- const config = {
63
- addons: ['storybook-vrhythm'],
64
- } satisfies StorybookConfig;
65
-
66
- export default config;
67
- ```
68
-
69
- Optional defaults and overrides still use `parameters.vrhythm` in `.storybook/preview.ts`:
70
-
71
- ```typescript
72
- export const parameters = {
73
- vrhythm: {
74
- color: 'rgba(178, 86, 18, 0.5)',
75
- lineHeight: '16px',
76
- offset: 0,
77
- },
78
- };
79
- ```
80
-
81
- ### Manual decorator
82
-
83
- If you prefer not to use the preset, import the decorator in `.storybook/preview.ts`:
84
-
85
- ```typescript
86
- import { withVRhythm } from 'storybook-vrhythm';
87
-
88
- export const decorators = [withVRhythm];
89
-
90
- export const parameters = {
91
- vrhythm: {
92
- color: 'rgba(178, 86, 18, 0.5)',
93
- lineHeight: '16px',
94
- offset: 0,
95
- },
96
- };
97
- ```
98
-
99
- ### Per-story configuration
100
-
101
- Override or hide the overlay on individual stories:
102
-
103
- ```typescript
104
- export const MyStory = {
105
- parameters: {
106
- vrhythm: {
107
- hide: true,
108
- },
109
- },
110
- };
111
- ```
112
-
113
- ## ⚙ïļ Options
114
-
115
- | Option | Type | Default | Description |
116
- | ------------ | ------------------ | ---------------------- | ------------------------------------------ |
117
- | `color` | `string` | `'rgb(204, 204, 204)'` | Any valid CSS color for the guide lines |
118
- | `lineHeight` | `string \| number` | `'16px'` | Baseline grid height (e.g. `16px`, `1rem`) |
119
- | `offset` | `string \| number` | `0` | Vertical offset from the top |
120
- | `hide` | `boolean` | `false` | Hide the overlay for specific stories |
121
-
122
- ## ðŸ’Ą Why vertical rhythm?
123
-
124
- Vertical rhythm is the practice of spacing elements on a page based on a consistent baseline grid. It improves readability and creates a sense of visual harmony. This decorator lets you **see** the grid while developing, so you can catch alignment issues before they reach production.
125
-
126
- ## 🛠ïļ Development
127
-
128
- ```bash
129
- pnpm install # Install dependencies
130
- pnpm build # Build the package
131
- pnpm test # Run tests
132
- pnpm lint # Lint source code
133
- pnpm format # Format with Prettier
134
- ```
135
-
136
- ## ðŸĪ Contributing
137
-
138
- Contributions are welcome! Feel free to open an [issue](https://github.com/jmlweb/storybook-vrhythm/issues) or submit a pull request.
139
-
140
- ## 🙏 Inspiration
141
-
142
- [Baseliner](https://jpedroribeiro.com/2015/08/baseliner-my-first-chrome-extension/) — a Chrome extension by JP Ribeiro for overlaying baseline grids.
143
-
144
- ## 📄 License
145
-
146
- [MIT](LICENSE)
147
-
148
- [npm-badge]: https://img.shields.io/npm/v/storybook-vrhythm.svg
149
- [npm]: https://www.npmjs.org/package/storybook-vrhythm
150
- [license-badge]: https://img.shields.io/badge/license-MIT-blue.svg
151
- [license]: https://github.com/jmlweb/storybook-vrhythm/blob/master/LICENSE