ref: learningequality/kolibri-design-system#330
Presumably this component will be used for all CoreTable
instances, not just sortable ones?
I'd recommend using simply KTable
(with option to enable sorting on a per-column basis) rather than KSortableTable
which implies that it's not meant for static tables.
I would not recommend building off of the SortableHeader
component from KDP because it is built to handle one very specific scenario and makes heavy use of global state (like columnSorting
) and props that don't generalize (like pos
).
Instead, I'd recommend making the header component fairly "dumb" and let the user control it from the outside. For example:
- Props
- boolean
sortable
(whether or not the column is clickable and can be sorted) - string
order
(ifsortable
, one of an enumerated list of sort types, e.g. for ascending, descending, or unsorted)
- boolean
- Events
- simple
click
handler, just like a button. Only used ifsortable
.
- simple
Folders of resources in a channel have a built-in sort order which reflects a learning pathway of sorts, as defined by the content curator. This means that sometimes e.g. in progress reports it's not sufficient to simply toggle between sorted ascending and descending: there's a third "original" or "unsorted" state that needs to be reachable. For example:
Unsorted | Descending ↓ |
Ascending ↑ |
---|---|---|
Introduction | Final quiz | Second video |
First video | First video | Introduction |
Second video | Introduction | First video |
Final quiz | Second video | Final quiz |
Most columns will not need the unsorted state, so this would need to be an "opt-in" feature to give the user the ability to "clear" the sorting when necessary.
There are really three kinds of sorting behaviors possible. From a UX perspective, the question is what happens when a user clicks repeatedly on the same header. Does it:
- Stay sorted in a single fixed order (probably unusual?)
- Toggle between ascending and descending order (most common)
- Cycle between ascending, descending, and some "original" order (applies to resources)
Currently the CoreTable
relies heavily on /deep/
selectors and some special CSS classes (core-table-checkbox-col
and core-table-button-col
). The developer then uses "standard" table sub-elements such as th
and td
within the named slots.
We also use transition group 'move' transitions extensively to help users visually see what happens when they change sort order, and this behavior should preferably become part of the KSortableTable
.
All of this would make the current CoreTable
component API hard to document in the Design System, which relies on components and props as the fundamental vocabulary - not CSS classes and native HTML tags.
An alternative strategy which would fit better with the design system is would be to create a set of components that "play nicely" together, similar to [KButton
, KButtonGroup
] and [KGrid
, KGridItem
].
For example, instead of:
<CoreTable>
<template #headers>
<th>...</th>
<th>...</th>
<th></th>
</template>
<template #tbody>
<transition-group tag="tbody" name="list">
<tr v-for="tableRow in tableData" :key="tableRow.id">
<td>...</td>
<td>...</td>
<td class="core-table-button-col">...</td>
</tr>
</transition-group>
</template>
</CoreTable>
It might be something along the lines of:
<KTable>
<template #headers>
<KTableHeader sortable>...</KTableHeader>
<KTableHeader sortable>...</KTableHeader>
<KTableHeader />
</template>
<template #rows>
<KTableRow v-for="tableRow in tableData" :key="tableRow.id">
<KTableCell>...</KTableCell>
<KTableCell>...</KTableCell>
<KTableCell button-col>...</KTableCell>
</KTableRow>
</template>
</KTable>
[CoreTable
, transition-group
, tbody
, th
, tr
, td
, .core-table-button-col
]
vs
[KTable
, KTableHeader
, KTableRow
, KTableCell
] with associated props
Notes:
- Above,
tbody
is handled byKTable
and the named slot is renamed torows
- sometimes
th
tags appear in rows because both columns and rows can have header cells. So with this API<KTableCell>
would need a default-false "header" flag like<KTableCell th>
which would render ath
instead of atd
for that cell
When pagination is involved, sorting requires a round-trip request to the server which means introducing a 'loading' state. It is probably out-of-scope for this work, but it would be worth auditing how many of our CoreTable
instances use pagination. If it's significant, it might be worth building in consistent pagination functionality along with async loading states.
You rule @indirectlylit thanks for this. I love the idea of abstracting all that table HTML business and behavior away into some simple components. This is going to be a great help!