11import React , { memo , forwardRef } from "react" ;
2+ import type { ReactNode } from "react" ;
23import { symToStr } from "tsafe/symToStr" ;
34import { assert } from "tsafe/assert" ;
45import type { Equals } from "tsafe" ;
56import { fr } from "./lib" ;
67import { 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
1416export 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> */
2326export 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
5257Stepper . 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+
5480export default Stepper ;
0 commit comments