PBToolboxAI v4 ← Site

stepbar — u_pbt_stepbar #

← Component reference · Guide contents

Step trail for a wizard: the steps already completed, the current one and the ones still ahead, horizontally or vertically.

▶ See it live — Demo application, Stepbar tile: the preview, the code behind it and this page, side by side.


At a glance #

Userobjectu_pbt_stepbar
Item classn_pbt_stepbar_step (one step)
Used forShowing users where they stand in a wizard, a multi-page form or an approval process
PrincipleYou declare the steps, then you move ii_current: the states work themselves out

Quick start #

// window open event
uo_steps.of_add_step(/*key*/ "account",   /*label*/ "Account")
uo_steps.of_add_step(/*key*/ "profile",   /*label*/ "Profile")
uo_steps.of_add_step(/*key*/ "payment", /*label*/ "Payment")
uo_steps.of_add_step(/*key*/ "done",      /*label*/ "Confirmation")

// Current step (1 = the first one)
uo_steps.ii_current = 1
// Next button of the wizard : the next step, skipping the hidden and disabled ones
uo_steps.of_next()

// Back button
uo_steps.of_previous()

The model: one step, three automatic states #

A step has no state for you to manage by hand. It is derived from its position relative to ii_current:

PositionStateRendering
Before the current stepdone — completedChecked badge
The current stepcurrent — in progressHighlighted badge
After the current steptodo — upcomingNumbered badge, subdued shade

Three more states are never reached automatically: you force them on a step — error when it has failed, warning when it is passed but something is left to review, skipped when it was skipped (see below).


Properties #

PropertyTypeDefaultPurpose
ii_currentinteger1Current step, numbered from 1 (number of steps + 1 = everything done). Setting it raises ue_step_changed when the bar moves. The current step is followed by its identity: adding, removing or moving a step before it does not change the current step. Set before the steps, the value is kept and applied as soon as that step exists. A hidden current step leaves no step shown "in progress". "Everything done" is anchored on the last step of that moment: a step added after it becomes the current step (and raises ue_step_changed); one inserted before it changes nothing
is_positionstring"top"Orientation: top / bottom (horizontal trail) or start / end (vertical trail) — constants POSITION_TOP, POSITION_BOTTOM, POSITION_START, POSITION_END. START/END are logical and follow the writing direction
is_navigation_modestring"free"What a click may reach: NAV_FREE (any step, the default), NAV_BACKWARD (only the steps already passed — go back, never jump ahead), NAV_VISITED (every step already reached, except the current one — after going back, the steps reached further on stay one click away) or NAV_NONE (nothing: a plain progress indicator, driven by your code alone). Whatever stays clickable raises ue_step_clicked; the bar itself never moves on a click
is_overflow_modestring"auto"Too many steps for the width: OVERFLOW_AUTO compacts the bar below a readable floor per step (every step becomes a dot, only the current one keeps its label, and all of them stay clickable), OVERFLOW_SCROLL keeps the labels and scrolls, keeping the current step in view, OVERFLOW_SHRINK squeezes them until they ellipsize. A vertical trail never compacts
is_theme_stylestring""Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change
is_theme_modestring""Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change
il_theme_accentlong-1Accent colour of this component (-1 = the application accent, or the theme's)
is_tooltipstring""Simple tooltip shown when hovering the component
is_super_tooltip_titlestring""Title of the rich tooltip (takes precedence over is_tooltip)
is_super_tooltip_textstring""Text of the rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""Image of the rich tooltip

Properties of a step — n_pbt_stepbar_step #

Obtained through of_step(id):

PropertyTypeDefaultPurpose
is_statestringSTATE_TODOForces the state of the step: STATE_TODO, STATE_CURRENT, STATE_DONE, STATE_ERROR, STATE_WARNING (passed, but with something to review: amber bullet marked “!”, amber label), STATE_SKIPPED (skipped, neither done nor to do: hollow bullet with a dashed ring marked “–”, label in italics). Screen readers announce them “with a warning” and “skipped”; after either one, the line is drawn as travelled, as after a done step. STATE_AUTO = back to automatic computation; reading it back returns the step's effective state, not the forced one. Set on a key that names no step, it is ignored
is_textstring—Changes the caption of the step, rich text markup accepted
is_descriptionstring""Second line of the step — Optional, a date, an amount. Rich text markup accepted. Announced to a screen reader as the step's description, after its name. An empty string removes it; a compacted bar drops it to stay one line tall
is_imagestring""Icon displayed in place of the step's rank (accepted forms)
ib_enabledbooleantrueStep enabled; a disabled step no longer responds to clicks
ib_visiblebooleantrueHides the step without removing it from the model

Methods #

MethodPurpose
of_add_step (string as_key, string as_label)Adds a step at the end of the trail. Returns 0 once applied, -5 on an empty key, a key holding / or `, or a key already in the bar, -2` when the component is not created
of_add_step (string as_key, string as_label, string as_icon_file)The same, with the icon shown in place of the step's rank. Returns 0 once applied, -5 on an empty key, a key holding / or `, or a key already in the bar, -2` when the component is not created
of_add_step (string as_key, string as_label, string as_icon_file, string as_desc)The same, with the icon and the second line. Returns 0 once applied, -5 on an empty key, a key holding / or `, or a key already in the bar, -2` when the component is not created
of_insert_step (string as_key, string as_label, integer ai_index)Inserts a step at the given position (counted from 1; 0 or less = first, past the end = last). Returns 0 once applied, -5 on an empty key, a key holding / or `, or a key already in the bar, -2` when the component is not created
of_insert_step (string as_key, string as_label, string as_icon_file, integer ai_index)The same, with the icon. Returns 0 once applied, -5 on an empty key, a key holding / or `, or a key already in the bar, -2` when the component is not created
of_insert_step (string as_key, string as_label, string as_icon_file, string as_desc, integer ai_index)The same, with the icon and the second line. Returns 0 once applied, -5 on an empty key, a key holding / or `, or a key already in the bar, -2` when the component is not created
of_move_step (string as_key, integer ai_index)Moves an existing step; the current step stays current. Returns 0 once applied, -5 on an empty key or a key that names no step, -2 when the component is not created
of_next ( )Moves to the next step, skipping the hidden and the disabled ones — the ones ii_current + 1 would land on. Stops on the last one it can reach. The navigation mode is not consulted: it restricts the user, not your code. No question is asked, but ue_step_changed is raised. Returns 0 once applied, -2 when the component is not created
of_previous ( )Moves back to the previous step, same rules. From the "everything done" position it comes back to the last step. Returns 0 once applied, -2 when the component is not created
of_remove_step (string as_key)Removes a step; the others keep their state. Removing the current step moves on to the next step the bar can land on (or to "everything done") and raises ue_step_changed. Returns 0 once applied, -5 on an empty key or a key that names no step, -2 when the component is not created
of_clear_steps ( )Empties the trail. The bar starts again on its first step: the steps added next make a new workflow. Returns 0 once applied, -2 when the component is not created
of_step (string as_key) → n_pbt_stepbar_stepHandle to a step, to set its properties
of_reset ( )Clears the steps and resets every property to its default. Returns 0 once applied, -2 when the component is not created
of_set_redraw (boolean)Groups a burst of changes into a single render. Returns 0 once applied, -2 when the component is not created
of_save_as_png (string) · of_save_as_jpg (string)Exports the rendering as an image. Returns 0 once the image is written, -4 when writing fails, -2 when the component is not created

The third argument is the icon, as everywhere else in the library (of_add_item of the listbar, of_add_panel of the statusbar, of_add_tile of the tilesbox). The second line comes after it.


Events #

EventRaised when
ue_step_clicked (integer ai_index, string as_key)The user clicked a step. The bar does not move: script this event, run your checks, then set ii_current if you agree
ue_step_changed (integer ai_from_index, string as_from_key, integer ai_index, string as_key)The bar has moved: ii_current was set to another step, of_next / of_previous was called, the current step was removed, or a step was added after "everything done". A click never lands here
ue_ready ( )The component has finished loading; everything sent beforehand has been replayed
ue_runtime_missing ( )The WebView2 runtime is missing: the component stays empty
ue_bg_color (long al_color)The component has computed its theme background color; the userobject has already adopted it (backcolor)

The bar does NOT navigate on its own. A click reports (ue_step_clicked) and nothing else: the bar stays where it is. You are the one who moves it, by setting ii_current or by calling of_next / of_previous — and those moves announce themselves through ue_step_changed.

This split is not a constraint, it is what the component means: a step bar mirrors a workflow your application drives. Reaching step 3 usually means a form was valid and a record was saved; no click can decide that for you.

ue_step_clicked carries the step aimed at, ue_step_changed also carries the step left — by business identifier as much as by rank. That pair is what you log or save the step being left with; the rule "going back is allowed, jumping ahead is not" is written with NAV_BACKWARD.

is_navigation_mode stays the filter on the click: NAV_NONE raises nothing at all, NAV_BACKWARD only lets the already-completed steps be clicked. NAV_VISITED goes further: every step already reached stays clickable, even ahead of the current one — a user who went back to fix step 2 returns to step 4, which they had reached, in one click, which NAV_BACKWARD never allows. A new list of steps forgets what was reached, and an inserted step has never been reached.


Keyboard #

The bar is a single tab stop: once reached, it is entirely navigable from the keyboard.

KeyEffect
ArrowsMove the focus from one step to the next, wrapping around; hidden, disabled or out-of-reach steps (see is_navigation_mode) are skipped
Home / EndFirst / last reachable step
Enter or SpaceReports a click on the focused step (ue_step_clicked) — the bar does not move

The arrows do not select, unlike the tabs of a dockcontainer: they move the focus. Enter or Space on a step reports the click (ue_step_clicked), like the mouse; your application is the one that moves the bar. Walking an eight-step bar with the keyboard must not send eight clicks.

Every step is a real button: it carries its label and its state in its spoken name ("Account - completed"), the current step is marked aria-current="step", and a disabled step is a disabled button — not merely greyed-out text. The numbered bullet is not read aloud: a rank teaches nothing.


Examples #

Moving through the wizard #

// The four steps of the wizard, in order
uo_steps.of_add_step(/*key*/ "account",   /*label*/ "Account")
uo_steps.of_add_step(/*key*/ "profile",   /*label*/ "Profile")
uo_steps.of_add_step(/*key*/ "payment", /*label*/ "Payment")
uo_steps.of_add_step(/*key*/ "done",      /*label*/ "Confirmation")

// Steps 1 and 2 automatically switch to "completed" (checked)
uo_steps.ii_current = 3

Flagging a step in error #

// The state of a step is forced through its handle
uo_steps.of_step(/*key*/ "profile").is_state = n_pbt_stepbar_step.STATE_ERROR
// Once the problem is fixed, hand control back to automatic computation
uo_steps.of_step(/*key*/ "profile").is_state = n_pbt_stepbar_step.STATE_AUTO

Skipped step, step to review, going forward again #

// The four steps of the order
uo_steps.of_add_step(/*key*/ "cart",    /*label*/ "Cart")
uo_steps.of_add_step(/*key*/ "coupon",    /*label*/ "Coupon")
uo_steps.of_add_step(/*key*/ "delivery", /*label*/ "Delivery")
uo_steps.of_add_step(/*key*/ "payment",  /*label*/ "Payment")

// The customer has no promo code : the step is skipped, neither done nor to do
uo_steps.of_step(/*key*/ "coupon").is_state = n_pbt_stepbar_step.STATE_SKIPPED

// Address not verified : the step is passed, but it needs a second look
uo_steps.of_step(/*key*/ "delivery").is_state = n_pbt_stepbar_step.STATE_WARNING

// Every step already reached stays clickable, even ahead of the current one
uo_steps.is_navigation_mode = u_pbt_stepbar.NAV_VISITED

// The wizard reached step 4, then goes back to the cart : steps 2 to 4 stay one click away
uo_steps.ii_current = 4
uo_steps.ii_current = 1

Vertical trail #

// POSITION_START / POSITION_END : the trail is drawn vertically, ideal alongside a form
uo_steps.is_position = uo_steps.POSITION_START

// The THIRD argument is the icon : it takes the place of the step rank
uo_steps.of_add_step(/*key*/ "account", /*label*/ "Account", /*icon_file*/ "mono:img\packimages.dll:svg/samples/folder-open")

Rich captions on two lines #

// The caption of a step accepts rich text markup
uo_steps.of_add_step(/*key*/ "account",   /*label*/ "[b]Account[/b][br][size=9](sign-in)")
uo_steps.of_add_step(/*key*/ "profile",   /*label*/ "[b]Profile[/b][br][size=9](your details)")
uo_steps.of_add_step(/*key*/ "payment", /*label*/ "[b]Payment[/b][br][size=9](card)")
uo_steps.of_add_step(/*key*/ "done",      /*label*/ "[accent][b]Done[/b][/accent]")

// The user is on step 2 : step 1 shows as completed
uo_steps.ii_current = 2

Click navigation #

// event ue_step_clicked de uo_steps : (integer ai_index, string as_key)
// The bar has NOT moved : this is where you decide.
if ai_index > uo_steps.ii_current then
    MessageBox("Wizard", "Finish the current step before moving on.")
    return
end if
uo_steps.ii_current = ai_index

Conditional step #

// A returning customer has no "Profile" step to fill in
uo_steps.of_step(/*key*/ "profile").ib_visible = false

Best practices #

Inherited from the common base #

These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.

MembersRoleDetailed in
of_count · of_keys_at · of_hasWalk what the component holds3.2 Items
of_resetPut the component back to zero3.6 Resetting a component: of_reset()
of_register_shortcut · of_clear_shortcutsThe component's keyboard chords3.5 Keyboard shortcuts
of_is_created · of_is_ready · of_get_last_errorWhether it was born, whether it is ready, what failed3.7 Diagnostics
of_save_as_png · of_save_as_jpgExport the rendering as an image3.8 Exporting the rendering as an image
of_set_redrawGroup changes into a single repaint3.10 Best practices
of_preload_iconsIcons shown with no delayInstant display: of_icon
of_set_translationTranslate one of the component's labels5.2 Adapting a label: of_set_translation
of_focus_webviewGive the component the focus6.4 Keyboard and focus
of_print · of_print_to_pdfPrint, or write a PDF6.9 Printing
of_set_property · of_get_property · of_component_nameDriving a property by its name3.1 The property engine

Two helpers are not inherited: of_icon and of_escape_markup live on n_pbt_utils. Declare one — n_pbt_utils lnv_utils, nothing to create — and call them on it.


← Component reference · Guide contents