Releases: stephenWanjala/DataTable
Release list
0.4.0
A fix release. No signatures changed, so 0.4.0 is a drop-in for 0.3.0 — but four things the
documentation promised and the code did not actually do now work, so the table may behave in ways
your 0.3.0 workarounds were compensating for. Those two cases are called out below.
implementation("io.github.stephenwanjala:datatable:0.4.0")Sorting cycles past ascending
Clicking a header in 0.3.0 always sorted ascending, however many times you clicked it. The
click handler captured the sort state from its first composition and never saw an update, so the
cycle logic always compared against an empty SortState.
Clicking now cycles ascending → descending → none. Multi-sort with Ctrl+click was stuck
the same way and is fixed with it.
onSortChange, remove that — you
will now get the inversion twice.
Keyboard navigation works at all
The table never took focus, so no key event ever reached it and every shortcut was dead in every
release to date. It now requests focus when clicked, and arrow keys, Home,
End, Enter, and Space behave as documented.
Focus is taken on click rather than on appearing, so a table dropped into a form still does not
steal focus from whatever the user is typing in.
Tabbing past a table no longer costs a stop per row
Per-row checkboxes and expand buttons are out of the Tab order. Previously a three-row table with
selection and expansion took eight Tab presses to get past, and a forty-row grid took
eighty. The cost is now fixed regardless of row count.
Both controls stay clickable, and Space on the focused row still toggles selection. The
header select-all checkbox and the pagination controls keep their focus — there is a fixed handful
of them, and they are real controls a keyboard user should reach.
Weighted columns have a real width
A column with width = null collapsed to zero inside the horizontally scrolling area, because
Modifier.weight had nothing bounded to take a share of. Weighted columns now divide up the
viewport minus the fixed columns, the leading controls, and any frozen section, with
minColumnWidth as the floor when the fixed columns already overflow.
wider — and visible — weighted columns where they previously rendered nothing.
Also in this release
- A test suite covering sorting, selection, pagination, keyboard navigation, tab order, column
widths, and header-tree validation. The sort-cycle bug above is the one it found first. - Built against Compose Multiplatform 1.11.1, up from 1.9.2. Compose is an
apidependency, so
Gradle will resolve your project's Compose artifacts up to 1.11.1 unless you constrain them. - The documented requirements were wrong and are now correct. The artifact targets Java 11,
not the "JVM 21+" the docs claimed; Kotlin metadata is emitted at language level 2.2. Nothing
about the published bytecode changed — only the claim about it. - Documentation: keyboard shortcuts render as keycaps instead of literal
++ctrl++text, and
the site now states plainly
what the table does not do —
cell editing, cell selection, clipboard, filtering, export, column reordering, layout
persistence, tree tables, and accessibility semantics are all absent. - Demo packages for the sample gallery are attached below.
Links
Full Changelog: 0.3.0...0.4.0
0.3.0
What's Changed
No signatures changed, so 0.3.0 compiles against 0.2.0 call sites untouched. Three behaviour
changes are worth checking.
Sorting and pagination are properly controlled
Supplying onSortChange, onMultiSortChange, or onPageChange now makes that piece of state
controlled: the table renders the parameter and never changes it on its own.
In 0.2.0 the table kept an internal copy that it updated on interaction regardless, so a caller
who passed the callback but ignored the parameter still saw sorting work. That now does nothing
visible — the click fires the callback, and the table waits for you to feed the value back:
// Broken in 0.3.0: the callback fires, but sortBy never changes
DataTable(
sortBy = SortState(), // constant!
onSortChange = { analytics.track(it) },
)
// Correct: hoist it
var sort by remember { mutableStateOf(SortState()) }
DataTable(
sortBy = sort,
onSortChange = { sort = it; analytics.track(it) },
)Passing no callback is unchanged — the table owns the state, and click-to-sort works with no wiring.
Nested headers render
DataTableHeader.children was accepted and silently ignored in every version up to 0.2.0. If you
set it, expecting nothing, you now get a grouped header; both throw rather
than misrender.
Misconfigured frozen columns throw
fixed = true without a width used to be quietly demoted to a normal scrolling column. It now
throws with a message naming the column. If pinning appeared not to work for you before, this is
why, and the fix is to give the column an explicit width.
Also in this release
manualSorting,manualPagination, andtotalItemsfor server-side data.- Reworked pagination footer: grouped controls, a divider above it, hover states, and a
rows-per-page menu that opens upward instead of off the bottom of the window. DataTableHeaderandSortStateare@Immutable, and Compose is exposed asapirather
thanimplementationso consumers get it transitively.- Press-and-drag no longer pans the table horizontally; wheel and trackpad scrolling are
unchanged. This also stops drags fighting the column resize handles.
Focus now stays on its row when the table is re-sorted, instead of holding a fixed position.
If the focused row leaves the view — filtered out, or on another page — the next arrow key
starts again from the first row.
Fixes that may change what you see
No API change needed for these, but the rendering differs:
- Alternating row colors were offset by the total item count, flipping which rows were
tinted on odd-sized lists. They now start correctly at the first row. - The keyboard focus indicator never appeared in any configuration. It now renders on the
focused row, so afocusedRowBordercolor you set in 0.1.x becomes visible for the first time. - Enter and Space acted on the wrong row when
groupBywas set, because navigation walked
the pre-grouping order. They now follow display order. - Arrow-key scrolling overshot when group headers or summaries were present.
Full Changelog: v0.2.0...0.3.0
v0.2.0
v0.1.1
Release Notes — v0.1.1
New Features
Frozen/Pinned Columns
Columns marked with fixed = true and an explicit width are now pinned to the left edge of the table and remain visible during horizontal scrolling.
Multi-Column Sort
Ctrl+click column headers to sort by multiple columns simultaneously. Use the new multiSortBy and onMultiSortChange parameters alongside the existing single-sort API.
Column Resizing
Enable resizableColumns = true to let users drag column edges to resize. Use minColumnWidth to set a lower bound, and DataTableState.resetColumnWidths() to revert to defaults.
Keyboard Navigation
The table is now focusable and supports Arrow Up/Down to move between rows, Enter to trigger onRowClick, Space to toggle selection, and Home/End to jump to the first or last row.
Selection Modes
A new SelectionMode enum (NONE, SINGLE, MULTI) replaces the implicit multi-select behavior previously tied to showSelect. The showSelect parameter remains for backwards compatibility.
Right-Click Context Menu
New onRowContextMenu: (T, Offset) -> Unit callback fired on right-click, providing the item and the pointer position.
DataTableState
New state holder created via rememberDataTableState(). Supports programmatic animateScrollToItem(index) and resetColumnWidths().
Items-Per-Page Selector
The pagination footer now includes a page-size picker. Configure available options with itemsPerPageOptions and respond to changes via onItemsPerPageChange.
Enhancements
- Alternating row colors — set
colors.rowAlternatefor zebra-striped rows. - Row hover highlight — set
colors.hoveredRowfor a mouse-over tint. - Focused row border — set
colors.focusedRowBorderto highlight the keyboard-focused row. - Per-column text overflow —
DataTableHeadernow acceptsmaxLinesandoverflow(TextOverflow) to control cell text truncation. - Custom sort comparator — set
DataTableHeader.comparatorto override the defaultComparable-based sort for a column. - Column visibility toggle — set
DataTableHeader.visible = falseto hide a column without removing it from the header list. - Multi-sort takes precedence over single-sort when both are provided.
Bug Fixes
- Global row index was not tracked correctly across groups, causing mismatched focus and selection highlights in grouped tables.
- Horizontal scrollbar was duplicated (rendered for both header and body) when
showScrollbars = trueand frozen columns were not in use.
Breaking Changes
DataTableRowandDataTableHeaderRownow requireselectionMode,rowIndex,isFocused,state, andonContextMenuparameters. If you are calling these internal composables directly, update your call sites.TableDividerandenableTrackpadHorizontalScrollare nowinternal. They were previouslyprivatebut accessible in the same module — direct external use is no longer supported.
Full Changelog: 0.1.0...0.1.1
0.1.0
- Initial implementation of the DataTable component for Compose Desktop supporting features such as sorting, grouping, and pagination.