Skip to content

Commit 0d64119

Browse files
committed
Fieldset handles RadioRichButtons
1 parent ebf290f commit 0d64119

File tree

6 files changed

+204
-14
lines changed

6 files changed

+204
-14
lines changed

src/Checkbox.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import React, { memo, forwardRef } from "react";
22
import { symToStr } from "tsafe/symToStr";
33
import { Fieldset, type FieldsetProps } from "./shared/Fieldset";
44

5-
export type CheckboxProps = FieldsetProps.Common;
5+
export type CheckboxProps = Omit<FieldsetProps.Checkbox, "type">;
66

77
/** @see <https://components.react-dsfr.codegouv.studio/?path=/docs/components-checkbox> */
88
export const Checkbox = memo(
99
forwardRef<HTMLFieldSetElement, CheckboxProps>((props, ref) => (
10-
<Fieldset ref={ref} type="checkbox" {...props} />
10+
<Fieldset ref={ref} {...props} type="checkbox" />
1111
))
1212
);
1313

src/RadioButtons.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import React, { memo, forwardRef } from "react";
22
import { symToStr } from "tsafe/symToStr";
33
import { Fieldset, type FieldsetProps } from "./shared/Fieldset";
44

5-
export type RadioButtonsProps = FieldsetProps.Common & { name?: string };
5+
export type RadioButtonsProps = Omit<FieldsetProps.Radio, "type">;
66

77
/** @see <https://components.react-dsfr.codegouv.studio/?path=/docs/components-radiobutton> */
88
export const RadioButtons = memo(
99
forwardRef<HTMLFieldSetElement, RadioButtonsProps>((props, ref) => (
10-
<Fieldset ref={ref} type="radio" {...props} />
10+
<Fieldset ref={ref} {...props} type="radio" />
1111
))
1212
);
1313

src/RadioRichButtons.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React, { memo, forwardRef } from "react";
2+
import { symToStr } from "tsafe/symToStr";
3+
import { Fieldset, type FieldsetProps } from "./shared/Fieldset";
4+
5+
export type RadioRichButtonsProps = Omit<FieldsetProps.RadioRich, "type" | "rich">;
6+
7+
/** @see <https://components.react-dsfr.codegouv.studio/?path=/docs/components-radiobutton> */
8+
export const RadioRichButtons = memo(
9+
forwardRef<HTMLFieldSetElement, RadioRichButtonsProps>((props, ref) => (
10+
<Fieldset ref={ref} {...props} type="radio" rich />
11+
))
12+
);
13+
14+
RadioRichButtons.displayName = symToStr({ RadioRichButtons });
15+
16+
export default RadioRichButtons;

src/shared/Fieldset.tsx

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,28 @@ import { cx } from "../tools/cx";
1414
import { fr } from "../fr";
1515
import { useAnalyticsId } from "../tools/useAnalyticsId";
1616

17-
export type FieldsetProps = FieldsetProps.Radio | FieldsetProps.Checkbox;
17+
export type FieldsetProps = FieldsetProps.Radio | FieldsetProps.Checkbox | FieldsetProps.RadioRich;
1818

1919
export namespace FieldsetProps {
20+
export type RegularOption = {
21+
label: ReactNode;
22+
hintText?: ReactNode;
23+
nativeInputProps: DetailedHTMLProps<
24+
InputHTMLAttributes<HTMLInputElement>,
25+
HTMLInputElement
26+
>;
27+
};
28+
export type RadioRichOption = RegularOption & {
29+
illustration: ReactNode;
30+
};
2031
export type Common = {
2132
className?: string;
2233
id?: string;
2334
classes?: Partial<Record<"root" | "legend" | "content", string>>;
2435
style?: CSSProperties;
2536
legend?: ReactNode;
2637
hintText?: ReactNode;
27-
options: {
28-
label: ReactNode;
29-
hintText?: ReactNode;
30-
nativeInputProps: DetailedHTMLProps<
31-
InputHTMLAttributes<HTMLInputElement>,
32-
HTMLInputElement
33-
>;
34-
}[];
38+
3539
/** Default: "vertical" */
3640
orientation?: "vertical" | "horizontal";
3741
/** Default: "default" */
@@ -50,11 +54,22 @@ export namespace FieldsetProps {
5054
export type Radio = Common & {
5155
type: "radio";
5256
name?: string;
57+
rich?: false;
58+
options: RegularOption[];
5359
};
5460

5561
export type Checkbox = Common & {
5662
type: "checkbox";
5763
name?: never;
64+
rich?: false;
65+
options: RegularOption[];
66+
};
67+
68+
export type RadioRich = Common & {
69+
type: "radio";
70+
name?: string;
71+
rich: true;
72+
options: RadioRichOption[];
5873
};
5974
}
6075

@@ -76,6 +91,7 @@ export const Fieldset = memo(
7691
type,
7792
name: name_props,
7893
small = false,
94+
rich,
7995
...rest
8096
} = props;
8197

@@ -147,7 +163,11 @@ export const Fieldset = memo(
147163
<div className={cx(fr.cx("fr-fieldset__content"), classes.content)}>
148164
{options.map(({ label, hintText, nativeInputProps }, i) => (
149165
<div
150-
className={fr.cx(`fr-${type}-group`, small && `fr-${type}-group--sm`)}
166+
className={fr.cx(
167+
`fr-${type}-group`,
168+
rich && "fr-radio-rich",
169+
small && `fr-${type}-group--sm`
170+
)}
151171
key={i}
152172
>
153173
<input
@@ -162,6 +182,11 @@ export const Fieldset = memo(
162182
<span className={fr.cx("fr-hint-text")}>{hintText}</span>
163183
)}
164184
</label>
185+
{rich && (
186+
<div className={fr.cx("fr-radio-rich__img")}>
187+
{options[i].illustration}
188+
</div>
189+
)}
165190
</div>
166191
))}
167192
</div>

test/types/Checkbox.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from "react";
2+
import { Checkbox } from "../../src/Checkbox";
3+
4+
{
5+
<Checkbox
6+
legend="Label"
7+
options={[
8+
{
9+
"label": "Label 1",
10+
"hintText": "Hint text",
11+
"nativeInputProps": {
12+
"value": 1
13+
}
14+
},
15+
{
16+
"label": "Label 2",
17+
"hintText": "Hint text",
18+
"nativeInputProps": {
19+
"value": 2
20+
}
21+
}
22+
]}
23+
/>;
24+
}
25+
{
26+
<Checkbox
27+
orientation="horizontal"
28+
className={"fr-mt-1w"}
29+
options={[
30+
{
31+
"label": "Label 1",
32+
"hintText": "Hint text",
33+
"nativeInputProps": {
34+
"value": 1
35+
}
36+
},
37+
{
38+
"label": "Label 2",
39+
"hintText": "Hint text",
40+
"nativeInputProps": {
41+
"value": 2
42+
},
43+
// @ts-expect-error
44+
"illustration": <img src="https://placehold.it/100x100" alt="illustration" />
45+
}
46+
]}
47+
/>;
48+
}

test/types/RadioButtons.tsx

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import React from "react";
2+
import { RadioButtons } from "../../src/RadioButtons";
3+
import { RadioRichButtons } from "../../src/RadioRichButtons";
4+
5+
{
6+
<RadioButtons
7+
legend="Label"
8+
name="name"
9+
options={[
10+
{
11+
"label": "Label 1",
12+
"hintText": "Hint text",
13+
"nativeInputProps": {
14+
"value": 1
15+
}
16+
},
17+
{
18+
"label": "Label 2",
19+
"hintText": "Hint text",
20+
"nativeInputProps": {
21+
"value": 2
22+
}
23+
}
24+
]}
25+
/>;
26+
}
27+
28+
{
29+
<RadioRichButtons
30+
legend="Label"
31+
name="name"
32+
options={[
33+
{
34+
"label": "Label 1",
35+
"hintText": "Hint text",
36+
"nativeInputProps": {
37+
"value": 1
38+
},
39+
"illustration": <img src="https://placehold.it/100x100" alt="illustration" />
40+
},
41+
{
42+
"label": "Label 2",
43+
"hintText": "Hint text",
44+
"nativeInputProps": {
45+
"value": 2
46+
},
47+
"illustration": <img src="https://placehold.it/100x100" alt="illustration" />
48+
}
49+
]}
50+
/>;
51+
}
52+
53+
{
54+
<RadioButtons
55+
legend="Label"
56+
name="name"
57+
options={[
58+
{
59+
"label": "Label 1",
60+
"hintText": "Hint text",
61+
"nativeInputProps": {
62+
"value": 1
63+
},
64+
// @ts-expect-error
65+
"illustration": <img src="https://placehold.it/100x100" alt="illustration" />
66+
},
67+
{
68+
"label": "Label 2",
69+
"hintText": "Hint text",
70+
"nativeInputProps": {
71+
"value": 2
72+
}
73+
}
74+
]}
75+
/>;
76+
}
77+
78+
{
79+
<RadioRichButtons
80+
legend="Label"
81+
name="name"
82+
options={[
83+
{
84+
"label": "Label 1",
85+
"hintText": "Hint text",
86+
"nativeInputProps": {
87+
"value": 1
88+
},
89+
"illustration": <img src="https://placehold.it/100x100" alt="illustration" />
90+
},
91+
// @ts-expect-error
92+
{
93+
"label": "Label 2",
94+
"hintText": "Hint text",
95+
"nativeInputProps": {
96+
"value": 2
97+
}
98+
}
99+
]}
100+
/>;
101+
}

0 commit comments

Comments
 (0)