Skip to content

Commit

Permalink
feat(notebooks): make panels focusable (#18233)
Browse files Browse the repository at this point in the history
* feat: make panels click to focus instead of hover

* chore: prettier

* fix: prevent event bubbling from move panel button

This causes the focus behavior to do weird things

* feat: add title attributes to notebook panel buttons

* refactor: change default cell name to "Cell"

* refactor: show panel buttons on hover and focus state

* refactor: wrap updatePanelFocus in useCallback
  • Loading branch information
alexpaxton authored May 27, 2020
1 parent ba63968 commit 0eb1e06
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 34 deletions.
16 changes: 13 additions & 3 deletions ui/src/notebooks/components/panel/MovePanelButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Libraries
import React, {FC} from 'react'
import React, {FC, MouseEvent} from 'react'

// Components
import {SquareButton, IconFont, ComponentStatus} from '@influxdata/clockface'
Expand All @@ -13,13 +13,23 @@ const MovePanelUpButton: FC<Props> = ({onClick, direction}) => {
const status = onClick ? ComponentStatus.Default : ComponentStatus.Disabled
const icon = direction === 'up' ? IconFont.CaretUp : IconFont.CaretDown

const handleClick = (): void => {
const handleClick = (e: MouseEvent<HTMLButtonElement>): void => {
if (onClick) {
e.stopPropagation()
onClick()
}
}

return <SquareButton icon={icon} onClick={handleClick} status={status} />
const title = `Move this cell ${direction}`

return (
<SquareButton
icon={icon}
onClick={handleClick}
titleText={title}
status={status}
/>
)
}

export default MovePanelUpButton
35 changes: 28 additions & 7 deletions ui/src/notebooks/components/panel/NotebookPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Libraries
import React, {FC, useContext, useCallback, ReactNode} from 'react'
import React, {FC, useContext, useCallback, ReactNode, MouseEvent} from 'react'
import classnames from 'classnames'

// Components
Expand All @@ -8,6 +8,7 @@ import {
ComponentSize,
AlignItems,
JustifyContent,
ClickOutside,
} from '@influxdata/clockface'
import RemovePanelButton from 'src/notebooks/components/panel/RemovePanelButton'
import PanelVisibilityToggle from 'src/notebooks/components/panel/PanelVisibilityToggle'
Expand All @@ -18,7 +19,7 @@ import NotebookPanelTitle from 'src/notebooks/components/panel/NotebookPanelTitl
import {PipeContextProps} from 'src/notebooks'

// Contexts
import {NotebookContext} from 'src/notebooks/context/notebook'
import {NotebookContext, PipeMeta} from 'src/notebooks/context/notebook'

export interface Props extends PipeContextProps {
index: number
Expand Down Expand Up @@ -75,20 +76,40 @@ const NotebookPanelHeader: FC<HeaderProps> = ({index, controls}) => {
}

const NotebookPanel: FC<Props> = ({index, children, controls}) => {
const {meta} = useContext(NotebookContext)
const {meta, updateMeta} = useContext(NotebookContext)

const isVisible = meta[index].visible
const isFocused = meta[index].focus

const panelClassName = classnames('notebook-panel', {
[`notebook-panel__visible`]: isVisible,
[`notebook-panel__hidden`]: !isVisible,
'notebook-panel__focus': isFocused,
})

const updatePanelFocus = useCallback(
(focus: boolean): void => {
updateMeta(index, {focus} as PipeMeta)
},
[index, meta]
)

const handleClick = (e: MouseEvent<HTMLDivElement>): void => {
e.stopPropagation()
updatePanelFocus(true)
}

const handleClickOutside = (): void => {
updatePanelFocus(false)
}

return (
<div className={panelClassName}>
<NotebookPanelHeader index={index} controls={controls} />
<div className="notebook-panel--body">{children}</div>
</div>
<ClickOutside onClickOutside={handleClickOutside}>
<div className={panelClassName} onClick={handleClick}>
<NotebookPanelHeader index={index} controls={controls} />
<div className="notebook-panel--body">{children}</div>
</div>
</ClickOutside>
)
}

Expand Down
3 changes: 2 additions & 1 deletion ui/src/notebooks/components/panel/PanelVisibilityToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ const PanelVisibilityToggle: FC<Props> = ({index}) => {
const {meta, updateMeta} = useContext(NotebookContext)

const icon = meta[index].visible ? IconFont.EyeOpen : IconFont.EyeClosed
const title = meta[index].visible ? 'Collapse cell' : 'Expand cell'

const handleClick = (): void => {
updateMeta(index, {
visible: !meta[index].visible,
} as PipeMeta)
}

return <SquareButton icon={icon} onClick={handleClick} />
return <SquareButton icon={icon} onClick={handleClick} titleText={title} />
}

export default PanelVisibilityToggle
8 changes: 7 additions & 1 deletion ui/src/notebooks/components/panel/RemovePanelButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ const RemoveButton: FC<Props> = ({onRemove}) => {
onRemove()
}

return <SquareButton icon={IconFont.Remove} onClick={handleClick} />
return (
<SquareButton
icon={IconFont.Remove}
onClick={handleClick}
titleText="Remove this cell"
/>
)
}

export default RemoveButton
3 changes: 2 additions & 1 deletion ui/src/notebooks/context/notebook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {PipeData} from 'src/notebooks'
export interface PipeMeta {
title: string
visible: boolean
focus: boolean
}

export interface NotebookContextType {
Expand Down Expand Up @@ -63,7 +64,7 @@ export const NotebookProvider: FC = ({children}) => {
_setPipes(add(pipe))
_setMeta(
add({
title: `Notebook_${++GENERATOR_INDEX}`,
title: `Cell_${++GENERATOR_INDEX}`,
visible: true,
})
)
Expand Down
46 changes: 25 additions & 21 deletions ui/src/notebooks/style.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "@influxdata/clockface/dist/variables.scss";
@import '@influxdata/clockface/dist/variables.scss';

$notebook-header-height: 46px;
$notebook-size-toggle: 16px;
Expand Down Expand Up @@ -29,23 +29,15 @@ $notebook-divider-height: ($cf-marg-a * 2) + $cf-border;
}

&:last-of-type:after {
display: none;
display: none;
}
}

// Highlight panel on hover
.notebook-panel--header,
.notebook-panel--body {
transition: background-color 0.25s ease;
}

.notebook-panel:hover {
.notebook-panel--header,
.notebook-panel--body {
background-color: $notebook-panel--bg;
}
}

.notebook-panel--header {
border-radius: $cf-radius $cf-radius 0 0;
height: $notebook-header-height;
Expand All @@ -66,10 +58,6 @@ $notebook-divider-height: ($cf-marg-a * 2) + $cf-border;
opacity: 0;
}

.notebook-panel:hover .notebook-panel--header-right {
opacity: 1;
}

.notebook-panel--title,
.notebook-panel--data-source {
font-size: 14px;
Expand Down Expand Up @@ -103,6 +91,21 @@ $notebook-divider-height: ($cf-marg-a * 2) + $cf-border;
}
}

// Focus state
.notebook-panel__focus,
.notebook-panel:hover {
.notebook-panel--header-right {
opacity: 1;
}
}

.notebook-panel__focus {
.notebook-panel--header,
.notebook-panel--body {
background-color: $notebook-panel--bg;
}
}

.notebook-panel--data-caret {
display: inline-block;
margin-left: $cf-marg-a;
Expand All @@ -128,7 +131,8 @@ $notebook-divider-height: ($cf-marg-a * 2) + $cf-border;
left: 50%;
transform: translate(-50%, -50%);
width: $notebook-size-toggle;
transition: height 0.25s cubic-bezier(0.25, 1, 0.5, 1), border-color 0.25s ease;
transition: height 0.25s cubic-bezier(0.25, 1, 0.5, 1),
border-color 0.25s ease;
border: $cf-border solid $g8-storm;
border-radius: $cf-radius / 2;
}
Expand Down Expand Up @@ -226,11 +230,11 @@ $notebook-divider-height: ($cf-marg-a * 2) + $cf-border;
}

.notebook-header--buttons {
display: inline-flex;
flex: 0 0 auto;
flex-wrap: wrap;
display: inline-flex;
flex: 0 0 auto;
flex-wrap: wrap;

> * {
margin-left: 4px;
}
> * {
margin-left: 4px;
}
}

0 comments on commit 0eb1e06

Please sign in to comment.