-
-
Notifications
You must be signed in to change notification settings - Fork 366
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
Improve "subgrid" support in Composite
#3170
Comments
Thanks for the comprehensive feature request, @andrewhayward! I've been planning to introduce this feature into a dedicated The |
Do you have any suggestions for workarounds with the existing <Composite store={ store } render={ <table /> }>
<thead>
<CompositeRow render={ <tr /> }>
<th>
<CompositeItem render={ <SortButton /> }>Name</CompositeItem>
</th>
<th>
<CompositeItem render={ <SortButton /> }>Date</CompositeItem>
</th>
<CompositeItem render={ <th /> }>Can...</CompositeItem>
<CompositeItem render={ <th /> }Actions</CompositeItem>
<CompositeItem render={ <th /> }Useful information</CompositeItem>
</tr>
</thead>
<tbody>
{ items.forEach((item) => (
<CompositeRow render={ <tr /> }>
<CompositeItem render={ <td /> }>{ item.displayName }</CompositeItem>
<CompositeItem render={ <td /> }>{ item.date }</CompositeItem>
<td>
<CompositeItem render={ <ItemCanCheckbox item={ item } /> } />
</td>
<td>
{ item.actions.forEach((action) => (
<CompositeItem render={ <ActionButton action={ action } /> } />
) }
</td>
<CompositeItem render={ <td /> }>{ item.usefulInformation }</CompositeItem>
</CompositeRow>
) }
</Composite>
</table> Because the 'actions' column can contain any number of interactive widgets, there's no obvious way to set up the navigation correctly. It would actually be great if instead each cell could remain a // This is very naive!
let currentActionIndex = null;
const getAndUpdateAction = ( index ) => {
const action = actions[index];
if ( !action ) return;
currentActionIndex = index;
return { id: action.id, element: action.ref };
}
const getNextAction = () => getAndUpdateAction( (currentActionIndex ?? -1) + 1 );
const getPreviousAction = () => getAndUpdateAction( (currentActionIndex ?? actions.length) - 1 ); ...
<CompositeItem render={ <td /> } getPreviousItem={ getPreviousAction } getNextItem={ getNextAction }>
{ item.actions.forEach((action) => (
<ActionButton action={ action } />
) }
</CompositeItem>
... |
Let me know if that |
You can put all the action buttons into a single cell and follow the pattern described in Editing and Navigating Inside a Cell. I think it will be less confusing than using Ariakit has an experimental import { CompositeContainer } from "@ariakit/react-core/composite/composite-container";
<CompositeItem render={<CompositeContainer />}>
<input />
<button />
<Menu />
<Select />
etc.
</CompositeItem>
That can be a separate feature request, but I believe it could also be achieved with a custom |
Motivation
With traditional tables, it is possible to create somewhat complex arrangements, such that cells occupy more than one row or column, using
rowspan
andcolspan
.It is not currently possible to add
Composite
support to such arrangements, where directional navigation behaves in an expected manner.While setting
focusShift
totrue
in the store configuration resolves some of the navigation issues, it adds them in other places, so is not a viable solution.Usage example
This could potentially be done in a couple of ways.
The first would be to mirror how HTML tables work, with
rowSpan
andcolSpan
props:The second would be to allow
Composite*
items to nest, and take over/hand off directional navigation as appropriate:Alternatively/additionally, a more functional
colId
could be introduced, akin to the existingrowId
, allowing for more explicit control. This would allow for more intelligent use ofgetNextId
when the store is navigating, skipping over cells if they do not belong in the current row/column. This could perhaps have a declarative equivalent of the HTML<col>
/<colgroup>
elements.Requirements
CompositeItem
should have a means of declaring which column it belongs to (implicitly or explicitly)store.up()
should take into account explicit column ownershipstore.down()
should take into account explicit column ownershipstore.previous()
should take into account explicit column ownershipstore.next()
should take into account explicit column ownershipWorkaround
No response
Possible implementations
Directional movement could be modified to take into account item row and column spans, but this would be rather naive...
This only helps when you can look ahead, of course –
previous
andup
would require rather more work – and doesn't take into account any additionalrowSpan
orcolSpan
variants elsewhere in the column or row.Instead,
getNextId
could be modified to take into account any*Span
values set on items when traversing the item data:There would be other scenarios to validate too, I'm sure, such as in
verticalizeItems
andgetMaxRowLength
.A similar approach could be taken if an implicit/explicit
colId
is supported, ensuring that items are appropriately excluded if they don't belong in the requested context.The text was updated successfully, but these errors were encountered: