feat(list): drag and drop reordering (#DS-4454) - #1911
Conversation
Options of `kbq-list-selection` can be reordered by dragging or with `Alt` + arrow keys once `draggable` is set, and moved between lists connected via `connectedTo`. The list never mutates the projected data: it reports the move through the `dropped` event and the consumer applies it. The new position is announced to assistive tech only once that move has actually been applied, and `aria-keyshortcuts` advertises the keyboard alternative to dragging. Dragging inside `kbq-optgroup` or `cdk-virtual-scroll-viewport` reports indices that do not address the backing array, so both now warn in development mode.
There was a problem hiding this comment.
Pull request overview
Adds opt-in drag-and-drop (and keyboard) reordering/transfer for kbq-list-selection, including accessible announcements and documentation/examples, while keeping the list “data-immutable” (consumer applies reorders based on a dropped event).
Changes:
- Introduces
draggable,connectedTo, anddroppedonKbqListSelection, plus keyboard reordering/transfer viaAlt+ arrow keys and live-region announcements. - Adds styling for drag preview/placeholder/animations and updates a11y locale strings to support move announcements.
- Adds docs examples, dev-app demos, and unit/e2e coverage for drag/drop + keyboard flows.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/public_api_guard/components/list.api.md | Public API snapshot updated for new list drag/drop inputs/outputs and types. |
| tools/public_api_guard/components/core.api.md | Public API snapshot updated for new a11y locale key (listOptionMoved). |
| packages/e2e/routes.ts | Registers new list drag-and-drop E2E route/component. |
| packages/docs-examples/example-module.ts | Adds new live examples entries for draggable list variants. |
| packages/docs-examples/components/list/list-draggable/list-draggable-example.ts | New docs example: in-list reordering via dropped. |
| packages/docs-examples/components/list/list-draggable-connected/list-draggable-connected-example.ts | New docs example: transferring options between connected lists. |
| packages/docs-examples/components/list/index.ts | Exports and registers the new list draggable examples module-side. |
| packages/components/list/list.scss | Adds drag/drop interaction styling (placeholder, preview, cursor, transitions). |
| packages/components/list/list.ru.md | Documents draggable lists + keyboard shortcuts (RU). |
| packages/components/list/list.en.md | Documents draggable lists + keyboard shortcuts (EN). |
| packages/components/list/list-tokens.scss | Adds tokens for drag preview surface/shadow; ensures preview inherits tokens in <body>. |
| packages/components/list/list-selection.component.ts | Core implementation: CDK drag/drop wiring, keyboard move/transfer, dropped event, live-region announcements, dev warnings. |
| packages/components/list/list-selection.component.spec.ts | Unit + axe coverage for drag/drop opt-in, keyboard behavior, announcements, and shortcuts. |
| packages/components/list/e2e.ts | Adds E2E fixture component with two connected draggable lists and consumer-applied reorder/transfer. |
| packages/components/list/e2e.playwright-spec.ts | Adds Playwright coverage for pointer drag, keyboard reorder/transfer, and transition settling behavior. |
| packages/components/core/locales/types.ts | Extends KbqA11yLocaleConfiguration with listOptionMoved announcement template. |
| packages/components/core/locales/tk-TM.ts | Adds listOptionMoved locale string (tk-TM). |
| packages/components/core/locales/ru-RU.ts | Adds listOptionMoved locale string (ru-RU). |
| packages/components/core/locales/pt-BR.ts | Adds listOptionMoved locale string (pt-BR). |
| packages/components/core/locales/es-LA.ts | Adds listOptionMoved locale string (es-LA). |
| packages/components/core/locales/en-US.ts | Adds listOptionMoved locale string (en-US). |
| packages/components-dev/list/template.html | Adds dev-app demos for draggable reorder and connected transfer. |
| packages/components-dev/list/module.ts | Wires demo data + handlers for the new draggable behaviors in dev app. |
Suppressed comments (1)
packages/components/list/list-selection.component.ts:814
- To ensure unsupported-container warnings are emitted when
draggablebecomes enabled after initial render (e.g. dynamic bindings), callwarnOnUnsupportedDragContainer()fromsyncDraggableState(), which already runs whendraggable/disabledchange.
/** Keeps the underlying CDK directives in sync with the resolved `draggable` state. */
private syncDraggableState(): void {
this.dropList.disabled = !this.draggable;
this.options?.forEach((option) => option.syncDraggableState());
this.changeDetectorRef.markForCheck();
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| /** | ||
| * Data attached to the underlying `CdkDrag` while a list option is being dragged. | ||
| * | ||
| * @docs-private | ||
| */ | ||
| export type KbqListOptionDragData = { option: KbqListOption }; | ||
|
|
| private warnOnUnsupportedDragContainer(): void { | ||
| if (!isDevMode() || !this.draggable) { | ||
| return; | ||
| } |
|
Visit the preview URL for this PR (updated for commit e6fbf46): https://koobiq-next--prs-1911-o55jwo31.web.app (expires Fri, 21 Aug 2026 10:22:02 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: c9e37e518febda70d0317d07e8ceb35ac43c534c |
`KbqListOptionDragData` is only read inside the component file, so it no longer leaves the package and no longer widens the public API surface. `warnOnUnsupportedDragContainer()` now also runs from `syncDraggableState()`, so enabling `draggable` after the initial render still warns. It tolerates being called before the content children exist and reports each list only once.
Options of
kbq-list-selectioncan be reordered by dragging or withAlt+ arrow keys oncedraggableis set, and moved between lists connected viaconnectedTo.The list never mutates the projected data: it reports the move through the
droppedevent and the consumer applies it. The new position is announced to assistive tech only once that move has actually been applied, andaria-keyshortcutsadvertises the keyboard alternative to dragging.Dragging inside
kbq-optgrouporcdk-virtual-scroll-viewportreports indices that do not address the backing array, so both now warn in development mode.