My usecase is a grid for a timetable where the vertical coordinates are 15 min timeslots and the horizontal axis are events (in my case lessons) happening simultaneously. I can imagine this being a use case for others, too. Unfortunately I donβt have the time now to look at it myself, so just an idea for now. Thank you for sharing with the community!
oki. what you need is a time(table) widget. This is a bit different, but that might be an interesting challenge once Iβll have reached v1 (I hope soon).
Atm, target is dashboard/grid engine for stuff like analytics, iot (like grafana) etc. But sure, it can also be used for building UI with lazy loading (and itβs also composable with others slivers which is handy).
Actually, my goal is to fill the gap between Flutter and JS grid engines.. the direct βJS contenderβ is react-grid-layout (Iβve been heavily inspired by this package). And I added some fancy features and opti.
Remaining tasks on my todo:
- Allow to create your own custom compaction and positioning algo
- Sections/visual headers to segment the dashboard, with sticky option
- Allow items to be dropped into or dragged out of groups.
For those following my iterations, in next coming version (0.9) :
- new feat: add your custom compaction algo, by implementing CompactorDelegate to define custom rules (e.g., specific gravity, fixed zones).
- huge performance boost on compaction algo. noticeable when there are a lot of items in dashboard
Compaction algo comparison v.0.8 (old) vs 0.9 (new), on desktop:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BENCHMARK RESULTS β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββ€
β Test β Time β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ€
β COMPACTION β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ€
β Vertical Old (100 items) β 1.22 ms β
β Vertical New (100 items) β 17 Β΅s β
β Horizontal Old (100 items) β 355 Β΅s β
β Horizontal New (100 items) β 17 Β΅s β
β Vertical Old (500 items) β 99.90 ms β
β Vertical New (500 items) β 99 Β΅s β
β Horizontal Old (500 items) β 10.30 ms β
β Horizontal New (500 items) β 101 Β΅s β
β Vertical Old (1000 items) β 898.88 ms β
β Vertical New (1000 items) β 222 Β΅s β
β Horizontal Old (1000 items) β 37.99 ms β
β Horizontal New (1000 items) β 217 Β΅s β
β MOVE β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ€
β Move Element (100 items) β 72 Β΅s β
β Move Element (500 items) β 1.40 ms β
β SORT β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ€
β Sort Layout (100 items) β 6 Β΅s β
β Sort Layout (500 items) β 43 Β΅s β
β Sort Layout (1000 items) β 99 Β΅s β
β OPTIMIZE β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ€
β Defrag (100 items) β 4.76 ms β
β Defrag (500 items) β 855.42 ms β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββ
Optimize Defrag is not called by dashboard, this is an api that can ponctually be used when you want to βdefragmentβ your dashboard.
Would be interesting to compare to the JS contender I mentioned previously. Although they use mutable state if Iβm not wrong, and my package uses immutable and copyWith, I wouldnβt be suprised if we get better results thx to AOT (maybe same for web wasm..). When Iβll have more time, Iβll compare both.
Final stretch before the 1.0 β¦
POC: nested dashboards/groups

- Sections
- Folders/Groups (nested dashboard)
- scrollToItem by its logical id

Hi there.
Since last time, sliver_dashboard has grown a lot, and the upcoming 2.0 feels like the right moment to check back in. Itβs also getting more popularity on pub dev which I think is pretty cool and encouraging ![]()
If thereβs one sentence to remember, itβs this: sliver_dashboard is not a classic grid widget. Itβs a deterministic, testable layout engine that happens to render through Flutter slivers.
You can use it to build interactive, draggable/resizable dashboard grid, on Flutterβs sliver protocol, so it virtualizes. Only visible tiles are built, and drag/resize stay allocation-free in the layout hot path. If youβve used gridstack.js or react-grid-layout on the web, this is it; this is a native Flutter take on the same idea, with a single codebase, crossplatform.
If you read me.. Thank you Dart/Flutter Team ![]()
Smooth on Flutter Web/JS even when when I stress tested it with 1000 items, scroll, drag/drop feel smooth. You can already check this using v1.x demo link on pub dev
V2 is not released yet on pub dev, I need a few more days of testing, just to be sure. But itβs already available on github if youβre curious or need it.
This 1.x demo is available on pub dev:

And, whatβs new in upcoming 2.0:
- Nested grids: embed a full dashboard inside any tile
- Cross-grid drag & drop: move tiles between nested, sibling, or independent grids, with dimension projection between different column counts
- Paint-phase reflow animations (opt-in): pushed tiles slide on the GPU, no widget rebuilds
- A richer minimap (markers, multiple viewports)
- etc.


Hello.
As promised, sliver_dashboard v2 is now available on pub.dev! ![]()
Built for βproduction-gradeβ stability:
- 98% code coverage with 450 unit & widget tests to prevent layout regressions (8K lines of production code, 10K for tests).
- Strict type safety and linting using very_good_analysis.
Check out the updated documentation:
[Link to pub.dev]
I might be biased, but I think this is a unique solution in the Flutter ecosystem; a true sliver-based alternative to GridStack and react-grid-layout.
I would love to hear your feedback, thoughts, or see what you build with it.
Enjoy!
Iβm continuing to stress-test sliver_dashboard. This is purely out of curiosity, to see how far itβs possible to push the layout engine to its limits.. because to be honest, Iβve never seen a dashboard with 4 000 or 10 000 items ![]()
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BENCHMARK RESULTS β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ€
β Test β Median β Best β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β COMPACTION (DEEP INPUT) β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β Vertical Standard (100 items) β 44 Β΅s β 42 Β΅s β
β Vertical Fast/Tide (100 items) β 35 Β΅s β 34 Β΅s β
β Horizontal Standard (100 items) β 89 Β΅s β 86 Β΅s β
β Horizontal Fast/Tide (100 items) β 35 Β΅s β 34 Β΅s β
β Vertical Standard (500 items) β 299 Β΅s β 293 Β΅s β
β Vertical Fast/Tide (500 items) β 250 Β΅s β 238 Β΅s β
β Horizontal Standard (500 items) β 487 Β΅s β 476 Β΅s β
β Horizontal Fast/Tide (500 items) β 266 Β΅s β 262 Β΅s β
β Vertical Standard (1000 items) β 586 Β΅s β 542 Β΅s β
β Vertical Fast/Tide (1000 items) β 525 Β΅s β 509 Β΅s β
β Horizontal Standard (1000 items) β 992 Β΅s β 900 Β΅s β
β Horizontal Fast/Tide (1000 items) β 568 Β΅s β 539 Β΅s β
β Vertical Standard (2000 items) β 1.35 ms β 1.29 ms β
β Vertical Fast/Tide (2000 items) β 1.15 ms β 1.12 ms β
β Horizontal Standard (2000 items) β 2.14 ms β 2.04 ms β
β Horizontal Fast/Tide (2000 items) β 1.27 ms β 1.21 ms β
β Vertical Standard (4000 items) β 2.88 ms β 2.51 ms β
β Vertical Fast/Tide (4000 items) β 2.62 ms β 2.54 ms β
β Horizontal Standard (4000 items) β 4.69 ms β 4.54 ms β
β Horizontal Fast/Tide (4000 items) β 2.70 ms β 2.53 ms β
β Vertical Standard (10000 items) β 7.49 ms β 7.30 ms β
β Vertical Fast/Tide (10000 items) β 7.66 ms β 7.44 ms β
β Horizontal Standard (10000 items) β 20.31 ms β 18.85 ms β
β Horizontal Fast/Tide (10000 items) β 7.58 ms β 7.07 ms β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β COMPACTION (ALREADY COMPACT) β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β Vertical Standard (100 items) β 35 Β΅s β 34 Β΅s β
β Vertical Standard (500 items) β 203 Β΅s β 200 Β΅s β
β Vertical Standard (1000 items) β 445 Β΅s β 441 Β΅s β
β Vertical Standard (2000 items) β 1.06 ms β 961 Β΅s β
β Vertical Standard (4000 items) β 2.15 ms β 2.13 ms β
β Vertical Standard (10000 items) β 6.69 ms β 6.14 ms β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β RESIZE (TOP OF GRID) β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β resizeItem push at top (500 items) β 1.10 ms β 1.07 ms β
β resizeItem push at top (1000 items) β 816 Β΅s β 766 Β΅s β
β resizeItem push at top (2000 items) β 139 Β΅s β 135 Β΅s β
β resizeItem push at top (4000 items) β 292 Β΅s β 288 Β΅s β
β resizeItem push at top (10000 items) β 27.66 ms β 25.86 ms β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β MOVE β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β Move Element (100 items) β 61 Β΅s β 57 Β΅s β
β Move Element (500 items) β 389 Β΅s β 348 Β΅s β
β Move Element (1000 items) β 705 Β΅s β 699 Β΅s β
β Move Element (2000 items) β 1.48 ms β 1.46 ms β
β Move Element (4000 items) β 3.18 ms β 2.91 ms β
β Move Element (10000 items) β 8.77 ms β 8.22 ms β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β SORT β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β Sort Layout (100 items) β 14 Β΅s β 14 Β΅s β
β Sort Layout (500 items) β 93 Β΅s β 91 Β΅s β
β Sort Layout (1000 items) β 213 Β΅s β 204 Β΅s β
β Sort Layout (2000 items) β 512 Β΅s β 472 Β΅s β
β Sort Layout (4000 items) β 1.03 ms β 1.01 ms β
β Sort Layout (10000 items) β 4.02 ms β 3.83 ms β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β OPTIMIZE β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββ€
β Defrag (100 items) β 236 Β΅s β 234 Β΅s β
β Defrag (500 items) β 1.77 ms β 1.62 ms β
β Defrag (1000 items) β 3.63 ms β 3.56 ms β
β Defrag (2000 items) β 8.58 ms β 7.88 ms β
β Defrag (4000 items) β 21.87 ms β 21.05 ms β
β Defrag (10000 items) β 92.49 ms β 79.24 ms β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ
Note: operations like Defrag are separate from realtime interaction loops. While draggingn, resizing and scrolling run many times/sec on the layout βhot pathβ, which is why their sub 10ms perf is so critical, defragmentation on the other side is an on-demand operation usually triggered by a user clicking a button and has no impact on UI fluidity.
I benchmark sliver_dashboard engine in AOT mode, on an βoldβ Ryzen 2600 machine, Windows 11.
Release 2.2.0.
Brings a few optimizations, and 100% code coverage.
I think itβs feature complete, at least for me, but if you need a feature or any help, donβt hesitate to ask me.
I use it in production projects, so Iβll continue maintenance.
Sadly I tried to showcase it on reddit flutterdev, my handwritten posts got filtered twice.. no idea why, maybe because Iβm a new user, no way to contact modos, so, never mind, Iβm giving up to showcase it there.
Have a good day!
I just released sliver_dashboard 2.4.0.
It allows dropping into collapsible folders/hosts, and also provides a new projection policy preservePixelSizeβ.
I modified the nested example to show how you can now build size-driven collapsible folders by using the itemBreakpointBuilder (instead of the regular itemBuilder), which rebuilds only when its item breakpoint resolver callback is called:
shrink a card to collapse it into an interactive drop-target icon (onItemDroppedOnHost) to file items away, or expand it to reopen the full nested grid.
And you can pair it in your projects, with the new preservePixelSize projection policy, dragged tiles will automatically adapt across different grid densities while preserving their exact physical screen size.

