Skip to content

Commit 5598169

Browse files
author
Elliot
authored
TreeItem: Support Cmd + Enter callback prop (#1556)
* Added onMetaEnter prop to TreeItem to catch CMD + Enter key * Added docs for onMetaEnterKeyDown * Added proper prop name * Change prop name from onMetaEnterKeyDown to onMetaEnter * Modified handleKeyDown to trigger onClick on Cmd + Enter when onMetaEnter is NOT provided * Removed fallback behavior of cmd+enter to onClick and updated event.keyCode usages to event.key * Combined enter and cmd+enter checks in handleKeyDown * Replaced passed-in handler undefined checks with noop default value assign * Added better explanation of onMetaEnter on tree docs
1 parent 42353ee commit 5598169

File tree

3 files changed

+29
-9
lines changed

3 files changed

+29
-9
lines changed

packages/components/src/Tree/TreeItem.tsx

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
uiTransparencyBlend,
4545
} from '@looker/design-tokens'
4646
import Omit from 'lodash/omit'
47+
import noop from 'lodash/noop'
4748
import { Space, FlexItem } from '../Layout'
4849
import { Icon, IconNames } from '../Icon'
4950
import { useHovered } from '../utils/useHovered'
@@ -89,6 +90,11 @@ export interface TreeItemProps
8990
* onClick callback
9091
*/
9192
onClick?: () => void
93+
/**
94+
* Callback that is triggered on CMD + Enter on Mac
95+
* or Windows key + Enter on PC
96+
*/
97+
onMetaEnter?: () => void
9298
/**
9399
* Determines if this TreeItem is in a selected state or not
94100
*/
@@ -103,6 +109,7 @@ const TreeItemLayout: FC<TreeItemProps> = ({
103109
children,
104110
className,
105111
gapSize = 'xsmall',
112+
onMetaEnter = noop,
106113
selected,
107114
truncate,
108115
...props
@@ -113,7 +120,13 @@ const TreeItemLayout: FC<TreeItemProps> = ({
113120
const [isHovered] = useHovered(itemRef)
114121
const [isFocusVisible, setFocusVisible] = useState(false)
115122

116-
const { onBlur, onClick, onKeyDown, onKeyUp, ...restProps } = Omit(props, [
123+
const {
124+
onBlur = noop,
125+
onClick = noop,
126+
onKeyDown = noop,
127+
onKeyUp = noop,
128+
...restProps
129+
} = Omit(props, [
117130
'color',
118131
'detail',
119132
'detailAccessory',
@@ -142,14 +155,14 @@ const TreeItemLayout: FC<TreeItemProps> = ({
142155
}
143156

144157
setFocusVisible(false)
145-
onClick && onClick()
158+
onClick()
146159
}
147160

148161
const handleKeyUp = (event: KeyboardEvent<HTMLDivElement>) => {
149-
if (event.keyCode === 9 && event.currentTarget === event.target)
162+
if (event.key === 'Tab' && event.currentTarget === event.target)
150163
setFocusVisible(true)
151164

152-
onKeyUp && onKeyUp(event)
165+
onKeyUp(event)
153166
}
154167

155168
const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
@@ -162,16 +175,16 @@ const TreeItemLayout: FC<TreeItemProps> = ({
162175
return
163176
}
164177

165-
if (event.keyCode === 13 && event.target === event.currentTarget) {
166-
onClick && onClick()
178+
if (event.key === 'Enter') {
179+
event.metaKey ? onMetaEnter() : onClick()
167180
}
168181

169-
onKeyDown && onKeyDown(event)
182+
onKeyDown(event)
170183
}
171184

172185
const handleBlur = (event: FocusEvent<HTMLDivElement>) => {
173186
setFocusVisible(false)
174-
onBlur && onBlur(event)
187+
onBlur(event)
175188
}
176189

177190
const defaultIconSize = 12
@@ -185,6 +198,7 @@ const TreeItemLayout: FC<TreeItemProps> = ({
185198
)
186199

187200
const TextWrapper = truncate ? Truncate : Fragment
201+
const isTreeItemTabbable = onClick || onMetaEnter ? 0 : -1
188202

189203
return (
190204
<HoverDisclosureContext.Provider value={{ visible: isHovered }}>
@@ -197,7 +211,7 @@ const TreeItemLayout: FC<TreeItemProps> = ({
197211
onKeyDown={handleKeyDown}
198212
onKeyUp={handleKeyUp}
199213
ref={itemRef}
200-
tabIndex={onClick ? 0 : -1}
214+
tabIndex={isTreeItemTabbable}
201215
{...restProps}
202216
>
203217
<TreeItemLabel gap={gapSize} hovered={isHovered} selected={selected}>

packages/components/src/Tree/stories/FieldPicker.story.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ const PickerItem = ({ children = 'Cost', truncate = false }) => {
114114
}
115115
detailHoverDisclosure={!overlay}
116116
onClick={() => alert('Clicked on cost!')}
117+
onMetaEnter={() => alert("Cmd + Enter'ed on cost!")}
117118
selected={!!overlay}
118119
icon="FieldNumber"
119120
>

www/src/documentation/components/content/tree.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,17 @@ Use the `gapSize` prop to control the distance between elements in your `TreeIte
181181

182182
Use the `selected` prop to display a light grey background on a given `TreeItem`.
183183

184+
Use the `onClick` prop to trigger a callback on click or when pressing the "Enter" key on a focused `TreeItem`.
185+
186+
Use the `onMetaEnter` prop to trigger a callback when pressing the "Enter" key in combination with the meta key (i.e. "Command" or "Windows" key) on a focused `TreeItem`.
187+
184188
```jsx
185189
<Tree label="Cheeses" defaultOpen>
186190
<TreeItem
187191
icon="LogoRings"
188192
detail={<Text variant="text2">is great</Text>}
189193
onClick={() => alert('Clicked Swiss')}
194+
onMetaEnter={() => alert('Clicked Swiss while holding meta key')}
190195
selected
191196
>
192197
Swiss

0 commit comments

Comments
 (0)