Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
There was a problem hiding this comment.
I have to say it was pretty wild to see Claude ingest the Figma spec using the Figma MCP and derive these values directly from it. Made the job much, much easier.
openspec/changes/archive/2026-02-03-add-steps-component/specs/nimbus-steps/spec.md
Show resolved
Hide resolved
| ### With descriptions | ||
|
|
||
| Add optional descriptions below labels to provide additional context for each step: | ||
|
|
There was a problem hiding this comment.
I'm of a mind to push this onto consumers (for now), we could program the component to aggressively wrap text to preserve x-overflow, but I don't know that it's necessary to ship it as-is
There was a problem hiding this comment.
see also the 'container queries' example here: https://piccalil.li/blog/a-workaround-for-using-custom-properties-in-media-queries/#downsides
It should be possible to grab the width of the steps parent wrapper, width of the wrapper for the steps, and compare them, and if the parent wrapper is smaller then update the styling for each step
There was a problem hiding this comment.
I think we could indeed leverage container queries, but through the existing conditionals-system.
We could use the large sizes tokens to create default container-queries.
Add to system:
import { defineConfig, createSystem, defaultConfig } from "@chakra-ui/react"
const config = defineConfig({
conditions: {
// Custom container query condition
cq3xl: "@container (min-width: 768px)",
cqSm: "@container (min-width: 384px)",
// ...
},
})
export const system = createSystem(defaultConfig, config);Usage:
<Stepper orientation={{
cqSm: 'vertical',
cq3xl: 'horizontal',
}} />There was a problem hiding this comment.
We have an example story for this now that dynamically switches. Consumers specify it at the moment. If we feel we want to internalize this, we can, but I ran out of time today.
misama-ct
left a comment
There was a problem hiding this comment.
Couple of things. Happy, we're still needed.
| key: "nimbusSteps", | ||
| }); | ||
|
|
||
| export const StepsRootSlot: SlotComponent<HTMLDivElement, StepsRootSlotProps> = |
There was a problem hiding this comment.
Not that it's a harm, but is SlotComponent as type still needed now that we generate the recipe types on the client side?
There was a problem hiding this comment.
Hmm, I'm not sure actually, might need more exploration since we have 20+ components that use this pattern.
Maybe we can scope it to another unit of work
openspec/changes/archive/2026-02-03-add-steps-component/tasks.md
Outdated
Show resolved
Hide resolved
ByronDWall
left a comment
There was a problem hiding this comment.
This is a good start, but I have significant questions. The biggest one is around controls - I think we need persistent next/previous buttons.
I also really think we should only display the active content, similar to how tabs work, rather than show all steps on the page.
Also, I have some styling concerns.
| }, | ||
| "&[data-state='complete']": { | ||
| borderColor: "primary.9", | ||
| color: "colorPalette.contrast", |
There was a problem hiding this comment.
I believe contrast is meant to be a background color that will provide an acceptable contrast ratio for any of the colors in a palette that are meant to be used for text (.10+?). Also, we don't set a colorPalette for this recipe, are we sure that this will be primary.contrast or will it be the default color palette set on ::root (neutral, I think)?
Also, it results in not being able to see the indicator title in dark mode:
| borderColor: "neutral.7", | ||
| color: "neutral.12", |
There was a problem hiding this comment.
One thing chakra does in its steps component that's interesting is it allows the user to configure color palettes for the indicators. I feel like this is in keeping with nimbus' stance on configurability, but also we don't need to implement it
| /** | ||
| * # Steps.Root | ||
| * | ||
| * Container component that manages step state and provides context to child components. | ||
| */ | ||
| Root: StepsRoot, | ||
|
|
||
| /** | ||
| * # Steps.List | ||
| * | ||
| * Flex container that wraps all step items and separators. | ||
| */ | ||
| List: StepsList, | ||
|
|
||
| /** | ||
| * # Steps.Item | ||
| * | ||
| * Container for a single step. Automatically derives state from its index. | ||
| */ | ||
| Item: StepsItem, | ||
|
|
||
| /** | ||
| * # Steps.Indicator | ||
| * | ||
| * Visual indicator showing step number or icon. | ||
| */ | ||
| Indicator: StepsIndicator, | ||
|
|
||
| /** | ||
| * # Steps.Separator | ||
| * | ||
| * Visual line connecting step indicators. | ||
| */ | ||
| Separator: StepsSeparator, | ||
|
|
||
| /** | ||
| * # Steps.Content | ||
| * | ||
| * Container for step label and optional description. | ||
| */ | ||
| Content: StepsContent, | ||
|
|
||
| /** | ||
| * # Steps.Label | ||
| * | ||
| * Displays the step title. | ||
| */ | ||
| Label: StepsLabel, | ||
|
|
||
| /** | ||
| * # Steps.Description | ||
| * | ||
| * Displays optional hint text below the label. | ||
| */ | ||
| Description: StepsDescription, |
There was a problem hiding this comment.
These are the descriptions users actually see in the ts autocomplete - I think they could be expanded a bit?
| const [styleProps, functionalProps] = extractStyleProps(restProps); | ||
|
|
||
| return ( | ||
| <StepsContentSlot |
There was a problem hiding this comment.
It's super weird to me that the content for all the steps is always on the page - shouldn't each step act more like a tab where only the active panel is visible?
| <Button | ||
| variant="outline" | ||
| size="sm" | ||
| onClick={() => setCurrentStep(Math.max(0, currentStep - 1))} | ||
| isDisabled={currentStep === 0} | ||
| > | ||
| Previous | ||
| </Button> | ||
| <Button | ||
| variant="solid" | ||
| size="sm" | ||
| onClick={() => setCurrentStep(Math.min(4, currentStep + 1))} | ||
| isDisabled={currentStep === 4} | ||
| > | ||
| Next | ||
| </Button> |
There was a problem hiding this comment.
These buttons are acting funny(same for the 'step states' example in dev docs). Claude really is hot for size="sm" to implemented I guess.
There was a problem hiding this comment.
Fwiw, there was a PR in flight to enable small size buttons, I just hadn't rebased yet

Summary
Adds the Steps component - a display-only progress indicator for multi-step
processes like forms, wizards, and onboarding flows.
Figma link here
Features
Steps.Root,Steps.List,Steps.Item,Steps.Indicator,Steps.Separator,Steps.Content,Steps.Label,Steps.Descriptionxs,sm,mdhorizontal,verticalcomplete,current,incompletestates from step indexlist,listitem),aria-current="step", screenreader labels
Usage