Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions skills/tedi-react/references/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,86 @@ const [page, setPage] = useState(1);
<Pagination pageCount={10} page={page} onPageChange={setPage} arrowVariant="default" showPrevNextButtons md={{ arrowVariant: 'primary' }} />
```

### VerticalStepper
Compound vertical wizard / progress stepper. Sub-components: `VerticalStepper.Item` (auto-numbered) and `VerticalStepper.SubItem`. A step is a link/button when `href`/`onClick` is set (plain text when `disabled`); a step with sub-steps adds a separate expand toggle next to the title, so the title can still navigate.

**`VerticalStepper`** — `VerticalStepperProps` | fRef (`<ol>`)
- `children: ReactNode` (required) — `Item`s (+ optional `Separator`s)
- `compact?: boolean = false` — smaller indicators; completed/error show the state icon in the indicator instead of the number
- `aria-label?: string` — names the `<nav>` landmark

**`VerticalStepper.Item`** — `VerticalStepperItemProps`
- `title: ReactNode` (required), `description?: ReactNode`
- `state?: 'default' | 'completed' | 'error' | 'disabled' = 'default'`
- `current?: boolean` — active step (blue ring, `aria-current="step"`); independent from `state`
- `href?` / `onClick?` / `as?: 'a' | 'button'` — makes the title a link/button; works for steps with sub-steps too (title navigates, a separate toggle expands). Ignored when `disabled`.
- `info?: ReactNode` — trailing asset under the title (`StatusBadge`, `Link`, `Button`, `Text`)
- `children?: ReactNode` — `SubItem`s; makes the step expandable
- `open?` / `defaultOpen?` / `onToggle?` — controlled / uncontrolled sub-step disclosure

**`VerticalStepper.SubItem`** — `VerticalStepperSubItemProps`
- `title: ReactNode` (required), `state?: 'default' | 'completed' | 'error' | 'disabled' | 'informative'`
- `current?`, `href?` / `onClick?` / `as?`, `info?`

```tsx
<VerticalStepper aria-label="Application progress">
<VerticalStepper.Item title="Personal data" state="completed" href="#step-1" />
<VerticalStepper.Item title="Contacts" current defaultOpen>
<VerticalStepper.SubItem title="Phone" state="completed" onClick={goPhone} />
<VerticalStepper.SubItem title="Email" current onClick={goEmail} />
</VerticalStepper.Item>
<VerticalStepper.Item title="Review" />
</VerticalStepper>
```

### CardStepper
The mobile / compact form of a stepper — a single card showing the active step, a `N / M` counter, a segmented progress bar, optional prev/next arrows, and a list button that opens the full step list in a `Modal` (rendered as a `VerticalStepper`). Pair it with `VerticalStepper` on wider screens (swap on a breakpoint via `useBreakpoint`), or use standalone.

Sub-component: `CardStepper.Step` — declarative per-step config (compound API).

**Props:** `CardStepperProps` | fRef
- Steps — either as compound `CardStepper.Step` children **or** the `steps` data prop (one is required; children win when both are given):
- `<CardStepper.Step title state? description? id? disabled? bottomSlot? />` — `CardStepperStepProps`
- `steps?: CardStepperStepProps[]` — `{ title, description?, state?, id?, disabled?, bottomSlot? }`
- The active step shows on the card, all steps in the modal. `disabled` steps are skipped by the arrows and non-clickable in the list.
- `bottomSlot?: ReactNode` — custom content (e.g. an `Alert` or action button) rendered at the bottom of the card for the active step only
- `activeStep?: number` (controlled, 0-based) + `onStepChange?: (index) => void`, or `defaultActiveStep?: number` (uncontrolled)
- `showStepNumber?: boolean = true` — active step number in a ring indicator (ignored when `showNavigation`)
- `showStatusIcon?: boolean = false` — status icon next to the active step's title: a success check when its `state` is `'completed'`, a danger icon when `'error'` (nothing otherwise)
- `infoPosition?: 'top' | 'bottom' = 'bottom'` — places the active step's `description` above or below its title
- `counterPosition?: 'inline' | 'top' = 'inline'` — `'top'` floats the `N / M` counter above the title (and removes it from the trailing controls)
- `showProgress?: boolean = true` — segmented progress bar (one segment per step; filled up to and including the active step, so the green count equals the N in N / M)
- `showNavigation?: boolean = false` — prev / next arrow buttons (sequential, skip `disabled` steps, disabled at the bounds)
- `showStepList?: boolean = true` — the list button + step-list modal. Turn off for a read-only tracker / arrows-only flow.
- `allowJump?: boolean | 'completed' | 'completed-or-next' = true` — which steps the modal list can jump to (`false` = read-only list; per-step `disabled` always wins). Arrows are not gated by this.
- `headingElement?: 'h2'..'h6' = 'h4'` — semantic level of the title (visual size unchanged)
- `labels?: { previous?, next?, openSteps?, modalHeading?, status? }` — per-instance label overrides; otherwise sourced from the `LabelProvider` (`stepper.previous`, `stepper.next`, `stepper.open-steps`, `stepper.steps`, `stepper.status`). `status: (current, total) => string` is the screen-reader phrasing for the `N / M` counter
- `aria-label?: string`, `className?: string`

```tsx
const [step, setStep] = useState(0);

// Compound API
<CardStepper aria-label="Application steps" activeStep={step} onStepChange={setStep} showNavigation>
<CardStepper.Step title="Personal data" state="completed" />
<CardStepper.Step title="Contacts" description="Phone and email" />
<CardStepper.Step title="Review" />
</CardStepper>

