Skip to content

Commit a14d2c0

Browse files
committed
chore: improve, add exemple and story
1 parent c815d2e commit a14d2c0

File tree

5 files changed

+448
-131
lines changed

5 files changed

+448
-131
lines changed

src/Follow.tsx

Lines changed: 172 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export type FollowProps = {
2525
| "newsletter-title"
2626
| "newsletter-desc"
2727
| "newsletter-form-wrapper"
28+
| "newsletter-form-hint"
2829
| "social-col"
2930
| "social"
3031
| "social-title"
@@ -33,36 +34,29 @@ export type FollowProps = {
3334
CxArg
3435
>
3536
>;
36-
social?: FollowProps.Social;
3737
style?: CSSProperties;
3838
newsletter?: FollowProps.Newsletter;
39-
};
39+
social?: FollowProps.Social;
40+
} & (FollowProps.EitherNewsletter | FollowProps.EitherSocial | FollowProps.EitherBoth);
4041

4142
//https://main--ds-gouv.netlify.app/example/component/follow/
4243
export namespace FollowProps {
43-
/**
44-
* From DSFR `$follow-icons` + `copy` and `mail`
45-
*/
46-
export type SocialType =
47-
| "copy"
48-
| "dailymotion"
49-
| "facebook"
50-
| "github"
51-
| "instagram"
52-
| "linkedin"
53-
| "mail"
54-
| "mastodon"
55-
| "snapchat"
56-
| "telegram"
57-
| "threads"
58-
| "tiktok"
59-
| "twitch"
60-
| "twitter"
61-
| "twitter-x"
62-
| "vimeo"
63-
| "youtube";
44+
export type EitherNewsletter = {
45+
newsletter: Newsletter;
46+
social?: Social;
47+
};
48+
49+
export type EitherSocial = {
50+
newsletter?: Newsletter;
51+
social: Social;
52+
};
53+
54+
export type EitherBoth = {
55+
newsletter: Newsletter;
56+
social: Social;
57+
};
6458

65-
type TitleAs = {
59+
export type TitleAs = {
6660
title?: ReactNode;
6761
/**
6862
* Display only. The tag will stay `h2`.
@@ -72,15 +66,6 @@ export namespace FollowProps {
7266
titleAs?: `h${2 | 3 | 4 | 5 | 6}`;
7367
};
7468

75-
export type SocialButton = {
76-
type: SocialType;
77-
linkProps: RegisteredLinkProps;
78-
};
79-
80-
export type Social = TitleAs & {
81-
buttons: [SocialButton, ...SocialButton[]];
82-
};
83-
8469
export type NewsletterForm = {
8570
/** Bound props to display success alert */
8671
success: boolean;
@@ -99,18 +84,62 @@ export namespace FollowProps {
9984
*/
10085
formComponent: <TProps extends PropsWithChildren>({ children }: TProps) => React.ReactNode;
10186
consentHint?: ReactNode;
102-
inputProps: Omit<InputProps.RegularInput, "addon">;
87+
inputProps?: Partial<Omit<InputProps.RegularInput, "addon">>;
10388
};
10489

105-
export type Newsletter = TitleAs & {
106-
desc?: ReactNode;
90+
export type NewsletterWithForm = {
10791
/** "Subscribe" button */
10892
buttonProps: ButtonProps.Common &
10993
ButtonProps.AsButton &
11094
// optional children
11195
Partial<ButtonProps.WithoutIcon>;
11296
/** When using a form */
113-
form?: NewsletterForm;
97+
form: NewsletterForm;
98+
};
99+
100+
export type NewsletterWithoutForm = {
101+
/** "Subscribe" button */
102+
buttonProps: ButtonProps.Common &
103+
(ButtonProps.AsButton | ButtonProps.AsAnchor) &
104+
// optional children
105+
Partial<ButtonProps.WithoutIcon>;
106+
/** When using a form */
107+
form?: never;
108+
};
109+
110+
export type Newsletter = TitleAs & {
111+
desc?: ReactNode;
112+
} & (NewsletterWithForm | NewsletterWithoutForm);
113+
114+
/**
115+
* From DSFR `$follow-icons` + `copy` and `mail`
116+
*/
117+
export type SocialType =
118+
| "copy"
119+
| "dailymotion"
120+
| "facebook"
121+
| "github"
122+
| "instagram"
123+
| "linkedin"
124+
| "mail"
125+
| "mastodon"
126+
| "snapchat"
127+
| "telegram"
128+
| "threads"
129+
| "tiktok"
130+
| "twitch"
131+
| "twitter"
132+
| "twitter-x"
133+
| "vimeo"
134+
| "youtube";
135+
136+
export type SocialButton = {
137+
type: SocialType;
138+
linkProps: RegisteredLinkProps;
139+
};
140+
141+
export type Social = TitleAs & {
142+
buttons: [SocialButton, ...SocialButton[]];
114143
};
115144
}
116145

@@ -149,100 +178,113 @@ const FollowNewsletter = (
149178
</p>
150179
)}
151180
</div>
152-
</div>
153-
{form !== undefined
154-
? (() => {
155-
const {
156-
success,
157-
consentHint,
158-
formComponent,
159-
inputProps,
160-
successMessage = t("your registration has been processed"),
161-
...restForm
162-
} = form;
163-
assert<Equals<keyof typeof restForm, never>>();
164-
165-
if (success)
166-
return (
167-
<Alert
168-
severity="success"
169-
description={successMessage}
170-
title={
171-
// force default size without title
172-
undefined as unknown as string
173-
}
174-
/>
175-
);
176-
177-
// prepare inputProps with default values
178-
const {
179-
label: inputLabel = t("your email address"),
180-
hintText: inputHintText = consentHint ?? t("consent hint"),
181-
nativeInputProps: {
182-
title: inputTitle = t("your email address"),
183-
placeholder: inputPlaceholder = t("your email address"),
184-
autoComplete: inputAutoComplete = "email",
185-
type: inputType = "email",
186-
...nativeInputProps
187-
} = {},
188-
...restInputProps
189-
} = inputProps;
190-
191-
// prepare buttonProps with default values
192-
const {
193-
children: buttonContent = t("subscribe"),
194-
title: buttonTitle = t("subscribe to our newsletter (2)"),
195-
type: buttonType = "button",
196-
...restButtonProps
197-
} = buttonProps;
198-
199-
// use wrapper to add form
200-
return formComponent({
201-
children: (
202-
<Input
203-
label={inputLabel}
204-
hintText={inputHintText}
205-
nativeInputProps={{
206-
title: inputTitle,
207-
placeholder: inputPlaceholder,
208-
autoComplete: inputAutoComplete,
209-
type: inputType,
181+
<div>
182+
{form !== undefined
183+
? (() => {
184+
const {
185+
success,
186+
consentHint = t("consent hint"),
187+
formComponent,
188+
inputProps = {},
189+
successMessage = t("your registration has been processed"),
190+
...restForm
191+
} = form;
192+
assert<Equals<keyof typeof restForm, never>>();
193+
194+
if (success)
195+
return (
196+
<Alert
197+
severity="success"
198+
description={successMessage}
199+
title={
200+
// force default size without title
201+
undefined as unknown as string
202+
}
203+
/>
204+
);
205+
206+
// prepare inputProps with default values
207+
const {
208+
label: inputLabel = t("your email address"),
209+
hintText: inputHintText = consentHint,
210+
nativeInputProps: {
211+
title: inputTitle = t("your email address"),
212+
placeholder: inputPlaceholder = t("your email address"),
213+
autoComplete: inputAutoComplete = "email",
214+
type: inputType = "email",
210215
...nativeInputProps
211-
}}
212-
{...restInputProps}
213-
addon={
214-
<Button
215-
{...restButtonProps}
216-
title={buttonTitle}
217-
type={buttonType}
218-
>
219-
{buttonContent}
220-
</Button>
221-
}
222-
/>
223-
)
224-
});
225-
})()
226-
: (() => {
227-
const {
228-
children: buttonContent = t("subscribe"),
229-
title: buttonTitle = t("subscribe to our newsletter (2)"),
230-
...restButtonProps
231-
} = buttonProps;
232-
233-
return (
234-
<ButtonsGroup
235-
inlineLayoutWhen="md and up"
236-
buttons={[
237-
{
238-
children: buttonContent,
239-
title: buttonTitle,
240-
...restButtonProps
241-
}
242-
]}
243-
/>
244-
);
245-
})()}
216+
} = {},
217+
...restInputProps
218+
} = inputProps;
219+
220+
// prepare buttonProps with default values
221+
const {
222+
children: buttonContent = t("subscribe"),
223+
title: buttonTitle = t("subscribe to our newsletter (2)"),
224+
type: buttonType = "button",
225+
...restButtonProps
226+
} = buttonProps;
227+
228+
// use wrapper to add form
229+
return formComponent({
230+
children: (
231+
<>
232+
<Input
233+
label={inputLabel}
234+
nativeInputProps={{
235+
title: inputTitle,
236+
placeholder: inputPlaceholder,
237+
autoComplete: inputAutoComplete,
238+
type: inputType,
239+
...nativeInputProps
240+
}}
241+
{...restInputProps}
242+
addon={
243+
<Button
244+
{...restButtonProps}
245+
title={buttonTitle}
246+
type={buttonType}
247+
>
248+
{buttonContent}
249+
</Button>
250+
}
251+
/>
252+
{inputHintText !== undefined && (
253+
<p
254+
className={cx(
255+
fr.cx("fr-hint-text"),
256+
classes["newsletter-form-hint"]
257+
)}
258+
>
259+
{inputHintText}
260+
</p>
261+
)}
262+
</>
263+
)
264+
});
265+
})()
266+
: (() => {
267+
const {
268+
children: buttonContent = t("subscribe"),
269+
title: buttonTitle = t("subscribe to our newsletter (2)"),
270+
...restButtonProps
271+
} = buttonProps;
272+
273+
return (
274+
<ButtonsGroup
275+
inlineLayoutWhen="md and up"
276+
buttons={[
277+
{
278+
children: buttonContent,
279+
title: buttonTitle,
280+
...restButtonProps
281+
}
282+
]}
283+
/>
284+
);
285+
})()}
286+
</div>
287+
</div>
246288
</div>
247289
);
248290
};

stories/ButtonsGroup.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const { meta, getStory } = getStoryFactory({
8888
"control": { "type": "select" }
8989
},
9090
"buttons": {
91-
"description": `An array of ButtonProps (at least 2, RGAA)`,
91+
"description": `An array of ButtonProps (at least 1)`,
9292
"control": { "type": null }
9393
}
9494
},

0 commit comments

Comments
 (0)