Tour
Use CTour with direct CTourStep declarations for a short modal walkthrough. Every title, body, and media slot renders on the server. A step can point to an exact element ID or remain centered in the viewport.
Tour at a glance
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class TourAtAGlance(Component):
template = """
<div>
<button id="tour-save" type="button">Save project</button>
<c-CTour>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Show tour</c-CButton>
</c-fill>
<c-fill name="default">
<c-CTourStep value="welcome">
<c-fill name="title">Welcome to the workspace</c-fill>
<c-fill name="default">This short tour explains the primary workflow.</c-fill>
</c-CTourStep>
<c-CTourStep value="save" target_id="tour-save" placement="bottom-end">
<c-fill name="title">Save your work</c-fill>
<c-fill name="default">Use this action when the project is ready.</c-fill>
</c-CTourStep>
</c-fill>
</c-CTour>
</div>
"""
preview = TourAtAGlance()
preview # noqa: B018
Explain page targets
Set target_id to a stable HTML ID. Tour scrolls that element into view, positions the card using logical placement, and keeps the highlighted target noninteractive while the modal is open.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class TourTargets(Component):
template = """
<section class="tour-targets">
<c-CButton c-attrs="{'id':'tour-filter'}" variant="outline">Filter</c-CButton>
<c-CButton c-attrs="{'id':'tour-export'}">Export</c-CButton>
<c-CTour>
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Explain actions</c-CButton>
</c-fill>
<c-fill name="default">
<c-CTourStep value="filter" target_id="tour-filter" placement="bottom-start">
<c-fill name="title">Narrow the results</c-fill>
<c-fill name="default">Choose filters before exporting.</c-fill>
</c-CTourStep>
<c-CTourStep value="export" target_id="tour-export" placement="inline-end">
<c-fill name="title">Export the current view</c-fill>
<c-fill name="default">The export respects the active filters.</c-fill>
</c-CTourStep>
</c-fill>
</c-CTour>
</section>
"""
css = ":where(.tour-targets){display:flex;flex-wrap:wrap;gap:1rem;align-items:center}"
preview = TourTargets()
preview # noqa: B018
Use centered introduction and finish steps
Omit target_id for a centered dialog step. Centered steps work well for an introduction, a summary, or a finish message that does not belong to one page control.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class TourCentered(Component):
template = """
<c-CTour size="sm">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Open introduction</c-CButton>
</c-fill>
<c-fill name="default">
<c-CTourStep value="intro" c-describe="True">
<c-fill name="title">A focused introduction</c-fill>
<c-fill name="default">Centered steps do not require a page target.</c-fill>
</c-CTourStep>
<c-CTourStep value="finish">
<c-fill name="title">You are ready</c-fill>
<c-fill name="default">Finish closes the modal and restores focus.</c-fill>
</c-CTourStep>
</c-fill>
</c-CTour>
"""
preview = TourCentered()
preview # noqa: B018
Control open and active state
open and active are independent $c-props controls. In controlled mode, onOpenChange and onActiveChange report requests; update your Alpine state to accept them. Each detail includes a reason and the stable step value.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class TourControlled(Component):
template = """
<section x-data="{open:false,active:0,last:'No request'}">
<c-CButton @click="open=true">Open controlled tour</c-CButton>
<output x-text="last">No request</output>
<c-CTour
$c-props="{
open,
active,
onOpenChange:(next,detail)=>{last=`Open: ${detail.reason}`;open=next},
onActiveChange:(next,detail)=>{last=`Step: ${detail.reason}`;active=next},
}"
>
<c-CTourStep value="first">
<c-fill name="title">First controlled step</c-fill>
<c-fill name="default">The parent accepts each requested index.</c-fill>
</c-CTourStep>
<c-CTourStep value="second">
<c-fill name="title">Second controlled step</c-fill>
<c-fill name="default">Open and active ownership are independent.</c-fill>
</c-CTourStep>
</c-CTour>
</section>
"""
preview = TourControlled()
preview # noqa: B018
Handle conditional targets
With missing_target="skip", Tour searches in the navigation direction for the next available or centered step. Use close when continuing without the requested target would be misleading. Tour accepts IDs, not arbitrary CSS selectors or trusted HTML.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class TourMissingTargets(Component):
template = """
<c-CTour missing_target="skip">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Show conditional tour</c-CButton>
</c-fill>
<c-fill name="default">
<c-CTourStep value="intro">
<c-fill name="title">Conditional features</c-fill>
<c-fill name="default">Unavailable targeted steps are skipped.</c-fill>
</c-CTourStep>
<c-CTourStep value="optional" target_id="feature-not-rendered">
<c-fill name="title">Optional feature</c-fill>
<c-fill name="default">This step is skipped because its target is absent.</c-fill>
</c-CTourStep>
<c-CTourStep value="summary">
<c-fill name="title">Summary</c-fill>
<c-fill name="default">The next available centered step remains usable.</c-fill>
</c-CTourStep>
</c-fill>
</c-CTour>
"""
preview = TourMissingTargets()
preview # noqa: B018
Customize Tour
Public parts and --cui-tour-* variables customize the card, mask, spotlight, spacing, and focus treatment without replacing modal behavior.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class TourCustomization(Component):
template = """
<c-CTour c-class_="['ocean-tour']">
<c-fill name="activator" data="{ activator_attrs }">
<c-CButton c-attrs="activator_attrs">Open custom tour</c-CButton>
</c-fill>
<c-fill name="close"><c-CIcon name="close" /></c-fill>
<c-fill name="default">
<c-CTourStep value="theme">
<c-fill name="title">Ocean theme</c-fill>
<c-fill name="default">Variables customize the stable Tour anatomy.</c-fill>
</c-CTourStep>
</c-fill>
</c-CTour>
"""
css = """
:where(.ocean-tour) {
--cui-tour-background: light-dark(#eff8ff, #102a43);
--cui-tour-border-color: light-dark(#84caff, #2e90fa);
--cui-tour-backdrop-color: rgb(2 32 71 / 62%);
--cui-tour-radius: 1.25rem;
}
"""
preview = TourCustomization()
preview # noqa: B018
Accessibility and localization
Tour uses native modal <dialog> behavior, keeps Tab inside the card, supports Escape when allowed, and restores focus to the activator. Step changes focus the new title. describe=True explicitly connects a step body through aria-describedby; leave it false for complex structured content.
Close, previous, next, finish, skip, and progress text come from the Citry UI catalog. Explicit label inputs remain fixed; catalog defaults are server rendered and update through $c-tr under a client-enabled i18n provider.
The highlighted page target is deliberately inert in this modal release. Use ordinary application UI outside Tour when a user must interact with a target.
API reference
Inputs
CTour server inputs
Server inputs are passed in a template through <c-CTour ... /> or in Python through CTour(...).
| Input | Type | Default | Effect |
|---|---|---|---|
id | str | None | generated | Sets the host ID and bases dialog title and description IDs. |
open | bool | False | Sets initial open state. |
active | int | 0 | Sets the initial zero-based step index. |
dismissible | bool | True | Enables the built-in close action and permitted dismissal. |
close_on_escape | bool | True | Allows Escape dismissal when dismissible. |
close_on_outside | bool | False | Allows pointer dismissal outside the card when dismissible. |
skippable | bool | True | Shows and enables the skip action. |
scroll | CTourScroll (CTourScroll) | "auto" | Selects target scrolling or disables it. |
missing_target | CTourMissingTarget (CTourMissingTarget) | "skip" | Skips unavailable targeted steps or closes the Tour. |
size | CTourSize (CTourSize) | "md" | Selects the default card width profile. |
close_label | str | "Close tour" | Overrides the localized close action name. |
previous_label | str | "Previous" | Overrides the localized previous action text. |
next_label | str | "Next" | Overrides the localized next action text. |
finish_label | str | "Finish" | Overrides the localized finish action text. |
skip_label | str | "Skip tour" | Overrides the localized skip action text. |
progress_label | str | "Step {current} of {total}" | Overrides progress text and must retain both placeholders. |
class_ | CClassValue | None (CClassValue) | None | Adds classes to the Tour host. |
style | CStyleValue | None (CStyleValue) | None | Adds styles to the Tour host. |
attrs | Mapping[str, object] | None | None | Adds copied allowed host attributes without replacing owned modal state identity or behavior. |
CTour client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CTour />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
open | boolean | null | Releases control to the committed value. | Controls modal visibility independently from active step. |
active | number | null | Releases control to the committed value. | Controls the zero-based active step independently from visibility. |
dismissible | boolean | Uses the server value. | Controls dismissal availability. |
closeOnEscape | boolean | Uses the server value. | Controls Escape dismissal. |
closeOnOutside | boolean | Uses the server value. | Controls outside-pointer dismissal. |
skippable | boolean | Uses the server value. | Controls skip availability. |
scroll | CTourScroll (CTourScroll) | Uses the server value. | Controls target scroll behavior. |
missingTarget | CTourMissingTarget (CTourMissingTarget) | Uses the server value. | Controls missing-target reconciliation. |
size | CTourSize (CTourSize) | Uses the server value. | Controls card width profile. |
onOpenChange | function | No open-state callback. | Receives reasoned visibility requests and commits. |
onActiveChange | function | No active-step callback. | Receives reasoned step requests and commits. |
CTourStep server inputs
Server inputs are passed in a template through <c-CTourStep ... /> or in Python through CTourStep(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | str | required | Supplies unique stable step identity. |
target_id | str | None | None | Targets one exact document element ID; omission creates a centered step. |
placement | CTourPlacement (CTourPlacement) | "bottom" | Requests logical target-relative card placement with flip and clamp. |
arrow | bool | True | Shows the target-pointing arrow for targeted steps. |
describe | bool | False | Connects the active body through aria-describedby. |
class_ | CClassValue | None (CClassValue) | None | Adds classes to the native step section. |
style | CStyleValue | None (CStyleValue) | None | Adds styles to the native step section. |
attrs | Mapping[str, object] | None | None | Adds copied allowed step attributes without replacing owned identity state or visibility. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CTour slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
default | yes | {} (CTourDefaultSlotData) | None; contains direct CTourStep declarations. |
activator | no | {activator_attrs} (CTourActivatorSlotData) | Omitted. |
close | no | {} (CTourCloseSlotData) | Decorative multiplication sign. |
CTourStep slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
title | yes | {index, total, value} (CTourStepTitleSlotData) | None. |
default | yes | {index, total, value} (CTourStepDefaultSlotData) | None. |
media | no | {index, total, value} (CTourStepMediaSlotData) | Omitted. |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CTour events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onOpenChange | (open: boolean, detail: CTourOpenChangeDetail) => void (CTourOpenChangeDetail) | Activator dismissal skip finish target loss or native lifecycle requests a visibility change. | {reason, active, value, controlled, source} (CTourOpenChangeDetail) | Uncontrolled state commits before notification; controlled state is request-only. |
onActiveChange | (active: number, detail: CTourActiveChangeDetail) => void (CTourActiveChangeDetail) | Previous next client reconciliation or missing-target skip requests a step change. | {previousActive, value, previousValue, reason, controlled, source} (CTourActiveChangeDetail) | Uncontrolled state commits before notification; controlled state is request-only. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CTour CSS variables
Apply these variables to CTour or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-tour-width | length | Card inline size overriding the selected profile. | sm 20rem; md 24rem; lg 30rem |
--cui-tour-background | color | Card and arrow background. | Adaptive canvas |
--cui-tour-foreground | color | Card text and control color. | CanvasText |
--cui-tour-border-color | color | Card control and arrow borders. | Adaptive neutral |
--cui-tour-shadow | shadow | Card elevation. | Modal elevation |
--cui-tour-radius | length | Card corner radius. | 0.875rem |
--cui-tour-padding | length | Step panel padding. | 1.25rem |
--cui-tour-gap | length | Step anatomy spacing. | 1rem |
--cui-tour-offset | length | Target-to-card distance. | 0.75rem |
--cui-tour-spotlight-padding | length | Space around the highlighted target. | 0.5rem |
--cui-tour-spotlight-radius | length | Highlighted target corner radius. | 0.625rem |
--cui-tour-backdrop-color | color | Centered mask and target spotlight surround. | rgb(0 0 0 / 58%) |
--cui-tour-focus-color | color | Action and title focus outline. | Highlight |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CTour attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
data-open | Tour host and dialog | present | absent | Marks effective modal visibility. |
data-active | Tour host | nonnegative integer | Mirrors effective active index. |
data-value | Tour host and step panels | string | Mirrors stable active or declared step identity. |
data-size | Tour host and surface | CTourSize (CTourSize) | Mirrors card width profile. |
data-targeted | Tour host | present | absent | Marks an active available target step. |
aria-labelledby | Native dialog | IDREF | Refers to the active step title. |
aria-describedby | Native dialog | IDREF | absent | Refers to the active body only when describe is enabled. |
data-index | Step panel | nonnegative integer | Mirrors server-rendered order. |
data-current | Step panel | present | absent | Marks the active panel. |
data-placement | Step panel and surface | string | Stores requested logical and applied physical placement respectively. |
data-target-id | Step panel | IDREF | absent | Stores the exact authored target ID. |
data-describe | Step panel | boolean-string | Mirrors whether the body describes the dialog. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CTour selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="tour"] | Host div | State reflections and customization destination. |
[data-citry-ui-part="dialog"] | Native dialog | Modal top-layer owner. |
[data-citry-ui-part="spotlight"] | Decorative div | Target geometry and mask cutout. |
[data-citry-ui-part="surface"] | Fixed card div | Placement scroll and visual surface. |
[data-citry-ui-part="panel"] | Native section | Server-rendered step content and visibility owner. |
[data-citry-ui-part="media"] | Optional div | Authored step media. |
[data-citry-ui-part="header"] | Native header | Active step heading region. |
[data-citry-ui-part="title"] | Native h2 | Dialog name and step focus destination. |
[data-citry-ui-part="description"] | Native div | Authored step body and optional dialog description. |
[data-citry-ui-part="arrow"] | Decorative span | Target direction indicator. |
[data-citry-ui-part="close"] | Native Button | Dismissal action. |
[data-citry-ui-part="footer"] | Native footer | Progress and navigation grouping. |
[data-citry-ui-part="progress"] | Polite span | Localized step position. |
[data-citry-ui-part="actions"] | Div | Skip previous next and finish controls. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CTourPlacement | Literal["top-start", "top", "top-end", "bottom-start", "bottom", "bottom-end", "inline-start", "inline-end"] |
CTourScroll | Literal["auto", "smooth", "none"] |
CTourMissingTarget | Literal["skip", "close"] |
CTourSize | Literal["sm", "md", "lg"] |
CTourOpenReason | Literal["activator", "close", "escape", "outside", "skip", "finish", "missing-target", "native"] |
CTourActiveReason | Literal["next", "previous", "client", "missing-target"] |
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, object] | Sequence[CStyleValue] |
CTourDefaultSlotData
Empty dataclass: {}.
CTourActivatorSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
activator_attrs | dict[str, object] | - | Form-safe dialog activation ARIA and behavior attributes. |
CTourCloseSlotData
Empty dataclass: {}.
CTourStepSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
index | int | - | Zero-based server-rendered index. |
total | int | - | Total rendered step count. |
value | str | - | Stable step identity. |
CTourStepTitleSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
index | int | - | Zero-based server-rendered index. |
total | int | - | Total rendered step count. |
value | str | - | Stable step identity. |
CTourStepDefaultSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
index | int | - | Zero-based server-rendered index. |
total | int | - | Total rendered step count. |
value | str | - | Stable step identity. |
CTourStepMediaSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
index | int | - | Zero-based server-rendered index. |
total | int | - | Total rendered step count. |
value | str | - | Stable step identity. |
CTourOpenChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
reason | CTourOpenReason (CTourOpenReason) | - | Cause of the visibility request or commit. |
active | int | - | Effective active index. |
value | str | - | Effective stable step identity. |
controlled | bool | - | Whether client state controls visibility. |
source | object | None | - | Native source element or null for client reconciliation. |
CTourActiveChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
previousActive | int | - | Effective index before the request. |
value | str | - | Requested stable step identity. |
previousValue | str | - | Effective stable identity before the request. |
reason | CTourActiveReason (CTourActiveReason) | - | Cause of the step request or commit. |
controlled | bool | - | Whether client state controls the active index. |
source | object | None | - | Native source element or null for client reconciliation. |
Translation keys
Catalog keys used by this family. An explicit component input or slot listed in Override takes precedence over the catalog for that instance.
CTour translation keys
| Key | Purpose | Variables | Override | Browser updates |
|---|---|---|---|---|
citry-ui-tour-close | Names the built-in dismissal control. | None. | close_label | $c-tr updates each stable aria-label destination. |
citry-ui-tour-previous | Labels previous-step actions. | None. | previous_label | $c-tr updates server-rendered action text. |
citry-ui-tour-next | Labels next-step actions. | None. | next_label | $c-tr updates server-rendered action text. |
citry-ui-tour-finish | Labels final-step completion actions. | None. | finish_label | $c-tr updates server-rendered action text. |
citry-ui-tour-skip | Labels skip actions. | None. | skip_label | $c-tr updates server-rendered action text. |
citry-ui-tour-progress | Reports current step position. | current: str; total: str | progress_label with {current} and {total} | $c-tr updates every stable progress destination with checked literal values. |