-
Notifications
You must be signed in to change notification settings - Fork 1.2k
TableView Column resizing #2883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a762c26
1d4e93d
3a4645a
e8dda05
3851565
b5fcedc
5c562b9
28cd3ba
6146c8c
1499f75
5ae06bd
2237b91
de81e6d
d9c5052
8edb449
fa85efa
790c5d2
5d9a476
8b5b06d
ff76327
c8508eb
bc38051
ea8d7fc
eb74736
fff9177
a5e071d
6decb42
ff58f69
4521e09
b713fff
2f2ec3d
f010127
0c501f4
8fc42d1
b153299
133baf1
eef5cb0
8a2408d
8f26199
ddff409
85a885a
f083e67
f45fcb7
bfe6c4c
5b9fd90
a5854ce
b036393
5735265
4d8ae16
8bcf528
f03035b
59aa98c
c8ac9c0
85f859b
d14e886
19d3aed
d6438ab
9294509
34b6e3a
2c2d3a8
4ea86eb
8240301
378e97a
9d22061
32f00dd
d0f1f94
5813ef6
2908a53
8126f9a
7c51665
ca6e38c
bf24fd7
3e73974
74c6b1f
ff53d5c
cc0bfcb
d308046
381e50f
16f6f0b
40198c4
f7fd8ee
518a0e6
376c942
88f3c22
9115326
79b1ccd
b0596b1
188b536
c26ebd8
20b851a
25c89ac
0e9c12e
3bf4357
5ca0f8f
12250eb
26f5364
9221f11
87a973b
f9549f9
d2c322b
3c0be58
04253c9
4f5d360
272dc71
0abad4e
fb75d7d
7ad117f
1999421
b3f2941
1212451
c2571b5
77c0b56
4ffa912
38ef25f
8e22ad1
21d6ea2
e1b3314
8329218
e7d7973
7259f56
1e2ee48
ca2f0a8
ca48557
6ad30c1
0c73f6b
25eb15f
d7b6e74
a7fc5cd
dd013db
50ebf80
c68881d
d4ef1a8
5741bd3
588f0fd
452d284
7e9f9bd
b34aa30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright 2020 Adobe. All rights reserved. | ||
* This file is licensed to you under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. You may obtain a copy | ||
* of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under | ||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS | ||
* OF ANY KIND, either express or implied. See the License for the specific language | ||
* governing permissions and limitations under the License. | ||
*/ | ||
|
||
import {focusSafely, useFocusable} from '@react-aria/focus'; | ||
import {mergeProps} from '@react-aria/utils'; | ||
import {useKeyboard, useMove} from '@react-aria/interactions'; | ||
import {useLocale} from '@react-aria/i18n'; | ||
import {useRef} from 'react'; | ||
|
||
export function useTableColumnResize(state, item, ref): any { | ||
const stateRef = useRef(null); | ||
// keep track of what the cursor on the body is so it can be restored back to that when done resizing | ||
const cursor = useRef(null); | ||
stateRef.current = state; | ||
|
||
let {direction} = useLocale(); | ||
let {focusableProps} = useFocusable({excludeFromTabOrder: true}, ref); | ||
let {keyboardProps} = useKeyboard({ | ||
onKeyDown: (e) => { | ||
if (e.key === 'Tab') { | ||
// useKeyboard stops propagation by default. We want to continue propagation for tab so focus leaves the table | ||
e.continuePropagation(); | ||
} | ||
if (e.key === 'Escape' || e.key === 'Enter' || e.key === ' ') { | ||
// switch focus back to the column header on escape | ||
const columnHeader = ref.current.previousSibling; | ||
if (columnHeader) { | ||
focusSafely(columnHeader); | ||
} | ||
} | ||
} | ||
}); | ||
|
||
const columnResizeWidthRef = useRef(null); | ||
const {moveProps} = useMove({ | ||
onMoveStart() { | ||
stateRef.current.onColumnResizeStart(); | ||
columnResizeWidthRef.current = stateRef.current.getColumnWidth(item.key); | ||
snowystinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
cursor.current = document.body.style.cursor; | ||
document.body.style.setProperty('cursor', 'col-resize'); | ||
}, | ||
onMove({deltaX, pointerType}) { | ||
if (direction === 'rtl') { | ||
deltaX *= -1; | ||
} | ||
// if moving up/down only, no need to resize | ||
if (deltaX !== 0) { | ||
if (pointerType === 'keyboard') { | ||
deltaX *= 10; | ||
} | ||
columnResizeWidthRef.current += deltaX; | ||
stateRef.current.onColumnResize(item, columnResizeWidthRef.current); | ||
} | ||
}, | ||
onMoveEnd() { | ||
stateRef.current.onColumnResizeEnd(); | ||
columnResizeWidthRef.current = 0; | ||
document.body.style.cursor = cursor.current; | ||
} | ||
}); | ||
|
||
return { | ||
resizerProps: { | ||
...mergeProps(moveProps, focusableProps, keyboardProps) | ||
} | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* eslint-disable jsx-a11y/role-supports-aria-props */ | ||
import {classNames} from '@react-spectrum/utils'; | ||
import {FocusRing} from '@react-aria/focus'; | ||
import React from 'react'; | ||
import styles from '@adobe/spectrum-css-temp/components/table/vars.css'; | ||
import {useTableColumnResize} from '@react-aria/table/src/useTableColumnResize'; | ||
import {useTableContext} from './TableView'; | ||
|
||
|
||
function Resizer(props, ref) { | ||
const {item} = props; | ||
let state = useTableContext(); | ||
let {resizerProps} = useTableColumnResize(state, item, ref); | ||
return ( | ||
<FocusRing focusRingClass={classNames(styles, 'focus-ring')}> | ||
<div | ||
ref={ref} | ||
{...resizerProps} | ||
className={classNames(styles, 'spectrum-Table-columnResizer')} | ||
role="separator" | ||
aria-orientation="vertical" | ||
aria-label="Resize column" | ||
aria-labelledby={item.key} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't actually point to a As an aside I noticed that the column headers also have lost their "columnheader" role in favor of the "button" role provided by MenuTrigger, note to self to double check that the rest of the attributes are still valid (it seems ok so far?) |
||
aria-valuenow={state.getColumnWidth(item.key)} | ||
aria-valuemin={state.getColumnMinWidth(item.key)} | ||
aria-valuemax={state.getColumnMaxWidth(item.key)} /> | ||
</FocusRing> | ||
); | ||
} | ||
|
||
const _Resizer = React.forwardRef(Resizer); | ||
export {_Resizer as Resizer}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps a minor point:
Is adding a menu trigger to the column header when the column supports resizing an interaction pattern we'll be recommending for a non-Spectrum tables as well? If not, then I don't know if we wanna disable the press to sort interactions here, perhaps the pressProps from this hook should be overridden in the TableView instead.
Just thinking about a case where someone using our table hooks implements column resizing in a such a way that pressing the column headers should perform the sort action still and resizing via keyboard is handled in a different way (keyboard shortcut maybe? I'll need to dig to see if any other tables support resizing columns via keyboard).