{
  "_copyright": "Copyright (c) 2026, Salesforce, Inc., All rights reserved. For full license text, see the LICENSE.txt file",
  "$schema": "https://slds.lightningdesignsystem.com/schemas/uif-foundation.v1.json",
  "apiVersion": "1.0.0",
  "name": "DuelingPicklist",
  "description": "A dueling-picklist is used to move options between two lists and is often referred to as a multi-select. Sometimes, the list options can then be re-ordered, depending on the use case.",
  "structure": {
    "name": "root",
    "restrict": [
      "fieldset",
      "div"
    ],
    "description": "Form-element wrapper carrying the group label, optional tooltip, optional required indicator, and the dueling-list control",
    "attributes": {
      "static": {
        "role": "group"
      },
      "bound": {
        "aria-labelledby": {
          "prop": "labelId",
          "required": true
        }
      }
    },
    "children": [
      {
        "name": "groupLabel",
        "restrict": [
          "span",
          "legend"
        ],
        "description": "Group label text shown above the two columns; pairs with `aria-labelledby` on the root",
        "slot": {
          "name": "groupLabel",
          "required": true
        },
        "children": [
          {
            "name": "requiredIndicator",
            "restrict": [
              "abbr"
            ],
            "description": "Required asterisk shown when the field is required",
            "renderWhen": {
              "prop": "required",
              "eq": "true"
            },
            "attributes": {
              "static": {
                "title": "required",
                "aria-hidden": "true"
              }
            }
          }
        ]
      },
      {
        "name": "tooltipTrigger",
        "restrict": [
          "div"
        ],
        "description": "Optional help-text trigger and tooltip popover associated with the group label",
        "renderWhen": "slotFilled",
        "children": [
          {
            "name": "tooltipButton",
            "restrict": [
              "button"
            ],
            "description": "Icon-only button that exposes the help tooltip",
            "attributes": {
              "bound": {
                "aria-describedby": {
                  "prop": "tooltipId",
                  "required": true
                }
              }
            },
            "children": [
              {
                "name": "tooltipButtonIcon",
                "description": "Help icon glyph",
                "component": "PrimitiveIcon"
              },
              {
                "name": "tooltipButtonAssistiveText",
                "restrict": [
                  "span"
                ],
                "description": "Visually hidden label for the help button",
                "slot": {
                  "name": "tooltipButtonAssistiveText"
                }
              }
            ]
          },
          {
            "name": "tooltipPopover",
            "restrict": [
              "div"
            ],
            "description": "Tooltip popover anchored to the help button",
            "attributes": {
              "static": {
                "role": "tooltip"
              },
              "bound": {
                "id": {
                  "prop": "tooltipId",
                  "required": true
                }
              }
            },
            "children": [
              {
                "name": "tooltipBody",
                "restrict": [
                  "div"
                ],
                "description": "Tooltip body text",
                "slot": {
                  "name": "tooltipBody",
                  "required": true
                }
              }
            ]
          }
        ]
      },
      {
        "name": "control",
        "restrict": [
          "div"
        ],
        "description": "Form-element control region that wraps the dueling list (or the static value in view mode)",
        "children": [
          {
            "name": "viewModeValue",
            "restrict": [
              "span"
            ],
            "description": "Read-only comma-separated list of selected values rendered in place of the dueling list",
            "renderWhen": {
              "prop": "mode",
              "eq": "view"
            },
            "slot": {
              "name": "viewModeValue",
              "required": true
            }
          },
          {
            "name": "duelingList",
            "restrict": [
              "div"
            ],
            "description": "Dueling-list container with the two columns, the move-button column, and live regions",
            "renderWhen": {
              "prop": "mode",
              "eq": "edit"
            },
            "children": [
              {
                "name": "dragLiveRegion",
                "restrict": [
                  "div"
                ],
                "description": "Assertive live region used to announce drag-and-drop movements",
                "attributes": {
                  "static": {
                    "aria-live": "assertive"
                  },
                  "bound": {
                    "id": {
                      "prop": "liveRegionId",
                      "required": true
                    }
                  }
                },
                "slot": {
                  "name": "dragLiveRegion"
                }
              },
              {
                "name": "dragInstructions",
                "restrict": [
                  "div"
                ],
                "description": "Visually hidden keyboard-instruction text referenced by each listbox via aria-describedby",
                "attributes": {
                  "bound": {
                    "id": {
                      "prop": "instructionsId",
                      "required": true
                    }
                  }
                },
                "slot": {
                  "name": "dragInstructions"
                }
              },
              {
                "name": "sourceList",
                "restrict": [
                  "div"
                ],
                "description": "Source column containing the source label and source listbox",
                "children": [
                  {
                    "name": "sourceLabel",
                    "restrict": [
                      "span"
                    ],
                    "description": "Label for the source listbox",
                    "attributes": {
                      "bound": {
                        "id": {
                          "prop": "sourceLabelId",
                          "required": true
                        }
                      }
                    },
                    "slot": {
                      "name": "sourceLabel",
                      "required": true
                    }
                  },
                  {
                    "name": "sourceListboxWrapper",
                    "restrict": [
                      "div"
                    ],
                    "description": "Visual wrapper around the source listbox; receives the disabled state class when the picklist is disabled",
                    "children": [
                      {
                        "name": "sourceListbox",
                        "restrict": [
                          "ul"
                        ],
                        "description": "Source listbox of options",
                        "attributes": {
                          "static": {
                            "role": "listbox",
                            "aria-multiselectable": "true"
                          },
                          "bound": {
                            "aria-labelledby": {
                              "prop": "sourceLabelId",
                              "required": true
                            },
                            "aria-describedby": {
                              "prop": "instructionsId",
                              "required": true
                            }
                          }
                        },
                        "children": [
                          {
                            "name": "sourceOptionItem",
                            "restrict": [
                              "li"
                            ],
                            "description": "List item wrapping each option; role='presentation' so the option div is the ARIA leaf",
                            "repeats": true,
                            "attributes": {
                              "static": {
                                "role": "presentation"
                              }
                            },
                            "slot": {
                              "name": "sourceOptions",
                              "required": true
                            },
                            "children": [
                              {
                                "name": "sourceOption",
                                "restrict": [
                                  "div"
                                ],
                                "description": "Selectable option; pairs the option role with aria-selected and (when locked) aria-disabled",
                                "attributes": {
                                  "static": {
                                    "role": "option"
                                  },
                                  "bound": {
                                    "aria-selected": {
                                      "prop": "selected",
                                      "required": true
                                    },
                                    "draggable": {
                                      "prop": "draggable",
                                      "required": true
                                    },
                                    "tabindex": {
                                      "prop": "tabindex",
                                      "required": true
                                    }
                                  },
                                  "conditional": {
                                    "aria-disabled": {
                                      "when": "locked",
                                      "value": "true"
                                    }
                                  }
                                },
                                "children": [
                                  {
                                    "name": "sourceOptionBody",
                                    "restrict": [
                                      "span"
                                    ],
                                    "description": "Option text container",
                                    "children": [
                                      {
                                        "name": "sourceOptionLabel",
                                        "restrict": [
                                          "span"
                                        ],
                                        "description": "Truncated option label",
                                        "slot": {
                                          "name": "sourceOptionLabel",
                                          "required": true
                                        }
                                      }
                                    ]
                                  },
                                  {
                                    "name": "sourceOptionFigure",
                                    "restrict": [
                                      "span"
                                    ],
                                    "description": "Trailing media figure used to host the lock icon for locked options",
                                    "renderWhen": {
                                      "prop": "locked",
                                      "eq": "true"
                                    },
                                    "children": [
                                      {
                                        "name": "sourceOptionLockIconContainer",
                                        "restrict": [
                                          "span"
                                        ],
                                        "description": "Icon container for the lock glyph",
                                        "attributes": {
                                          "static": {
                                            "title": "Locked item"
                                          }
                                        },
                                        "children": [
                                          {
                                            "name": "sourceOptionLockIcon",
                                            "description": "Lock icon glyph",
                                            "component": "PrimitiveIcon"
                                          },
                                          {
                                            "name": "sourceOptionLockAssistiveText",
                                            "restrict": [
                                              "span"
                                            ],
                                            "description": "Visually hidden description of why the option is locked",
                                            "slot": {
                                              "name": "sourceOptionLockAssistiveText"
                                            }
                                          }
                                        ]
                                      }
                                    ]
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              },
              {
                "name": "moveButtons",
                "restrict": [
                  "div"
                ],
                "description": "Column hosting the buttons that move selections between the two lists",
                "children": [
                  {
                    "name": "moveRightButton",
                    "restrict": [
                      "button"
                    ],
                    "description": "Moves the selection from the source list to the selected list",
                    "children": [
                      {
                        "name": "moveRightIcon",
                        "description": "Right-arrow icon glyph",
                        "component": "PrimitiveIcon"
                      },
                      {
                        "name": "moveRightAssistiveText",
                        "restrict": [
                          "span"
                        ],
                        "description": "Visually hidden label for the move-right button",
                        "slot": {
                          "name": "moveRightAssistiveText"
                        }
                      }
                    ]
                  },
                  {
                    "name": "moveLeftButton",
                    "restrict": [
                      "button"
                    ],
                    "description": "Moves the selection from the selected list back to the source list",
                    "children": [
                      {
                        "name": "moveLeftIcon",
                        "description": "Left-arrow icon glyph",
                        "component": "PrimitiveIcon"
                      },
                      {
                        "name": "moveLeftAssistiveText",
                        "restrict": [
                          "span"
                        ],
                        "description": "Visually hidden label for the move-left button",
                        "slot": {
                          "name": "moveLeftAssistiveText"
                        }
                      }
                    ]
                  }
                ]
              },
              {
                "name": "selectedList",
                "restrict": [
                  "div"
                ],
                "description": "Selected column containing the selected label and selected listbox",
                "children": [
                  {
                    "name": "selectedLabel",
                    "restrict": [
                      "span"
                    ],
                    "description": "Label for the selected listbox",
                    "attributes": {
                      "bound": {
                        "id": {
                          "prop": "selectedLabelId",
                          "required": true
                        }
                      }
                    },
                    "slot": {
                      "name": "selectedLabel",
                      "required": true
                    }
                  },
                  {
                    "name": "selectedListboxWrapper",
                    "restrict": [
                      "div"
                    ],
                    "description": "Visual wrapper around the selected listbox; receives the disabled state class when the picklist is disabled",
                    "children": [
                      {
                        "name": "selectedListbox",
                        "restrict": [
                          "ul"
                        ],
                        "description": "Selected listbox of options",
                        "attributes": {
                          "static": {
                            "role": "listbox",
                            "aria-multiselectable": "true"
                          },
                          "bound": {
                            "aria-labelledby": {
                              "prop": "selectedLabelId",
                              "required": true
                            },
                            "aria-describedby": {
                              "prop": "instructionsId",
                              "required": true
                            }
                          }
                        },
                        "children": [
                          {
                            "name": "selectedOptionItem",
                            "restrict": [
                              "li"
                            ],
                            "description": "List item wrapping each selected option; role='presentation' so the option div is the ARIA leaf",
                            "repeats": true,
                            "attributes": {
                              "static": {
                                "role": "presentation"
                              }
                            },
                            "slot": {
                              "name": "selectedOptions",
                              "required": true
                            },
                            "children": [
                              {
                                "name": "selectedOption",
                                "restrict": [
                                  "div"
                                ],
                                "description": "Selectable option; pairs the option role with aria-selected and (when locked) aria-disabled",
                                "attributes": {
                                  "static": {
                                    "role": "option"
                                  },
                                  "bound": {
                                    "aria-selected": {
                                      "prop": "selected",
                                      "required": true
                                    },
                                    "draggable": {
                                      "prop": "draggable",
                                      "required": true
                                    },
                                    "tabindex": {
                                      "prop": "tabindex",
                                      "required": true
                                    }
                                  },
                                  "conditional": {
                                    "aria-disabled": {
                                      "when": "locked",
                                      "value": "true"
                                    }
                                  }
                                },
                                "children": [
                                  {
                                    "name": "selectedOptionBody",
                                    "restrict": [
                                      "span"
                                    ],
                                    "description": "Option text container",
                                    "children": [
                                      {
                                        "name": "selectedOptionLabel",
                                        "restrict": [
                                          "span"
                                        ],
                                        "description": "Truncated option label",
                                        "slot": {
                                          "name": "selectedOptionLabel",
                                          "required": true
                                        }
                                      }
                                    ]
                                  },
                                  {
                                    "name": "selectedOptionFigure",
                                    "restrict": [
                                      "span"
                                    ],
                                    "description": "Trailing media figure used to host the lock icon for locked options",
                                    "renderWhen": {
                                      "prop": "locked",
                                      "eq": "true"
                                    },
                                    "children": [
                                      {
                                        "name": "selectedOptionLockIconContainer",
                                        "restrict": [
                                          "span"
                                        ],
                                        "description": "Icon container for the lock glyph",
                                        "attributes": {
                                          "static": {
                                            "title": "Locked item"
                                          }
                                        },
                                        "children": [
                                          {
                                            "name": "selectedOptionLockIcon",
                                            "description": "Lock icon glyph",
                                            "component": "PrimitiveIcon"
                                          },
                                          {
                                            "name": "selectedOptionLockAssistiveText",
                                            "restrict": [
                                              "span"
                                            ],
                                            "description": "Visually hidden description of why the option is locked",
                                            "slot": {
                                              "name": "selectedOptionLockAssistiveText"
                                            }
                                          }
                                        ]
                                      }
                                    ]
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              },
              {
                "name": "reorderButtons",
                "restrict": [
                  "div"
                ],
                "description": "Optional column hosting the buttons that reorder items within the selected list",
                "renderWhen": {
                  "prop": "reorderable",
                  "eq": "true"
                },
                "children": [
                  {
                    "name": "moveUpButton",
                    "restrict": [
                      "button"
                    ],
                    "description": "Moves the selection up within its list",
                    "children": [
                      {
                        "name": "moveUpIcon",
                        "description": "Up-arrow icon glyph",
                        "component": "PrimitiveIcon"
                      },
                      {
                        "name": "moveUpAssistiveText",
                        "restrict": [
                          "span"
                        ],
                        "description": "Visually hidden label for the move-up button",
                        "slot": {
                          "name": "moveUpAssistiveText"
                        }
                      }
                    ]
                  },
                  {
                    "name": "moveDownButton",
                    "restrict": [
                      "button"
                    ],
                    "description": "Moves the selection down within its list",
                    "children": [
                      {
                        "name": "moveDownIcon",
                        "description": "Down-arrow icon glyph",
                        "component": "PrimitiveIcon"
                      },
                      {
                        "name": "moveDownAssistiveText",
                        "restrict": [
                          "span"
                        ],
                        "description": "Visually hidden label for the move-down button",
                        "slot": {
                          "name": "moveDownAssistiveText"
                        }
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "states": [
    {
      "name": "required",
      "type": "boolean",
      "description": "Whether the dueling picklist must have a value before submission"
    },
    {
      "name": "disabled",
      "type": "boolean",
      "aria": "aria-disabled",
      "description": "Whether the dueling picklist is disabled"
    },
    {
      "name": "itemDisabled",
      "type": "boolean",
      "aria": "aria-disabled",
      "description": "Whether an individual option is locked and cannot be moved"
    },
    {
      "name": "grabbed",
      "type": "boolean",
      "description": "Whether an option is currently being dragged"
    },
    {
      "name": "itemSelected",
      "type": "boolean",
      "aria": "aria-selected",
      "description": "Whether a list option is selected"
    }
  ],
  "accessibility": {
    "requirements": [
      {
        "id": "group-role",
        "description": "The form-element wrapper carries role='group' with aria-labelledby pointing at the group label"
      },
      {
        "id": "listbox-role",
        "description": "Both lists carry role='listbox' with aria-multiselectable='true'"
      },
      {
        "id": "option-role",
        "description": "Each option carries role='option' and an aria-selected value, with its parent <li> using role='presentation'"
      },
      {
        "id": "drag-live-region",
        "description": "An aria-live='assertive' region announces drag-and-drop progress; both listboxes reference a hidden instruction node via aria-describedby"
      },
      {
        "id": "multi-select",
        "description": "Lists support multi-select with Shift+click and the keyboard drag interactions described by the instructions node"
      }
    ]
  },
  "componentRefs": {
    "PrimitiveIcon": {
      "description": "Bare SVG icon composed directly inside the component. The host node supplies the SVG class (e.g. slds-button__icon, slds-menu__item-icon) via componentProps; PrimitiveIcon contributes the sprite-href binding.",
      "props": {
        "iconName": {
          "type": "string",
          "required": true,
          "description": "Sprite reference for the icon glyph"
        }
      }
    }
  }
}
