Skip to content

Conversation

@vnbaaij
Copy link
Collaborator

@vnbaaij vnbaaij commented Jan 27, 2026

This pull request introduces a new FluentSortableList component for Blazor Fluent UI, providing a drag-and-drop sortable list powered by SortableJS. The update includes the component implementation, JavaScript interop, documentation, and a comprehensive set of usage examples demonstrating sorting, moving, cloning, filtering, disabling, drag handles, and fallback behaviors.

Although SortableJS does not come with a11y support, we enhanced the FluentSortableList component to support keyboard accessibility. Users can navigate through the list items using the arrow up/down keys. An item can be grabbed and released by using the space bar or pressing enter. A grabbed item can then be moved in the list with the arrow up and down keys.

The component also provides appropriate ARIA attributes to enhance screen reader support.

sortablelist_a11y

The most important changes are:

Component Implementation and Integration

  • Added the generic FluentSortableList Blazor component, which renders a sortable list using a provided ItemTemplate and exposes event hooks for sorting and moving items. (FluentSortableList.razor)
  • Introduced JavaScript interop with SortableJS to handle drag-and-drop operations, group management, filtering, cloning, drag handles, and fallback mode, and to synchronize DOM changes with Blazor state. (FluentSortableList.ts)
  • Declared sortablejs as a new dependency in the project. (package.json)

Documentation

  • Added thorough documentation for the new component, including usage instructions, integration steps, and detailed explanations of all parameters and events. (FluentSortableList.md)

Examples and Demos

  • Added multiple example .razor files showcasing different use cases:
    • Basic sortable list
    • Moving items between lists
    • Cloning items across lists
    • Disabling sorting and restricting drop targets
    • Drag handles for item reordering
    • Filtering draggable items
    • Fallback (non-HTML5) drag-and-drop mode

Minor Improvements

  • Added a pragma to suppress an analyzer warning in the data grid component to allow synchronous disposal. (FluentDataGrid.razor.cs)


@if (ItemTemplate is not null)
{
<div @ref="@_element" id="@Id" class="@ClassValue" style="@StyleValue">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should add AdditionalAttributes

/// Gets or sets the list of items to be displayed in a sortable list.
/// </summary>
[Parameter, AllowNull]
public IEnumerable<TItem> Items { get; set; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this allows null should it be IEnumerable<TItem>? instead?

/// Gets or sets whether elements are cloned instead of moved. Set Pull to "clone" to enable this.
/// </summary>
[Parameter]
public bool Clone { get; set; } = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false is the default value and don't need to be specified

/// Set to true to use an element with classname `.sortable-grab` as the handle.
/// </summary>
[Parameter]
public bool Handle { get; set; } = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false is the default value and don't need to be specified

/// Gets or sets the border width on the list. Must be a valid CSS measurement.
/// </summary>
[Parameter]
public string? ListBorderWidth { get; set; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about all of this parameters for changing basic CSS. What do you think @dvoituron ?

/// <summary />
protected override async Task OnAfterRenderAsync(bool firstRender)
{

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

public bool Disabled { get; set; } = false;
}

public List<Item> items1 = Enumerable.Range(1, 10).Select(i => new Item { Id = i, Name = $"Item {i}" }).ToList();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should remove public and private from the demos to keep them lighter and be consistent with the other demos

@github-actions
Copy link

github-actions bot commented Feb 2, 2026

Unit Tests

  • ❌[FAILED] Microsoft.FluentUI.AspNetCore.Components.Tests.Components.SortableList.FluentSortableListTests.FluentSortableList_ItemFilter
  • ❌[FAILED] Microsoft.FluentUI.AspNetCore.Components.Tests.Components.SortableList.FluentSortableListTests.FluentSortableList_IdIsAdded
  • ❌[FAILED] Microsoft.FluentUI.AspNetCore.Components.Tests.Components.SortableList.FluentSortableListTests.FluentSortableList_Default

Details on your Workflow / Core Tests page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants