ComponentsIconsGuidesExamplesGetting started
ComponentsIconsGuidesExamplesGetting started
GitHub repository

Steps

A vertical trace of a task as it runs: statuses, durations, and stages that open while they work and close when they are done.

c2-steps

A vertical list of steps: the trace of a task as it runs, or a wizard's progress. Each row is a marker, a label, an optional dimmed detail beside it and trailing text at the end — a duration, a count, a timestamp.

A step with sub-steps is a group, and a group is a disclosure: its own row is the summary and its sub-steps are the detail. Every step is a row, and every row is visible — a group starts expanded and nothing ever folds one away on its own. The chevron is there for the reader, collapsed in the markup starts a stage folded, and the run only ever brings a folded stage back into view when it starts running or something in it fails.

Author it either way, and mix them freely:

  • Declarative — slot c2-step children and nest them for sub-steps.
  • Data-driven — hand it a steps array of { id, label, detail, trailing, status, children } and it renders the tree itself. The array wins when both are present. During a run, updateStep(id, patch) changes one step without rebuilding the array.

Everything the markup fills with a slot, the data-driven mode fills with a renderer: renderMarker for the marker slot, renderToggle for toggle, renderLabel / renderDetail / renderTrailing for the text, and renderItem for that text all at once. Each is handed the node, its depth, its position, its dotted path and the status actually in effect.

A parent step that does not author a status takes one from its children: the most urgent thing inside wins, so a stage reports that it is running, or that something under it failed, without you setting it.

current is the shortcut a wizard wants: set it to the index of the active step and every top-level step that has neither an explicit status nor sub-steps becomes success before it, current at it and pending after.

A step that arrives while the list is already on screen grows into place rather than appearing, and a marker gives one beat as its status settles — which is what a trace being written in front of you should look like. --c2-step--enter-duration: 0s turns the first off, and prefers-reduced-motion turns both off.

The connector rail between markers is drawn by CSS and off by default, because a trace does not want one — give --c2-step__rail--width a width and a stepper gets its rail.

Numbering follows the tree: marker="number" draws a dotted path, so the first child of the third step reads 3.1 rather than a second 1.

Attributes

NameTypeDefaultDescription
markerStepsMarkericonHow each marker is drawn: a status glyph, the step's number, or nothing.
currentnumber-1Index of the active step, for a wizard. -1 (the default) leaves every status alone; otherwise a top-level step with neither an explicit status nor sub-steps becomes success before this index, current at it and pending after it.
stepsStepNode[] | undefinedundefinedThe steps as data, instead of c2-step children. Takes precedence over the slot.
aria-labelstring | nullnullAccessible name for the list.

Slots

NameDescription
(default)The c2-step children. Ignored when steps is set.

Events

NameTypeDescription
step-toggleCustomEvent<StepToggleEventDetail>Fired by a c2-step when a group opens or closes, and bubbling to here. event.target is the step; detail.path says where it sits.

CSS custom properties

Grouped by semantic target and state from --c2-component__target__state--property. Click a group to collapse it; click a name to copy it.

NameTypeDefaultDescription
c2-steps
--c2-steps--gappixel0pxSpace between rows. A stepper usually wants some; a trace does not.
--c2-steps--backgroundcolor—
--c2-steps--borderborder—
--c2-steps--border-radiusborder-radius—
--c2-steps--padding-blockpadding0px
--c2-steps--padding-inlinepadding0px
--c2-steps--overflow-yoverflowvisibleauto with a max-height keeps a long run in its own scroller.
--c2-steps--max-heightmax-heightnone

c2-step

One row of a Steps list: a marker, a label with optional dimmed detail, and trailing text at the end of the row — a duration, a count, a timestamp.

A step with sub-steps is a group. Nest c2-step children and the row becomes the summary of a disclosure and the children its detail, so a long run collapses to the shape of the task rather than to a wall of lines. There is no second element to learn: the same tag is a leaf or a group depending on what is inside it.

Every step is a row, and every row is visible. A group starts expanded and nothing ever folds one away on its own: the chevron is there for the reader, and collapsed in the markup starts a stage folded. The run only ever brings a stage back into view — a folded one reopens when it starts running (running, current) or when something in it goes wrong (error, warning).

A step is one row. Label, detail and trailing text sit on a single line and truncate with an ellipsis rather than wrapping, so a hundred-step trace stays scannable, and a sub-step is indented far enough that its marker lands under its parent's label. --c2-step__text--flex-direction: column still stacks the detail under the label, which a wizard's descriptions want — that is two lines on purpose, and each of them is still one line.