// Data API (equivalent)
<CardStepper
aria-label="Application steps"
steps={[
{ title: 'Personal data', state: 'completed' },
{ title: 'Contacts', description: 'Phone and email' },
{ title: 'Review' },
]}
activeStep={step}
onStepChange={setStep}
showNavigation
/>
```

## Notifications

### Alert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { Icon } from '../../../../tedi/components/base/icon/icon';
import Collapse from '../../../../tedi/components/content/collapse/collapse';
import styles from '../vertical-stepper.module.scss';

/**
* @deprecated Use `VerticalStepper.Item` from `@tedi-design-system/react/tedi` instead.
*/
export interface StepItemProps {
/**
* SubItems
Expand Down Expand Up @@ -35,6 +38,9 @@ export interface StepItemProps {
onToggle?: (isOpen: boolean) => void;
}

/**
* @deprecated Use `VerticalStepper.Item` from `@tedi-design-system/react/tedi` instead.
*/
export const StepItem = ({
children,
className,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { Text } from '../../../../tedi';
import { Icon } from '../../../../tedi/components/base/icon/icon';
import styles from '../vertical-stepper.module.scss';

/**
* @deprecated Use `VerticalStepper.SubItem` from `@tedi-design-system/react/tedi` instead.
*/
export interface SubItemProps {
/**
* Additional info components like StatusBadge, Button, Link or Text.
Expand All @@ -22,6 +25,9 @@ export interface SubItemProps {
as?: 'a' | 'button';
}

/**
* @deprecated Use `VerticalStepper.SubItem` from `@tedi-design-system/react/tedi` instead.
*/
export const SubItem = ({
children,
className,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const meta: Meta<typeof VerticalStepper> = {
title: 'Community/VerticalStepper',
subcomponents: { StepItem, SubItem } as never,
parameters: {
status: {
type: ['deprecated', 'ExistsInTediReady'],
},
docs: {
description: {
component: 'Vertical Stepper with StepItem and SubItem. Currently supports desktop only. ',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import cn from 'classnames';

import styles from './vertical-stepper.module.scss';

/**
* @deprecated Use `VerticalStepper` from `@tedi-design-system/react/tedi` instead.
*/
export interface VerticalStepperProps {
/**
* SubItem or Separator
Expand All @@ -15,6 +18,9 @@ export interface VerticalStepperProps {
isCompact?: boolean;
}

/**
* @deprecated Use `VerticalStepper` from `@tedi-design-system/react/tedi` instead.
*/
export const VerticalStepper = (props: VerticalStepperProps): JSX.Element => {
const { className, children, isCompact } = props;

Expand Down
12 changes: 10 additions & 2 deletions src/tedi/components/buttons/card-button/card-button.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
background-color: var(--button-card-hover-background);
}

[data-name='icon'] {
[data-name='icon']:not(
[class*='tedi-icon--color-success'],
[class*='tedi-icon--color-warning'],
[class*='tedi-icon--color-danger']
) {
color: var(--button-card-icon-hover);
}

Expand All @@ -42,7 +46,11 @@
background-color: var(--button-card-active-background);
}

[data-name='icon'] {
[data-name='icon']:not(
[class*='tedi-icon--color-success'],
[class*='tedi-icon--color-warning'],
[class*='tedi-icon--color-danger']
) {
color: var(--button-card-icon-hover);
}

Expand Down
90 changes: 90 additions & 0 deletions src/tedi/components/navigation/card-stepper/card-stepper-step.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from 'react';

import { VerticalStepperItemState } from '../vertical-stepper/vertical-stepper-item';
import { VerticalStepperSubItemState } from '../vertical-stepper/vertical-stepper-sub-item';

export interface CardStepperSubStepProps {
/**
* Sub-step label.
*/
title: React.ReactNode;
/**
* Visual / semantic state shown in the step-list modal.
* @default default
*/
state?: VerticalStepperSubItemState;
/**
* Marks the sub-step as the active one.
*/
current?: boolean;
/**
* Stable key for the sub-step. Falls back to the array index.
*/
id?: string;
/**
* Renders the sub-step as disabled (non-interactive) in the modal.
*/
disabled?: boolean;
/**
* Click handler — makes the sub-step navigable in the modal and closes the list when picked.
*/
onClick?: (event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => void;
/**
* Navigates when set; renders the sub-step as a link in the modal.
*/
href?: string;
}

export interface CardStepperStepProps {
/**
* Step title.
*/
title: React.ReactNode;
/**
* Optional secondary line shown under the title (on the card for the active
* step, and always in the step-list modal).
*/
description?: React.ReactNode;
/**
* Visual / semantic state used in the progress bar and the step-list modal.
* @default default
*/
state?: VerticalStepperItemState;
/**
* Stable key for the step. Falls back to the array index.
*/
id?: string;
/**
* Excludes the step from navigation — not reachable via the arrows or the step
* list, and rendered as disabled in the modal.
*/
disabled?: boolean;
/**
* Custom content rendered at the bottom of the card when this step is active —
* e.g. an inline `Alert`, a "read more" link or an action button. Only shown for
* the active step. Matches the Figma "with bottom slot" variant.
*/
bottomSlot?: React.ReactNode;
/**
* Sub-steps shown under this step in the step-list modal. When present the step
* becomes a collapsible parent — the title navigates and a chevron expands the
* sub-step list.
*/
subSteps?: CardStepperSubStepProps[];
/**
* Whether the sub-step list starts expanded in the modal. Defaults to expanded
* for the active step. Only relevant with `subSteps`.
*/
defaultExpanded?: boolean;
}

/**
* Declarative step config for `CardStepper`. It renders nothing on its own — the
* parent reads its props to build the active card, the progress bar and the
* step-list modal. Use it as `CardStepper.Step`.
*/
export const CardStepperStep = (_props: CardStepperStepProps): null => null;

CardStepperStep.displayName = 'CardStepperStep';

export default CardStepperStep;
Loading
Loading