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
We already have the useDataGrid query hook working on the ui-kit, however, we don’t have a component that consumes it, also in order to implement the new SQL Playground in Console, we’ll require to have a DataGrid component for the result visualization.
What are the requirements?
Following the same pattern we have for other components, the DataGrid component should provide a higher-level API that enables customers to setup a basic DataGrid easily but also enable exposing a lower-level API to access the inner table components directly, hopefully the library we use enables us to export its API directly similar to what we do on Chart.js with chartConfigProps.
We already have the useDataGrid hook to query the data so the most important concern is how we display it and enable customizing it.
For v1, we can probably focus on getting a basic version out while we provide data visualization features that we also require on Console
Default state should render a table with basic styles, with a column to index rows (example from Snowflake)
Columns should be resizable in order to enable viewing larger elements
Cells should be selectable and open a drawer with the cell’s data, in case of containing a JSON, it should be formatted. This drawer should also be customizable and provide an option to disable it
Rows should enable/disable showing a cell with the row’s index to the left
Clicking on a row’s index should select the row and open a drawer with the row’s data. This drawer should also be customizable and provide an option to disable it
DataGrid should include built-in pagination
Clicking on a column header should change sorting, clicking once should set to ASC, clicking twice should set to DESC and clicking a third time should reset, sorting should be made client-side for static mode and server-side for connected mode.
Requirements for table component:
The DataGrid component should return a table with the received data from DataGrid API,
Should enable column resize
Rows should listen to click events and send row data
Cells should listen to click events and send cell data
Should enable pagination
Should be based on <table /> elements for better a11y
Should be fully customizable
Should enable sorting by column
Should enable showing/hiding row numbers
Should enable showing/hiding headers
Should enable showing a drawer on column/cell click
Should support virtualized scrolling
Good performance with thousands of rows or more.
Sticky columns
Download query data as .csv
Enable keyboard interactions (selecting whole table, copying a row/cell)
In pro of following consistency with the way we implement charts, helper components, etc we should probably opt for finding a library that would best fit our needs
Tanstack Table provides a headless React hook that makes it easy to implement a Table component, this is similar to what we do today with base-ui’s Select component
❌ Should enable pagination (does not provide built-in support for pagination)
⚠️ Should be based on <table /> elements for better a11y (based on div elements)
⚠️ Should be fully customizable
react-data-grid exports a high level component that receives a renderers prop, this one enables overriding their Checkbox component, Row , SortStatus ,noRowsFallback, while this provides a certain level of customization some things seems to be missing (e.g header)
✅ Should enable showing a drawer on column/cell click
⚠️ Should be a lightweight library (752kb might be not so lightweight for a headless hook library)
✅ Should be a well maintained library (last commit 4 days ago)
Other options are either paid or not as good as Tanstack Table, we decided to proceed with Tanstack Table
Detailed design
The component should receive a set of headers and rows for static mode, as well as other properties we already set in static mode for other components.
Subcomponents should also include a className and style prop in order to enable styles customization.
Loader state
For loader we probably want to do something different to just a loading rectangle, we probably want to try something similar to console, cells in loading state and headers shown for static mode, for connected mode cells should be in loading state as well
Requirements implementation
Based on the decision of using Tanstack Table for the Table, we should rely on their examples on how to implement the features we require, here are some of the guides provided by Tanstack table:
Some features however we will have to implement on our own: drawer, exporting to .csv
Interactivity and customization
It’s necessary to enable handling most of interactivity via props, for this we will require:
Props to handle click events on Cells, Rows and Headers
Prop to disable/enable the drawer
Prop to customize drawer content
We can follow our current pattern of using fallbacks/overrides in order to provide the best level of customization, we can have RowOverride, CellOverride, DrawerOverride, HeaderOverride and PaginationOverride
Rows
For rows we would have the rowOverride but also a top-level prop in order to hide the indexes
Prop
Type
Description
rowOverride
Element | ({props: RowProps, RowComponent: Row, CellComponent: Cell}) => Element
Overrides the row component
indexColumn
'left' | 'right' | 'hide'
Sets the position of the index column to either left or right or disables it.
RowProps
Prop
Type
Description
onIndexClick
(rowData: string[] | Element[]) => void
Callback called when an index (row) is clicked
cellValues
string[] | Element[]
Values that will fill each Cell
className
string
Classname to be applied to the Row container
styles
CSSStyles
CSS Styles to be applied to the Row container
Cells
Prop
Type
Description
cellOverride
Element | (props: CellProps, CellComponent: Cell) => Element
Override for the row component
CellProps
Prop
Type
Description
onCellClick
(cellValue: string | Element) => void
Callback called when an cell is clicked
cellValue
string | Element
The value of the cell
className
string
Classname to be applied to the Cell container
styles
CSSStyles
CSS Styles to be applied to the Cell container
onIndexClick and onCellclick should act as middlewares rather than overriding our setup for opening the drawer, however, if the drawer is disabled those should act as overrides
Drawer
For Drawer, besides of having a drawerOverride component we should have a top-level disableDrawer prop so customers can easily just disable it when they require it without having to add a fallback with an empty result.
Prop
Type
Description
disableDrawer
boolean
When true, will disable the drawer
drawerOverride
Element | (props: DrawerProps, Component: Drawer) => Element
The override for the drawer component
DrawerProps
For v1, it would be enough that the Drawer just shows the data in the cell/row but in order to enable customization we’ll need to enable an onClose prop
Prop
Type
Description
onClose
() => void
Callback called when the close button in the drawer is clicked
displayValue
string | Element
Value that the Drawer would display
className
string
Classname to be applied to the Drawer container
style
CSSStyles
CSS Styles to be applied to the Drawer container
Pagination
Regarding pagination, we can provide high-level customization as well as low-level customization, for this, we most likely will want to change the rows per page options for now and then customers can fully customize the component with an override prop
Prop
Type
Description
pageSizeOptions
number[]
The page sizes options for pagination
paginationOverride
Element | (props: PaginationProps, Component: Pagination) => Element
The override for the pagination component
paginationBehavior
'infinite' | 'paginated'
Determines whether the pagination should be performed as a virtualized infinite or a paginated way
The Pagination component should then be uncontrolled, so customers can easily call the setter and default value from props in their custom pagination component as well as the onNext and onBack
PaginationProps
Prop
Type
Description
setPageSize
(pageSize: number) => void
Setter to be called when the pageSize changes
defaultPageSize
number
The default pageSize for the paginator, should be one of pageSizeOptions otherwise should throw a warning
onNext
() => void
Callback to be called when the “next” button is clicked
onBack
() => void
Callback to be called when the “back” button is clicked
currentPage
number
The current page index
setCurrentPage
(page: number) => void
Setter to change the current page
hasNext
boolean
Whether a next page is available or not
hasPrevious
boolean
Whether a previous page is available or not
className
string
Classname to be applied to the Pagination container
style
CSSStyles
CSS Styles to be applied to the Pagination container
Then we would have Header which we could split in HeaderRow and HeaderCell those would be very similar to Row and Cell but should be distinct as it’s a common use case to customize the header different to the other rows/cells, additionally we should have a top-level prop to hide the header
Prop
Type
Description
hideHeader
boolean
If true, hides the header
Drawbacks
In order to provide a good level of customization it could require a lot of work, as DataGrid has a lot of components where we should enable customization.
Alternatives
Customers already have a useDataGrid hook that they could use in their own tables
Adoption strategy
DataGrid would be a new component, however, customers could be already using the useDataGrid hook, we could encourage them to start using the DataGrid component, however this is not a breaking change nor it has to be mandatory to migrate from useDataGrid to DataGrid component.
Unresolved questions
What component library to use, probably the best option is Tanstack Table, there are not so many good libraries for our use case
Is this too much for a v1? It is important to provide our customers with enough customization for their use cases which adds a fair amount of work and based on the library we select we may require more or less work on implementing the required features, should we shrink requirements for v1?
Pagination in static mode. In the current design we only consider connected mode for this, although customers could implement pagination on their own using the override, should we also care about supporting pagination in static mode for v1?
Should we enable downloading query data as .csv?
The text was updated successfully, but these errors were encountered:
What's the problem?
We already have the useDataGrid query hook working on the ui-kit, however, we don’t have a component that consumes it, also in order to implement the new SQL Playground in Console, we’ll require to have a DataGrid component for the result visualization.
What are the requirements?
Following the same pattern we have for other components, the
DataGrid
component should provide a higher-level API that enables customers to setup a basicDataGrid
easily but also enable exposing a lower-level API to access the inner table components directly, hopefully the library we use enables us to export its API directly similar to what we do on Chart.js withchartConfigProps
.We already have the
useDataGrid
hook to query the data so the most important concern is how we display it and enable customizing it.For v1, we can probably focus on getting a basic version out while we provide data visualization features that we also require on Console
ASC
, clicking twice should set toDESC
and clicking a third time should reset, sorting should be made client-side for static mode and server-side for connected mode.Requirements for table component:
The DataGrid component should return a table with the received data from DataGrid API,
<table />
elements for better a11yIn pro of following consistency with the way we implement charts, helper components, etc we should probably opt for finding a library that would best fit our needs
Candidates:
Tanstack Table (React Table)
Tanstack Table provides a headless React hook that makes it easy to implement a Table component, this is similar to what we do today with base-ui’s Select component
✅ Should enable column resize
✅ Should enable pagination
✅ Should be based on
<table />
elements for better a11y (you can base it either on div elements or table)✅ Should be fully customizable (as it’s a headless hook we have full control on the table styles’ customization)
✅ Should enable sorting by column
✅ Should enable showing/hiding row numbers
✅ Should enable showing/hiding headers
✅ Should enable showing a drawer on column/cell click
✅ Should be a lightweight library (752kb npm, 15kb with tree-shaking)
✅ Should be a well maintained library (last commit yesterday)
react-data-grid
react-data-grid provides a react component for building data grids,
react-data-grid
is currently in beta✅ Should enable column resize
❌ Should enable pagination (does not provide built-in support for pagination)
<table />
elements for better a11y (based on div elements)renderers
prop, this one enables overriding theirCheckbox
component,Row
,SortStatus
,noRowsFallback
, while this provides a certain level of customization some things seems to be missing (e.g header)✅ Should enable sorting by column
✅ Should enable showing/hiding row numbers
❌ Should enable showing/hiding headers
✅ Should enable showing a drawer on column/cell click
✅ Should be a well maintained library (last commit 4 days ago)
Other options are either paid or not as good as Tanstack Table, we decided to proceed with Tanstack Table
Detailed design
The component should receive a set of
headers
androws
for static mode, as well as other properties we already set in static mode for other components.Subcomponents should also include a
className
andstyle
prop in order to enable styles customization.Loader state
For loader we probably want to do something different to just a loading rectangle, we probably want to try something similar to console, cells in loading state and headers shown for static mode, for connected mode cells should be in loading state as well
Requirements implementation
Based on the decision of using Tanstack Table for the Table, we should rely on their examples on how to implement the features we require, here are some of the guides provided by Tanstack table:
Some features however we will have to implement on our own: drawer, exporting to .csv
Interactivity and customization
It’s necessary to enable handling most of interactivity via props, for this we will require:
We can follow our current pattern of using fallbacks/overrides in order to provide the best level of customization, we can have
RowOverride
,CellOverride
,DrawerOverride
,HeaderOverride
andPaginationOverride
Rows
For rows we would have the
rowOverride
but also a top-level prop in order to hide the indexesRowProps
Cells
CellProps
(cellValue: string | Element) => void
string | Element
onIndexClick
andonCellclick
should act as middlewares rather than overriding our setup for opening the drawer, however, if the drawer is disabled those should act as overridesDrawer
For Drawer, besides of having a
drawerOverride
component we should have a top-leveldisableDrawer
prop so customers can easily just disable it when they require it without having to add a fallback with an empty result.DrawerProps
For v1, it would be enough that the Drawer just shows the data in the cell/row but in order to enable customization we’ll need to enable an
onClose
propstring | Element
Pagination
Regarding pagination, we can provide high-level customization as well as low-level customization, for this, we most likely will want to change the rows per page options for now and then customers can fully customize the component with an override prop
The
Pagination
component should then be uncontrolled, so customers can easily call the setter and default value from props in their custom pagination component as well as theonNext
andonBack
PaginationProps
Then we would have
Header
which we could split inHeaderRow
andHeaderCell
those would be very similar toRow
andCell
but should be distinct as it’s a common use case to customize the header different to the other rows/cells, additionally we should have a top-level prop to hide the headerDrawbacks
Alternatives
useDataGrid
hook that they could use in their own tablesAdoption strategy
DataGrid
would be a new component, however, customers could be already using theuseDataGrid
hook, we could encourage them to start using theDataGrid
component, however this is not a breaking change nor it has to be mandatory to migrate fromuseDataGrid
toDataGrid
component.Unresolved questions
What component library to use, probably the best option is Tanstack Table, there are not so many good libraries for our use caseThe text was updated successfully, but these errors were encountered: