diff --git a/ui/src/notebooks/components/panel/MovePanelButton.tsx b/ui/src/notebooks/components/panel/MovePanelButton.tsx index ae13d78c36..12faef8678 100644 --- a/ui/src/notebooks/components/panel/MovePanelButton.tsx +++ b/ui/src/notebooks/components/panel/MovePanelButton.tsx @@ -1,5 +1,5 @@ // Libraries -import React, {FC} from 'react' +import React, {FC, MouseEvent} from 'react' // Components import {SquareButton, IconFont, ComponentStatus} from '@influxdata/clockface' @@ -13,13 +13,23 @@ const MovePanelUpButton: FC = ({onClick, direction}) => { const status = onClick ? ComponentStatus.Default : ComponentStatus.Disabled const icon = direction === 'up' ? IconFont.CaretUp : IconFont.CaretDown - const handleClick = (): void => { + const handleClick = (e: MouseEvent): void => { if (onClick) { + e.stopPropagation() onClick() } } - return + const title = `Move this cell ${direction}` + + return ( + + ) } export default MovePanelUpButton diff --git a/ui/src/notebooks/components/panel/NotebookPanel.tsx b/ui/src/notebooks/components/panel/NotebookPanel.tsx index 9e26bd97aa..70cecd4b0d 100644 --- a/ui/src/notebooks/components/panel/NotebookPanel.tsx +++ b/ui/src/notebooks/components/panel/NotebookPanel.tsx @@ -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 @@ -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' @@ -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 @@ -75,20 +76,40 @@ const NotebookPanelHeader: FC = ({index, controls}) => { } const NotebookPanel: FC = ({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): void => { + e.stopPropagation() + updatePanelFocus(true) + } + + const handleClickOutside = (): void => { + updatePanelFocus(false) + } + return ( -
- -
{children}
-
+ +
+ +
{children}
+
+
) } diff --git a/ui/src/notebooks/components/panel/PanelVisibilityToggle.tsx b/ui/src/notebooks/components/panel/PanelVisibilityToggle.tsx index 891ea2cf37..b36be4d4d8 100644 --- a/ui/src/notebooks/components/panel/PanelVisibilityToggle.tsx +++ b/ui/src/notebooks/components/panel/PanelVisibilityToggle.tsx @@ -13,6 +13,7 @@ const PanelVisibilityToggle: FC = ({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, { @@ -20,7 +21,7 @@ const PanelVisibilityToggle: FC = ({index}) => { } as PipeMeta) } - return + return } export default PanelVisibilityToggle diff --git a/ui/src/notebooks/components/panel/RemovePanelButton.tsx b/ui/src/notebooks/components/panel/RemovePanelButton.tsx index f8d0db3799..56471be00b 100644 --- a/ui/src/notebooks/components/panel/RemovePanelButton.tsx +++ b/ui/src/notebooks/components/panel/RemovePanelButton.tsx @@ -17,7 +17,13 @@ const RemoveButton: FC = ({onRemove}) => { onRemove() } - return + return ( + + ) } export default RemoveButton diff --git a/ui/src/notebooks/context/notebook.tsx b/ui/src/notebooks/context/notebook.tsx index fab72356bc..6da564524e 100644 --- a/ui/src/notebooks/context/notebook.tsx +++ b/ui/src/notebooks/context/notebook.tsx @@ -4,6 +4,7 @@ import {PipeData} from 'src/notebooks' export interface PipeMeta { title: string visible: boolean + focus: boolean } export interface NotebookContextType { @@ -63,7 +64,7 @@ export const NotebookProvider: FC = ({children}) => { _setPipes(add(pipe)) _setMeta( add({ - title: `Notebook_${++GENERATOR_INDEX}`, + title: `Cell_${++GENERATOR_INDEX}`, visible: true, }) ) diff --git a/ui/src/notebooks/style.scss b/ui/src/notebooks/style.scss index e4f43a934f..b2524c562b 100644 --- a/ui/src/notebooks/style.scss +++ b/ui/src/notebooks/style.scss @@ -1,4 +1,4 @@ -@import "@influxdata/clockface/dist/variables.scss"; +@import '@influxdata/clockface/dist/variables.scss'; $notebook-header-height: 46px; $notebook-size-toggle: 16px; @@ -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; @@ -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; @@ -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; @@ -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; } @@ -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; + } }