@repobuddy/storybook 2.8.0 → 2.9.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/esm/index.d.ts CHANGED
@@ -41,6 +41,13 @@ declare function ShowHtml({
41
41
  }: ShowHtmlProps): react_jsx_runtime0.JSX.Element;
42
42
  //#endregion
43
43
  //#region src/components/story_card.d.ts
44
+ /**
45
+ * Visual status of the card, affecting its background color.
46
+ * - `'error'`: Red background (rbsb:bg-red-100 rbsb:dark:bg-red-900)
47
+ * - `'warn'`: Yellow background (rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900)
48
+ * - `'info'`: Blue background (rbsb:bg-sky-100 rbsb:dark:bg-sky-900) - default
49
+ */
50
+ type StoryCardStatus = 'error' | 'warn' | 'info' | undefined;
44
51
  type StoryCardProps = {
45
52
  /**
46
53
  * Optional title displayed as a heading in the card.
@@ -53,7 +60,7 @@ type StoryCardProps = {
53
60
  * - `'warn'`: Yellow background (rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900)
54
61
  * - `'info'`: Blue background (rbsb:bg-sky-100 rbsb:dark:bg-sky-900) - default
55
62
  */
56
- status?: 'error' | 'warn' | 'info' | undefined;
63
+ status?: StoryCardStatus;
57
64
  /**
58
65
  * Additional CSS classes or a function to compute classes.
59
66
  *
@@ -145,6 +152,19 @@ type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'> & {
145
152
  * ```
146
153
  *
147
154
  * @example
155
+ * Using defineStoryCard parameter:
156
+ * ```tsx
157
+ * export const MyStory: Story = {
158
+ * parameters: defineStoryCard({
159
+ * title: 'Important Notice',
160
+ * status: 'warn',
161
+ * content: <p>Please review this carefully.</p>
162
+ * }),
163
+ * decorators: [withStoryCard()]
164
+ * }
165
+ * ```
166
+ *
167
+ * @example
148
168
  * With custom content:
149
169
  * ```tsx
150
170
  * export const MyStory: Story = {
@@ -191,6 +211,7 @@ declare function withStoryCard<TRenderer extends Renderer = Renderer>({
191
211
  title,
192
212
  status,
193
213
  content: contentProp,
214
+ className,
194
215
  ...rest
195
216
  }?: WithStoryCardProps): DecoratorFunction<TRenderer>;
196
217
  //#endregion
@@ -685,6 +706,87 @@ type StorybookBuiltInParams = Partial<BackgroundsParam | GlobalApiBackgroundsPar
685
706
  */
686
707
  declare function defineParameters<P extends Record<string, any>>(param: P & StorybookBuiltInParams, ...rest: Array<StorybookBuiltInParams>): StorybookBuiltInParams;
687
708
  //#endregion
709
+ //#region src/parameters/define_story_card_param.d.ts
710
+ interface StoryCardParam {
711
+ storyCard: {
712
+ /**
713
+ * Optional title displayed as a heading in the card.
714
+ * Can be any React node (string, JSX, etc.).
715
+ */
716
+ title?: ReactNode | undefined;
717
+ /**
718
+ * Visual status of the card, affecting its background color.
719
+ * - `'error'`: Red background
720
+ * - `'warn'`: Yellow background
721
+ * - `'info'`: Blue background - default
722
+ */
723
+ status?: StoryCardStatus;
724
+ /**
725
+ * Additional CSS classes or a function to compute classes.
726
+ *
727
+ * If a string is provided, it will be merged with the default classes.
728
+ * If a function is provided, it receives the card state and default className,
729
+ * and should return the final className string.
730
+ */
731
+ className?: ((state: Pick<StoryCardProps, 'status'> & {
732
+ defaultClassName: string;
733
+ }) => string) | string | undefined;
734
+ /**
735
+ * Content to display in the card body.
736
+ * Can be any React node (string, JSX, etc.).
737
+ *
738
+ * If not provided, the decorator will automatically use:
739
+ * 1. Story description (`parameters.docs.description.story`)
740
+ * 2. Component description (`parameters.docs.description.component`)
741
+ * 3. Nothing (card won't render if no content and no title)
742
+ */
743
+ content?: ReactNode | undefined;
744
+ };
745
+ }
746
+ /**
747
+ * Defines story card parameters for Storybook stories.
748
+ *
749
+ * These parameters can be consumed by the `withStoryCard` decorator
750
+ * to automatically configure story cards without passing props directly.
751
+ *
752
+ * @param storyCard - Configuration for story card parameters
753
+ * @returns An object containing the story card parameter configuration
754
+ *
755
+ * @example
756
+ * ```tsx
757
+ * import { defineStoryCard, withStoryCard } from '@repobuddy/storybook'
758
+ *
759
+ * export const MyStory: Story = {
760
+ * parameters: defineStoryCard({
761
+ * title: 'Important Notice',
762
+ * status: 'warn',
763
+ * content: <p>Please review this carefully.</p>
764
+ * }),
765
+ * decorators: [withStoryCard()]
766
+ * }
767
+ * ```
768
+ *
769
+ * @example
770
+ * With automatic content from story description:
771
+ * ```tsx
772
+ * export const MyStory: Story = {
773
+ * parameters: {
774
+ * ...defineDocsParam({
775
+ * description: {
776
+ * story: 'This description will be shown in the card'
777
+ * }
778
+ * }),
779
+ * ...defineStoryCard({
780
+ * title: 'Story Information',
781
+ * status: 'info'
782
+ * })
783
+ * },
784
+ * decorators: [withStoryCard()]
785
+ * }
786
+ * ```
787
+ */
788
+ declare function defineStoryCard(storyCard: StoryCardParam['storyCard']): StoryCardParam;
789
+ //#endregion
688
790
  //#region src/testing/decorators/when_running_in_test.d.ts
689
791
  /**
690
792
  * executes the specified decorator or handler if the code is running in test.
@@ -812,4 +914,4 @@ type ExtendsStoryObj<S extends {
812
914
  tags?: ExtractStringLiterals<NonNullable<S['tags']>[number]> extends infer MT ? IsStringLiteral<MT> extends true ? Array<(string & {}) | MT | E['tag']> | undefined : Array<(string & {}) | E['tag']> | undefined : never;
813
915
  };
814
916
  //#endregion
815
- export { ActionsParam, BackgroundsParam, DocsParam, ExtendMeta, ExtendStoryObj, ExtendsMeta, ExtendsStoryObj, FnToArgTypes, GlobalApiBackgroundsParam, GlobalApiViewportParam, LayoutParam, ShowHtml, ShowHtmlProps, SourceProps, StoryCard, StoryCardProps, StorySortParam, StorybookBuiltInParams, TestParam, Viewport, ViewportParam, WithStoryCardProps, defineActionsParam, defineBackgroundsParam, defineDocsParam, defineLayoutParam, defineParameters, defineTestParam, defineViewportParam, showDocSource, whenRunningInTest, withStoryCard };
917
+ export { ActionsParam, BackgroundsParam, DocsParam, ExtendMeta, ExtendStoryObj, ExtendsMeta, ExtendsStoryObj, FnToArgTypes, GlobalApiBackgroundsParam, GlobalApiViewportParam, LayoutParam, ShowHtml, ShowHtmlProps, SourceProps, StoryCard, StoryCardParam, StoryCardProps, StoryCardStatus, StorySortParam, StorybookBuiltInParams, TestParam, Viewport, ViewportParam, WithStoryCardProps, defineActionsParam, defineBackgroundsParam, defineDocsParam, defineLayoutParam, defineParameters, defineStoryCard, defineTestParam, defineViewportParam, showDocSource, whenRunningInTest, withStoryCard };
package/esm/index.js CHANGED
@@ -162,6 +162,19 @@ function generateKey(prefix) {
162
162
  * ```
163
163
  *
164
164
  * @example
165
+ * Using defineStoryCard parameter:
166
+ * ```tsx
167
+ * export const MyStory: Story = {
168
+ * parameters: defineStoryCard({
169
+ * title: 'Important Notice',
170
+ * status: 'warn',
171
+ * content: <p>Please review this carefully.</p>
172
+ * }),
173
+ * decorators: [withStoryCard()]
174
+ * }
175
+ * ```
176
+ *
177
+ * @example
165
178
  * With custom content:
166
179
  * ```tsx
167
180
  * export const MyStory: Story = {
@@ -204,16 +217,22 @@ function generateKey(prefix) {
204
217
  * or fall back to the component description.
205
218
  * - Cards are collected and displayed in the order they are defined in the decorators array.
206
219
  */
207
- function withStoryCard({ title, status = "info", content: contentProp, ...rest } = {}) {
220
+ function withStoryCard({ title, status, content: contentProp, className, ...rest } = {}) {
208
221
  return (Story, { parameters, viewMode }) => {
209
222
  if (viewMode === "docs") return /* @__PURE__ */ jsx(Story, {});
210
- const content = contentProp ?? parameters.docs?.description?.story ?? parameters.docs?.description?.component;
211
- if (!content && !title) return /* @__PURE__ */ jsx(Story, {});
223
+ const storyCardParam = parameters.storyCard;
224
+ const finalTitle = title ?? storyCardParam?.title;
225
+ const finalStatus = status ?? storyCardParam?.status ?? "info";
226
+ const finalContent = contentProp ?? storyCardParam?.content;
227
+ const finalClassName = className ?? storyCardParam?.className;
228
+ const content = finalContent ?? parameters.docs?.description?.story ?? parameters.docs?.description?.component;
229
+ if (!content && !finalTitle) return /* @__PURE__ */ jsx(Story, {});
212
230
  return /* @__PURE__ */ jsx(StoryCardContainerWrapper, {
213
231
  Story,
214
232
  content,
215
- title,
216
- status,
233
+ title: finalTitle,
234
+ status: finalStatus,
235
+ className: finalClassName,
217
236
  ...rest
218
237
  });
219
238
  };
@@ -384,6 +403,54 @@ function defineParameters(param, ...rest) {
384
403
  return rest.reduce((acc, param) => Object.assign(acc, param), param);
385
404
  }
386
405
 
406
+ //#endregion
407
+ //#region src/parameters/define_story_card_param.ts
408
+ /**
409
+ * Defines story card parameters for Storybook stories.
410
+ *
411
+ * These parameters can be consumed by the `withStoryCard` decorator
412
+ * to automatically configure story cards without passing props directly.
413
+ *
414
+ * @param storyCard - Configuration for story card parameters
415
+ * @returns An object containing the story card parameter configuration
416
+ *
417
+ * @example
418
+ * ```tsx
419
+ * import { defineStoryCard, withStoryCard } from '@repobuddy/storybook'
420
+ *
421
+ * export const MyStory: Story = {
422
+ * parameters: defineStoryCard({
423
+ * title: 'Important Notice',
424
+ * status: 'warn',
425
+ * content: <p>Please review this carefully.</p>
426
+ * }),
427
+ * decorators: [withStoryCard()]
428
+ * }
429
+ * ```
430
+ *
431
+ * @example
432
+ * With automatic content from story description:
433
+ * ```tsx
434
+ * export const MyStory: Story = {
435
+ * parameters: {
436
+ * ...defineDocsParam({
437
+ * description: {
438
+ * story: 'This description will be shown in the card'
439
+ * }
440
+ * }),
441
+ * ...defineStoryCard({
442
+ * title: 'Story Information',
443
+ * status: 'info'
444
+ * })
445
+ * },
446
+ * decorators: [withStoryCard()]
447
+ * }
448
+ * ```
449
+ */
450
+ function defineStoryCard(storyCard) {
451
+ return { storyCard };
452
+ }
453
+
387
454
  //#endregion
388
455
  //#region src/parameters/define_test_param.ts
389
456
  /**
@@ -455,4 +522,4 @@ function whenRunningInTest(decoratorOrHandler) {
455
522
  }
456
523
 
457
524
  //#endregion
458
- export { ShowHtml, StoryCard, defineActionsParam, defineBackgroundsParam, defineDocsParam, defineLayoutParam, defineParameters, defineTestParam, defineViewportParam, showDocSource, whenRunningInTest, withStoryCard };
525
+ export { ShowHtml, StoryCard, defineActionsParam, defineBackgroundsParam, defineDocsParam, defineLayoutParam, defineParameters, defineStoryCard, defineTestParam, defineViewportParam, showDocSource, whenRunningInTest, withStoryCard };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repobuddy/storybook",
3
- "version": "2.8.0",
3
+ "version": "2.9.0",
4
4
  "description": "Storybook repo buddy",
5
5
  "keywords": [
6
6
  "storybook",
@@ -2,6 +2,14 @@ import { cva } from 'class-variance-authority'
2
2
  import type { ReactNode } from 'react'
3
3
  import { twJoin, twMerge } from 'tailwind-merge'
4
4
 
5
+ /**
6
+ * Visual status of the card, affecting its background color.
7
+ * - `'error'`: Red background (rbsb:bg-red-100 rbsb:dark:bg-red-900)
8
+ * - `'warn'`: Yellow background (rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900)
9
+ * - `'info'`: Blue background (rbsb:bg-sky-100 rbsb:dark:bg-sky-900) - default
10
+ */
11
+ export type StoryCardStatus = 'error' | 'warn' | 'info' | undefined
12
+
5
13
  export type StoryCardProps = {
6
14
  /**
7
15
  * Optional title displayed as a heading in the card.
@@ -14,7 +22,7 @@ export type StoryCardProps = {
14
22
  * - `'warn'`: Yellow background (rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900)
15
23
  * - `'info'`: Blue background (rbsb:bg-sky-100 rbsb:dark:bg-sky-900) - default
16
24
  */
17
- status?: 'error' | 'warn' | 'info' | undefined
25
+ status?: StoryCardStatus
18
26
  /**
19
27
  * Additional CSS classes or a function to compute classes.
20
28
  *
@@ -11,6 +11,7 @@ import {
11
11
  import type { DecoratorFunction, Renderer } from 'storybook/internal/csf'
12
12
  import type { RequiredPick } from 'type-plus'
13
13
  import { StoryCard, type StoryCardProps } from '../components/story_card.js'
14
+ import type { StoryCardParam } from '../parameters/define_story_card_param.js'
14
15
  import { generateKey } from '../utils/generate_key.js'
15
16
 
16
17
  export type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'> & {
@@ -57,6 +58,19 @@ export type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'>
57
58
  * ```
58
59
  *
59
60
  * @example
61
+ * Using defineStoryCard parameter:
62
+ * ```tsx
63
+ * export const MyStory: Story = {
64
+ * parameters: defineStoryCard({
65
+ * title: 'Important Notice',
66
+ * status: 'warn',
67
+ * content: <p>Please review this carefully.</p>
68
+ * }),
69
+ * decorators: [withStoryCard()]
70
+ * }
71
+ * ```
72
+ *
73
+ * @example
60
74
  * With custom content:
61
75
  * ```tsx
62
76
  * export const MyStory: Story = {
@@ -101,17 +115,37 @@ export type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'>
101
115
  */
102
116
  export function withStoryCard<TRenderer extends Renderer = Renderer>({
103
117
  title,
104
- status = 'info',
118
+ status,
105
119
  content: contentProp,
120
+ className,
106
121
  ...rest
107
122
  }: WithStoryCardProps = {}): DecoratorFunction<TRenderer> {
108
123
  return (Story, { parameters, viewMode }) => {
109
124
  if (viewMode === 'docs') return <Story />
110
125
 
111
- const content = contentProp ?? parameters.docs?.description?.story ?? parameters.docs?.description?.component
112
- if (!content && !title) return <Story />
113
-
114
- return <StoryCardContainerWrapper Story={Story} content={content} title={title} status={status} {...rest} />
126
+ // Get story card config from parameters if available
127
+ const storyCardParam = (parameters as Partial<StoryCardParam>).storyCard
128
+ // Decorator props override parameter values
129
+ // Use parameters as fallback when decorator props are not provided
130
+ const finalTitle = title ?? storyCardParam?.title
131
+ const finalStatus = status ?? storyCardParam?.status ?? 'info'
132
+ const finalContent = contentProp ?? storyCardParam?.content
133
+ const finalClassName = className ?? storyCardParam?.className
134
+
135
+ // Fallback to docs description if no content provided
136
+ const content = finalContent ?? parameters.docs?.description?.story ?? parameters.docs?.description?.component
137
+ if (!content && !finalTitle) return <Story />
138
+
139
+ return (
140
+ <StoryCardContainerWrapper
141
+ Story={Story}
142
+ content={content}
143
+ title={finalTitle}
144
+ status={finalStatus}
145
+ className={finalClassName}
146
+ {...rest}
147
+ />
148
+ )
115
149
  }
116
150
  }
117
151
 
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export * from './parameters/define_backgrounds_param.ts'
9
9
  export * from './parameters/define_docs_param.ts'
10
10
  export * from './parameters/define_layout_param.ts'
11
11
  export * from './parameters/define_parameters.ts'
12
+ export * from './parameters/define_story_card_param.ts'
12
13
  export * from './parameters/define_test_param.ts'
13
14
  export * from './parameters/define_viewport_param.ts'
14
15
  export * from './parameters/story_sort.ts'
@@ -0,0 +1,83 @@
1
+ import type { ReactNode } from 'react'
2
+ import type { StoryCardProps, StoryCardStatus } from '../components/story_card.js'
3
+
4
+ export interface StoryCardParam {
5
+ storyCard: {
6
+ /**
7
+ * Optional title displayed as a heading in the card.
8
+ * Can be any React node (string, JSX, etc.).
9
+ */
10
+ title?: ReactNode | undefined
11
+ /**
12
+ * Visual status of the card, affecting its background color.
13
+ * - `'error'`: Red background
14
+ * - `'warn'`: Yellow background
15
+ * - `'info'`: Blue background - default
16
+ */
17
+ status?: StoryCardStatus
18
+ /**
19
+ * Additional CSS classes or a function to compute classes.
20
+ *
21
+ * If a string is provided, it will be merged with the default classes.
22
+ * If a function is provided, it receives the card state and default className,
23
+ * and should return the final className string.
24
+ */
25
+ className?: ((state: Pick<StoryCardProps, 'status'> & { defaultClassName: string }) => string) | string | undefined
26
+ /**
27
+ * Content to display in the card body.
28
+ * Can be any React node (string, JSX, etc.).
29
+ *
30
+ * If not provided, the decorator will automatically use:
31
+ * 1. Story description (`parameters.docs.description.story`)
32
+ * 2. Component description (`parameters.docs.description.component`)
33
+ * 3. Nothing (card won't render if no content and no title)
34
+ */
35
+ content?: ReactNode | undefined
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Defines story card parameters for Storybook stories.
41
+ *
42
+ * These parameters can be consumed by the `withStoryCard` decorator
43
+ * to automatically configure story cards without passing props directly.
44
+ *
45
+ * @param storyCard - Configuration for story card parameters
46
+ * @returns An object containing the story card parameter configuration
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * import { defineStoryCard, withStoryCard } from '@repobuddy/storybook'
51
+ *
52
+ * export const MyStory: Story = {
53
+ * parameters: defineStoryCard({
54
+ * title: 'Important Notice',
55
+ * status: 'warn',
56
+ * content: <p>Please review this carefully.</p>
57
+ * }),
58
+ * decorators: [withStoryCard()]
59
+ * }
60
+ * ```
61
+ *
62
+ * @example
63
+ * With automatic content from story description:
64
+ * ```tsx
65
+ * export const MyStory: Story = {
66
+ * parameters: {
67
+ * ...defineDocsParam({
68
+ * description: {
69
+ * story: 'This description will be shown in the card'
70
+ * }
71
+ * }),
72
+ * ...defineStoryCard({
73
+ * title: 'Story Information',
74
+ * status: 'info'
75
+ * })
76
+ * },
77
+ * decorators: [withStoryCard()]
78
+ * }
79
+ * ```
80
+ */
81
+ export function defineStoryCard(storyCard: StoryCardParam['storyCard']): StoryCardParam {
82
+ return { storyCard }
83
+ }
package/styles.css CHANGED
@@ -4,13 +4,16 @@
4
4
  @layer theme {
5
5
  :root, :host {
6
6
  --rbsb-color-red-100: oklch(93.6% 0.032 17.717);
7
+ --rbsb-color-red-500: oklch(63.7% 0.237 25.331);
7
8
  --rbsb-color-red-800: oklch(44.4% 0.177 26.899);
8
9
  --rbsb-color-red-900: oklch(39.6% 0.141 25.723);
9
10
  --rbsb-color-amber-300: oklch(87.9% 0.169 91.605);
10
11
  --rbsb-color-amber-900: oklch(41.4% 0.112 45.904);
11
12
  --rbsb-color-yellow-100: oklch(97.3% 0.071 103.193);
13
+ --rbsb-color-yellow-500: oklch(79.5% 0.184 86.047);
12
14
  --rbsb-color-yellow-900: oklch(42.1% 0.095 57.708);
13
15
  --rbsb-color-green-200: oklch(92.5% 0.084 155.995);
16
+ --rbsb-color-green-500: oklch(72.3% 0.219 149.579);
14
17
  --rbsb-color-green-800: oklch(44.8% 0.119 151.328);
15
18
  --rbsb-color-sky-100: oklch(95.1% 0.026 236.824);
16
19
  --rbsb-color-sky-500: oklch(68.5% 0.169 237.323);
@@ -37,9 +40,18 @@
37
40
  }
38
41
  }
39
42
  @layer utilities {
43
+ .rbsb\:ml-4 {
44
+ margin-left: calc(var(--rbsb-spacing) * 4);
45
+ }
40
46
  .rbsb\:flex {
41
47
  display: flex;
42
48
  }
49
+ .rbsb\:list-inside {
50
+ list-style-position: inside;
51
+ }
52
+ .rbsb\:list-disc {
53
+ list-style-type: disc;
54
+ }
43
55
  .rbsb\:flex-col {
44
56
  flex-direction: column;
45
57
  }
@@ -52,6 +64,9 @@
52
64
  .rbsb\:gap-4 {
53
65
  gap: calc(var(--rbsb-spacing) * 4);
54
66
  }
67
+ .rbsb\:self-start {
68
+ align-self: flex-start;
69
+ }
55
70
  .rbsb\:rounded {
56
71
  border-radius: 0.25rem;
57
72
  }
@@ -65,9 +80,24 @@
65
80
  .rbsb\:border-blue-500 {
66
81
  border-color: var(--rbsb-color-blue-500);
67
82
  }
83
+ .rbsb\:border-gray-500 {
84
+ border-color: var(--rbsb-color-gray-500);
85
+ }
86
+ .rbsb\:border-green-500 {
87
+ border-color: var(--rbsb-color-green-500);
88
+ }
68
89
  .rbsb\:border-purple-500 {
69
90
  border-color: var(--rbsb-color-purple-500);
70
91
  }
92
+ .rbsb\:border-red-500 {
93
+ border-color: var(--rbsb-color-red-500);
94
+ }
95
+ .rbsb\:border-sky-500 {
96
+ border-color: var(--rbsb-color-sky-500);
97
+ }
98
+ .rbsb\:border-yellow-500 {
99
+ border-color: var(--rbsb-color-yellow-500);
100
+ }
71
101
  .rbsb\:bg-amber-300 {
72
102
  background-color: var(--rbsb-color-amber-300);
73
103
  }
@@ -116,6 +146,9 @@
116
146
  .rbsb\:px-4 {
117
147
  padding-inline: calc(var(--rbsb-spacing) * 4);
118
148
  }
149
+ .rbsb\:py-2 {
150
+ padding-block: calc(var(--rbsb-spacing) * 2);
151
+ }
119
152
  .rbsb\:py-3 {
120
153
  padding-block: calc(var(--rbsb-spacing) * 3);
121
154
  }