Skip to content

Commit 1d8ffb1

Browse files
ggascoignetannerlinsley
authored andcommitted
Add fixed width column support to useFlexLayout (TanStack#1810)
* Add fixed width column support to useFlexLayout * Allow useFlexLayout to honor canResize by calculating flex width separately from total width. * Update example to show the selection checkbox since that's a common fixed width use case. * Add example for right aligning columns. * Tweaked the styles for the table to better align the resize handles (since it made verifying the rest easier when they weren't misaligned by the scroll bar width) Note that the resize behavior is still rather strange, but that's a separate problem that this change didn't really effect. * swich to react-table@latest
1 parent ed2fe54 commit 1d8ffb1

File tree

5 files changed

+2165
-1240
lines changed

5 files changed

+2165
-1240
lines changed

examples/full-width-resizable-table/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"namor": "^1.1.2",
1111
"react": "^16.8.6",
1212
"react-dom": "^16.8.6",
13-
"react-scripts": "3.0.1",
13+
"react-scripts": "3.3.0",
1414
"react-table": "latest",
1515
"styled-components": "^4.3.2"
1616
},

examples/full-width-resizable-table/src/App.js

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import React from 'react'
22
import styled from 'styled-components'
3-
import { useTable, useResizeColumns, useFlexLayout } from 'react-table'
3+
import {
4+
useTable,
5+
useResizeColumns,
6+
useFlexLayout,
7+
useRowSelect,
8+
} from 'react-table'
49

510
import makeData from './makeData'
611

@@ -35,13 +40,13 @@ const Styles = styled.div`
3540
border-bottom: 0;
3641
}
3742
}
43+
border-bottom: 1px solid black;
3844
}
3945
4046
.th,
4147
.td {
4248
margin: 0;
4349
padding: 0.5rem;
44-
border-bottom: 1px solid black;
4550
border-right: 1px solid black;
4651
4752
${'' /* In this example we use an absolutely position resizer,
@@ -53,12 +58,11 @@ const Styles = styled.div`
5358
}
5459
5560
.resizer {
56-
display: inline-block;
61+
right: -5px;
5762
background: blue;
5863
width: 10px;
5964
height: 100%;
6065
position: absolute;
61-
right: 0;
6266
top: 0;
6367
z-index: 1;
6468
${'' /* prevents from scrolling while dragging on touch devices */}
@@ -69,9 +73,51 @@ const Styles = styled.div`
6973
}
7074
}
7175
}
76+
77+
.th {
78+
&:last-of-type {
79+
.resizer {
80+
${'' /* note that the 15 is the scroll width and if also referenced in the getHeaderGroupProps for the header row below */}
81+
${'' /* todo: resolve this value dynamicaly from element.scrollWidth to account for OS/Browser differences */}
82+
right: -15px;
83+
}
84+
}
85+
}
7286
}
7387
`
7488

89+
const headerProps = (props, { column }) => getStyles(props, column.align)
90+
91+
const cellProps = (props, { cell }) => getStyles(props, cell.column.align)
92+
93+
const getStyles = (props, align = 'left') => [
94+
props,
95+
{
96+
style: {
97+
justifyContent: align === 'right' ? 'flex-end' : 'flex-start',
98+
alignItems: 'flex-start',
99+
display: 'flex',
100+
},
101+
},
102+
]
103+
104+
const IndeterminateCheckbox = React.forwardRef(
105+
({ indeterminate, ...rest }, ref) => {
106+
const defaultRef = React.useRef()
107+
const resolvedRef = ref || defaultRef
108+
109+
React.useEffect(() => {
110+
resolvedRef.current.indeterminate = indeterminate
111+
}, [resolvedRef, indeterminate])
112+
113+
return (
114+
<>
115+
<input type="checkbox" ref={resolvedRef} {...rest} />
116+
</>
117+
)
118+
}
119+
)
120+
75121
function Table({ columns, data }) {
76122
const defaultColumn = React.useMemo(
77123
() => ({
@@ -96,36 +142,77 @@ function Table({ columns, data }) {
96142
defaultColumn,
97143
},
98144
useResizeColumns,
99-
useFlexLayout
145+
useFlexLayout,
146+
useRowSelect,
147+
hooks => {
148+
hooks.flatColumns.push(columns => [
149+
// Let's make a column for selection
150+
{
151+
id: 'selection',
152+
disableResizing: true,
153+
minWidth: 35,
154+
width: 35,
155+
maxWidth: 35,
156+
// The header can use the table's getToggleAllRowsSelectedProps method
157+
// to render a checkbox
158+
Header: ({ getToggleAllRowsSelectedProps }) => (
159+
<div>
160+
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
161+
</div>
162+
),
163+
// The cell can use the individual row's getToggleRowSelectedProps method
164+
// to the render a checkbox
165+
Cell: ({ row }) => (
166+
<div>
167+
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
168+
</div>
169+
),
170+
},
171+
...columns,
172+
])
173+
hooks.useInstanceBeforeDimensions.push(({ headerGroups }) => {
174+
// fix the parent group of the selection button to not be resizable
175+
const selectionGroupHeader = headerGroups[0].headers[0]
176+
selectionGroupHeader.canResize = false
177+
})
178+
}
100179
)
101180

102181
return (
103182
<div {...getTableProps()} className="table">
104183
<div>
105184
{headerGroups.map(headerGroup => (
106-
<div {...headerGroup.getHeaderGroupProps()} className="tr">
185+
<div
186+
{...headerGroup.getHeaderGroupProps({
187+
style: { paddingRight: '15px' },
188+
})}
189+
className="tr"
190+
>
107191
{headerGroup.headers.map(column => (
108-
<div {...column.getHeaderProps()} className="th">
192+
<div {...column.getHeaderProps(headerProps)} className="th">
109193
{column.render('Header')}
110194
{/* Use column.getResizerProps to hook up the events correctly */}
111-
<div
112-
{...column.getResizerProps()}
113-
className={`resizer ${column.isResizing ? 'isResizing' : ''}`}
114-
/>
195+
{column.canResize && (
196+
<div
197+
{...column.getResizerProps()}
198+
className={`resizer ${
199+
column.isResizing ? 'isResizing' : ''
200+
}`}
201+
/>
202+
)}
115203
</div>
116204
))}
117205
</div>
118206
))}
119207
</div>
120-
121208
<div {...getTableBodyProps()} className="tbody">
122209
{rows.map((row, i) => {
123210
prepareRow(row)
124211
return (
125212
<div {...row.getRowProps()} className="tr">
126213
{row.cells.map(cell => {
127214
return (
128-
<div {...cell.getCellProps()} className="td">
215+
<div {...cell.getCellProps(cellProps)} className="td">
129216
{cell.render('Cell')}
130217
</div>
131218
)
@@ -161,11 +248,13 @@ function App() {
161248
Header: 'Age',
162249
accessor: 'age',
163250
width: 50,
251+
align: 'right',
164252
},
165253
{
166254
Header: 'Visits',
167255
accessor: 'visits',
168256
width: 50,
257+
align: 'right',
169258
},
170259
{
171260
Header: 'Status',

0 commit comments

Comments
 (0)