@scm-manager/ui-components 4.0.0-REACT18-20250701-125025 → 4.0.0-REACT19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/package.json +46 -51
  2. package/src/BranchSelector.stories.tsx +60 -11
  3. package/src/Breadcrumb.stories.tsx +131 -57
  4. package/src/Breadcrumb.tsx +3 -3
  5. package/src/CardColumn.stories.tsx +94 -27
  6. package/src/CardColumnSmall.stories.tsx +102 -27
  7. package/src/CommaSeparatedList.tsx +2 -2
  8. package/src/Date.stories.tsx +64 -17
  9. package/src/Duration.stories.tsx +92 -45
  10. package/src/ErrorBoundary.tsx +38 -58
  11. package/src/ErrorNotification.tsx +1 -1
  12. package/src/Help.stories.tsx +61 -17
  13. package/src/Help.tsx +5 -11
  14. package/src/Icon.stories.tsx +93 -13
  15. package/src/LinkPaginator.tsx +9 -6
  16. package/src/Loading.stories.tsx +26 -6
  17. package/src/Logo.stories.tsx +44 -13
  18. package/src/Notification.stories.tsx +111 -23
  19. package/src/OverviewPageActions.tsx +5 -5
  20. package/src/Paginator.test.tsx +115 -94
  21. package/src/PdfViewer.stories.tsx +83 -5
  22. package/src/PreformattedCodeBlock.stories.tsx +97 -26
  23. package/src/ProtectedRoute.tsx +14 -39
  24. package/src/SmallLoadingSpinner.stories.tsx +26 -6
  25. package/src/SyntaxHighlighter.stories.tsx +122 -40
  26. package/src/SyntaxHighlighterRenderer.tsx +7 -7
  27. package/src/Tag.stories.tsx +135 -18
  28. package/src/Tag.tsx +2 -1
  29. package/src/Tooltip.stories.tsx +147 -34
  30. package/src/__snapshots__/storyshots.test.ts.snap +6 -112
  31. package/src/avatar/Avatar.ts +1 -1
  32. package/src/avatar/AvatarImage.tsx +1 -1
  33. package/src/avatar/AvatarWrapper.tsx +2 -2
  34. package/src/buttons/Button.stories.tsx +159 -0
  35. package/src/buttons/Button.tsx +5 -5
  36. package/src/config/ConfigurationBinder.tsx +39 -39
  37. package/src/config/ConfigurationForm.tsx +2 -1
  38. package/src/config/TitledSettings.tsx +4 -1
  39. package/src/forms/AddKeyValueEntryToTableField.stories.tsx +60 -25
  40. package/src/forms/Checkbox.stories.tsx +165 -27
  41. package/src/forms/Checkbox.tsx +1 -0
  42. package/src/forms/DropDown.stories.tsx +81 -35
  43. package/src/forms/FileInput.stories.tsx +85 -10
  44. package/src/forms/InputField.stories.tsx +210 -37
  45. package/src/forms/InputField.tsx +1 -0
  46. package/src/forms/Radio.stories.tsx +181 -34
  47. package/src/forms/Radio.tsx +1 -0
  48. package/src/forms/Select.stories.tsx +266 -46
  49. package/src/forms/Select.tsx +1 -0
  50. package/src/forms/Textarea.stories.tsx +99 -53
  51. package/src/forms/Textarea.tsx +1 -0
  52. package/src/forms/index.ts +3 -1
  53. package/src/index.ts +5 -5
  54. package/src/jest-dom.d.ts +17 -0
  55. package/src/layout/Footer.stories.tsx +114 -22
  56. package/src/layout/FooterSection.tsx +1 -0
  57. package/src/layout/Header.tsx +2 -1
  58. package/src/layout/Page.tsx +1 -3
  59. package/src/layout/PrimaryContentColumn.tsx +2 -2
  60. package/src/layout/SecondaryNavigationColumn.tsx +3 -3
  61. package/src/layout/SubSubtitle.tsx +2 -1
  62. package/src/layout/Subtitle.tsx +2 -1
  63. package/src/layout/Title.tsx +2 -5
  64. package/src/markdown/LazyMarkdownView.tsx +16 -5
  65. package/src/markdown/MarkdownHeadingRenderer.test.ts +9 -1
  66. package/src/markdown/MarkdownHeadingRenderer.tsx +3 -3
  67. package/src/markdown/MarkdownImageRenderer.test.ts +8 -1
  68. package/src/markdown/MarkdownImageRenderer.tsx +2 -1
  69. package/src/markdown/MarkdownLinkRenderer.test.tsx +9 -0
  70. package/src/markdown/MarkdownLinkRenderer.tsx +6 -4
  71. package/src/markdown/MarkdownView.stories.tsx +224 -72
  72. package/src/markdown/markdownExtensions.ts +6 -4
  73. package/src/modals/ConfirmAlert.stories.tsx +133 -44
  74. package/src/modals/ConfirmAlert.tsx +5 -4
  75. package/src/modals/Modal.stories.tsx +461 -252
  76. package/src/modals/Modal.tsx +12 -11
  77. package/src/modals/useRegisterModal.test.tsx +5 -4
  78. package/src/navigation/MenuContext.tsx +2 -2
  79. package/src/navigation/NavLink.tsx +4 -7
  80. package/src/navigation/PrimaryNavigation.tsx +2 -2
  81. package/src/navigation/PrimaryNavigationLink.tsx +6 -5
  82. package/src/navigation/RoutingProps.ts +1 -3
  83. package/src/navigation/SecondaryNavigation.stories.tsx +157 -45
  84. package/src/navigation/SecondaryNavigation.tsx +17 -16
  85. package/src/navigation/SecondaryNavigationItem.tsx +2 -1
  86. package/src/navigation/SubNavigation.tsx +4 -8
  87. package/src/navigation/useActiveMatch.ts +20 -22
  88. package/src/navigation/useNavigationLock.ts +1 -0
  89. package/src/popover/Popover.stories.tsx +111 -41
  90. package/src/popover/Popover.tsx +2 -5
  91. package/src/repos/Diff.stories.tsx +418 -223
  92. package/src/repos/Diff.tsx +1 -5
  93. package/src/repos/HunkExpandDivider.tsx +2 -2
  94. package/src/repos/LoadingDiff.tsx +11 -6
  95. package/src/repos/RepositoryEntry.stories.tsx +217 -53
  96. package/src/repos/RepositoryFlag.tsx +2 -1
  97. package/src/repos/TokenizedDiffView.tsx +4 -2
  98. package/src/repos/annotate/Annotate.stories.tsx +225 -111
  99. package/src/repos/annotate/AnnotateLine.tsx +2 -1
  100. package/src/repos/changesets/ChangesetAuthor.tsx +2 -2
  101. package/src/repos/changesets/ChangesetButtonGroup.test.tsx +9 -5
  102. package/src/repos/changesets/ChangesetDiff.test.ts +10 -2
  103. package/src/repos/changesets/Changesets.stories.tsx +388 -197
  104. package/src/repos/changesets/ContributorRow.tsx +2 -2
  105. package/src/repos/changesets/SignatureIcon.tsx +1 -0
  106. package/src/repos/diff/DiffFileTree.tsx +1 -1
  107. package/src/repos/diff/styledElements.tsx +4 -3
  108. package/src/repos/index.ts +15 -15
  109. package/src/search/Hit.tsx +3 -2
  110. package/src/search/TextHitField.stories.tsx +131 -43
  111. package/src/search/TextHitField.tsx +3 -2
  112. package/src/search/index.ts +1 -1
  113. package/src/storyshots.test.ts +66 -60
  114. package/src/table/Table.stories.tsx +146 -48
  115. package/src/table/Table.tsx +7 -8
  116. package/src/table/TextColumn.tsx +0 -9
  117. package/src/toast/Toast.tsx +2 -1
  118. package/src/toast/ToastArea.tsx +2 -2
  119. package/src/toast/ToastButton.tsx +2 -1
  120. package/src/toast/ToastButtons.tsx +4 -2
  121. package/src/toast/ToastNotification.tsx +2 -1
  122. package/src/toast/index.stories.tsx +144 -39
  123. package/src/toast/index.ts +1 -1
  124. package/src/buttons/index.stories.tsx +0 -85
@@ -14,21 +14,140 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
+ // import React, { FC, useRef, useState } from "react";
18
+ // import { storiesOf } from "@storybook/react";
19
+ // import styled from "styled-components";
20
+ // import InputField from "./InputField";
21
+ // import Button from "../buttons/Button";
22
+ // import { MemoryRouter } from "react-router-dom";
23
+ // import { useForm } from "react-hook-form";
24
+ // import { SubmitButton } from "../buttons";
25
+ //
26
+ // const Decorator = styled.div`
27
+ // padding: 2rem;
28
+ // max-width: 30rem;
29
+ // `;
30
+ //
31
+ // const Ref: FC = () => {
32
+ // const ref = useRef<HTMLInputElement>(null);
33
+ // return (
34
+ // <>
35
+ // <InputField ref={ref} placeholder="Click the button to focus me" />
36
+ // <Button action={() => ref.current?.focus()} color="primary">
37
+ // Focus InputField
38
+ // </Button>
39
+ // </>
40
+ // );
41
+ // };
42
+ //
43
+ // const AutoFocusAndRef: FC = () => {
44
+ // const ref = useRef<HTMLInputElement>(null);
45
+ // return (
46
+ // <>
47
+ // <InputField ref={ref} autofocus={true} placeholder="Click the button to focus me" />
48
+ // <InputField placeholder="Click me to switch focus" />
49
+ // <Button action={() => ref.current?.focus()} color="primary">
50
+ // Focus First InputField
51
+ // </Button>
52
+ // </>
53
+ // );
54
+ // };
55
+ //
56
+ // type Name = {
57
+ // readonly: string;
58
+ // disabled: string;
59
+ // firstName: string;
60
+ // lastName: string;
61
+ // };
62
+ //
63
+ // const ReactHookForm: FC = () => {
64
+ // const {
65
+ // register,
66
+ // handleSubmit,
67
+ // formState: { errors },
68
+ // } = useForm<Name>();
69
+ // const [stored, setStored] = useState<Name>();
70
+ //
71
+ // const onSubmit = (person: Name) => {
72
+ // setStored(person);
73
+ // };
74
+ //
75
+ // return (
76
+ // <>
77
+ // <form onSubmit={handleSubmit(onSubmit)}>
78
+ // <InputField
79
+ // label="Readonly"
80
+ // defaultValue="I am readonly but still show up on submit!"
81
+ // readOnly={true}
82
+ // {...register("readonly")}
83
+ // />
84
+ // <InputField
85
+ // label="Disabled"
86
+ // defaultValue="I am disabled and dont show up on submit!"
87
+ // disabled={true}
88
+ // {...register("disabled")}
89
+ // />
90
+ // <InputField label="First Name" autofocus={true} {...register("firstName")} />
91
+ // <InputField
92
+ // label="Last Name"
93
+ // {...register("lastName", { required: true })}
94
+ // validationError={!!errors.lastName}
95
+ // errorMessage={"Last name is required"}
96
+ // />
97
+ // <div className="pt-2">
98
+ // <SubmitButton>Submit</SubmitButton>
99
+ // </div>
100
+ // </form>
101
+ // {stored ? (
102
+ // <div className="mt-5">
103
+ // <pre>
104
+ // <code>{JSON.stringify(stored, null, 2)}</code>
105
+ // </pre>
106
+ // </div>
107
+ // ) : null}
108
+ // </>
109
+ // );
110
+ // };
111
+ //
112
+ // const LegacyEvents: FC = () => {
113
+ // const [value, setValue] = useState<string>("");
114
+ // return (
115
+ // <>
116
+ // <InputField placeholder="Legacy onChange handler" value={value} onChange={(e) => setValue(e)} />
117
+ // <div className="mt-3">{value}</div>
118
+ // </>
119
+ // );
120
+ // };
121
+ //
122
+ // storiesOf("Forms/InputField", module)
123
+ // .addDecorator((storyFn) => <Decorator>{storyFn()}</Decorator>)
124
+ // .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
125
+ // .add("AutoFocus", () => <InputField label="Field with AutoFocus" autofocus={true} />)
126
+ // .add("Default Value", () => <InputField label="Field with Default Value" defaultValue={"I am a default value"} />)
127
+ // .add("Ref", () => <Ref />)
128
+ // .add("Legacy Events", () => <LegacyEvents />)
129
+ // .add("AutoFocusAndRef", () => <AutoFocusAndRef />)
130
+ // .add("React Hook Form", () => <ReactHookForm />);
131
+
17
132
  import React, { FC, useRef, useState } from "react";
18
- import { storiesOf } from "@storybook/react";
133
+ import type { Meta, StoryObj } from "@storybook/react";
19
134
  import styled from "styled-components";
135
+ import { useForm } from "react-hook-form";
136
+ import { MemoryRouter } from "react-router-dom";
137
+
20
138
  import InputField from "./InputField";
21
139
  import Button from "../buttons/Button";
22
- import { MemoryRouter } from "react-router-dom";
23
- import { useForm } from "react-hook-form";
24
140
  import { SubmitButton } from "../buttons";
25
141
 
26
142
  const Decorator = styled.div`
27
143
  padding: 2rem;
28
144
  max-width: 30rem;
145
+ display: flex;
146
+ flex-direction: column;
147
+ gap: 1rem;
29
148
  `;
30
149
 
31
- const Ref: FC = () => {
150
+ const RefExample: FC = () => {
32
151
  const ref = useRef<HTMLInputElement>(null);
33
152
  return (
34
153
  <>
@@ -40,41 +159,46 @@ const Ref: FC = () => {
40
159
  );
41
160
  };
42
161
 
43
- const AutoFocusAndRef: FC = () => {
44
- const ref = useRef<HTMLInputElement>(null);
162
+ const OnChangeExample: FC = () => {
163
+ const [value, setValue] = useState("");
45
164
  return (
46
165
  <>
47
- <InputField ref={ref} autofocus={true} placeholder="Click the button to focus me" />
48
- <InputField placeholder="Click me to switch focus" />
49
- <Button action={() => ref.current?.focus()} color="primary">
50
- Focus First InputField
51
- </Button>
166
+ {/* @ts-ignore*/}
167
+ <InputField
168
+ placeholder="Legacy onChange handler"
169
+ value={value}
170
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value)}
171
+ />
172
+ <div className="mt-3">
173
+ <strong>Value:</strong> {value}
174
+ </div>
52
175
  </>
53
176
  );
54
177
  };
55
178
 
56
- type Name = {
179
+ // Helper-Komponente für die "ReactHookForm"-Story
180
+ type FormValues = {
57
181
  readonly: string;
58
182
  disabled: string;
59
183
  firstName: string;
60
184
  lastName: string;
61
185
  };
62
186
 
63
- const ReactHookForm: FC = () => {
187
+ const ReactHookFormExample: FC = () => {
64
188
  const {
65
189
  register,
66
190
  handleSubmit,
67
191
  formState: { errors },
68
- } = useForm<Name>();
69
- const [stored, setStored] = useState<Name>();
192
+ } = useForm<FormValues>();
193
+ const [stored, setStored] = useState<FormValues>();
70
194
 
71
- const onSubmit = (person: Name) => {
72
- setStored(person);
195
+ const onSubmit = (data: FormValues) => {
196
+ setStored(data);
73
197
  };
74
198
 
75
199
  return (
76
200
  <>
77
- <form onSubmit={handleSubmit(onSubmit)}>
201
+ <form onSubmit={handleSubmit(onSubmit)} style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
78
202
  <InputField
79
203
  label="Readonly"
80
204
  defaultValue="I am readonly but still show up on submit!"
@@ -98,33 +222,82 @@ const ReactHookForm: FC = () => {
98
222
  <SubmitButton>Submit</SubmitButton>
99
223
  </div>
100
224
  </form>
101
- {stored ? (
225
+ {stored && (
102
226
  <div className="mt-5">
103
227
  <pre>
104
228
  <code>{JSON.stringify(stored, null, 2)}</code>
105
229
  </pre>
106
230
  </div>
107
- ) : null}
231
+ )}
108
232
  </>
109
233
  );
110
234
  };
111
235
 
112
- const LegacyEvents: FC = () => {
113
- const [value, setValue] = useState<string>("");
114
- return (
115
- <>
116
- <InputField placeholder="Legacy onChange handler" value={value} onChange={(e) => setValue(e)} />
117
- <div className="mt-3">{value}</div>
118
- </>
119
- );
236
+ // --- Storybook Metadata ---
237
+
238
+ const meta: Meta<typeof InputField> = {
239
+ title: "Forms/InputField",
240
+ component: InputField,
241
+ decorators: [
242
+ (Story) => (
243
+ <Decorator>
244
+ <Story />
245
+ </Decorator>
246
+ ),
247
+ (Story) => (
248
+ <MemoryRouter>
249
+ <Story />
250
+ </MemoryRouter>
251
+ ),
252
+ ],
253
+ argTypes: {
254
+ onChange: { action: "changed" },
255
+ },
256
+ tags: ["autodocs"],
120
257
  };
121
258
 
122
- storiesOf("Forms/InputField", module)
123
- .addDecorator((storyFn) => <Decorator>{storyFn()}</Decorator>)
124
- .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
125
- .add("AutoFocus", () => <InputField label="Field with AutoFocus" autofocus={true} />)
126
- .add("Default Value", () => <InputField label="Field with Default Value" defaultValue={"I am a default value"} />)
127
- .add("Ref", () => <Ref />)
128
- .add("Legacy Events", () => <LegacyEvents />)
129
- .add("AutoFocusAndRef", () => <AutoFocusAndRef />)
130
- .add("React Hook Form", () => <ReactHookForm />);
259
+ export default meta;
260
+
261
+ // --- Story Definitions ---
262
+
263
+ type Story = StoryObj<typeof meta>;
264
+
265
+ // Einfache Stories, die direkt `args` verwenden
266
+ export const Default: Story = {
267
+ args: {
268
+ label: "Default Input",
269
+ placeholder: "Type something here...",
270
+ },
271
+ };
272
+
273
+ export const WithHelpText: Story = {
274
+ args: {
275
+ ...Default.args,
276
+ label: "With Help Text",
277
+ helpText: "This is some helpful information.",
278
+ },
279
+ };
280
+
281
+ export const Disabled: Story = {
282
+ args: {
283
+ ...Default.args,
284
+ label: "Disabled Input",
285
+ disabled: true,
286
+ },
287
+ };
288
+
289
+ // Komplexe Stories, die eine `render`-Funktion benötigen
290
+ export const WithRef: Story = {
291
+ name: "Using Refs",
292
+ render: () => <RefExample />,
293
+ };
294
+
295
+ export const WithOnChange: Story = {
296
+ name: "Handling onChange",
297
+ render: () => <OnChangeExample />,
298
+ };
299
+
300
+ export const WithReactHookForm: Story = {
301
+ name: "With React Hook Form",
302
+ render: () => <ReactHookFormExample />,
303
+ };
@@ -132,6 +132,7 @@ export const InnerInputField: FC<FieldProps<BaseProps, HTMLInputElement, string>
132
132
  );
133
133
  };
134
134
 
135
+ // @ts-ignore
135
136
  const InputField: FieldType<BaseProps, HTMLInputElement, string> = createFormFieldWrapper(InnerInputField);
136
137
 
137
138
  export default InputField;
@@ -14,14 +14,133 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
+ // import React, { FC, useRef, useState } from "react";
18
+ // import { storiesOf } from "@storybook/react";
19
+ // import Radio from "./Radio";
20
+ // import styled from "styled-components";
21
+ // import Button from "../buttons/Button";
22
+ // import { useForm } from "react-hook-form";
23
+ // import { SubmitButton } from "../buttons";
24
+ // import { MemoryRouter } from "react-router-dom";
25
+ //
26
+ // const Spacing = styled.div`
27
+ // padding: 2em;
28
+ // `;
29
+ //
30
+ // const RadioList = styled.div`
31
+ // display: flex;
32
+ // flex-direction: column;
33
+ // > label:not(:last-child) {
34
+ // margin-bottom: 0.75rem;
35
+ // }
36
+ // padding: 2em;
37
+ // `;
38
+ //
39
+ // const Ref: FC = () => {
40
+ // const ref = useRef<HTMLInputElement>(null);
41
+ // return (
42
+ // <>
43
+ // <Radio label={"Ref Radio Button"} checked={false} ref={ref} />
44
+ // <Button
45
+ // action={() => {
46
+ // if (ref.current) {
47
+ // ref.current.checked = true;
48
+ // }
49
+ // }}
50
+ // color="primary"
51
+ // >
52
+ // Check InputField
53
+ // </Button>
54
+ // </>
55
+ // );
56
+ // };
57
+ //
58
+ // type Settings = {
59
+ // rememberMe: string;
60
+ // scramblePassword: string;
61
+ // readonly: string;
62
+ // disabled: string;
63
+ // };
64
+ //
65
+ // const ReactHookForm: FC = () => {
66
+ // const { register, handleSubmit } = useForm<Settings>();
67
+ // const [stored, setStored] = useState<Settings>();
68
+ //
69
+ // const onSubmit = (settings: Settings) => {
70
+ // setStored(settings);
71
+ // };
72
+ //
73
+ // return (
74
+ // <>
75
+ // <form onSubmit={handleSubmit(onSubmit)}>
76
+ // <RadioList>
77
+ // <Radio defaultChecked={true} value={"true"} label="Remember Me" {...register("rememberMe")} />
78
+ // <Radio value={"false"} label="Dont Remember Me" {...register("rememberMe")} />
79
+ // </RadioList>
80
+ // <Radio className="ml-2" value={"false"} label="Scramble Password" {...register("scramblePassword")} />
81
+ // <Radio value={"false"} label="Disabled wont be submitted" disabled={true} {...register("disabled")} />
82
+ // <Radio value={"false"} label="Readonly will be submitted" {...register("readonly")} />
83
+ // <div className="pt-2">
84
+ // <SubmitButton>Submit</SubmitButton>
85
+ // </div>
86
+ // </form>
87
+ // {stored ? (
88
+ // <div className="mt-5">
89
+ // <pre>
90
+ // <code>{JSON.stringify(stored, null, 2)}</code>
91
+ // </pre>
92
+ // </div>
93
+ // ) : null}
94
+ // </>
95
+ // );
96
+ // };
97
+ //
98
+ // const LegacyEvents: FC = () => {
99
+ // const [value, setValue] = useState<boolean>(false);
100
+ // return (
101
+ // <>
102
+ // <Radio checked={value} onChange={setValue} />
103
+ // <div className="mt-3">{JSON.stringify(value)}</div>
104
+ // </>
105
+ // );
106
+ // };
107
+ //
108
+ // storiesOf("Forms/Radio", module)
109
+ // .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
110
+ // .add("Default", () => (
111
+ // <Spacing>
112
+ // <Radio label="Not checked" checked={false} />
113
+ // <Radio label="Checked" checked={true} />
114
+ // </Spacing>
115
+ // ))
116
+ // .add("Disabled", () => (
117
+ // <Spacing>
118
+ // <Radio label="Checked but disabled" checked={true} disabled={true} />
119
+ // </Spacing>
120
+ // ))
121
+ // .add("With HelpText", () => (
122
+ // <RadioList>
123
+ // <Radio label="Classic helpText" checked={false} helpText="This is a classic help text." />
124
+ // <Radio
125
+ // label="Long helpText"
126
+ // checked={true}
127
+ // helpText="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
128
+ // />
129
+ // </RadioList>
130
+ // ))
131
+ // .add("Ref", () => <Ref />)
132
+ // .add("Legacy Events", () => <LegacyEvents />)
133
+ // .add("ReactHookForm", () => <ReactHookForm />);
134
+
17
135
  import React, { FC, useRef, useState } from "react";
18
- import { storiesOf } from "@storybook/react";
19
- import Radio from "./Radio";
136
+ import { MemoryRouter } from "react-router-dom";
137
+ import { useForm } from "react-hook-form";
20
138
  import styled from "styled-components";
139
+ import type { Meta, StoryObj } from "@storybook/react";
140
+
141
+ import Radio from "./Radio";
21
142
  import Button from "../buttons/Button";
22
- import { useForm } from "react-hook-form";
23
143
  import { SubmitButton } from "../buttons";
24
- import { MemoryRouter } from "react-router-dom";
25
144
 
26
145
  const Spacing = styled.div`
27
146
  padding: 2em;
@@ -36,11 +155,11 @@ const RadioList = styled.div`
36
155
  padding: 2em;
37
156
  `;
38
157
 
39
- const Ref: FC = () => {
158
+ const RefExample: FC = () => {
40
159
  const ref = useRef<HTMLInputElement>(null);
41
160
  return (
42
- <>
43
- <Radio label={"Ref Radio Button"} checked={false} ref={ref} />
161
+ <Spacing>
162
+ <Radio label={"Ref Radio Button"} name="ref-example" ref={ref} />
44
163
  <Button
45
164
  action={() => {
46
165
  if (ref.current) {
@@ -48,10 +167,11 @@ const Ref: FC = () => {
48
167
  }
49
168
  }}
50
169
  color="primary"
170
+ className="ml-2"
51
171
  >
52
- Check InputField
172
+ Check Radio Button
53
173
  </Button>
54
- </>
174
+ </Spacing>
55
175
  );
56
176
  };
57
177
 
@@ -62,7 +182,7 @@ type Settings = {
62
182
  disabled: string;
63
183
  };
64
184
 
65
- const ReactHookForm: FC = () => {
185
+ const ReactHookFormExample: FC = () => {
66
186
  const { register, handleSubmit } = useForm<Settings>();
67
187
  const [stored, setStored] = useState<Settings>();
68
188
 
@@ -71,7 +191,7 @@ const ReactHookForm: FC = () => {
71
191
  };
72
192
 
73
193
  return (
74
- <>
194
+ <Spacing>
75
195
  <form onSubmit={handleSubmit(onSubmit)}>
76
196
  <RadioList>
77
197
  <Radio defaultChecked={true} value={"true"} label="Remember Me" {...register("rememberMe")} />
@@ -84,50 +204,77 @@ const ReactHookForm: FC = () => {
84
204
  <SubmitButton>Submit</SubmitButton>
85
205
  </div>
86
206
  </form>
87
- {stored ? (
207
+ {stored && (
88
208
  <div className="mt-5">
89
209
  <pre>
90
210
  <code>{JSON.stringify(stored, null, 2)}</code>
91
211
  </pre>
92
212
  </div>
93
- ) : null}
94
- </>
213
+ )}
214
+ </Spacing>
95
215
  );
96
216
  };
97
217
 
98
- const LegacyEvents: FC = () => {
99
- const [value, setValue] = useState<boolean>(false);
218
+ const OnChangeExample: FC = () => {
219
+ const [value, setValue] = useState(false);
100
220
  return (
101
- <>
102
- <Radio checked={value} onChange={setValue} />
221
+ <Spacing>
222
+ <Radio checked={value} onChange={setValue} name="onchange-example" />
103
223
  <div className="mt-3">{JSON.stringify(value)}</div>
104
- </>
224
+ </Spacing>
105
225
  );
106
226
  };
107
227
 
108
- storiesOf("Forms/Radio", module)
109
- .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
110
- .add("Default", () => (
228
+ const meta: Meta<typeof Radio> = {
229
+ title: "Forms/Radio",
230
+ component: Radio,
231
+ decorators: [(Story) => <MemoryRouter>{Story()}</MemoryRouter>],
232
+ tags: ["autodocs"],
233
+ };
234
+
235
+ export default meta;
236
+
237
+ type Story = StoryObj<typeof meta>;
238
+
239
+ export const Default: Story = {
240
+ render: () => (
111
241
  <Spacing>
112
- <Radio label="Not checked" checked={false} />
113
- <Radio label="Checked" checked={true} />
242
+ <Radio label="Not checked" name="default-group" />
243
+ <Radio label="Checked" name="default-group" checked={true} />
114
244
  </Spacing>
115
- ))
116
- .add("Disabled", () => (
245
+ ),
246
+ };
247
+
248
+ export const Disabled: Story = {
249
+ render: () => (
117
250
  <Spacing>
118
- <Radio label="Checked but disabled" checked={true} disabled={true} />
251
+ <Radio label="Checked but disabled" checked={true} disabled={true} name="disabled-group" />
119
252
  </Spacing>
120
- ))
121
- .add("With HelpText", () => (
253
+ ),
254
+ };
255
+
256
+ export const WithHelpText: Story = {
257
+ render: () => (
122
258
  <RadioList>
123
- <Radio label="Classic helpText" checked={false} helpText="This is a classic help text." />
259
+ <Radio label="Classic helpText" checked={false} helpText="This is a classic help text." name="help-group" />
124
260
  <Radio
125
261
  label="Long helpText"
126
262
  checked={true}
263
+ name="help-group"
127
264
  helpText="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
128
265
  />
129
266
  </RadioList>
130
- ))
131
- .add("Ref", () => <Ref />)
132
- .add("Legacy Events", () => <LegacyEvents />)
133
- .add("ReactHookForm", () => <ReactHookForm />);
267
+ ),
268
+ };
269
+
270
+ export const UsingRefs: Story = {
271
+ render: () => <RefExample />,
272
+ };
273
+
274
+ export const HandlingOnChange: Story = {
275
+ render: () => <OnChangeExample />,
276
+ };
277
+
278
+ export const WithReactHookForm: Story = {
279
+ render: () => <ReactHookFormExample />,
280
+ };
@@ -103,6 +103,7 @@ const InnerRadio: FC<FieldProps<BaseProps, HTMLInputElement, boolean>> = ({
103
103
  /**
104
104
  * @deprecated
105
105
  */
106
+ // @ts-ignore
106
107
  const Radio: FieldType<BaseProps, HTMLInputElement, boolean> = createFormFieldWrapper(InnerRadio);
107
108
 
108
109
  export default Radio;