You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First of all, thank you for the amazing work on TanStack Table. This is one of the most thoughtfully designed headless table libraries I've used.
I'd like to raise what I believe is an API design discussion around Column Pinning, especially while v9 is still evolving.
I know issue #5986 discusses RTL support for column pinning. I think the underlying issue is broader than RTL, so I'd like to discuss the public API design itself rather than a specific RTL behavior.
The architectural issue
One of TanStack Table's greatest strengths is its headless design.
Most of the public API models table concepts rather than rendering implementation details:
sorting
filtering
grouping
selection
column order
column visibility
row models
etc.
These concepts are independent of how the table is ultimately rendered.
Column Pinning feels different.
The current API models pinned columns as physical sides:
columnPinning: {left: [...],right: [...],}
But left and right are rendering/layout concepts.
From a headless library, I would expect the API to expose the logical table concept - pinning to the beginning or end of the table - while the rendering layer decides how those concepts map onto the physical layout.
In other words, the logical model seems like:
columnPinning: {start: [...],end: [...],}
not:
columnPinning: {left: [...],right: [...],}
Why this is more than a naming preference
If this were only about terminology, it probably would not be worth changing.
The real issue is that physical directions leak through the public API into application code.
Suppose an application supports dynamic language switching.
The user can switch between English (LTR) and Hebrew/Arabic (RTL) at runtime.
The logical behavior of the table should remain the same:
Name should stay at the start of the table.
Actions should stay at the end of the table.
Users usually don't think:
Pin this column to the left side of the screen.
They think:
Keep this column at the beginning of the table.
or:
Keep the actions column at the end of the table.
Those are stable logical concepts, regardless of layout direction.
Example
Suppose I have this table in English:
| Name | Email | Phone | Actions |
In LTR, I naturally want:
Name pinned to the start
Actions pinned to the end
When switching to Hebrew or Arabic, I expect the table direction to flip:
| Actions | Phone | Email | Name |
The logical pinning did not change.
Name is still pinned to the start.
Actions is still pinned to the end.
However, with the current API, the application has to translate that logical state into physical state.
In LTR:
left: ["name"]
right: ["actions"]
In RTL:
right: ["name"]
left: ["actions"]
So changing the writing direction requires changing the column pinning state, even though the logical table state did not actually change.
That feels like a sign that the state is modeled at the wrong level of abstraction.
The complexity goes beyond state
The rendering code also has to become direction-dependent.
It becomes even more complicated when users can pin and unpin columns interactively, because the application has to translate user actions between logical intent and physical state whenever the writing direction changes.
So every bidirectional application has to build an adapter layer on top of TanStack Table just to translate between:
logical application state
TanStack's physical pinning API
physical rendering order
That feels like an implementation detail leaking through the public API into every bidirectional application.
regardless of whether the table is currently LTR or RTL.
That seems more consistent with the philosophy of a headless library.
This is also consistent with the existing getStart / getAfter API, which already describes offsets in logical row-axis terms rather than as getLeftOffset / getRightOffset. The current inconsistency is that the pinning state and position arguments are still physical (left / right), even though the underlying offset concept is naturally logical.
Why start/end is a better abstraction
Modern CSS has gone through a similar evolution.
Instead of relying only on physical properties such as:
margin-left
padding-right
CSS now also has logical properties such as:
margin-inline-start
padding-inline-end
because logical APIs compose much better with different writing directions.
I think Column Pinning has the same characteristic.
start and end describe the table concept.
left and right describe one possible physical implementation.
Why I think this should happen before v9
I realize this would be a breaking API change.
Normally I would avoid proposing that.
However, v9 is already introducing significant breaking changes, and this seems like a good opportunity to improve the API while v9 is still evolving.
After v9 is finalized, this would likely become much harder to change before the next major version.
The migration appears relatively straightforward:
left -> start
right -> end
while the long-term API becomes:
more semantic
direction-independent
simpler for bidirectional applications
better aligned with the headless philosophy
I'd be happy to help
If the maintainers think this direction makes sense, I'd be happy to implement the change myself and open a PR.
Before investing the time, I'd like to know whether the maintainers think this direction is consistent with the goals for v9.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
First of all, thank you for the amazing work on TanStack Table. This is one of the most thoughtfully designed headless table libraries I've used.
I'd like to raise what I believe is an API design discussion around Column Pinning, especially while v9 is still evolving.
I know issue #5986 discusses RTL support for column pinning. I think the underlying issue is broader than RTL, so I'd like to discuss the public API design itself rather than a specific RTL behavior.
The architectural issue
One of TanStack Table's greatest strengths is its headless design.
Most of the public API models table concepts rather than rendering implementation details:
These concepts are independent of how the table is ultimately rendered.
Column Pinning feels different.
The current API models pinned columns as physical sides:
But
leftandrightare rendering/layout concepts.From a headless library, I would expect the API to expose the logical table concept - pinning to the beginning or end of the table - while the rendering layer decides how those concepts map onto the physical layout.
In other words, the logical model seems like:
not:
Why this is more than a naming preference
If this were only about terminology, it probably would not be worth changing.
The real issue is that physical directions leak through the public API into application code.
Suppose an application supports dynamic language switching.
The user can switch between English (LTR) and Hebrew/Arabic (RTL) at runtime.
The logical behavior of the table should remain the same:
Users usually don't think:
They think:
or:
Those are stable logical concepts, regardless of layout direction.
Example
Suppose I have this table in English:
In LTR, I naturally want:
Namepinned to the startActionspinned to the endWhen switching to Hebrew or Arabic, I expect the table direction to flip:
The logical pinning did not change.
Nameis still pinned to the start.Actionsis still pinned to the end.However, with the current API, the application has to translate that logical state into physical state.
In LTR:
In RTL:
So changing the writing direction requires changing the column pinning state, even though the logical table state did not actually change.
That feels like a sign that the state is modeled at the wrong level of abstraction.
The complexity goes beyond state
The rendering code also has to become direction-dependent.
In LTR:
In RTL:
It becomes even more complicated when users can pin and unpin columns interactively, because the application has to translate user actions between logical intent and physical state whenever the writing direction changes.
So every bidirectional application has to build an adapter layer on top of TanStack Table just to translate between:
That feels like an implementation detail leaking through the public API into every bidirectional application.
Proposed API
Instead of:
use logical directions:
Likewise:
Applications could then always render:
regardless of whether the table is currently LTR or RTL.
That seems more consistent with the philosophy of a headless library.
This is also consistent with the existing
getStart/getAfterAPI, which already describes offsets in logical row-axis terms rather than asgetLeftOffset/getRightOffset. The current inconsistency is that the pinning state and position arguments are still physical (left/right), even though the underlying offset concept is naturally logical.Why
start/endis a better abstractionModern CSS has gone through a similar evolution.
Instead of relying only on physical properties such as:
margin-leftpadding-rightCSS now also has logical properties such as:
margin-inline-startpadding-inline-endbecause logical APIs compose much better with different writing directions.
I think Column Pinning has the same characteristic.
startandenddescribe the table concept.leftandrightdescribe one possible physical implementation.Why I think this should happen before v9
I realize this would be a breaking API change.
Normally I would avoid proposing that.
However, v9 is already introducing significant breaking changes, and this seems like a good opportunity to improve the API while v9 is still evolving.
After v9 is finalized, this would likely become much harder to change before the next major version.
The migration appears relatively straightforward:
while the long-term API becomes:
I'd be happy to help
If the maintainers think this direction makes sense, I'd be happy to implement the change myself and open a PR.
Before investing the time, I'd like to know whether the maintainers think this direction is consistent with the goals for v9.
Beta Was this translation helpful? Give feedback.
All reactions