Skip to content

Commit 823050c

Browse files
committed
Stepper: i18n + classes support
1 parent 9c52f1a commit 823050c

File tree

1 file changed

+41
-15
lines changed

1 file changed

+41
-15
lines changed

src/Stepper.tsx

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, { memo, forwardRef } from "react";
2+
import type { ReactNode } from "react";
23
import { symToStr } from "tsafe/symToStr";
34
import { assert } from "tsafe/assert";
45
import type { Equals } from "tsafe";
56
import { fr } from "./lib";
67
import { cx } from "./lib/tools/cx";
8+
import { createComponentI18nApi } from "./lib/i18n";
79

810
// We make users import dsfr.css, so we don't need to import the scoped CSS
911
// but in the future if we have a complete component coverage it
@@ -13,35 +15,38 @@ import "./dsfr/component/stepper/stepper.css";
1315

1416
export type StepperProps = {
1517
className?: string;
16-
currentStep: number;
17-
steps: number;
18-
title: string;
19-
nextTitle?: string;
18+
step: number;
19+
stepCount: number;
20+
title: ReactNode;
21+
nextTitle?: ReactNode;
22+
classes?: Partial<Record<"root" | "title" | "state" | "steps" | "details", string>>;
2023
};
2124

2225
/** @see <https://react-dsfr-components.etalab.studio/?path=/docs/components-stepper> */
2326
export const Stepper = memo(
2427
forwardRef<HTMLDivElement, StepperProps>((props, ref) => {
25-
const { className, currentStep, steps, title, nextTitle, ...rest } = props;
28+
const { className, step, stepCount, title, nextTitle, classes = {}, ...rest } = props;
2629

2730
assert<Equals<keyof typeof rest, never>>();
2831

32+
const { t } = useTranslation();
33+
2934
return (
30-
<div className={cx(fr.cx("fr-stepper"), className)} ref={ref}>
31-
<h2 className="fr-stepper__title">
32-
<span className="fr-stepper__state">
33-
Étape {currentStep} sur {steps}
35+
<div className={cx(fr.cx("fr-stepper"), classes.root, className)} ref={ref}>
36+
<h2 className={cx(fr.cx("fr-stepper__title"), classes.title)}>
37+
<span className={cx(fr.cx("fr-stepper__state"), classes.state)}>
38+
{t("progress", { step, stepCount })}
3439
</span>
3540
{title}
3641
</h2>
3742
<div
38-
className="fr-stepper__steps"
39-
data-fr-current-step={currentStep}
40-
data-fr-steps={steps}
43+
className={cx(fr.cx("fr-stepper__steps"), classes.steps)}
44+
data-fr-current-step={step}
45+
data-fr-steps={stepCount}
4146
></div>
42-
{nextTitle && (
43-
<p className="fr-stepper__details">
44-
<span className="fr-text--bold">Étape suivante :</span> {nextTitle}
47+
{nextTitle !== undefined && (
48+
<p className={cx(fr.cx("fr-stepper__details"), classes.details)}>
49+
<span className={fr.cx("fr-text--bold")}>{t("next step")}</span> {nextTitle}
4550
</p>
4651
)}
4752
</div>
@@ -51,4 +56,25 @@ export const Stepper = memo(
5156

5257
Stepper.displayName = symToStr({ Stepper });
5358

59+
const { useTranslation, addStepperTranslations } = createComponentI18nApi({
60+
"componentName": symToStr({ Stepper }),
61+
"frMessages": {
62+
/* spell-checker: disable */
63+
"progress": (p: { step: number; stepCount: number }) =>
64+
`Étape ${p.step} sur ${p.stepCount}`,
65+
"next step": `Étape suivante :`
66+
/* spell-checker: enable */
67+
}
68+
});
69+
70+
addStepperTranslations({
71+
"lang": "en",
72+
"messages": {
73+
"progress": ({ step, stepCount }) => `Step ${step} over ${stepCount}`,
74+
"next step": "Next step: "
75+
}
76+
});
77+
78+
export { addStepperTranslations };
79+
5480
export default Stepper;

0 commit comments

Comments
 (0)