Hereβs how sliver_dashboard compares to two well-known Web grid libraries.
| Feature | sliver_dashboard | GridStack | React Grid Layout |
|---|---|---|---|
| Ecosystem | Dart/Flutter | JS/TypeScript | JS/TypeScript |
| Platforms | |||
| Vertical dashboard | |||
| Horizontal dashboard | |||
| Segmented grids / Section barriers | |||
| Native scroll integration | HTML scrolling | HTML scrolling | |
| Viewport virtualization | |||
| Drag & Drop | |||
| Custom drag handles | |||
| Resize | |||
| Responsive layouts | |||
| Per-item breakpoints | |||
| Nested dashboards | |||
| Collapsible nested dashboards | |||
| Drag between dashboards | |||
| Cross-sliver / Multi-sliver drag | |||
| External drag sources | |||
| Built-in trash / delete target | |||
| Built-in guidance / drop hints | |||
| Push collision | |||
| Push-or-shrink collision | |||
| Auto-shrink neighbors on drag | |||
| Reflow animations | |||
| Layout persistence | |||
| Layout import / export | |||
| Extensible layout algorithms | |||
| Extensible compaction algorithms | |||
| Multi-selection | |||
| Mini-map | |||
| Keyboard accessibility | |||
| Screen reader announcement | |||
| Large-scale dashboards (1000+ items) | οΈ Not documented | οΈ Not documented |
But why does it matter?
βShow me your architecture, not your features.β
If youβre curious about how and why sliver_dashboard was designed this way, here are a few links:
Note: I used AI assistants during development (Gemini, Claude), but with a strict discipline to ensure long-term maintainability and robustness: no coding agents (no auto-commit, no βlet it run freeβ). I wanted for this project to stay in full control and truly know my codebase; not delegate ownership to an agent.
Only chat-based assistance, with careful review, all decisions human-driven.
I learnt so many things during this process, about custom slivers etc, I donβt regret it even if it has been more work than using a coding agent (using only chat also saved some credits on my AI subscriptions for my others projects. less requests, tools calls..).
Feedback, questions, and ideas welcome.
sliver_dashboard v2.5 is available.
- You can revert or re-apply layout changes with controller.undo() / redo(), reactive canUndo / canRedo, and async veto hooks. It can be disabled with maxHistoryLength: 0. Default is 30.
- Tiles displaced by push cascades can be highlighted during drag operations (βImpact Previewβ). This configurable visual feedback is also painted live on the DashboardMinimap.
- Hold Alt or Option (configurable key) when dragging a tile to pull out a copy while leaving the original in place. Driven by your applicationβs onCloneRequested callback to mint new IDs and custom metadata.
Impact preview, and undo/redo:
