diff --git a/giraffe/package.json b/giraffe/package.json index 267e557f..f576eda5 100644 --- a/giraffe/package.json +++ b/giraffe/package.json @@ -1,6 +1,6 @@ { "name": "@influxdata/giraffe", - "version": "2.16.1", + "version": "2.16.2", "main": "dist/index.js", "module": "src/index.js", "license": "MIT", diff --git a/giraffe/src/components/AnnotationLayer.tsx b/giraffe/src/components/AnnotationLayer.tsx index 9de4bf8d..b664a8e9 100644 --- a/giraffe/src/components/AnnotationLayer.tsx +++ b/giraffe/src/components/AnnotationLayer.tsx @@ -16,6 +16,7 @@ import {AnnotationLine} from './AnnotationLine' export interface AnnotationLayerProps extends LayerProps { spec: AnnotationLayerSpec config: AnnotationLayerConfig + onHover: (forceHide: boolean) => void } const ANNOTATION_OVERLAY_DEFAULT_STYLE = { @@ -23,7 +24,17 @@ const ANNOTATION_OVERLAY_DEFAULT_STYLE = { } as CSSProperties export const AnnotationLayer: FunctionComponent = props => { - const {config, spec, width, height, hoverX, hoverY, xScale, yScale} = props + const { + config, + spec, + width, + height, + hoverX, + hoverY, + xScale, + yScale, + onHover, + } = props const lineWidth = config.lineWidth || 2 const annotationsPositions = useMemo( () => getAnnotationsPositions(spec.annotationData, xScale, yScale), @@ -97,6 +108,7 @@ export const AnnotationLayer: FunctionComponent = props => strokeWidth={lineWidth} pin={annotationData.pin} id={annotationData.id} + onHover={onHover} /> ) )} diff --git a/giraffe/src/components/AnnotationLine.tsx b/giraffe/src/components/AnnotationLine.tsx index cf7470db..04007ca1 100644 --- a/giraffe/src/components/AnnotationLine.tsx +++ b/giraffe/src/components/AnnotationLine.tsx @@ -12,6 +12,7 @@ interface AnnotationLineProps { length: number pin: AnnotationPinType id: string + onHover?: (forceHide: boolean) => void } // These could become configurable values @@ -46,6 +47,14 @@ const RANGE_HEIGHT = 9 * * style: {cursor: 'pointer'} * + * the 'onHover' method is for firing when the user is hovering over + * a clickable area. it sends a 'true' when the user entered a clickable area + * and a 'false' when it leaves. This is so if there is a hover legend showing, + * then it will be hidden while on the clickable area. + * + * adding the 'onHover' to the tops of the annotations that are clickable: + * the range rectangle and the 'start' pin for vertical annotation lines. + * * */ export const AnnotationLine: FunctionComponent = props => { const { @@ -56,6 +65,7 @@ export const AnnotationLine: FunctionComponent = props => { stopValue, length, pin, + onHover = () => {}, } = props // This prevents blurry sub-pixel rendering as well as clipped lines @@ -106,8 +116,6 @@ export const AnnotationLine: FunctionComponent = props => { ) } - // dimension is x: - /** * This is the rectangle or 'hat' that goes on top of a range annotation. * The entire hat is click to edit for the annotation. @@ -128,6 +136,12 @@ export const AnnotationLine: FunctionComponent = props => { fill: color, id: props.id, style: {cursor: 'pointer', opacity: '60%'}, + onMouseEnter: () => { + onHover(true) + }, + onMouseLeave: () => { + onHover(false) + }, }) } @@ -166,6 +180,12 @@ export const AnnotationLine: FunctionComponent = props => { style: {cursor: 'pointer'}, id: props.id, className: 'giraffe-annotation-click-target', + onMouseEnter: () => { + onHover(true) + }, + onMouseLeave: () => { + onHover(false) + }, }) case 'stop': return createElement('polygon', { diff --git a/giraffe/src/components/SizedPlot.tsx b/giraffe/src/components/SizedPlot.tsx index cae35cab..d5e3bd13 100644 --- a/giraffe/src/components/SizedPlot.tsx +++ b/giraffe/src/components/SizedPlot.tsx @@ -3,6 +3,7 @@ import React, { FunctionComponent, RefObject, useCallback, + useState, } from 'react' import {Axes} from './Axes' @@ -60,6 +61,17 @@ export const SizedPlot: FunctionComponent = ({ const hoverX = dragEvent ? null : hoverEvent.x const hoverY = dragEvent ? null : hoverEvent.y + const [forceHoverLegendHide, setForceHoverLegendHide] = useState(false) + + const hideLegend = hideMe => { + if (legendHide) { + return + // it is already hiding, nothing else to do + // optimization to reduce unecessary re-renderings + } + setForceHoverLegendHide(hideMe) + } + const handleYBrushEnd = useCallback( (yRange: number[]) => { env.yDomain = rangeToDomain(yRange, env.yScale, env.innerHeight).reverse() @@ -258,7 +270,7 @@ export const SizedPlot: FunctionComponent = ({ const sharedProps = { hoverX, hoverY, - legendHide, + legendHide: legendHide || forceHoverLegendHide, plotConfig: config, xScale: env.xScale, yScale: env.yScale, @@ -276,6 +288,7 @@ export const SizedPlot: FunctionComponent = ({ {...sharedProps} spec={spec} config={layerConfig as AnnotationLayerConfig} + onHover={hideLegend} /> ) case SpecTypes.Line: diff --git a/stories/src/annotation.stories.tsx b/stories/src/annotation.stories.tsx index b2d0cb48..6467580c 100644 --- a/stories/src/annotation.stories.tsx +++ b/stories/src/annotation.stories.tsx @@ -68,6 +68,7 @@ storiesOf('Annotations', module) const legendFont = legendFontKnob() const legendOrientationThreshold = tooltipOrientationThresholdKnob() const legendColorizeRows = tooltipColorizeRowsKnob() + const legendHide = boolean('Hide Hover Legend', false) const xTotalTicks = number('X Total Ticks', 8) const yTotalTicks = number('Y Total Ticks', 10) @@ -131,6 +132,7 @@ storiesOf('Annotations', module) xScale, yScale, legendFont, + legendHide, legendOrientationThreshold, legendColorizeRows, tickFont, @@ -505,6 +507,7 @@ storiesOf('Annotations', module) const legendFont = legendFontKnob() const legendOrientationThreshold = tooltipOrientationThresholdKnob() const legendColorizeRows = tooltipColorizeRowsKnob() + const legendHide = boolean('Hide Hover Legend', false) const xTotalTicks = number('X Total Ticks', 8) const yTotalTicks = number('Y Total Ticks', 10) @@ -577,6 +580,7 @@ storiesOf('Annotations', module) xScale, yScale, legendFont, + legendHide, legendOrientationThreshold, legendColorizeRows, tickFont,