shoelace
shoelace copied to clipboard
Tables
Having used element on a more recent project I really liked their data tables. I propose to see the table component as part of 2.1
https://element.eleme.io/#/en-US/component/table
Table Requirements
Ok, super-raw 30-min holidy sum up of what I think are my consolidated expectations when it comes to a hero-table-component.
I have bits of this implemented in Stencil in my project so could talk about how to collaborate.
In general I found the Angular Material Table to be very comfortable to work with in enterprise projects. I've used it successfully over the last 2 years in an automotive OEM project that got management attention. It's a very data-heavy app and the component solved the purpose very well.
Column Definition
In my opinion array based definition of columns has proved to be very practible as in most real-world scenarios you'll have the column information available in some list form available anyways. Also this supports easy ordering, filtering, toggling of visibility of columns which is nice for a personalized UX.
It was also required in the past to have some kind of dynamic flexibility in the rendering of cell data depending on some data cirumstances. A simple renderFn
can work wonders here. This can also solve the issue of formatting data e.g. based on it's type (date, string, numbers, ...)
As we are implementing a web components based table I think it should support "sub-componenting" as easy as posible. So why not copy how Ionic does it with component
?
Also FunctionalComponents
are super helpful and should be supported.
Example pseudo code:
const columns = [
{
name: 'employeeId', // The prop name in the data set
caption: '#'
},
{
name: 'joinDate',
caption: 'Joined',
renderFn: (record) => record.joinDate instanceof Date ? formatDate(record.joinDate) : 'No date available'
},
{
name: 'avatar',
caption: 'Avatar',
component: 'my-avatar-render-cell',
componentPropMapping: {
image: 'avatar' // Maps the field `avatar` of the record which holds a string path to the image to the property `image` of the component
},
componentProps: {
someOtherPropTheComponentNeeds: true
}
},
{
name: 'sumOfMonthlyHours',
caption: 'Monthly hours',
renderFn: (record) => <MonthlyHourSum data={record.hours}>
}
]
Cell Templating
In most cases I had to deal with I needed some kind of custom cell templating. Like a whole little "component" put inside a table cell. In Angular this can be achieved with a <template>
or similiar templating mechanisms. Maybe <slot>
could help here or a renderProp
per column which we can feed with JSX and which is handover the cell or row data or at least the row index.
Such templating engine could also be used to implement an "action button" feature. Or the "row actions" could be built-in - not sure here.
Virtualization
The component should suport some kind of slicing of large data sets out of the box.
Options to slice large data sets:
- [ ] Virtual Scroll
- [ ] Pagination
Sorting
Sorting (at least on one column) should be supported out of the box.
Tags
Whether to use <table></table>
or <div></div>
still is not a clear one for me. I've appreciated the auto-sizing of table
in the past but also felt it's limitations. So maybe the component could offer a toggle to switch between classic table and div/flexbox/layout:table.
Auto-generate columns from data set
For an easy start I also implement a simple auto-generate from data feature in the past which would extract the column name from the first record or similiar.
Multi-Select
Always required at some stage in every project ;-)
Content Truncation/ Formatting
For an easy start it's always good to truncate content with ellipsis or similiar. ost of the time the raw data is too big for a clean table look and this helps in the first place.
Index Column
I often found it useful to have an index column auto-generate without having to provide it in the column definitions.
One more thing towards what one might expect from a "modern" table component: responsiveness.
I think a table should be able to deal with various screen resolution based on some simple input from the developer. I image something like a level
or priority
setting per column which would help to decide whether or not to display the column once the available space gets too small.
What could also work is a different cell rendering rendering based on breakpoints to adapt the the available screen better. Some like renderFnSizeM
, renderFnSizeS
etc.
@jacebot Just checked out the element table and seems to have some serious scroll lag issue? Even on my MB 2019 the rows are not "synced" when scrolling. Did you experience that too?
Would it possibly make sense to build the component around a feature-complete "data structure engine" like https://danfo.jsdata.org/api-reference/dataframe ?
I think this request is really two things:
- A basic table component that handles styles and possibly facilitates pagination/sorting/filtering
- A data table / grid component that does, well, a ton of other things
I'm not interested in building a replacement for the many high-level data table plugins that are out there. I'm more interested in option 1, as it will be of interest to the majority of the users. Option 2 is a huge undertaking and much more opinionated. There are entire projects dedicated to these advanced features.
Remember that it's perfectly fine to use something like DataFrame, Grid.js, etc. in conjunction with Shoelace βΒ they're not mutually exclusive. I'd really prefer to keep core components lower-level than that.
Totally agree and understand the strategy. My requirements above might have been more of a self-reflection outcome. A simpler pure UI table would definitely be a good start for any complex use case.
Sorry for the delay on the conversation, but I agree with the outcome here. I would like to see a nice table component, with some basic features (Option 1). And yes, I think the more dynamic sub set of features can come from something third party where they really know their role/feature sets extremely well, and just use Shoelace for the styles.
Side note , thanks for the hard work @claviska great stuff!
It sounds like we're all on the same page. Send me some nice table designs for inspirations. π
I use a basic table with sorting and paging in practically every project I build. This would be a great addition.
@claviska I think Element has a nice table that you can be inspired from that fits the shoelace 'look' (ignore me, I forgot I linked this originally.)
An alternative that kinda fits could be SemanticUI as well.
Both have nice padding and features. A little partial to the Element design.
One trouble with tables is that it's difficult to targets things reliably with the ::slotted
selector, so if this component used a slot (e.g. if it were composable), it will probably require light DOM styles. I'd really like to avoid that.
People: "Just don't use shadow DOM then!"
Well, this would be the first and only component that doesn't use shadow DOM. It would become the edge case as styles leak in and work differently than all other Shoelace components.
I need to experiment with some ideas, but it might be that tables are not a component and instead part of an optional extension to the base theme that styles core elements using design tokens:
- headings
- fonts
- links
- lists
- tables
- etc.
I think it's valuable to have a "reset" like this. Tailwind offers one with their typography plugin, so maybe some inspiration can be drawn from there.
I've created a proposal for this here: https://github.com/shoelace-style/shoelace/issues/413
So now is 2022, we still don't have a table component.
@claviska, How can we integrate third party component in showlace? As the show lace component dosn't have the data table component currently. I want to use the smart html table component https://www.htmlelements.com/demos/table/overview/.
Shoelace can be used in conjunction with any other component or library you'd like to use. There's nothing special required to use both.
@claviska I want to use a third-party package of table components as a shoelace child component. I did import the package inside the shoelace component but it doesn't work. Can you please reference how we can add a third-party package to the shoelace library?