shadcn.io is not affiliated with official shadcn/ui
Locked Gated Stepper Block for React Aria
A driving school lesson plan in four hairline cells where a lesson stays locked, with its reason in words, until the lessons it needs are passed.
Installation
Overview
Show what is waiting on what with this gated stepper for React with React Aria. A plus-marked frame holds a Steps strip of four cells for a driving school's plan (Theory, Hazard test, Mock exam and Practical). Each cell has a glyph, a state word and a line of why: a locked lesson shows a lock and "Pass Theory first", and Practical needs both the Hazard test and the Mock exam, so the rule is a map rather than a sequence. "Mark passed" is the block's one Shine Button; it unlocks whatever it can, the lock swaps to the lesson's number and the status line says which lesson opened. Pressing a locked cell does not move on: it says why. For courses, certifications and any plan where one step needs others.
FAQ
How do I change what unlocks what?
Edit needs on each entry of LESSONS: a list of lesson ids that must be passed first. lockedOf, the reasons, the cells and the status line are all derived from that map and the passed list, so a lesson can need one lesson, two, or none.
Why can I focus a locked lesson?
A locked cell is not disabled. It keeps aria-disabled and points at its reason with aria-describedby, so a keyboard or screen reader user reaches it and hears why it is locked instead of skipping over it. Pressing it keeps the step and says so in the status line.
How is a locked lesson told apart without colour?
By three things together: a lock glyph, the word "Locked" and the reason in the cell. Passed shows a check and "Passed"; open lessons show their number and "Open". Nothing relies on a hue.
What stays local?
Passing a lesson is component state and is lost on reload; nothing is booked or recorded. To make it real, call your API from the Mark passed handler and read the passed list from your data in the initial state.