The step never sets its own depth, position or marker mode: the parent c2-steps writes them on every pass, so a step used on its own renders as a single root-level row.

Attributes

NameTypeDefaultDescription
statusStepStatuspendingState of the step. Drives the marker glyph and the accent colour, and reopens a folded group.
labelstring—Primary text, when the label slot is empty.
detailstring—Dimmed secondary text beside the label, when the detail slot is empty.
trailingstring—Text at the end of the row, when the trailing slot is empty.
collapsedbooleanfalseWhether this group is folded away. A group is expanded by default — every step in the list is a row you can see — and only the reader, the markup or a reopening status ever changes that.

Slots

NameDescription
(default)Sub-steps. A step that has them is a group.
labelPrimary text. Falls back to the label attribute.
detailSecondary text beside the label. Falls back to the detail attribute.
trailingContent at the end of the row. Falls back to the trailing attribute.
markerReplaces the whole marker: a custom icon, an avatar, a number of your own.
toggleA disclosure affordance of your own — a chevron, a caret. Empty by default: a trace is a list of rows, and the row is already clickable. It is filled per step, so give a leaf an empty <span slot="toggle"></span> to keep its rows lined up with the groups above them.

Events

NameTypeDescription
step-toggleCustomEvent<StepToggleEventDetail>A group was folded away or brought back. Bubbles.

CSS parts

Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.

NameDescription
frameThe box around the whole step, which is what grows when a new step arrives.
rowThe row itself: toggle, marker, text and trailing content. A group's row is its <summary>.
toggleDisclosure region containing the assigned toggle slot for a group.
markerRound marker region containing the marker slot or status fallback at the start of the row.
railThe connector between this marker and the next.
labelPrimary-text region containing the label slot or property fallback.
detailSecondary-text region containing the detail slot or property fallback.
trailingEnd-aligned text region containing the trailing slot or property fallback.
childrenThe box holding the sub-steps.

CSS custom properties

Grouped by semantic target and state from --c2-component__target__state--property. Click a group to collapse it; click a name to copy it.

NameTypeDefaultDescription
c2-step
--c2-step--transition-durationtime150msColour transitions, and the beat a marker gives when its status settles.
--c2-step--enter-durationtime260msHow long a step arriving in a running trace takes to grow into place. 0s turns the animation off.
--c2-step--enter-translatetranslate-4pxHow far it slides while it does.
c2-step > row
--c2-step__row--gappixel10pxSpace between the marker, the text and the trailing content.
--c2-step__row--padding-blockpadding7px
--c2-step__row--padding-inlinepadding12px
--c2-step__row--indentpixelcalc(var(--c2-step__marker--size, 16px) + var(--c2-step__row--gap, 10px))Extra inset per level of nesting. The default puts a sub-step's marker under its parent's label, which is what makes the nesting read without drawing anything.
--c2-step__row--border-radiusborder-radius—
--c2-step__row--backgroundcolor—
--c2-step__row--border-bottomborder1px solid #e4e4e7The hairline under each row.
--c2-step__row--outlineborder2px solid rgb(2, 101, 220)Focus ring of a group's row, which is a button.
c2-step > row > hover
--c2-step__row__hover--backgroundcolor—Set it to make the rows respond to the pointer.
c2-step > toggle
--c2-step__toggle--sizepixel14pxWidth of the toggle slot's column, when it is filled.
--c2-step__toggle--gappixel4pxSpace between that column and the marker.
--c2-step__toggle--colorcolor#a1a1aa
c2-step > guide
--c2-step__guide--colorcolor#e4e4e7A vertical rule at each ancestor's depth, for a file-tree look. Off by default.
--c2-step__guide--widthpixel0pxWidth of that rule. 1px turns the guides on.
c2-step > marker
--c2-step__marker--sizepixel16px
--c2-step__marker--font-sizefont-size10pxSize of the dotted path in marker="number".
--c2-step__marker--padding-inlinepadding3pxBreathing room either side of a dotted path, which is what turns the circle into a pill when the number is long. Only marker="number" uses it.
--c2-step__marker--font-weightfont-weight600
--c2-step__marker--border-radiusborder-radius999px
--c2-step__marker--borderborder1px solid #bcbcc6The ring, drawn for the states that have no glyph of their own (pending, current, running) and for every marker="number" step. A finished step is its glyph, so it has no ring.
--c2-step__marker--backgroundcolortransparent
--c2-step__marker--colorcolor#71717a
c2-step > rail
--c2-step__rail--widthpixel0pxWidth of the connector. 0px is the trace look; 2px gives a stepper its rail.
--c2-step__rail--colorcolor#e4e4e7
--c2-step__rail--gappixel4pxSpace between the marker and the rail.
c2-step > label
--c2-step__label--colorcolor#18181b
--c2-step__label--font-sizefont-size13px
--c2-step__label--font-weightfont-weight500
--c2-step__label--font-familyfont-familyui-monospace, SFMono-Regular, Menlo, Consolas, monospace
c2-step > detail
--c2-step__detail--colorcolor#71717a
--c2-step__detail--font-sizefont-size—Falls back to the label size.
--c2-step__detail--font-weightfont-weight400
--c2-step__detail--gappixel8pxSpace between the label and the detail when they share a line.
--c2-step__detail--row-gappixel2pxSpace between them when they are stacked.
c2-step > text
--c2-step__text--flex-directionflex-direction-rowrowcolumn puts the detail on its own line under the label, which a wizard's descriptions want. It is the only variable that switch needs: the gap and the alignment follow it.
--c2-step__text--align-itemsalign-itemsbaselineHow the label and the detail line up across the row. Stacked, they are flush left whatever this says.
c2-step > trailing
--c2-step__trailing--colorcolor#71717a
--c2-step__trailing--font-sizefont-size—Falls back to the label size.
--c2-step__trailing--font-weightfont-weight400
c2-step > success
--c2-step__success--colorcolor#16a34aMarker colour when the step succeeded.
c2-step > error
--c2-step__error--colorcolor#dc2626
c2-step > warning
--c2-step__warning--colorcolor#d97706
c2-step > running
--c2-step__running--colorcolorrgb(2, 101, 220)
c2-step > current
--c2-step__current--colorcolorrgb(2, 101, 220)
c2-step > skipped
--c2-step__skipped--colorcolor#71717aMarker and label colour when the step was skipped.
escAccordionConnected, animated panels with shared borders and single or multiple expansion.LayoutArea chartA line chart with the region under each line filled — every line-chart attribute, plus a fill opacity.ChartAttachmentFile and image attachments with metadata, upload progress, failure states, and actions.Data displayAutocompleteSearchable combobox for local or remote items with customizable list rows.InputsAvatarImage, initials or icon for a person, with status dot and badge.Data displayBadgeTinted pill for status text, counts and dots, optionally pinned to a corner of another element.Data displayBar chartBars over categories or time buckets, with several series drawn side by side within each band.ChartBorder BeamA decorative beam that travels around the border of any positioned container.LayoutBreadcrumbNavigation trail of link buttons with separators, a current page and optional collapsing.NavigationButtonThemeable button with slots for text, prefix, suffix and running icons.ButtonsButton GroupJoined actions and polished segmented controls with single or multiple selection.ButtonsCandlestick chartAn ECharts OHLC chart for market sessions and other open-close ranges, with semantic positive and negative colours.ChartCardGroups related content and actions on a single bordered surface.LayoutCascaderSelect a value from related, multi-level data in one floating panel.InputsChat InputAuto-growing message composer with keyboard submission, toolbar actions and native form support.ChatChat MessageFlexible message row for conversations, assistant answers and activity updates.ChatCheckboxNative checkbox behaviour in a quiet, themeable box with an opt-in hover layer.InputsCode EditorEditable, syntax-highlighted source field on CodeMirror 6, themed entirely through CSS variables.InputsCode ViewerSyntax-highlighted code with line numbers, copy button and dark mode, powered by shiki.Data displayColor AreaTwo-dimensional area for picking saturation and value of a colour.InputsColor SelectColour swatch that opens a full picker built from area and slider.InputsColor SliderHorizontal slider for choosing a hue from 0 to 360.InputsCopy ButtonButton that copies text to the clipboard — the element it sits in, another element by id, or a literal string.ButtonsDashboardGrid of resizable panes, dragged by the edges they share.LayoutDate InputForm-associated single-date input with native picker, constraints, helper text and error states.InputsDate SelectorAccessible one- or two-month calendar for choosing a date range.InputsDetailsCollapsible disclosure built on native details and summary.LayoutGauge chartA focused radial KPI gauge drawn by ECharts, with a configurable scale, progress arc and pointer.ChartHeaderArranges brand, navigation, actions and a mobile trigger in a reusable site shell.LayoutIcon ButtonRound, hoverable button wrapping a slotted SVG icon.ButtonsKbdKeyboard key label for shortcuts and command hints, with the semantics of the native kbd element.Data displayLabelCaption that names and activates the control referenced by its for attribute, with a required marker.InputsLine chartA line chart over a time or numeric x axis, drawn on canvas by uPlot, with series declared as children.ChartLink ButtonText-styled control for link and navigation actions, rendered as a real anchor or a button.NavigationListVertical list container with single or multiple selection.Data displayList ItemSelectable row with icon slots, used on its own or as the option of list and select.Data displayMenuCommands, links, checkboxes and submenus in a popover anchored to a trigger.NavigationModalDialog built on the native dialog element: focus trap, backdrop, Escape, title, body and footer.FeedbackNavigation MenuSite navigation bar whose triggers open panels of links below the header.NavigationNumber InputForm-associated numeric input with native validation, step controls, adornments and helper states.InputsOverlayAnchored popup built on the browser Popover API, positioned with floating-ui.FeedbackPaginationPage navigation in three layouts: numbered pages, a simple page status, or a table-footer row with rows-per-page.NavigationPie chartA pie or donut chart drawn by ECharts, where one row is one slice and label-field names it.ChartProgressLinear progress bar, indeterminate or filling to a value, with an optional label and count.FeedbackQR CodeGenerate accessible, themeable QR codes locally as crisp SVG graphics.Data displayQuestionnaireA multi-step single- and multiple-choice flow with validation, shortcuts and form submission.InputsRadar chartCompare several profiles across the same set of normalized indicators.ChartRadioRadio options built on native inputs, grouped into one value with keyboard navigation.InputsRateAccessible star rating input with hover preview, keyboard control and optional half values.InputsReorder ListReorder a vertical queue with pointer or keyboard input while the application owns persistence.Data displayScatter chartAn ECharts scatter plot for finding relationships, clusters and outliers across two numeric measures.ChartSelectDropdown that pairs a themeable trigger with an anchored list of c2-list-item options.InputsSeperatorHorizontal or vertical rule with an optional label, for dividing content and toolbars.LayoutSheetDialog pinned to an edge of the screen, for content that complements the page rather than interrupting it.FeedbackSide NavResponsive navigation drawer beside the page: pushes the content on large screens, slides over it with a backdrop on small ones.NavigationSkeletonPlaceholder block standing in for content that has not arrived, in three shapes and three animations.FeedbackSliderRange input with a themeable track, thumb, step ticks and value bubble.InputsSparklineA chromeless trend line sized for a table cell, a list row or the trend slot of a c2-stat.ChartSpinnerCircular progress indicator, indeterminate or showing a value, with optional text.FeedbackStatDisplays a KPI with an optional icon, trend and supporting description.Data displayStatus PanelCommunicate empty states, operation outcomes and recoverable errors with clear next steps.FeedbackStepsA vertical trace of a task as it runs: statuses, durations, and stages that open while they work and close when they are done.Data displaySwitchOn/off toggle on a native switch input, with label, description and thumb icons.InputsTableVirtualized data grid with declarative columns, sorting, selection, pinning and resizing.Data displayTabsTab strip that shows one content panel at a time.NavigationText FieldSingle-line input with icon slots, clear button, helper and error text, and a character counter.InputsTextareaMultiline text input with resizing, helper and error text, and a character counter.InputsTheme SelectColour-theme switcher: click to step to the next mode, hover for the full menu.InputsToastNotification cards and a manager for stacked, queued notifications with independent lifetimes.FeedbackTooltipContextual hint shown when its target is hovered or focused, rendered in the top layer.FeedbackTreeHierarchical tree view with expansion, selection, checkboxes and lazy loading.Data displayUploadDrag-and-drop file selection with validation, upload progress, retry, cancellation, and attachment results.InputsVirtual ListWindowed list with built-in search, sorting, selection and an async data source.Data displayFeather Icons287 open-source Feather icons, one web component each.IconsMat Icon2,234 Material Icons ligatures rendered through a single element.IconsPhosphor Icons1,512 flexible icons in six weights, one web component each.IconsThemingTheme every c2n component from a handful of design tokens with @c2n/theme, or reach for any component variable directly.GuideFrameworksUse the components from React, Vue, Angular, Svelte, Lit or plain HTML — typed events, generated template types, and the one piece of configuration each framework needs.GuideUsing c2n in an applicationThe workflow behind every c2n app: load the theme once, use c2-* tags directly, and turn every repeated pattern into a small variant or composed component.GuideAI toolsGive Claude Code, Codex or Google Antigravity the c2n skill, live component APIs, examples and application conventions.Guide