Getting Started
Introduction
React Grid is a tabular View library used within the Tenqube company.
It is composed of React components and can be implemented easily and intuitively by passing the data constituting the table as Props.
It is still an early version, so there may be unstable parts. Please register the problematic part as an issue on GitHub.
Installation
npm install @tenqube/react-grid
Features
Change and remember column width
You can change the size of each column in the table by enabling the scalable setting in options, and the changes will be saved and persisted in web storage.
Fixed column not working to scroll
If you enter a size in the fixedSize setting in options, the column is fixed by that size. (default 0)
Other basic features..
Provided as a sorting status callback by column.
Specifying per-row classes for styling.
Provides column types such as checkbox and toggle.
Browser compatibility
Chrome | IE | Edge | Safari | Firefox |
---|---|---|---|---|
⃝ | ✕ | ⃝ | ⃝ | ⃝ |
Quick Start
React Grid makes it simple to construct a table view by passing the promised columns and rows as Props.
and below is a simple configuration example.
Simple Code
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const GridComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'week',
name: 'THIS WEEK',
type: GridType.String
}, {
id: 'title',
name: 'TITLE',
type: GridType.String
}, {
id: 'artist',
name: 'ARTIST',
type: GridType.String,
}, {
id: 'award',
name: 'AWARD',
type: GridType.String
}]
const rows: Array<Array<RowType>> = [[
'1', 'Last Night', 'Morgan Wallen', '★'
], [
'2', 'Flowers', 'Miley Cyrus', ''
], [
'3', 'Kill Bill', 'SZA', ''
], [
'4', 'Calm Down', 'Rema & Selena Gomez', '★'
], [
'5', 'Favorite Song', 'Toosii', '★'
]]
return (
<Grid id={'billboard'} columns={columns} rows={rows} />
)
}
export default GridComponent
Previews
THIS WEEK | TITLE | ARTIST | AWARD |
---|---|---|---|
1 | Last Night | Morgan Wallen | ★ |
2 | Flowers | Miley Cyrus | |
3 | Kill Bill | SZA | |
4 | Calm Down | Rema & Selena Gomez | ★ |
5 | Favorite Song | Toosii | ★ |
Props
React Grid provides props of id, columns, rows, options and addClassNameByRows.
ID
The id props use a unique value for each table element as a delimiter. Currently, this value is used as a separator to remember the column width value when using the scalable option.
If you don't use the scalable option, it doesn't matter too much if the value isn't unique, but it can affect future features.
A unique value is recommended.
Type | Required |
---|---|
String | ⃝ |
Columns, Rows
Column configuration is performed according to the data type of the corresponding column. Column type is provided as Enum under the name of GridType in the library.
Checkbox
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.Checkbox) | number(1) | ⃝ |
callback | (isAll: boolean, rowIdx: number, columnIdx: number): void | ⃝ |
width | number | |
className | string |
import React, { useState } from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const CheckboxTypeComponent = () => {
const [rows, setRows] = useState<Array<Array<RowType>>>([[true], [false]])
const handleClickCheckbox = (isAll: boolean, rowIdx: number, columnIdx: number) => {
if(isAll) {
const newRows = rows.map((row) => {
const cloneRow = [...row]
cloneRow[0] = !rows.every((row) => row[0] === true)
return cloneRow
})
setRows(newRows)
} else {
const cloneRows = rows.map(row => [...row])
cloneRows[rowIdx][columnIdx] = !cloneRows[rowIdx][columnIdx]
setRows(cloneRows)
}
}
const columns: Array<IPropsColumn> = [{
id: 'checkbox',
type: GridType.Checkbox,
callback: handleClickCheckbox
}]
return (
<Grid id={'checkbox'} columns={columns} rows={rows} />
)
}
export default CheckboxTypeComponent
The callback function provides three arguments, isAll, rowIdx, and columnIdx.
A value of isAll means the difference between checking the head checkbox and checking the body checkbox. Based on the above factors, freely compose and use a callback function.
Previews
String
enum OrderType {
Default,
ASC,
DESC
}
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.String) | number(2) | ⃝ |
name | string | |
width | number | |
className | string | |
isSorting | boolean | |
callback | (columnId: string, orderType: OrderType) => void |
import React, { useState } from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const StringTypeComponent = () => {
const ascRows = [['aaa'], ['bbb'], ['ccc']]
const descRows = [['ccc'], ['bbb'], ['aaa']]
const [rows, setRows] = useState<Array<Array<RowType>>>(ascRows)
const handleSorting = (columnId: string, orderType: OrderType) => {
setRows(orderType === OrderType.ASC ? ascRows : descRows)
}
const columns: Array<IPropsColumn> = [{
id: 'string',
name: 'Text',
type: GridType.String,
isSorting: true,
callback: handleSorting
}]
return (
<Grid id={'string'} columns={columns} rows={rows} />
)
}
export default StringTypeComponent
The callback property of string type has meaning only when isSorting property is true.
The callback function is called when the sort icon is selected and provides the columnId and orderType arguments.
Previews
Text |
---|
aaa |
bbb |
ccc |
Toggle
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.Toggle) | number(3) | ⃝ |
callback | (rowIdx: number, columnIdx: number) => void | ⃝ |
name | string | |
width | number | |
className | string |
import React, { useState } from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const ToggleTypeComponent = () => {
const [rows, setRows] = useState<Array<Array<RowType>>>([[true], [false]])
const handleToggle = (rowIdx: number, columnIdx: number) => {
const cloneRows = rows.map(row => [...row])
cloneRows[rowIdx][columnIdx] = !cloneRows[rowIdx][columnIdx]
setRows(cloneRows)
}
const columns: Array<IPropsColumn> = [{
id: 'toggle',
name: 'Toggle',
type: GridType.Toggle,
callback: handleToggle
}]
return (
<Grid id={'toggle'} columns={columns} rows={rows} />
)
}
export default ToggleTypeComponent
Previews
Toggle |
---|
Image
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.Image) | number(4) | ⃝ |
name | string | |
width | number | |
className | string |
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const ImageTypeComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'image',
name: 'Image',
type: GridType.Image
}]
const rows: Array<Array<RowType>> = [[
'https://tenqube-images.s3.ap-northeast-2.amazonaws.com/labs/imagetype-example.png'
]]
return (
<Grid id={'image'} columns={columns} rows={rows} />
)
}
export default ImageTypeComponent
The image type column data is in the form of a string, and the image is displayed using the URI Path.
Previews
Image |
---|
Link
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.Link) | number(5) | ⃝ |
name | string | |
width | number | |
className | string | |
isSorting | boolean | |
callback | (columnId: string, orderType: OrderType) => void |
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const LinkTypeComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'link',
name: 'Link',
type: GridType.Link
}]
const rows: Array<Array<RowType>> = [[{
name: 'tenqube website',
target: '_blank',
url: 'https://tenqube.com'
}]]
return (
<Grid id={'link'} columns={columns} rows={rows} />
)
}
export default LinkTypeComponent
interface ILinkRows {
name: string
target: string
url: string
}
Data of link type is composed of HTML a tag in object form like interface above.
Although not included in the sample code, the sorting function can be implemented through the isSorting property and callback function, just like the String type.
Previews
Link |
---|
Items
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.Items) | number(7) | ⃝ |
items | Array<FC<{ rowIdx: number; columnIdx: number }> | ReactNode> | ⃝ |
name | string | |
width | number | |
className | string | |
isSorting | boolean | |
callback | (columnId: string, orderType: OrderType) => void |
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const ItemComponent = ({ text }) => {
return (
<p style={{
lineHeight: '24px',
padding: '10px 15px'
}}>
{ text }
</p>
)
}
const ItemsTypeComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'items',
name: 'Items',
type: GridType.Items,
items: [
<ItemComponent text={'ReactNode Type.'} />,
({ rowIdx, columnIdx }) => {
const text = `FC Type. (rowIdx: ${rowIdx}, columnIdx: ${columnIdx})`
return (
<ItemComponent text={text} />
)
}
]
}]
const rows: Array<Array<RowType>> = [[
0
], [
1
]]
return (
<Grid id={'items'} columns={columns} rows={rows} />
)
}
export default ItemsTypeComponent
The Items type declares component-type array data in columns, and rows data is declared as the index value of the array. If the item component requires a rowIdx(row index) and columnIdx(column index), it can be configured as a functional component using the provided arguments.
Although not included in the sample code, the sorting function can be implemented through the isSorting property and callback function, just like the String type.
Previews
Items |
---|
ReactNode Type. |
FC Type. (rowIdx: 1, columnIdx: 0) |
Input(text)
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.InputText) | number(8) | ⃝ |
callback | (rowIdx: number, columnIdx: number, value: string) => void | ⃝ |
name | string | |
width | number | |
className | string |
import React, { useState } from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const InputTextTypeComponent = () => {
const [rows, setRows] = useState<Array<Array<RowType>>>([['aaa'], ['bbb']])
const handleChange = (rowIdx: number, columnIdx: number, value: string) => {
const cloneRows = rows.map(row => [...row])
cloneRows[rowIdx][columnIdx] = value
setRows(cloneRows)
}
const columns: Array<IPropsColumn> = [{
id: 'input-text',
name: 'Input Text',
type: GridType.InputText,
callback: handleChange
}]
return (
<Grid id={'input-text'} columns={columns} rows={rows} />
)
}
export default InputTextTypeComponent
The Input(text) type is an HTML input tag whose value can be modified by the user. Modification information can be checked through the callback function.
Previews
Input Text |
---|
Input(number)
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.InputNumber) | number(9) | ⃝ |
callback | (rowIdx: number, columnIdx: number, value: number) => void | ⃝ |
name | string | |
width | number | |
className | string |
import React, { useState } from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const InputNumberTypeComponent = () => {
const [rows, setRows] = useState<Array<Array<RowType>>>([[1], [2]])
const handleChange = (rowIdx: number, columnIdx: number, value: number) => {
const cloneRows = rows.map(row => [...row])
cloneRows[rowIdx][columnIdx] = value
setRows(cloneRows)
}
const columns: Array<IPropsColumn> = [{
id: 'input-nunber',
name: 'Input Number',
type: GridType.InputNumber,
callback: handleChange
}]
return (
<Grid id={'input-number'} columns={columns} rows={rows} />
)
}
export default InputNumberTypeComponent
Same as Input(text) type. However, the input's data type is number.
Previews
Input Number |
---|
Array
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.Array) | number(10) | ⃝ |
name | string | |
width | number | |
className | string |
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const ArrayTypeComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'array',
name: 'Array',
type: GridType.Array
}]
const rows: Array<Array<RowType>> = [[
['aaa', 'bbb', 'ccc']
]]
return (
<Grid id={'array'} columns={columns} rows={rows} />
)
}
export default ArrayTypeComponent
The array type receives data in the form of an array in rows and outputs them by creating small boxes in columns.
Previews
Array |
---|
aaabbbccc |
Component
Property | Type | Required |
---|---|---|
id | string | ⃝ |
type | Enum(GridType.Component) | number(11) | ⃝ |
name | string | |
width | number | |
className | string | |
isSorting | boolean | |
callback | (columnId: string, orderType: OrderType) => void |
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType } from '@tenqube/react-grid'
const ComponentTypeComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'component',
name: 'Component',
type: GridType.Component
}]
const rows: Array<Array<RowType>> = [[
items: [
<ItemComponent text={'ReactNode Type.'} />,
({ rowIdx, columnIdx }) => {
const text = `FC Type. (rowIdx: ${rowIdx}, columnIdx: ${columnIdx})`
return (
<ItemComponent text={text} />
)
}
]
]]
return (
<Grid id={'component'} columns={columns} rows={rows} />
)
}
export default ComponentTypeComponent
Although not included in the sample code, the sorting function can be implemented through the isSorting property and callback function, just like the String type.
Previews
Component |
---|
ReactNode Type. |
FC Type. (rowIdx: 1, columnIdx: 0) |
Options
Provides a scalable property that can change the size of a column and a fixedSize property that can specify the number of columns that do not operate on scrolling.
Property | Type | Default |
---|---|---|
scalable | boolean | IPropsScalableOption | false |
fixedSize | number | 0 |
scroll | IPropsScrollOption | null |
Scalable
You can change the size of a table column by activating the scalable option. And the changed size is saved and maintained in web storage.
Saving to session storage is the default option when the scalable option is enabled.
IPropsScalableOption
Property | Type | Default | Required |
---|---|---|---|
enable | boolean | false | ⃝ |
storage | boolean | IPropsStorageOption | true |
IPropsStorageOption
Property | Type | Default | Required |
---|---|---|---|
enable | boolean | true | ⃝ |
target | 'local' | 'session' | 'session' |
In IPropsStorageOption, target value means WebStorage.
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType, IPropsOptions } from '@tenqube/react-grid'
const ScalableComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'week',
name: 'THIS WEEK',
type: GridType.String
}, {
id: 'title',
name: 'TITLE',
type: GridType.String
}, {
id: 'artist',
name: 'ARTIST',
type: GridType.String,
}, {
id: 'award',
name: 'AWARD',
type: GridType.String
}, {
id: 'last-week',
name: 'LAST WEEK',
type: GridType.String
}, {
id: 'peak-pos',
name: 'PEAK POS.',
type: GridType.String
}]
const rows: Array<Array<RowType>> = [[
'1', 'Last Night', 'Morgan Wallen', '★', '1', '1'
], [
'2', 'Flowers', 'Miley Cyrus', '', '3', '1'
]]
const options: IPropsOptions = {
scalable: true
}
return (
<Grid id={'billboard-scalable'} columns={columns} rows={rows} options={options} />
)
}
export default ScalableComponent
In its most basic form, if the scalable value is set to true, the changed column size is stored in session storage and maintained until the tab is closed.
Previews
THIS WEEK | TITLE | ARTIST | AWARD | LAST WEEK | PEAK POS. |
---|---|---|---|---|---|
1 | Last Night | Morgan Wallen | ★ | 1 | 1 |
2 | Flowers | Miley Cyrus | 3 | 1 |
...
const options: IPropsOptions = {
scalable: {
enable: true,
storage: false
}
}
...
If the storage value is set to false while the scalable value is enabled, the size of the column will not be maintained when refreshing.
Previews
THIS WEEK | TITLE | ARTIST | AWARD | LAST WEEK | PEAK POS. |
---|---|---|---|---|---|
1 | Last Night | Morgan Wallen | ★ | 1 | 1 |
2 | Flowers | Miley Cyrus | 3 | 1 |
FixedSize
Columns are fixed from the left by the value of the fixedSize option.
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType, IPropsOptions } from '@tenqube/react-grid'
const FixedSizeOneComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'week',
name: 'THIS WEEK',
type: GridType.String
}, {
id: 'title',
name: 'TITLE',
type: GridType.String
}, {
id: 'artist',
name: 'ARTIST',
type: GridType.String,
}, {
id: 'award',
name: 'AWARD',
type: GridType.String
}, {
id: 'last-week',
name: 'LAST WEEK',
type: GridType.String
}, {
id: 'peak-pos',
name: 'PEAK POS.',
type: GridType.String
}]
const rows: Array<Array<RowType>> = [[
'1', 'Last Night', 'Morgan Wallen', '★', '1', '1'
], [
'2', 'Flowers', 'Miley Cyrus', '', '3', '1'
]]
const options: IPropsOptions = {
fixedSize: 1
}
return (
<Grid id={'billboard-fixed-1'} columns={columns} rows={rows} options={options} />
)
}
export default FixedSizeOneComponent
Previews
THIS WEEK | TITLE | ARTIST | AWARD | LAST WEEK | PEAK POS. |
---|---|---|---|---|---|
1 | Last Night | Morgan Wallen | ★ | 1 | 1 |
2 | Flowers | Miley Cyrus | 3 | 1 |
If the number of fixed columns is set to two, it is as follows.
const options: IPropsOptions = {
fixedSize: 2
}
Previews
THIS WEEK | TITLE | ARTIST | AWARD | LAST WEEK | PEAK POS. |
---|---|---|---|---|---|
1 | Last Night | Morgan Wallen | ★ | 1 | 1 |
2 | Flowers | Miley Cyrus | 3 | 1 |
Scroll
The scroll options let you decide whether scrolling is controlled internally or externally.
IPropsScrollOption
Property | Type | Default | Required |
---|---|---|---|
enable | boolean | false | ⃝ |
type | 'inner' | 'outer' | inner | |
height | number | 0 |
If you specify the inner type of the option and the height value, an inner scroll is created.
import React from 'react'
import Grid, { GridType, IPropsColumn, RowType, IPropsOptions } from '@tenqube/react-grid'
const ScrollInnerComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'week',
name: 'THIS WEEK',
type: GridType.String
}, {
id: 'title',
name: 'TITLE',
type: GridType.String
}, {
id: 'artist',
name: 'ARTIST',
type: GridType.String,
}, {
id: 'award',
name: 'AWARD',
type: GridType.String
}, {
id: 'last-week',
name: 'LAST WEEK',
type: GridType.String
}, {
id: 'peak-pos',
name: 'PEAK POS.',
type: GridType.String
}]
const rows: Array<Array<RowType>> = [[
'1', 'Last Night', 'Morgan Wallen', '★', '1', '1'
], [
'2', 'Flowers', 'Miley Cyrus', '', '3', '1'
], [
'3', 'Kill Bill', 'SZA', '', '', ''
], [
'4', 'Calm Down', 'Rema & Selena Gomez', '★', '', ''
], [
'5', 'Favorite Song', 'Toosii', '★', '', ''
]]
const options: IPropsOptions = {
scroll: {
enable: true,
type: 'inner',
height: 200
}
}
return (
<Grid id={'scroll-1'} columns={columns} rows={rows} options={options} />
)
}
export default ScrollInnerComponent
Previews
THIS WEEK | TITLE | ARTIST | AWARD | LAST WEEK | PEAK POS. |
---|---|---|---|---|---|
1 | Last Night | Morgan Wallen | ★ | 1 | 1 |
2 | Flowers | Miley Cyrus | 3 | 1 | |
3 | Kill Bill | SZA | |||
4 | Calm Down | Rema & Selena Gomez | ★ | ||
5 | Favorite Song | Toosii | ★ |
...
const options: IPropsOptions = {
scroll: {
enable: true,
type: 'outer'
}
}
return (
<div style={{
height: '200px',
overflow: 'auto'
}>
<p>...</p>
<Grid id={'scroll-2'} columns={columns} rows={rows} options={options} />
</div>
)
...
If you use the outer option, you can control the outer scrolling and the head of the table is sticky.
The height option is not used when outer options are used.
Previews
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
THIS WEEK | TITLE | ARTIST | AWARD | LAST WEEK | PEAK POS. |
---|
1 | Last Night | Morgan Wallen | ★ | 1 | 1 |
2 | Flowers | Miley Cyrus | 3 | 1 | |
3 | Kill Bill | SZA | |||
4 | Calm Down | Rema & Selena Gomez | ★ | ||
5 | Favorite Song | Toosii | ★ |
AddClassNameByRows
You can assign a className to a specific row via the addClassNameByRows setting. Used to style specific irregular rows.
interface IClassNameByRow {
index: number
className: string | Array<string>
}
import React from 'react'
import styled from '@emotion/styled'
import Grid, { GridType, IPropsColumn, RowType, IClassNameByRow } from '@tenqube/react-grid'
const AddClassComponent = () => {
const columns: Array<IPropsColumn> = [{
id: 'string',
name: 'Text',
type: GridType.String
}]
const rows: Array<Array<RowType>> = [[
'data1'
], [
'data2'
], [
'data3'
], [
'data4'
]]
const addClassNameByRows: Array<IClassNameByRow> = [{
index: 3,
className: 'color-red',
}]
return (
<$area>
<Grid id={'add-class'} columns={columns} rows={rows} addClassNameByRows={addClassNameByRows} />
</$area>
)
}
export default AddClassComponent
const $area = styled.div`
.color-red {
color: red;
}
`
The index value starts from 0.
Previews
Text |
---|
data1 |
data2 |
data3 |
data4 |
To add multiple classNames, add objects at the same index.
const addClassNameByRows: Array<IClassNameByRow> = [{
index: 3,
className: 'color-red',
}, {
index: 3,
className: 'background-black',
}]
...
const $area = styled.div`
.color-red {
color: red;
}
.background-black {
background: black;
}
`
Previews
Text |
---|
data1 |
data2 |
data3 |
data4 |
Building
React Grid only provides very basic functionality. However, it can be developed and extended in many ways.
Styling
A separate method for styling is not supported. Instead, it supports a className that can be distinguished for various items.
{id}-column-{index}
A className is declared for every column according to the grid id and index value of the column. Index starts from 0, and Hidden type columns are not included in the index because they are not displayed.
{GridType}-type
enum GridType {
Hidden,
Checkbox,
String
Toggle
Image
Link
Button
Items
InputText
InputNumber
Array
}
A className is declared in the column according to the grid type.
EX. string-type, toggle-type, input-text-type, ...
row-{index}
A className including index is given for each row.
fixed
Columns that are fixed using the fixedSize option are declared with a className of 'fixed'.