-
Notifications
You must be signed in to change notification settings - Fork 468
[dev-v5][DataGrid] Add pinned (sticky/frozen) column support #4671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
13
commits into
dev-v5
Choose a base branch
from
copilot/research-fluentdatagrid-implementation
base: dev-v5
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 11 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
7263ea1
feat: add pinned (sticky) column support to FluentDataGrid
Copilot e1acae8
chore: remove Core.Scripts build artifact and add .gitignore for obj/
Copilot 3040afb
chore: remove tracked Core.Scripts build artifact
Copilot dfec835
chore: start datagrid header layering fix
Copilot b0dcbdd
fix: move datagrid header popup z-index to menu layer
Copilot 4f21ed9
test: update datagrid snapshot expectations
Copilot 3ef8bb9
chore: start pinned resize min-width fix
Copilot f97c2c8
fix: preserve pinned column min-width on resize
Copilot ea97c1a
Example adjustments and CSS tweaks
vnbaaij 20196b9
refactor: avoid repeated computed style lookup for min width
Copilot cc6a697
Update docs
vnbaaij 71f59ba
Delete .gitignore
vnbaaij 3787a2a
Merge branch 'dev-v5' into copilot/research-fluentdatagrid-implementa…
vnbaaij File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
...uentUI.Demo.Client/Documentation/Components/DataGrid/Examples/DataGridPinnedColumns.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| <div style="overflow-x: auto;"> | ||
| <FluentDataGrid Items="@employees" | ||
| Style="min-width: max-content;" | ||
| StripedRows="true" | ||
| ResizableColumns="true" | ||
| DisplayMode="DataGridDisplayMode.Grid"> | ||
| <PropertyColumn Title="ID" Property="@(e => e.Id)" Width="100px" Pin="DataGridColumnPin.Left" Sortable="true" /> | ||
| <PropertyColumn Title="Full Name" Property="@(e => e.FullName)" Width="160px" Pin="DataGridColumnPin.Left" Sortable="true" /> | ||
| <PropertyColumn Title="Department" Property="@(e => e.Department)" Sortable="true" /> | ||
| <PropertyColumn Title="Location" Property="@(e => e.Location)" Sortable="true" /> | ||
| <PropertyColumn Title="Start Date" Property="@(e => e.StartDate)" Sortable="true" /> | ||
| <PropertyColumn Title="Salary" Property="@(e => e.Salary)" Width="120px" Sortable="true" Align="DataGridCellAlignment.End" /> | ||
| <TemplateColumn Title="Actions" Width="120px" Pin="DataGridColumnPin.Right"> | ||
| <FluentButton IconStart="@(new Icons.Regular.Size16.Edit())" Appearance="ButtonAppearance.Subtle" Title="Edit" @onclick="@(() => selectedName = context.FullName + " (edit)")" /> | ||
| <FluentButton IconStart="@(new Icons.Regular.Size16.Delete())" Appearance="ButtonAppearance.Subtle" Title="Delete" @onclick="@(() => selectedName = context.FullName + " (delete)")" /> | ||
| </TemplateColumn> | ||
| </FluentDataGrid> | ||
| </div> | ||
|
|
||
| @if (!string.IsNullOrEmpty(selectedName)) | ||
| { | ||
| <p style="margin-top: 1rem;">Last action: <strong>@selectedName</strong></p> | ||
| } | ||
|
|
||
| @code { | ||
| string selectedName = string.Empty; | ||
|
|
||
| record Employee(int Id, string FullName, string Department, string Location, string StartDate, string Salary); | ||
|
|
||
| IQueryable<Employee> employees = new[] | ||
| { | ||
| new Employee(1, "Denis Voituron", "Engineering", "Brussels", "2019-03-01", "$120,000"), | ||
| new Employee(2, "Vincent Baaij", "Engineering", "Amsterdam", "2018-07-15", "$130,000"), | ||
| new Employee(3, "Harry Mars", "Executive", "Medina", "1975-04-04", "$1,000,000"), | ||
| new Employee(4, "Bruno Styles", "Executive", "Bellevue", "1992-02-17", "$950,000"), | ||
| new Employee(5, "Taylor Eilish", "Developer Relations", "Portland", "2007-01-22", "$200,000"), | ||
| new Employee(6, "Billie Swift", "Languages", "Seattle", "2005-08-01", "$180,000"), | ||
| new Employee(7, "Jacky Bond", "Framework", "Seattle", "2010-06-14", "$190,000"), | ||
| new Employee(8, "James Chan", "Framework", "Cambridge", "2009-03-30", "$185,000"), | ||
| new Employee(9, "John Cage", "Community", "San Diego", "2011-11-01", "$160,000"), | ||
| new Employee(10, "Nick Travolta", "Engineering", "New York", "2016-05-20", "$155,000"), | ||
| }.AsQueryable(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
...emo.Client/Documentation/Components/DataGrid/Pages/DataGridPinnedColumnsPage.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| --- | ||
| title: Pinned columns | ||
| order: 0095 | ||
| route: /DataGrid/PinnedColumns | ||
| --- | ||
|
|
||
| # Pinned columns | ||
|
|
||
| Columns can be pinned (frozen) to the left or right edge of the grid so that they remain visible | ||
| while the user scrolls horizontally through wider datasets. | ||
|
|
||
| ## Parameters | ||
|
|
||
| Set the `Pin` parameter on any `PropertyColumn` or `TemplateColumn`: | ||
|
|
||
| | Value | Behavior | | ||
| |---|---| | ||
| | `DataGridColumnPin.None` | Default — column scrolls normally | | ||
| | `DataGridColumnPin.Left` | Column stays anchored to the left edge | | ||
| | `DataGridColumnPin.Right` | Column stays anchored to the right edge | | ||
|
|
||
| ## Rules | ||
|
|
||
| * **Explicit pixel width required.** Every pinned column must declare a `Width` in pixels | ||
| (e.g. `Width="150px"`). Relative units (`fr`, `%`) are not supported because the browser cannot | ||
| determine a fixed sticky offset from them at render time. | ||
| * **Left-pinned columns must be contiguous at the start.** Each left-pinned column must | ||
| immediately follow another left-pinned column, or be the very first column. | ||
| * **Right-pinned columns must be contiguous at the end.** Each right-pinned column must | ||
| immediately precede another right-pinned column, or be the very last column. | ||
| * Violating any of these rules throws an `ArgumentException` with a descriptive message. | ||
|
|
||
| ## Scrollable container | ||
|
|
||
| Sticky positioning only activates inside a scrollable ancestor. Wrap the grid in a container with | ||
| `overflow-x: auto` and give the grid `Style="min-width: max-content;"` so that a horizontal scroll | ||
| bar appears when columns overflow the container: | ||
|
|
||
| ```razor | ||
| <div style="overflow-x: auto;"> | ||
| <FluentDataGrid Items="@employees" Style="min-width: max-content;"> | ||
| <PropertyColumn Title="ID" Property="@(e => e.Id)" Width="60px" Pin="DataGridColumnPin.Left" /> | ||
| <PropertyColumn Title="Name" Property="@(e => e.Name)" Width="160px" Pin="DataGridColumnPin.Left" /> | ||
| <PropertyColumn Title="City" Property="@(e => e.City)" /> | ||
| <TemplateColumn Title="Actions" Width="120px" Pin="DataGridColumnPin.Right"> | ||
| ... | ||
| </TemplateColumn> | ||
| </FluentDataGrid> | ||
| </div> | ||
| ``` | ||
|
|
||
| ## Theming the pinned background | ||
|
|
||
| Pinned cells receive a solid background to prevent scrolling content from showing through. The | ||
| color defaults to `--colorNeutralBackground1` and can be overridden per-grid with the CSS custom | ||
| property `--fluent-data-grid-pinned-background`: | ||
|
|
||
| ```css | ||
| .my-grid { | ||
| --fluent-data-grid-pinned-background: var(--colorNeutralBackground2); | ||
| } | ||
| ``` | ||
|
|
||
| ## Notes | ||
|
|
||
| * Column resizing interacts correctly with sticky offsets — the JavaScript in | ||
| `FluentDataGrid.razor.ts` recalculates `left` / `right` values after every resize step via | ||
| `UpdatePinnedColumnOffsets`. | ||
| * Virtualization and paging are fully compatible because each rendered row's cells carry the | ||
| same `position: sticky` styling regardless of which page or scroll position is active. | ||
| * In RTL layouts the browser interprets `left` / `right` according to the document direction, so | ||
| pinned columns behave correctly without additional configuration. | ||
|
|
||
| ## Example | ||
|
|
||
| Demonstrates pinned (frozen) columns using `Pin="DataGridColumnPin.Left"` and `Pin="DataGridColumnPin.Right"`. | ||
| The two leftmost columns and the Actions column remain visible while the rest scroll horizontally. | ||
|
|
||
| Wrap the grid in a `<div style="overflow-x: auto;">` container and give the grid a `Style="min-width: max-content;"` | ||
| so that the horizontal scroll bar appears. | ||
|
|
||
| Pinned columns require an explicit pixel `Width`. | ||
|
|
||
| {{ DataGridPinnedColumns }} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| obj/ | ||
vnbaaij marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -187,6 +187,23 @@ public abstract partial class ColumnBase<TGridItem> | |
| [Parameter] | ||
| public string? Width { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets whether this column is pinned (frozen) to the left or right edge of the grid, | ||
| /// so it remains visible when the user scrolls horizontally. | ||
| /// Pinned columns require an explicit <see cref="Width"/> in pixels (e.g., <c>"150px"</c>). | ||
| /// Left-pinned columns must be contiguous at the start of the column list; | ||
| /// right-pinned columns must be contiguous at the end. | ||
| /// </summary> | ||
| [Parameter] | ||
| public DataGridColumnPin Pin { get; set; } = DataGridColumnPin.None; | ||
|
|
||
| /// <summary> | ||
| /// The sticky <c>left</c> or <c>right</c> CSS offset (in pixels) computed by | ||
| /// <see cref="FluentDataGrid{TGridItem}"/> when columns are collected. | ||
| /// Not intended for direct use by consumers. | ||
| /// </summary> | ||
| internal double PinOffsetPx { get; set; } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why a |
||
|
|
||
| /// <summary> | ||
| /// Gets or sets the minimal width of the column. | ||
| /// Defaults to 100px for a regular column and 50px for a select column. | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.