Skip to content

feat: Support Drag-and-Drop Reordering in SidebarItems #590

Description

@ghchinoy

Is your feature request related to a problem? Please describe.

When building complex macOS applications using macos_ui, it's convenient to allow users to manually reorder items in the Sidebar (e.g., reordering a list of projects, favorites, or folders) via drag-and-drop. This is a core macOS HIG pattern seen in Finder, Mail, and Messages.

Currently, the SidebarItems widget strictly requires a List<SidebarItem>. Because of this strict typing, developers cannot wrap a SidebarItem in standard Flutter drag-and-drop widgets like DragTarget, LongPressDraggable, or use ReorderableListView.

The rigid typing is explicitly defined in sidebar_items.dart line 59:

final List<SidebarItem> items;

If a developer attempts to wrap a SidebarItem to add reordering logic, the Dart analyzer throws:
The argument type 'Widget' can't be assigned to the parameter type 'SidebarItem'.

Describe the solution you'd like

There are two potential ways to solve this natively within the library:

Option 1: Relax the Type Signature (The Flexible Approach)
Change final List<SidebarItem> items; to final List<Widget> items; within SidebarItems.
This would allow developers to seamlessly wrap SidebarItem instances in whatever interaction detectors or DragTargets they need without breaking the visual styling of the internal _SidebarItem renderer.

Option 2: Native Reorderable Support (The "Batteries Included" Approach)
Implement a built-in callback inside SidebarItems (e.g., onReorder: (int oldIndex, int newIndex)) that automatically handles the internal Draggable and DragTarget logic, rendering the native macOS blue horizontal insertion line during the drag state.

Describe alternatives you've considered

  • Option 3: Developers can completely abandon SidebarItems and build a custom ReorderableListView inside the Sidebar, but this sacrifices the pixel-perfect HIG typography, spacing, and accent color states provided by macos_ui.
  • Option 4: Adding a Widget? wrapper builder parameter to the SidebarItem class itself so developers can inject interaction logic without changing the root list type.

Update: Internal Implementation Discovery

While attempting to implement Option 2 within a local fork, we discovered that wrapping a _SidebarItem inside a ReorderableDragStartListener accidentally triggers the internal FocusableActionDetector inside _SidebarItem.build. This causes the macOS layout engine to interpret the dragging state as a permanent "hover/focus" state, resulting in a solid unselectedColor (or selectedColor) block being drawn across the entire width of the sidebar (masking the transparent MacosWindow background).

If Option 2 is implemented natively, the _SidebarItem will need to be refactored to ensure its FocusableActionDetector gracefully ignores or yields to the outer Drag state so it doesn't draw phantom bounding boxes during a drag.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions