Theme
Version
GitHub PyPI Discord
On this page

Transfer List

Use CTransferList when people need to compare a finite set of available items with an ordered chosen set. CTransferListItem declares stable values, plain accessible labels, optional rich presentation, and disabled state.

Move items between two lists

The enhanced component uses two labeled multi-select listboxes and explicit buttons. Without JavaScript, the same values remain available through a native select[multiple] form control.

Choose and order reviewers
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class TransferListAtAGlance(Component):
    template = """
      <c-CTransferList name="reviewers" c-value="['grace']">
        <c-CTransferListItem value="ada" label="Ada Lovelace" />
        <c-CTransferListItem value="grace" label="Grace Hopper" />
        <c-CTransferListItem value="katherine" label="Katherine Johnson" />
        <c-CTransferListItem value="margaret" label="Margaret Hamilton" />
      </c-CTransferList>
    """


preview = TransferListAtAGlance()
preview  # noqa: B018

Selection inside a pane is separate from the chosen form value. Select one or more enabled options, then use Add or Remove. The Add all and Remove all buttons can be omitted with show_move_all=False. Chosen items retain the exact order in value and in submitted form entries.

Render rich, noninteractive items

The Item default slot can replace its visible label with server-rendered presentation. Keep label plain and descriptive because native fallback, typeahead, and assistive naming use it.

Render rich Transfer List items
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class TransferListRichItems(Component):
    template = """
      <c-CTransferList name="owners" c-value="['platform']">
        <c-CTransferListItem value="platform" label="Platform team">
          <strong>Platform</strong><br /><small>Runtime and release infrastructure</small>
        </c-CTransferListItem>
        <c-CTransferListItem value="design" label="Design systems team">
          <strong>Design systems</strong><br /><small>Components, tokens, and accessibility</small>
        </c-CTransferListItem>
        <c-CTransferListItem value="security" label="Security team" c-disabled="True">
          <strong>Security</strong><br /><small>Managed by policy</small>
        </c-CTransferListItem>
      </c-CTransferList>
    """


preview = TransferListRichItems()
preview  # noqa: B018

Do not place links, buttons, inputs, editable content, or other focus stops inside an Item. The family follows the listbox interaction model and rejects interactive descendants during enhancement.

Control chosen values from Alpine

Pass value and onValueChange through $c-props for controlled state. Transfer and reorder actions become requests: the visible order changes only after the owner accepts the proposed array.

Control a Transfer List
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class TransferListControlled(Component):
    template = """
      <section x-data="{chosen:['grace'],last:'No request'}">
        <c-CTransferList
          $c-props="{
            value:chosen,
            onValueChange:(next,detail)=>{chosen=next;last=`${detail.source}: ${next.join(', ') || 'none'}`},
          }"
        >
          <c-CTransferListItem value="ada" label="Ada" />
          <c-CTransferListItem value="grace" label="Grace" />
          <c-CTransferListItem value="katherine" label="Katherine" />
        </c-CTransferList>
        <output x-text="last">No request</output>
      </section>
    """


preview = TransferListControlled()
preview  # noqa: B018

Omit client value, or set it to null, for uncontrolled behavior. In that mode an accepted action updates the native form owner, emits native input then change, and calls onValueChange.

Submit and validate forms

Set name to submit one entry per chosen item in chosen order. form can associate the control with a non-ancestor form. required=True requires at least one chosen value and moves focus to the chosen list when native validation fails.

Submit a required ordered selection
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class TransferListForm(Component):
    template = """
      <form x-data="{result:'Not submitted'}"
        @submit.prevent="result=[...new FormData($el).getAll('reviewers')].join(' β†’ ')"
      >
        <c-CTransferList name="reviewers" c-required="True" c-value="['ada']">
          <c-CTransferListItem value="ada" label="Ada" />
          <c-CTransferListItem value="grace" label="Grace" />
          <c-CTransferListItem value="katherine" label="Katherine" />
        </c-CTransferList>
        <p><button type="submit">Submit order</button> <button type="reset">Reset</button></p>
        <output x-text="result">Not submitted</output>
      </form>
    """


preview = TransferListForm()
preview  # noqa: B018

Native reset restores the server-rendered value. A disabled Item cannot be moved or reordered. An initially chosen disabled Item remains submitted by the native fallback through an ordered hidden option proxy.

Keyboard and accessibility

Each pane has one tab stop and an active descendant. Arrow keys, Home, End, typeahead, Space, Enter, Shift+Arrow range selection, and Ctrl/Cmd+A are available. Explicit transfer and reorder buttons remain reachable in normal tab order, so drag and drop is never required.

Use disabled items and accessible labels
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class TransferListAccessibility(Component):
    template = """
      <c-CTransferList
        name="permissions"
        available_label="Available permissions"
        chosen_label="Granted permissions"
        c-value="['audit','read']"
      >
        <c-CTransferListItem value="read" label="Read records" />
        <c-CTransferListItem value="write" label="Write records" />
        <c-CTransferListItem value="audit" label="Audit access required by policy" c-disabled="True">
          <strong>Audit access</strong><br /><small>Required by policy; cannot be removed</small>
        </c-CTransferListItem>
      </c-CTransferList>
    """


preview = TransferListAccessibility()
preview  # noqa: B018

The family announces accepted moves and reorders through a polite live region. Pane labels, counts, controls, empty states, announcements, and required validation use Citry UI catalog messages by default. Any explicit *_label input belongs to the caller and does not switch with the Citry client locale.

Responsive layout and customization

The three-column layout stacks automatically in a narrow container and uses logical CSS properties for RTL. Customize the root and Items with class_, style, and attrs, or use the documented public variables and part selectors.

Customize Transfer List
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class TransferListCustomization(Component):
    template = """
      <c-CTransferList class_="brand-transfer" size="lg" c-value="['stable']">
        <c-CTransferListItem value="alpha" label="Alpha channel" />
        <c-CTransferListItem value="beta" label="Beta channel" />
        <c-CTransferListItem value="stable" label="Stable channel" />
      </c-CTransferList>
    """
    css = """
      .brand-transfer {
        --cui-transfer-list-selected: color-mix(in srgb, MediumPurple 25%, Canvas);
        --cui-transfer-list-focus: MediumPurple;
        --cui-transfer-list-radius: 1rem;
      }
    """


preview = TransferListCustomization()
preview  # noqa: B018

size changes the default list height. Forced colors preserve selected-state outlines, reduced-motion environments disable component motion, and print hides action controls while retaining both supplied panes.

Scope boundaries

This first family owns a complete finite server-rendered collection. It does not fetch, filter, virtualize, group into a tree, expose read-only mode, or provide drag and drop. Use CMultiSelect for compact selection and compose application state with CVirtualWindow when the collection cannot be fully rendered.

API reference

Inputs

CTransferList server inputs

Server inputs are passed in a template through <c-CTransferList ... /> or in Python through CTransferList(...).

InputTypeDefaultEffect
idstr | NonegeneratedSets the root ID and bases stable listbox and option IDs.
valueSequence[str]"()"Sets the ordered initial chosen values; every unique value must name one Item.
namestr | NoneNoneSets the repeated native form-entry name.
formstr | NoneNoneAssociates native and enhanced form values with an external Form ID.
requiredboolFalseRequires at least one chosen value.
disabledboolFalseDisables list selection controls and form contribution.
show_move_allboolTrueShows Add all and Remove all controls.
show_reorderboolTrueShows chosen-order controls.
sizeCTransferListSize (CTransferListSize)"md"Selects compact default or spacious list height.
available_labelstr"Available items"Overrides the localized available-pane title.
chosen_labelstr"Chosen items"Overrides the localized chosen-pane title and native fallback label.
available_empty_labelstr"No available items"Overrides the localized available empty state.
chosen_empty_labelstr"No chosen items"Overrides the localized chosen empty state.
count_labelstr"{selected} of {total} selected"Overrides pane counts and must retain both named placeholders.
transfer_controls_labelstr"Transfer controls"Overrides the transfer toolbar accessible name.
add_labelstr"Add selected"Overrides the Add selected action.
add_all_labelstr"Add all"Overrides the Add all action.
remove_labelstr"Remove selected"Overrides the Remove selected action.
remove_all_labelstr"Remove all"Overrides the Remove all action.
reorder_controls_labelstr"Chosen item order"Overrides the reorder toolbar accessible name.
move_top_labelstr"Move to top"Overrides the Move to top action.
move_up_labelstr"Move up"Overrides the Move up action.
move_down_labelstr"Move down"Overrides the Move down action.
move_bottom_labelstr"Move to bottom"Overrides the Move to bottom action.
added_labelstr"{count} items added"Overrides multi-item Add announcements and must retain count.
removed_labelstr"{count} items removed"Overrides multi-item Remove announcements and must retain count.
reordered_labelstr"{count} items reordered"Overrides multi-item reorder announcements and must retain count.
required_labelstr"Choose at least one item"Overrides the required-validation announcement.
class_CClassValue | None (CClassValue)NoneAdds classes to the root.
styleCStyleValue | None (CStyleValue)NoneAdds root styles before owned theme variables.
attrsMapping[str, object] | NoneNoneAdds copied allowed root attributes without replacing owned form semantics state or runtime markers.

CTransferList client inputs

Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CTransferList />.

InputTypeOmitted behaviorEffect
valuestring[] | nullOmission or null releases control to the committed value.Controls the exact ordered chosen values while supplied.
requiredbooleanUses the server value.Reactively changes required validity.
disabledbooleanUses the server and Fieldset state.Reactively disables interaction and form contribution.
onValueChangefunctionNo component callback runs.Receives transfer reorder and reset requests.

CTransferListItem server inputs

Server inputs are passed in a template through <c-CTransferListItem ... /> or in Python through CTransferListItem(...).

InputTypeDefaultEffect
valuestrrequiredSupplies nonempty unique stable identity and submitted value.
labelstrrequiredSupplies native fallback typeahead and accessible text.
disabledboolFalsePrevents selection transfer and reorder while preserving an initial chosen value.
class_CClassValue | None (CClassValue)NoneAdds classes to the enhanced Option.
styleCStyleValue | None (CStyleValue)NoneAdds styles to the enhanced Option.
attrsMapping[str, object] | NoneNoneAdds copied allowed Option attributes without replacing owned semantics identity or state.

Slots

Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.

CTransferList slots

SlotRequiredDataFallback
defaultno{} (CTransferListDefaultSlotData)Empty collection; accepts only CTransferListItem declarations.

CTransferListItem slots

SlotRequiredDataFallback
defaultno{value, label, disabled, in_target, index} (CTransferListItemDefaultSlotData)Plain label text.

Events

Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.

CTransferList events

EventSignatureTrigger and timingDetailControlled and cancellation behavior
onValueChange(value: string[], detail: CTransferListChangeDetail) => void (CTransferListChangeDetail)A transfer reorder reset or accepted client reconciliation requests another ordered value.{value, previousValue, moved, source, controlled, sourceEvent} (CTransferListChangeDetail)Uncontrolled state commits and emits native input/change first; controlled state is request-only until accepted.

Methods

-

CSS

CSS variables to theme the components. Set them on an ancestor or the component itself.

CTransferList CSS variables

Apply these variables to CTransferList or one of its ancestors.

VariableTypePurposeDefault
--cui-transfer-list-pane-sizelengthNative fallback and pane inline-size preference.15rem
--cui-transfer-list-list-sizelengthEnhanced listbox block size.sm 11rem; md 15rem; lg 20rem
--cui-transfer-list-gaplengthPane and control spacing.0.75rem
--cui-transfer-list-bordercomplete border valuePane control and Button borders.Adaptive 1px solid neutral
--cui-transfer-list-radiuslengthPane and native fallback corners.0.625rem
--cui-transfer-list-surfacecolorPane native fallback and Button surfaces.Canvas
--cui-transfer-list-selectedcolorSelected Option background.Adaptive blue
--cui-transfer-list-hovercolorHovered Option background.Adaptive neutral
--cui-transfer-list-focuscolorListbox and Button focus outline.Highlight
--cui-transfer-list-disabled-opacitynumberDisabled root Option and Button opacity.0.55

Attributes

HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.

CTransferList attributes

AttributeElementTypeMeaning
roleAvailable and chosen listbox divslistboxExposes each enhanced pane as a selectable collection.
aria-multiselectableBoth listboxestrueDeclares independent multi-selection.
aria-activedescendantFocused listboxIDREF | absentIdentifies the active Option while DOM focus remains on the listbox.
roleEnhanced Item divoptionExposes one declared choice.
aria-selectedEnhanced Item divboolean-stringReflects ephemeral pane selection rather than chosen membership.
aria-disabledRoot listboxes and disabled Itemsboolean-stringReflects effective unavailability.
aria-invalidRoottrue | absentMarks a failed required validity check.
data-valueEnhanced Item divstringExposes stable identity.
data-selectedEnhanced Item divpresent | absentReflects ephemeral pane selection.
data-disabledRoot and disabled Itemspresent | absentReflects effective unavailability.
data-requiredRootpresent | absentReflects required validity.
data-invalidRootpresent | absentReflects a failed native validity check.
data-sizeRootCTransferListSize (CTransferListSize)Mirrors list-height profile.
data-available-emptyRootpresent | absentMarks no available Items.
data-chosen-emptyRootpresent | absentMarks no chosen Items.

Selectors

Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.

CTransferList selectors

SelectorElementPurpose
[data-citry-ui-part="transfer-list"]Root divState reflections attrs and theme destination.
[data-citry-ui-part="native"]Native select multipleProgressive fallback validity reset and initial form owner.
[data-citry-ui-part="control"]Enhanced gridContains both panes and transfer controls.
[data-citry-ui-part="pane"]Available or chosen sectionPane surface.
[data-citry-ui-part="pane-header"]Pane headerGroups title and selection count.
[data-citry-ui-part="pane-title"]Pane h3Visible listbox label.
[data-citry-ui-part="count"]Count spanLocalized selected and total summary.
[data-citry-ui-part="listbox"]Pane listbox divFocus selection and Item-scroll owner.
[data-citry-ui-part="option"]Item divRich presentation selection and stable Item customization.
[data-citry-ui-part="empty"]Pane paragraphLocalized empty state.
[data-citry-ui-part="transfer-controls"]Transfer toolbarAdd and Remove actions.
[data-citry-ui-part="reorder-controls"]Reorder toolbarChosen-order actions.
[data-citry-ui-part="button"]Native action ButtonTransfer and reorder actions.
[data-citry-ui-part="status"]Visually hidden polite live regionAccepted action and validation announcements.

Interfaces

Aliases and data shapes referenced above.

Input type aliases

InterfaceDefinition
CTransferListSizeLiteral["sm", "md", "lg"]
CTransferListChangeSourceLiteral["add", "add-all", "remove", "remove-all", "move-top", "move-up", "move-down", "move-bottom", "reset", "client"]
CClassValuestr | Mapping[str, bool] | Sequence[CClassValue]
CStyleValuestr | Mapping[str, object] | Sequence[CStyleValue]

CTransferListDefaultSlotData

Empty dataclass: {}.

CTransferListItemDefaultSlotData

FieldTypeDefaultMeaning
valuestr-Stable declared Item value.
labelstr-Plain accessible and typeahead label.
disabledbool-Declared disabled state.
in_targetbool-Whether the Item is initially chosen.
indexint-Initial zero-based index in its pane.

CTransferListChangeDetail

FieldTypeDefaultMeaning
valuelist[str]-Requested or committed ordered chosen values.
previousValuelist[str]-Effective ordered chosen values before the request.
movedlist[str]-Values directly affected by the action in their action order.
sourceCTransferListChangeSource (CTransferListChangeSource)-Transfer reorder reset or client cause.
controlledbool-Whether client value currently owns chosen state.
sourceEventobject | None-Native source Event 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.

CTransferList translation keys

KeyPurposeVariablesOverrideBrowser updates
citry-ui-transfer-list-availableTitles the available pane.None.available_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-chosenTitles the chosen pane and native fallback.None.chosen_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-available-emptyDescribes an empty available pane.None.available_empty_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-chosen-emptyDescribes an empty chosen pane.None.chosen_empty_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-countSummarizes selected and total Items in one pane.selected: str; total: strcount_label with {selected} and {total}Two i18n.bind() registrations update when selection totals or locale change.
citry-ui-transfer-list-transfer-controlsNames the transfer toolbar.None.transfer_controls_labelStable $c-tr attribute follows client locale changes.
citry-ui-transfer-list-addLabels the Add selected action.None.add_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-add-allLabels the Add all action.None.add_all_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-removeLabels the Remove selected action.None.remove_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-remove-allLabels the Remove all action.None.remove_all_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-reorder-controlsNames the chosen-order toolbar.None.reorder_controls_labelStable $c-tr attribute follows client locale changes.
citry-ui-transfer-list-move-topLabels the Move to top action.None.move_top_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-move-upLabels the Move up action.None.move_up_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-move-downLabels the Move down action.None.move_down_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-move-bottomLabels the Move to bottom action.None.move_bottom_labelStable $c-tr text follows client locale changes.
citry-ui-transfer-list-added-oneAnnounces one accepted addition.None.added_label formats the fallbackOne-shot i18n.tr() writes the live region.
citry-ui-transfer-list-addedAnnounces multiple accepted additions.count: stradded_label with {count}One-shot i18n.tr() writes the live region.
citry-ui-transfer-list-removed-oneAnnounces one accepted removal.None.removed_label formats the fallbackOne-shot i18n.tr() writes the live region.
citry-ui-transfer-list-removedAnnounces multiple accepted removals.count: strremoved_label with {count}One-shot i18n.tr() writes the live region.
citry-ui-transfer-list-reordered-oneAnnounces one accepted reorder.None.reordered_label formats the fallbackOne-shot i18n.tr() writes the live region.
citry-ui-transfer-list-reorderedAnnounces multiple accepted reorders.count: strreordered_label with {count}One-shot i18n.tr() writes the live region.
citry-ui-transfer-list-requiredAnnounces failed required validity.None.required_labelOne-shot i18n.tr() writes the live region.