@repobuddy/storybook 2.13.0 → 2.14.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 +36 -17
- package/esm/index.js +33 -21
- package/package.json +1 -1
- package/src/components/story_card.tsx +52 -24
- package/src/contexts/story_card_registry_context.tsx +1 -2
- package/src/contexts/story_card_scope.tsx +2 -2
- package/src/decorators/show_doc_source.tsx +6 -4
- package/src/decorators/with_story_card.tsx +14 -3
- package/src/parameters/define_story_card_param.ts +10 -6
- package/styles.css +78 -0
package/esm/index.d.ts
CHANGED
|
@@ -42,10 +42,12 @@ declare function ShowHtml({
|
|
|
42
42
|
//#endregion
|
|
43
43
|
//#region src/components/story_card.d.ts
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
* Resolved appearance of the card (error | warn | info | source | output).
|
|
46
|
+
* Used for styling; when only `status` is provided it is mapped to this.
|
|
47
|
+
*/
|
|
48
|
+
type StoryCardAppearance = 'error' | 'warn' | 'info' | 'source' | 'output';
|
|
49
|
+
/**
|
|
50
|
+
* @deprecated Use `appearance` instead. Visual status of the card; equivalent to `appearance` for 'error' | 'warn' | 'info'.
|
|
49
51
|
*/
|
|
50
52
|
type StoryCardStatus = 'error' | 'warn' | 'info' | undefined;
|
|
51
53
|
type StoryCardProps = {
|
|
@@ -55,12 +57,18 @@ type StoryCardProps = {
|
|
|
55
57
|
*/
|
|
56
58
|
title?: ReactNode | undefined;
|
|
57
59
|
/**
|
|
58
|
-
*
|
|
59
|
-
* - `'error'`: Red background (rbsb:bg-red-100 rbsb:dark:bg-red-900)
|
|
60
|
-
* - `'warn'`: Yellow background (rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900)
|
|
61
|
-
* - `'info'`: Blue background (rbsb:bg-sky-100 rbsb:dark:bg-sky-900) - default
|
|
60
|
+
* @deprecated Use `appearance` instead. When set, behaves like `appearance` for the same value.
|
|
62
61
|
*/
|
|
63
62
|
status?: StoryCardStatus;
|
|
63
|
+
/**
|
|
64
|
+
* Appearance of the card, affecting its background and border color.
|
|
65
|
+
* - `'error'`: Red
|
|
66
|
+
* - `'warn'`: Yellow
|
|
67
|
+
* - `'info'`: Blue (default when neither appearance nor status is set)
|
|
68
|
+
* - `'source'`: Transparent
|
|
69
|
+
* - `'output'`: Green
|
|
70
|
+
*/
|
|
71
|
+
appearance?: StoryCardAppearance | undefined;
|
|
64
72
|
/**
|
|
65
73
|
* Additional CSS classes or a function to compute classes.
|
|
66
74
|
*
|
|
@@ -68,7 +76,7 @@ type StoryCardProps = {
|
|
|
68
76
|
* If a function is provided, it receives the card state and default className,
|
|
69
77
|
* and should return the final className string.
|
|
70
78
|
*/
|
|
71
|
-
className?: ((state: Pick<StoryCardProps, 'status'> & {
|
|
79
|
+
className?: ((state: Pick<StoryCardProps, 'status' | 'appearance'> & {
|
|
72
80
|
defaultClassName: string;
|
|
73
81
|
}) => string) | string | undefined;
|
|
74
82
|
/**
|
|
@@ -77,14 +85,18 @@ type StoryCardProps = {
|
|
|
77
85
|
*/
|
|
78
86
|
children?: ReactNode | undefined;
|
|
79
87
|
};
|
|
88
|
+
type StoryCardThemeState = Pick<StoryCardProps, 'status' | 'appearance'> & {
|
|
89
|
+
defaultClassName: string;
|
|
90
|
+
};
|
|
80
91
|
/**
|
|
81
|
-
* A card component that displays information with optional title and
|
|
92
|
+
* A card component that displays information with optional title and appearance styling.
|
|
82
93
|
*
|
|
83
94
|
* @param props - StoryCard component props
|
|
84
95
|
* @returns A section element containing the card content
|
|
85
96
|
*/
|
|
86
97
|
declare function StoryCard({
|
|
87
98
|
status,
|
|
99
|
+
appearance,
|
|
88
100
|
className,
|
|
89
101
|
children,
|
|
90
102
|
title
|
|
@@ -115,6 +127,10 @@ declare function showDocSource<TRenderer extends Renderer = Renderer, TArgs = Ar
|
|
|
115
127
|
//#endregion
|
|
116
128
|
//#region src/decorators/with_story_card.d.ts
|
|
117
129
|
type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'> & {
|
|
130
|
+
/**
|
|
131
|
+
* @deprecated Use `appearance` instead. When set, behaves like `appearance` for the same value.
|
|
132
|
+
*/
|
|
133
|
+
status?: StoryCardStatus;
|
|
118
134
|
/**
|
|
119
135
|
* Additional CSS classes or a function to compute classes.
|
|
120
136
|
*
|
|
@@ -122,7 +138,7 @@ type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'> & {
|
|
|
122
138
|
* If a function is provided, it receives the card state and default className,
|
|
123
139
|
* and should return the final className string.
|
|
124
140
|
*/
|
|
125
|
-
className?: ((state: Pick<StoryCardProps, 'status'> & {
|
|
141
|
+
className?: ((state: Pick<StoryCardProps, 'status' | 'appearance'> & {
|
|
126
142
|
defaultClassName: string;
|
|
127
143
|
}) => string) | string | undefined;
|
|
128
144
|
/**
|
|
@@ -213,10 +229,12 @@ type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'> & {
|
|
|
213
229
|
* - If `content` is not provided, it will automatically use the story description,
|
|
214
230
|
* or fall back to the component description.
|
|
215
231
|
* - Cards are collected and displayed in the order they are defined in the decorators array.
|
|
232
|
+
* - The `status` option is deprecated; use `appearance` instead for the same behavior and additional variants (`source`, `output`).
|
|
216
233
|
*/
|
|
217
234
|
declare function withStoryCard<TRenderer extends Renderer = Renderer>({
|
|
218
235
|
title,
|
|
219
236
|
status,
|
|
237
|
+
appearance,
|
|
220
238
|
content: contentProp,
|
|
221
239
|
className,
|
|
222
240
|
...rest
|
|
@@ -722,12 +740,13 @@ interface StoryCardParam {
|
|
|
722
740
|
*/
|
|
723
741
|
title?: ReactNode | undefined;
|
|
724
742
|
/**
|
|
725
|
-
*
|
|
726
|
-
* - `'error'`: Red background
|
|
727
|
-
* - `'warn'`: Yellow background
|
|
728
|
-
* - `'info'`: Blue background - default
|
|
743
|
+
* @deprecated Use `appearance` instead.
|
|
729
744
|
*/
|
|
730
745
|
status?: StoryCardStatus;
|
|
746
|
+
/**
|
|
747
|
+
* Appearance of the card (error | warn | info | source | output). Default: `'info'`.
|
|
748
|
+
*/
|
|
749
|
+
appearance?: StoryCardAppearance | undefined;
|
|
731
750
|
/**
|
|
732
751
|
* Additional CSS classes or a function to compute classes.
|
|
733
752
|
*
|
|
@@ -735,7 +754,7 @@ interface StoryCardParam {
|
|
|
735
754
|
* If a function is provided, it receives the card state and default className,
|
|
736
755
|
* and should return the final className string.
|
|
737
756
|
*/
|
|
738
|
-
className?: ((state: Pick<StoryCardProps, 'status'> & {
|
|
757
|
+
className?: ((state: Pick<StoryCardProps, 'status' | 'appearance'> & {
|
|
739
758
|
defaultClassName: string;
|
|
740
759
|
}) => string) | string | undefined;
|
|
741
760
|
/**
|
|
@@ -921,4 +940,4 @@ type ExtendStoryObj<TMetaOrCmpOrArgs, S extends StoryObj<TMetaOrCmpOrArgs>, E ex
|
|
|
921
940
|
tags?: Array<E['tag'] | (string & {})> | undefined;
|
|
922
941
|
};
|
|
923
942
|
//#endregion
|
|
924
|
-
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, defineStoryCardParam, defineTestParam, defineViewportParam, showDocSource, whenRunningInTest, withStoryCard };
|
|
943
|
+
export { ActionsParam, BackgroundsParam, DocsParam, ExtendMeta, ExtendStoryObj, ExtendsMeta, ExtendsStoryObj, FnToArgTypes, GlobalApiBackgroundsParam, GlobalApiViewportParam, LayoutParam, ShowHtml, ShowHtmlProps, SourceProps, StoryCard, StoryCardAppearance, StoryCardParam, StoryCardProps, StoryCardStatus, StoryCardThemeState, StorySortParam, StorybookBuiltInParams, TestParam, Viewport, ViewportParam, WithStoryCardProps, defineActionsParam, defineBackgroundsParam, defineDocsParam, defineLayoutParam, defineParameters, defineStoryCardParam, defineTestParam, defineViewportParam, showDocSource, whenRunningInTest, withStoryCard };
|
package/esm/index.js
CHANGED
|
@@ -39,31 +39,39 @@ function ShowHtml({ selector = "[data-testid=\"subject\"]", config, ...props })
|
|
|
39
39
|
|
|
40
40
|
//#endregion
|
|
41
41
|
//#region src/components/story_card.tsx
|
|
42
|
+
function resolveAppearance(appearance, status) {
|
|
43
|
+
if (appearance !== void 0) return appearance;
|
|
44
|
+
if (status !== void 0) return status;
|
|
45
|
+
return "info";
|
|
46
|
+
}
|
|
42
47
|
function storyCardTheme(state, className) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return twMerge(typeof className === "function" ? className({
|
|
46
|
-
...state,
|
|
47
|
-
defaultClassName
|
|
48
|
-
}) : twJoin(defaultClassName, className));
|
|
48
|
+
if (!className) return state.defaultClassName;
|
|
49
|
+
return twMerge(typeof className === "function" ? className(state) : twJoin(state.defaultClassName, className));
|
|
49
50
|
}
|
|
50
|
-
const storyCardVariants = cva("rbsb:flex rbsb:flex-col rbsb:gap-1 rbsb:py-3 rbsb:px-4 rbsb:rounded rbsb:text-black rbsb:dark:text-gray-100", {
|
|
51
|
-
variants: {
|
|
52
|
-
error: "rbsb:bg-red-100 rbsb:dark:bg-red-900",
|
|
53
|
-
warn: "rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900",
|
|
54
|
-
info: "rbsb:bg-sky-100 rbsb:dark:bg-sky-900"
|
|
51
|
+
const storyCardVariants = cva("rbsb:flex rbsb:flex-col rbsb:gap-1 rbsb:py-3 rbsb:px-4 rbsb:rounded rbsb:border rbsb:border-solid rbsb:text-black rbsb:dark:text-gray-100", {
|
|
52
|
+
variants: { appearance: {
|
|
53
|
+
error: "rbsb:bg-red-100 rbsb:dark:bg-red-900 rbsb:border-red-300 rbsb:dark:border-red-700",
|
|
54
|
+
warn: "rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900 rbsb:border-yellow-300 rbsb:dark:border-yellow-700",
|
|
55
|
+
info: "rbsb:bg-sky-100 rbsb:dark:bg-sky-900 rbsb:border-sky-300 rbsb:dark:border-sky-700",
|
|
56
|
+
source: "rbsb:bg-gray-100 rbsb:dark:bg-gray-900 rbsb:border-gray-300 rbsb:dark:border-gray-700",
|
|
57
|
+
output: "rbsb:bg-green-100 rbsb:dark:bg-green-900 rbsb:border-green-300 rbsb:dark:border-green-700"
|
|
55
58
|
} },
|
|
56
|
-
defaultVariants: {
|
|
59
|
+
defaultVariants: { appearance: "info" }
|
|
57
60
|
});
|
|
58
61
|
/**
|
|
59
|
-
* A card component that displays information with optional title and
|
|
62
|
+
* A card component that displays information with optional title and appearance styling.
|
|
60
63
|
*
|
|
61
64
|
* @param props - StoryCard component props
|
|
62
65
|
* @returns A section element containing the card content
|
|
63
66
|
*/
|
|
64
|
-
function StoryCard({ status, className, children, title }) {
|
|
67
|
+
function StoryCard({ status, appearance, className, children, title }) {
|
|
68
|
+
const resolvedAppearance = resolveAppearance(appearance, status);
|
|
65
69
|
return /* @__PURE__ */ jsxs("section", {
|
|
66
|
-
className: storyCardTheme({
|
|
70
|
+
className: storyCardTheme({
|
|
71
|
+
status,
|
|
72
|
+
appearance: resolvedAppearance,
|
|
73
|
+
defaultClassName: storyCardVariants({ appearance: resolvedAppearance })
|
|
74
|
+
}, className),
|
|
67
75
|
children: [title && /* @__PURE__ */ jsx("h2", {
|
|
68
76
|
className: "rbsb:text-lg rbsb:font-bold",
|
|
69
77
|
children: title
|
|
@@ -129,13 +137,14 @@ function StoryCardContainer({ children }) {
|
|
|
129
137
|
})
|
|
130
138
|
});
|
|
131
139
|
}
|
|
132
|
-
function StoryCardCollector({ Story, title, status, className, content }) {
|
|
140
|
+
function StoryCardCollector({ Story, title, status, appearance, className, content }) {
|
|
133
141
|
const context = useContext(StoryCardRegistryContext);
|
|
134
142
|
const cardIdRef = useRef(null);
|
|
135
143
|
useLayoutEffect(() => {
|
|
136
144
|
if (cardIdRef.current === null) cardIdRef.current = context.add({
|
|
137
145
|
title,
|
|
138
146
|
status,
|
|
147
|
+
appearance,
|
|
139
148
|
className,
|
|
140
149
|
content
|
|
141
150
|
});
|
|
@@ -183,7 +192,7 @@ function showDocSource(options) {
|
|
|
183
192
|
const sourceCardClassName = (state) => {
|
|
184
193
|
const modifiedState = {
|
|
185
194
|
...state,
|
|
186
|
-
defaultClassName: twJoin(state.defaultClassName, isOriginalSource
|
|
195
|
+
defaultClassName: twJoin(state.defaultClassName, isOriginalSource && "rbsb:bg-transparent rbsb:dark:bg-transparent")
|
|
187
196
|
};
|
|
188
197
|
const className = options?.className;
|
|
189
198
|
return typeof className === "function" ? className(modifiedState) : twJoin(modifiedState.defaultClassName, className);
|
|
@@ -195,7 +204,7 @@ function showDocSource(options) {
|
|
|
195
204
|
Story,
|
|
196
205
|
content: sourceContent,
|
|
197
206
|
className: sourceCardClassName,
|
|
198
|
-
|
|
207
|
+
appearance: "source"
|
|
199
208
|
})
|
|
200
209
|
});
|
|
201
210
|
return /* @__PURE__ */ jsx(ThemeProvider, {
|
|
@@ -208,7 +217,7 @@ function showDocSource(options) {
|
|
|
208
217
|
},
|
|
209
218
|
children: [/* @__PURE__ */ jsx(Story, {}), /* @__PURE__ */ jsx(StoryCard, {
|
|
210
219
|
className: sourceCardClassName,
|
|
211
|
-
|
|
220
|
+
appearance: "source",
|
|
212
221
|
children: sourceContent
|
|
213
222
|
})]
|
|
214
223
|
})
|
|
@@ -295,13 +304,15 @@ function showDocSource(options) {
|
|
|
295
304
|
* - If `content` is not provided, it will automatically use the story description,
|
|
296
305
|
* or fall back to the component description.
|
|
297
306
|
* - Cards are collected and displayed in the order they are defined in the decorators array.
|
|
307
|
+
* - The `status` option is deprecated; use `appearance` instead for the same behavior and additional variants (`source`, `output`).
|
|
298
308
|
*/
|
|
299
|
-
function withStoryCard({ title, status, content: contentProp, className, ...rest } = {}) {
|
|
309
|
+
function withStoryCard({ title, status, appearance, content: contentProp, className, ...rest } = {}) {
|
|
300
310
|
return (Story, { parameters, viewMode }) => {
|
|
301
311
|
if (viewMode === "docs") return /* @__PURE__ */ jsx(Story, {});
|
|
302
312
|
const storyCardParam = parameters.storyCard;
|
|
303
313
|
const finalTitle = title ?? storyCardParam?.title;
|
|
304
|
-
const
|
|
314
|
+
const finalAppearance = appearance ?? storyCardParam?.appearance ?? status ?? storyCardParam?.status ?? "info";
|
|
315
|
+
const finalStatus = status ?? storyCardParam?.status;
|
|
305
316
|
const finalContent = contentProp ?? storyCardParam?.content;
|
|
306
317
|
const finalClassName = className ?? storyCardParam?.className;
|
|
307
318
|
const content = finalContent ?? parameters.docs?.description?.story ?? parameters.docs?.description?.component;
|
|
@@ -311,6 +322,7 @@ function withStoryCard({ title, status, content: contentProp, className, ...rest
|
|
|
311
322
|
content,
|
|
312
323
|
title: finalTitle,
|
|
313
324
|
status: finalStatus,
|
|
325
|
+
appearance: finalAppearance,
|
|
314
326
|
className: finalClassName,
|
|
315
327
|
...rest
|
|
316
328
|
});
|
package/package.json
CHANGED
|
@@ -3,10 +3,13 @@ import type { ReactNode } from 'react'
|
|
|
3
3
|
import { twJoin, twMerge } from 'tailwind-merge'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
* Resolved appearance of the card (error | warn | info | source | output).
|
|
7
|
+
* Used for styling; when only `status` is provided it is mapped to this.
|
|
8
|
+
*/
|
|
9
|
+
export type StoryCardAppearance = 'error' | 'warn' | 'info' | 'source' | 'output'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Use `appearance` instead. Visual status of the card; equivalent to `appearance` for 'error' | 'warn' | 'info'.
|
|
10
13
|
*/
|
|
11
14
|
export type StoryCardStatus = 'error' | 'warn' | 'info' | undefined
|
|
12
15
|
|
|
@@ -17,12 +20,18 @@ export type StoryCardProps = {
|
|
|
17
20
|
*/
|
|
18
21
|
title?: ReactNode | undefined
|
|
19
22
|
/**
|
|
20
|
-
*
|
|
21
|
-
* - `'error'`: Red background (rbsb:bg-red-100 rbsb:dark:bg-red-900)
|
|
22
|
-
* - `'warn'`: Yellow background (rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900)
|
|
23
|
-
* - `'info'`: Blue background (rbsb:bg-sky-100 rbsb:dark:bg-sky-900) - default
|
|
23
|
+
* @deprecated Use `appearance` instead. When set, behaves like `appearance` for the same value.
|
|
24
24
|
*/
|
|
25
25
|
status?: StoryCardStatus
|
|
26
|
+
/**
|
|
27
|
+
* Appearance of the card, affecting its background and border color.
|
|
28
|
+
* - `'error'`: Red
|
|
29
|
+
* - `'warn'`: Yellow
|
|
30
|
+
* - `'info'`: Blue (default when neither appearance nor status is set)
|
|
31
|
+
* - `'source'`: Transparent
|
|
32
|
+
* - `'output'`: Green
|
|
33
|
+
*/
|
|
34
|
+
appearance?: StoryCardAppearance | undefined
|
|
26
35
|
/**
|
|
27
36
|
* Additional CSS classes or a function to compute classes.
|
|
28
37
|
*
|
|
@@ -30,7 +39,10 @@ export type StoryCardProps = {
|
|
|
30
39
|
* If a function is provided, it receives the card state and default className,
|
|
31
40
|
* and should return the final className string.
|
|
32
41
|
*/
|
|
33
|
-
className?:
|
|
42
|
+
className?:
|
|
43
|
+
| ((state: Pick<StoryCardProps, 'status' | 'appearance'> & { defaultClassName: string }) => string)
|
|
44
|
+
| string
|
|
45
|
+
| undefined
|
|
34
46
|
/**
|
|
35
47
|
* Content to display in the card body.
|
|
36
48
|
* Can be any React node (string, JSX, etc.).
|
|
@@ -38,39 +50,55 @@ export type StoryCardProps = {
|
|
|
38
50
|
children?: ReactNode | undefined
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
export type StoryCardThemeState = Pick<StoryCardProps, 'status' | 'appearance'> & { defaultClassName: string }
|
|
54
|
+
|
|
55
|
+
function resolveAppearance(
|
|
56
|
+
appearance: StoryCardProps['appearance'],
|
|
57
|
+
status: StoryCardProps['status']
|
|
58
|
+
): NonNullable<StoryCardAppearance> {
|
|
59
|
+
if (appearance !== undefined) return appearance
|
|
60
|
+
if (status !== undefined) return status
|
|
61
|
+
return 'info'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function storyCardTheme(state: StoryCardThemeState, className: StoryCardProps['className']) {
|
|
65
|
+
if (!className) return state.defaultClassName
|
|
66
|
+
return twMerge(typeof className === 'function' ? className(state) : twJoin(state.defaultClassName, className))
|
|
47
67
|
}
|
|
48
68
|
|
|
49
69
|
const storyCardVariants = cva(
|
|
50
|
-
'rbsb:flex rbsb:flex-col rbsb:gap-1 rbsb:py-3 rbsb:px-4 rbsb:rounded rbsb:text-black rbsb:dark:text-gray-100',
|
|
70
|
+
'rbsb:flex rbsb:flex-col rbsb:gap-1 rbsb:py-3 rbsb:px-4 rbsb:rounded rbsb:border rbsb:border-solid rbsb:text-black rbsb:dark:text-gray-100',
|
|
51
71
|
{
|
|
52
72
|
variants: {
|
|
53
|
-
|
|
54
|
-
error: 'rbsb:bg-red-100 rbsb:dark:bg-red-900',
|
|
55
|
-
warn: 'rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900',
|
|
56
|
-
info: 'rbsb:bg-sky-100 rbsb:dark:bg-sky-900'
|
|
73
|
+
appearance: {
|
|
74
|
+
error: 'rbsb:bg-red-100 rbsb:dark:bg-red-900 rbsb:border-red-300 rbsb:dark:border-red-700',
|
|
75
|
+
warn: 'rbsb:bg-yellow-100 rbsb:dark:bg-yellow-900 rbsb:border-yellow-300 rbsb:dark:border-yellow-700',
|
|
76
|
+
info: 'rbsb:bg-sky-100 rbsb:dark:bg-sky-900 rbsb:border-sky-300 rbsb:dark:border-sky-700',
|
|
77
|
+
source: 'rbsb:bg-gray-100 rbsb:dark:bg-gray-900 rbsb:border-gray-300 rbsb:dark:border-gray-700',
|
|
78
|
+
output: 'rbsb:bg-green-100 rbsb:dark:bg-green-900 rbsb:border-green-300 rbsb:dark:border-green-700'
|
|
57
79
|
}
|
|
58
80
|
},
|
|
59
81
|
defaultVariants: {
|
|
60
|
-
|
|
82
|
+
appearance: 'info'
|
|
61
83
|
}
|
|
62
84
|
}
|
|
63
85
|
)
|
|
64
86
|
|
|
65
87
|
/**
|
|
66
|
-
* A card component that displays information with optional title and
|
|
88
|
+
* A card component that displays information with optional title and appearance styling.
|
|
67
89
|
*
|
|
68
90
|
* @param props - StoryCard component props
|
|
69
91
|
* @returns A section element containing the card content
|
|
70
92
|
*/
|
|
71
|
-
export function StoryCard({ status, className, children, title }: StoryCardProps) {
|
|
93
|
+
export function StoryCard({ status, appearance, className, children, title }: StoryCardProps) {
|
|
94
|
+
const resolvedAppearance = resolveAppearance(appearance, status)
|
|
95
|
+
const state: StoryCardThemeState = {
|
|
96
|
+
status,
|
|
97
|
+
appearance: resolvedAppearance,
|
|
98
|
+
defaultClassName: storyCardVariants({ appearance: resolvedAppearance })
|
|
99
|
+
}
|
|
72
100
|
return (
|
|
73
|
-
<section className={storyCardTheme(
|
|
101
|
+
<section className={storyCardTheme(state, className)}>
|
|
74
102
|
{title && <h2 className="rbsb:text-lg rbsb:font-bold">{title}</h2>}
|
|
75
103
|
{children}
|
|
76
104
|
</section>
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
2
|
import { createContext } from 'react'
|
|
3
|
-
import type { RequiredPick } from 'type-plus'
|
|
4
3
|
import type { StoryCardProps } from '../components/story_card.js'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Payload for adding a card to the story card registry.
|
|
8
7
|
* Matches the shape of card props with `status` required.
|
|
9
8
|
*/
|
|
10
|
-
export type StoryCardEntry =
|
|
9
|
+
export type StoryCardEntry = Omit<StoryCardProps, 'children'> & { content?: ReactNode }
|
|
11
10
|
|
|
12
11
|
export interface StoryCardRegistryContextValue {
|
|
13
12
|
add: (card: StoryCardEntry) => string
|
|
@@ -59,7 +59,7 @@ type StoryCardEntryWithKey = StoryCardEntry & { key: string }
|
|
|
59
59
|
|
|
60
60
|
interface StoryCardCollectorProps extends StoryCardScopeProps {}
|
|
61
61
|
|
|
62
|
-
function StoryCardCollector({ Story, title, status, className, content }: StoryCardCollectorProps) {
|
|
62
|
+
function StoryCardCollector({ Story, title, status, appearance, className, content }: StoryCardCollectorProps) {
|
|
63
63
|
// StoryCardCollector is an internal component. Context is guaranteed to be not null by `StoryCardContainer`.
|
|
64
64
|
const context = useContext(StoryCardRegistryContext)!
|
|
65
65
|
const cardIdRef = useRef<string | null>(null)
|
|
@@ -68,7 +68,7 @@ function StoryCardCollector({ Story, title, status, className, content }: StoryC
|
|
|
68
68
|
useLayoutEffect(() => {
|
|
69
69
|
// Only add if not already added (handles Strict Mode double-render)
|
|
70
70
|
if (cardIdRef.current === null) {
|
|
71
|
-
cardIdRef.current = context.add({ title, status, className, content })
|
|
71
|
+
cardIdRef.current = context.add({ title, status, appearance, className, content })
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return () => {
|
|
@@ -58,12 +58,14 @@ export function showDocSource<TRenderer extends Renderer = Renderer, TArgs = Arg
|
|
|
58
58
|
|
|
59
59
|
const showBefore = options?.placement === 'before'
|
|
60
60
|
|
|
61
|
-
const sourceCardClassName = (
|
|
61
|
+
const sourceCardClassName = (
|
|
62
|
+
state: Pick<StoryCardProps, 'status' | 'appearance'> & { defaultClassName: string }
|
|
63
|
+
) => {
|
|
62
64
|
const modifiedState = {
|
|
63
65
|
...state,
|
|
64
66
|
defaultClassName: twJoin(
|
|
65
67
|
state.defaultClassName,
|
|
66
|
-
isOriginalSource
|
|
68
|
+
isOriginalSource && 'rbsb:bg-transparent rbsb:dark:bg-transparent'
|
|
67
69
|
)
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -78,13 +80,13 @@ export function showDocSource<TRenderer extends Renderer = Renderer, TArgs = Arg
|
|
|
78
80
|
if (showBefore) {
|
|
79
81
|
return (
|
|
80
82
|
<ThemeProvider theme={theme}>
|
|
81
|
-
<StoryCardScope Story={Story} content={sourceContent} className={sourceCardClassName}
|
|
83
|
+
<StoryCardScope Story={Story} content={sourceContent} className={sourceCardClassName} appearance="source" />
|
|
82
84
|
</ThemeProvider>
|
|
83
85
|
)
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
const storyCard = (
|
|
87
|
-
<StoryCard className={sourceCardClassName}
|
|
89
|
+
<StoryCard className={sourceCardClassName} appearance="source">
|
|
88
90
|
{sourceContent}
|
|
89
91
|
</StoryCard>
|
|
90
92
|
)
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
2
|
import type { DecoratorFunction, Renderer } from 'storybook/internal/csf'
|
|
3
|
-
import type { StoryCardProps } from '../components/story_card.js'
|
|
3
|
+
import type { StoryCardProps, StoryCardStatus } from '../components/story_card.js'
|
|
4
4
|
import { StoryCardScope } from '../contexts/story_card_scope.js'
|
|
5
5
|
import type { StoryCardParam } from '../parameters/define_story_card_param.js'
|
|
6
6
|
|
|
7
7
|
export type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'> & {
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Use `appearance` instead. When set, behaves like `appearance` for the same value.
|
|
10
|
+
*/
|
|
11
|
+
status?: StoryCardStatus
|
|
8
12
|
/**
|
|
9
13
|
* Additional CSS classes or a function to compute classes.
|
|
10
14
|
*
|
|
@@ -12,7 +16,10 @@ export type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'>
|
|
|
12
16
|
* If a function is provided, it receives the card state and default className,
|
|
13
17
|
* and should return the final className string.
|
|
14
18
|
*/
|
|
15
|
-
className?:
|
|
19
|
+
className?:
|
|
20
|
+
| ((state: Pick<StoryCardProps, 'status' | 'appearance'> & { defaultClassName: string }) => string)
|
|
21
|
+
| string
|
|
22
|
+
| undefined
|
|
16
23
|
/**
|
|
17
24
|
* Content to display in the card body.
|
|
18
25
|
* Can be any React node (string, JSX, etc.).
|
|
@@ -102,10 +109,12 @@ export type WithStoryCardProps = Omit<StoryCardProps, 'children' | 'className'>
|
|
|
102
109
|
* - If `content` is not provided, it will automatically use the story description,
|
|
103
110
|
* or fall back to the component description.
|
|
104
111
|
* - Cards are collected and displayed in the order they are defined in the decorators array.
|
|
112
|
+
* - The `status` option is deprecated; use `appearance` instead for the same behavior and additional variants (`source`, `output`).
|
|
105
113
|
*/
|
|
106
114
|
export function withStoryCard<TRenderer extends Renderer = Renderer>({
|
|
107
115
|
title,
|
|
108
116
|
status,
|
|
117
|
+
appearance,
|
|
109
118
|
content: contentProp,
|
|
110
119
|
className,
|
|
111
120
|
...rest
|
|
@@ -118,7 +127,8 @@ export function withStoryCard<TRenderer extends Renderer = Renderer>({
|
|
|
118
127
|
// Decorator props override parameter values
|
|
119
128
|
// Use parameters as fallback when decorator props are not provided
|
|
120
129
|
const finalTitle = title ?? storyCardParam?.title
|
|
121
|
-
const
|
|
130
|
+
const finalAppearance = appearance ?? storyCardParam?.appearance ?? status ?? storyCardParam?.status ?? 'info'
|
|
131
|
+
const finalStatus = status ?? storyCardParam?.status
|
|
122
132
|
const finalContent = contentProp ?? storyCardParam?.content
|
|
123
133
|
const finalClassName = className ?? storyCardParam?.className
|
|
124
134
|
|
|
@@ -132,6 +142,7 @@ export function withStoryCard<TRenderer extends Renderer = Renderer>({
|
|
|
132
142
|
content={content}
|
|
133
143
|
title={finalTitle}
|
|
134
144
|
status={finalStatus}
|
|
145
|
+
appearance={finalAppearance}
|
|
135
146
|
className={finalClassName}
|
|
136
147
|
{...rest}
|
|
137
148
|
/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
|
-
import type { StoryCardProps, StoryCardStatus } from '../components/story_card.js'
|
|
2
|
+
import type { StoryCardAppearance, StoryCardProps, StoryCardStatus } from '../components/story_card.js'
|
|
3
3
|
|
|
4
4
|
export interface StoryCardParam {
|
|
5
5
|
storyCard: {
|
|
@@ -9,12 +9,13 @@ export interface StoryCardParam {
|
|
|
9
9
|
*/
|
|
10
10
|
title?: ReactNode | undefined
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
* - `'error'`: Red background
|
|
14
|
-
* - `'warn'`: Yellow background
|
|
15
|
-
* - `'info'`: Blue background - default
|
|
12
|
+
* @deprecated Use `appearance` instead.
|
|
16
13
|
*/
|
|
17
14
|
status?: StoryCardStatus
|
|
15
|
+
/**
|
|
16
|
+
* Appearance of the card (error | warn | info | source | output). Default: `'info'`.
|
|
17
|
+
*/
|
|
18
|
+
appearance?: StoryCardAppearance | undefined
|
|
18
19
|
/**
|
|
19
20
|
* Additional CSS classes or a function to compute classes.
|
|
20
21
|
*
|
|
@@ -22,7 +23,10 @@ export interface StoryCardParam {
|
|
|
22
23
|
* If a function is provided, it receives the card state and default className,
|
|
23
24
|
* and should return the final className string.
|
|
24
25
|
*/
|
|
25
|
-
className?:
|
|
26
|
+
className?:
|
|
27
|
+
| ((state: Pick<StoryCardProps, 'status' | 'appearance'> & { defaultClassName: string }) => string)
|
|
28
|
+
| string
|
|
29
|
+
| undefined
|
|
26
30
|
/**
|
|
27
31
|
* Content to display in the card body.
|
|
28
32
|
* Can be any React node (string, JSX, etc.).
|
package/styles.css
CHANGED
|
@@ -3,19 +3,31 @@
|
|
|
3
3
|
@layer theme {
|
|
4
4
|
:root, :host {
|
|
5
5
|
--rbsb-color-red-100: oklch(93.6% 0.032 17.717);
|
|
6
|
+
--rbsb-color-red-300: oklch(80.8% 0.114 19.571);
|
|
6
7
|
--rbsb-color-red-500: oklch(63.7% 0.237 25.331);
|
|
8
|
+
--rbsb-color-red-700: oklch(50.5% 0.213 27.518);
|
|
7
9
|
--rbsb-color-red-800: oklch(44.4% 0.177 26.899);
|
|
8
10
|
--rbsb-color-red-900: oklch(39.6% 0.141 25.723);
|
|
9
11
|
--rbsb-color-amber-300: oklch(87.9% 0.169 91.605);
|
|
10
12
|
--rbsb-color-amber-900: oklch(41.4% 0.112 45.904);
|
|
11
13
|
--rbsb-color-yellow-100: oklch(97.3% 0.071 103.193);
|
|
14
|
+
--rbsb-color-yellow-300: oklch(90.5% 0.182 98.111);
|
|
12
15
|
--rbsb-color-yellow-500: oklch(79.5% 0.184 86.047);
|
|
16
|
+
--rbsb-color-yellow-700: oklch(55.4% 0.135 66.442);
|
|
13
17
|
--rbsb-color-yellow-900: oklch(42.1% 0.095 57.708);
|
|
18
|
+
--rbsb-color-green-100: oklch(96.2% 0.044 156.743);
|
|
14
19
|
--rbsb-color-green-200: oklch(92.5% 0.084 155.995);
|
|
20
|
+
--rbsb-color-green-300: oklch(87.1% 0.15 154.449);
|
|
15
21
|
--rbsb-color-green-500: oklch(72.3% 0.219 149.579);
|
|
22
|
+
--rbsb-color-green-700: oklch(52.7% 0.154 150.069);
|
|
16
23
|
--rbsb-color-green-800: oklch(44.8% 0.119 151.328);
|
|
24
|
+
--rbsb-color-green-900: oklch(39.3% 0.095 152.535);
|
|
25
|
+
--rbsb-color-emerald-200: oklch(90.5% 0.093 164.15);
|
|
26
|
+
--rbsb-color-emerald-800: oklch(43.2% 0.095 166.913);
|
|
17
27
|
--rbsb-color-sky-100: oklch(95.1% 0.026 236.824);
|
|
28
|
+
--rbsb-color-sky-300: oklch(82.8% 0.111 230.318);
|
|
18
29
|
--rbsb-color-sky-500: oklch(68.5% 0.169 237.323);
|
|
30
|
+
--rbsb-color-sky-700: oklch(50% 0.134 242.749);
|
|
19
31
|
--rbsb-color-sky-900: oklch(39.1% 0.09 240.876);
|
|
20
32
|
--rbsb-color-blue-200: oklch(88.2% 0.059 254.128);
|
|
21
33
|
--rbsb-color-blue-500: oklch(62.3% 0.214 259.815);
|
|
@@ -25,7 +37,9 @@
|
|
|
25
37
|
--rbsb-color-rose-400: oklch(71.2% 0.194 13.428);
|
|
26
38
|
--rbsb-color-rose-900: oklch(41% 0.159 10.272);
|
|
27
39
|
--rbsb-color-gray-100: oklch(96.7% 0.003 264.542);
|
|
40
|
+
--rbsb-color-gray-300: oklch(87.2% 0.01 258.338);
|
|
28
41
|
--rbsb-color-gray-500: oklch(55.1% 0.027 264.364);
|
|
42
|
+
--rbsb-color-gray-700: oklch(37.3% 0.034 259.733);
|
|
29
43
|
--rbsb-color-gray-900: oklch(21% 0.034 264.665);
|
|
30
44
|
--rbsb-color-black: #000;
|
|
31
45
|
--rbsb-color-white: #fff;
|
|
@@ -72,28 +86,51 @@
|
|
|
72
86
|
.rbsb\:rounded-lg {
|
|
73
87
|
border-radius: var(--rbsb-radius-lg);
|
|
74
88
|
}
|
|
89
|
+
.rbsb\:border {
|
|
90
|
+
border-style: var(--tw-border-style);
|
|
91
|
+
border-width: 1px;
|
|
92
|
+
}
|
|
75
93
|
.rbsb\:border-2 {
|
|
76
94
|
border-style: var(--tw-border-style);
|
|
77
95
|
border-width: 2px;
|
|
78
96
|
}
|
|
97
|
+
.rbsb\:border-solid {
|
|
98
|
+
--tw-border-style: solid;
|
|
99
|
+
border-style: solid;
|
|
100
|
+
}
|
|
79
101
|
.rbsb\:border-blue-500 {
|
|
80
102
|
border-color: var(--rbsb-color-blue-500);
|
|
81
103
|
}
|
|
104
|
+
.rbsb\:border-gray-300 {
|
|
105
|
+
border-color: var(--rbsb-color-gray-300);
|
|
106
|
+
}
|
|
82
107
|
.rbsb\:border-gray-500 {
|
|
83
108
|
border-color: var(--rbsb-color-gray-500);
|
|
84
109
|
}
|
|
110
|
+
.rbsb\:border-green-300 {
|
|
111
|
+
border-color: var(--rbsb-color-green-300);
|
|
112
|
+
}
|
|
85
113
|
.rbsb\:border-green-500 {
|
|
86
114
|
border-color: var(--rbsb-color-green-500);
|
|
87
115
|
}
|
|
88
116
|
.rbsb\:border-purple-500 {
|
|
89
117
|
border-color: var(--rbsb-color-purple-500);
|
|
90
118
|
}
|
|
119
|
+
.rbsb\:border-red-300 {
|
|
120
|
+
border-color: var(--rbsb-color-red-300);
|
|
121
|
+
}
|
|
91
122
|
.rbsb\:border-red-500 {
|
|
92
123
|
border-color: var(--rbsb-color-red-500);
|
|
93
124
|
}
|
|
125
|
+
.rbsb\:border-sky-300 {
|
|
126
|
+
border-color: var(--rbsb-color-sky-300);
|
|
127
|
+
}
|
|
94
128
|
.rbsb\:border-sky-500 {
|
|
95
129
|
border-color: var(--rbsb-color-sky-500);
|
|
96
130
|
}
|
|
131
|
+
.rbsb\:border-yellow-300 {
|
|
132
|
+
border-color: var(--rbsb-color-yellow-300);
|
|
133
|
+
}
|
|
97
134
|
.rbsb\:border-yellow-500 {
|
|
98
135
|
border-color: var(--rbsb-color-yellow-500);
|
|
99
136
|
}
|
|
@@ -106,9 +143,15 @@
|
|
|
106
143
|
.rbsb\:bg-blue-500 {
|
|
107
144
|
background-color: var(--rbsb-color-blue-500);
|
|
108
145
|
}
|
|
146
|
+
.rbsb\:bg-emerald-200 {
|
|
147
|
+
background-color: var(--rbsb-color-emerald-200);
|
|
148
|
+
}
|
|
109
149
|
.rbsb\:bg-gray-100 {
|
|
110
150
|
background-color: var(--rbsb-color-gray-100);
|
|
111
151
|
}
|
|
152
|
+
.rbsb\:bg-green-100 {
|
|
153
|
+
background-color: var(--rbsb-color-green-100);
|
|
154
|
+
}
|
|
112
155
|
.rbsb\:bg-green-200 {
|
|
113
156
|
background-color: var(--rbsb-color-green-200);
|
|
114
157
|
}
|
|
@@ -184,6 +227,31 @@
|
|
|
184
227
|
.rbsb\:ring-blue-200 {
|
|
185
228
|
--tw-ring-color: var(--rbsb-color-blue-200);
|
|
186
229
|
}
|
|
230
|
+
.rbsb\:dark\:border-gray-700 {
|
|
231
|
+
@media (prefers-color-scheme: dark) {
|
|
232
|
+
border-color: var(--rbsb-color-gray-700);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
.rbsb\:dark\:border-green-700 {
|
|
236
|
+
@media (prefers-color-scheme: dark) {
|
|
237
|
+
border-color: var(--rbsb-color-green-700);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
.rbsb\:dark\:border-red-700 {
|
|
241
|
+
@media (prefers-color-scheme: dark) {
|
|
242
|
+
border-color: var(--rbsb-color-red-700);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
.rbsb\:dark\:border-sky-700 {
|
|
246
|
+
@media (prefers-color-scheme: dark) {
|
|
247
|
+
border-color: var(--rbsb-color-sky-700);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
.rbsb\:dark\:border-yellow-700 {
|
|
251
|
+
@media (prefers-color-scheme: dark) {
|
|
252
|
+
border-color: var(--rbsb-color-yellow-700);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
187
255
|
.rbsb\:dark\:bg-amber-900 {
|
|
188
256
|
@media (prefers-color-scheme: dark) {
|
|
189
257
|
background-color: var(--rbsb-color-amber-900);
|
|
@@ -194,6 +262,11 @@
|
|
|
194
262
|
background-color: var(--rbsb-color-blue-900);
|
|
195
263
|
}
|
|
196
264
|
}
|
|
265
|
+
.rbsb\:dark\:bg-emerald-800 {
|
|
266
|
+
@media (prefers-color-scheme: dark) {
|
|
267
|
+
background-color: var(--rbsb-color-emerald-800);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
197
270
|
.rbsb\:dark\:bg-gray-500 {
|
|
198
271
|
@media (prefers-color-scheme: dark) {
|
|
199
272
|
background-color: var(--rbsb-color-gray-500);
|
|
@@ -209,6 +282,11 @@
|
|
|
209
282
|
background-color: var(--rbsb-color-green-800);
|
|
210
283
|
}
|
|
211
284
|
}
|
|
285
|
+
.rbsb\:dark\:bg-green-900 {
|
|
286
|
+
@media (prefers-color-scheme: dark) {
|
|
287
|
+
background-color: var(--rbsb-color-green-900);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
212
290
|
.rbsb\:dark\:bg-red-900 {
|
|
213
291
|
@media (prefers-color-scheme: dark) {
|
|
214
292
|
background-color: var(--rbsb-color-red-900);
|