/
githubmirror
/
material-ui
Обзор
Документация
Войти
/
githubmirror
/
material-ui
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
docs/data/material/components/steppers/HorizontalLinearStepper.js
141 строка
4 KB
Silviu Alexandru Avram
[docs][stepper] Fix focus management in examples (#48494)
11 май 2026, 20:28
Не верифицирован
11 май 2026, 20:28
0c0f7a2
Код
Авторство
О чём код?
import * as React from 'react'; import Box from '@mui/material/Box'; import Stepper from '@mui/material/Stepper'; import Step from '@mui/material/Step'; import StepLabel from '@mui/material/StepLabel'; import Button from '@mui/material/Button'; import Typography from '@mui/material/Typography'; const steps = ['Select campaign settings', 'Create an ad group', 'Create an ad']; export default function HorizontalLinearStepper() { const [activeStep, setActiveStep] = React.useState(0); const [skipped, setSkipped] = React.useState(new Set()); const isStepOptional = React.useCallback((step) => { return step === 1; }, []); const isStepSkipped = (step) => { return skipped.has(step); }; const handleNext = () => { let newSkipped = skipped; if (isStepSkipped(activeStep)) { newSkipped = new Set(newSkipped.values()); newSkipped.delete(activeStep); } setActiveStep((prevActiveStep) => prevActiveStep + 1); setSkipped(newSkipped); }; const handleBack = () => { setActiveStep((prevActiveStep) => prevActiveStep - 1); }; const handleSkip = () => { if (!isStepOptional(activeStep)) { // You probably want to guard against something like this, // it should never occur unless someone's actively trying to break something. throw new Error("You can't skip a step that isn't optional."); } setActiveStep((prevActiveStep) => prevActiveStep + 1); setSkipped((prevSkipped) => { const newSkipped = new Set(prevSkipped.values()); newSkipped.add(activeStep); return newSkipped; }); }; const handleReset = () => { setActiveStep(0); }; const previousActiveStepRef = React.useRef(activeStep); const resetButtonRef = React.useRef(null); const nextButtonRef = React.useRef(null); // Manage focus when the active step changes. React.useEffect(() => { const previousActiveStep = previousActiveStepRef.current; previousActiveStepRef.current = activeStep; if (activeStep === steps.length) { // If the user has completed all steps and hits "Finish", focus the "Reset" button. resetButtonRef.current.focus(); return; } if (activeStep === 0 && previousActiveStep === steps.length) { // If the user has completed all steps and hits "Reset", focus the "Next" button. nextButtonRef.current.focus(); return; } if (isStepOptional(previousActiveStep) && !isStepOptional(activeStep)) { // If the user hits "Skip" and the next step is not optional, focus the "Next" button. nextButtonRef.current.focus(); } }, [activeStep, isStepOptional]); return ( <Box sx={{ width: '100%' }}> <Stepper activeStep={activeStep}> {steps.map((label, index) => { const stepProps = {}; const labelProps = {}; if (isStepOptional(index)) { labelProps.optional = ( <Typography variant="caption">Optional</Typography> ); } if (isStepSkipped(index)) { stepProps.completed = false; } return ( <Step key={label} {...stepProps}> <StepLabel {...labelProps}>{label}</StepLabel> </Step> ); })} </Stepper> {activeStep === steps.length ? ( <React.Fragment> <Typography sx={{ mt: 2, mb: 1 }}> All steps completed - you're finished </Typography> <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}> <Box sx={{ flex: '1 1 auto' }} /> <Button onClick={handleReset} ref={resetButtonRef}> Reset </Button> </Box> </React.Fragment> ) : ( <React.Fragment> <Typography sx={{ mt: 2, mb: 1 }}>Step {activeStep + 1}</Typography> <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}> <Button color="inherit" disabled={activeStep === 0} onClick={handleBack} sx={{ mr: 1 }} > Back </Button> <Box sx={{ flex: '1 1 auto' }} /> {isStepOptional(activeStep) && ( <Button color="inherit" onClick={handleSkip} sx={{ mr: 1 }}> Skip </Button> )} <Button onClick={handleNext} ref={nextButtonRef}> {activeStep === steps.length - 1 ? 'Finish' : 'Next'} </Button> </Box> </React.Fragment> )} </Box> ); }