Theme
Version
GitHub PyPI Discord
On this page

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

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.

Target page elements
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.

Center Tour steps
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.

Control a Tour
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.

Choose a missing-target policy
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.

Customize Tour
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(...).

InputTypeDefaultEffect
idstr | NonegeneratedSets the host ID and bases dialog title and description IDs.
openboolFalseSets initial open state.
activeint0Sets the initial zero-based step index.
dismissibleboolTrueEnables the built-in close action and permitted dismissal.
close_on_escapeboolTrueAllows Escape dismissal when dismissible.
close_on_outsideboolFalseAllows pointer dismissal outside the card when dismissible.
skippableboolTrueShows and enables the skip action.
scrollCTourScroll (CTourScroll)"auto"Selects target scrolling or disables it.
missing_targetCTourMissingTarget (CTourMissingTarget)"skip"Skips unavailable targeted steps or closes the Tour.
sizeCTourSize (CTourSize)"md"Selects the default card width profile.
close_labelstr"Close tour"Overrides the localized close action name.
previous_labelstr"Previous"Overrides the localized previous action text.
next_labelstr"Next"Overrides the localized next action text.
finish_labelstr"Finish"Overrides the localized finish action text.
skip_labelstr"Skip tour"Overrides the localized skip action text.
progress_labelstr"Step {current} of {total}"Overrides progress text and must retain both placeholders.
class_CClassValue | None (CClassValue)NoneAdds classes to the Tour host.
styleCStyleValue | None (CStyleValue)NoneAdds styles to the Tour host.
attrsMapping[str, object] | NoneNoneAdds 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 />.

InputTypeOmitted behaviorEffect
openboolean | nullReleases control to the committed value.Controls modal visibility independently from active step.
activenumber | nullReleases control to the committed value.Controls the zero-based active step independently from visibility.
dismissiblebooleanUses the server value.Controls dismissal availability.
closeOnEscapebooleanUses the server value.Controls Escape dismissal.
closeOnOutsidebooleanUses the server value.Controls outside-pointer dismissal.
skippablebooleanUses the server value.Controls skip availability.
scrollCTourScroll (CTourScroll)Uses the server value.Controls target scroll behavior.
missingTargetCTourMissingTarget (CTourMissingTarget)Uses the server value.Controls missing-target reconciliation.
sizeCTourSize (CTourSize)Uses the server value.Controls card width profile.
onOpenChangefunctionNo open-state callback.Receives reasoned visibility requests and commits.
onActiveChangefunctionNo 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(...).

InputTypeDefaultEffect
valuestrrequiredSupplies unique stable step identity.
target_idstr | NoneNoneTargets one exact document element ID; omission creates a centered step.
placementCTourPlacement (CTourPlacement)"bottom"Requests logical target-relative card placement with flip and clamp.
arrowboolTrueShows the target-pointing arrow for targeted steps.
describeboolFalseConnects the active body through aria-describedby.
class_CClassValue | None (CClassValue)NoneAdds classes to the native step section.
styleCStyleValue | None (CStyleValue)NoneAdds styles to the native step section.
attrsMapping[str, object] | NoneNoneAdds 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

SlotRequiredDataFallback
defaultyes{} (CTourDefaultSlotData)None; contains direct CTourStep declarations.
activatorno{activator_attrs} (CTourActivatorSlotData)Omitted.
closeno{} (CTourCloseSlotData)Decorative multiplication sign.

CTourStep slots

SlotRequiredDataFallback
titleyes{index, total, value} (CTourStepTitleSlotData)None.
defaultyes{index, total, value} (CTourStepDefaultSlotData)None.
mediano{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

EventSignatureTrigger and timingDetailControlled 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.

VariableTypePurposeDefault
--cui-tour-widthlengthCard inline size overriding the selected profile.sm 20rem; md 24rem; lg 30rem
--cui-tour-backgroundcolorCard and arrow background.Adaptive canvas
--cui-tour-foregroundcolorCard text and control color.CanvasText
--cui-tour-border-colorcolorCard control and arrow borders.Adaptive neutral
--cui-tour-shadowshadowCard elevation.Modal elevation
--cui-tour-radiuslengthCard corner radius.0.875rem
--cui-tour-paddinglengthStep panel padding.1.25rem
--cui-tour-gaplengthStep anatomy spacing.1rem
--cui-tour-offsetlengthTarget-to-card distance.0.75rem
--cui-tour-spotlight-paddinglengthSpace around the highlighted target.0.5rem
--cui-tour-spotlight-radiuslengthHighlighted target corner radius.0.625rem
--cui-tour-backdrop-colorcolorCentered mask and target spotlight surround.rgb(0 0 0 / 58%)
--cui-tour-focus-colorcolorAction 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

AttributeElementTypeMeaning
data-openTour host and dialogpresent | absentMarks effective modal visibility.
data-activeTour hostnonnegative integerMirrors effective active index.
data-valueTour host and step panelsstringMirrors stable active or declared step identity.
data-sizeTour host and surfaceCTourSize (CTourSize)Mirrors card width profile.
data-targetedTour hostpresent | absentMarks an active available target step.
aria-labelledbyNative dialogIDREFRefers to the active step title.
aria-describedbyNative dialogIDREF | absentRefers to the active body only when describe is enabled.
data-indexStep panelnonnegative integerMirrors server-rendered order.
data-currentStep panelpresent | absentMarks the active panel.
data-placementStep panel and surfacestringStores requested logical and applied physical placement respectively.
data-target-idStep panelIDREF | absentStores the exact authored target ID.
data-describeStep panelboolean-stringMirrors 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

SelectorElementPurpose
[data-citry-ui-part="tour"]Host divState reflections and customization destination.
[data-citry-ui-part="dialog"]Native dialogModal top-layer owner.
[data-citry-ui-part="spotlight"]Decorative divTarget geometry and mask cutout.
[data-citry-ui-part="surface"]Fixed card divPlacement scroll and visual surface.
[data-citry-ui-part="panel"]Native sectionServer-rendered step content and visibility owner.
[data-citry-ui-part="media"]Optional divAuthored step media.
[data-citry-ui-part="header"]Native headerActive step heading region.
[data-citry-ui-part="title"]Native h2Dialog name and step focus destination.
[data-citry-ui-part="description"]Native divAuthored step body and optional dialog description.
[data-citry-ui-part="arrow"]Decorative spanTarget direction indicator.
[data-citry-ui-part="close"]Native ButtonDismissal action.
[data-citry-ui-part="footer"]Native footerProgress and navigation grouping.
[data-citry-ui-part="progress"]Polite spanLocalized step position.
[data-citry-ui-part="actions"]DivSkip previous next and finish controls.

Interfaces

Aliases and data shapes referenced above.

Input type aliases

InterfaceDefinition
CTourPlacementLiteral["top-start", "top", "top-end", "bottom-start", "bottom", "bottom-end", "inline-start", "inline-end"]
CTourScrollLiteral["auto", "smooth", "none"]
CTourMissingTargetLiteral["skip", "close"]
CTourSizeLiteral["sm", "md", "lg"]
CTourOpenReasonLiteral["activator", "close", "escape", "outside", "skip", "finish", "missing-target", "native"]
CTourActiveReasonLiteral["next", "previous", "client", "missing-target"]
CClassValuestr | Mapping[str, bool] | Sequence[CClassValue]
CStyleValuestr | Mapping[str, object] | Sequence[CStyleValue]

CTourDefaultSlotData

Empty dataclass: {}.

CTourActivatorSlotData

FieldTypeDefaultMeaning
activator_attrsdict[str, object]-Form-safe dialog activation ARIA and behavior attributes.

CTourCloseSlotData

Empty dataclass: {}.

CTourStepSlotData

FieldTypeDefaultMeaning
indexint-Zero-based server-rendered index.
totalint-Total rendered step count.
valuestr-Stable step identity.

CTourStepTitleSlotData

FieldTypeDefaultMeaning
indexint-Zero-based server-rendered index.
totalint-Total rendered step count.
valuestr-Stable step identity.

CTourStepDefaultSlotData

FieldTypeDefaultMeaning
indexint-Zero-based server-rendered index.
totalint-Total rendered step count.
valuestr-Stable step identity.

CTourStepMediaSlotData

FieldTypeDefaultMeaning
indexint-Zero-based server-rendered index.
totalint-Total rendered step count.
valuestr-Stable step identity.

CTourOpenChangeDetail

FieldTypeDefaultMeaning
reasonCTourOpenReason (CTourOpenReason)-Cause of the visibility request or commit.
activeint-Effective active index.
valuestr-Effective stable step identity.
controlledbool-Whether client state controls visibility.
sourceobject | None-Native source element or null for client reconciliation.

CTourActiveChangeDetail

FieldTypeDefaultMeaning
previousActiveint-Effective index before the request.
valuestr-Requested stable step identity.
previousValuestr-Effective stable identity before the request.
reasonCTourActiveReason (CTourActiveReason)-Cause of the step request or commit.
controlledbool-Whether client state controls the active index.
sourceobject | 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

KeyPurposeVariablesOverrideBrowser updates
citry-ui-tour-closeNames the built-in dismissal control.None.close_label$c-tr updates each stable aria-label destination.
citry-ui-tour-previousLabels previous-step actions.None.previous_label$c-tr updates server-rendered action text.
citry-ui-tour-nextLabels next-step actions.None.next_label$c-tr updates server-rendered action text.
citry-ui-tour-finishLabels final-step completion actions.None.finish_label$c-tr updates server-rendered action text.
citry-ui-tour-skipLabels skip actions.None.skip_label$c-tr updates server-rendered action text.
citry-ui-tour-progressReports current step position.current: str; total: strprogress_label with {current} and {total}$c-tr updates every stable progress destination with checked literal values.