Make it possible to navigate charts with the keyboard (https://github.com/woocommerce/woocommerce-admin/pull/399)

* Hide tooltip when mouse leaves chart bars

* Allow focus on chart lines/bars and show tooltip

* Extract position calculation to a function

* Make columns focusable instead of individual points in line charts
This commit is contained in:
Albert Juhé Lluveras 2018-09-14 14:57:09 +02:00 committed by GitHub
parent b5b84fe72c
commit 5669eb4b1a
1 changed files with 26 additions and 10 deletions

View File

@ -13,7 +13,7 @@ import {
scaleLinear as d3ScaleLinear,
scaleTime as d3ScaleTime,
} from 'd3-scale';
import { mouse as d3Mouse, select as d3Select } from 'd3-selection';
import { event as d3Event, mouse as d3Mouse, select as d3Select } from 'd3-selection';
import { line as d3Line } from 'd3-shape';
/**
* Internal dependencies
@ -297,9 +297,9 @@ export const drawAxis = ( node, params ) => {
.remove();
};
const showTooltip = ( node, params, d ) => {
const showTooltip = ( node, params, d, position ) => {
const chartCoords = node.node().getBoundingClientRect();
let [ xPosition, yPosition ] = d3Mouse( node.node() );
let [ xPosition, yPosition ] = position ? position : d3Mouse( node.node() );
xPosition = xPosition > chartCoords.width - 340 ? xPosition - 340 : xPosition + 100;
yPosition = yPosition > chartCoords.height - 150 ? yPosition - 200 : yPosition + 20;
const keys = params.orderedKeys.filter( row => row.visible ).map(
@ -327,25 +327,25 @@ const showTooltip = ( node, params, d ) => {
` );
};
const handleMouseOverBarChart = ( d, i, nodes, node, data, params ) => {
const handleMouseOverBarChart = ( d, i, nodes, node, data, params, position ) => {
d3Select( nodes[ i ].parentNode )
.select( '.barfocus' )
.attr( 'opacity', '0.1' );
showTooltip( node, params, d );
showTooltip( node, params, d, position );
};
const handleMouseOutBarChart = ( d, i, nodes, params ) => {
d3Select( nodes[ i ].parentNode )
.select( '.barfocus' )
.attr( 'opacity', '0' );
params.tooltip.style( 'display', 'flex' );
params.tooltip.style( 'display', 'none' );
};
const handleMouseOverLineChart = ( d, i, nodes, node, data, params ) => {
const handleMouseOverLineChart = ( d, i, nodes, node, data, params, position ) => {
d3Select( nodes[ i ].parentNode )
.select( '.focus-grid' )
.attr( 'opacity', '1' );
showTooltip( node, params, data.find( e => e.date === d.date ) );
showTooltip( node, params, data.find( e => e.date === d.date ), position );
};
const handleMouseOutLineChart = ( d, i, nodes, params ) => {
@ -355,6 +355,12 @@ const handleMouseOutLineChart = ( d, i, nodes, params ) => {
params.tooltip.style( 'display', 'none' );
};
const calculatePositionInChart = ( element, chart ) => {
const elementCoords = element.getBoundingClientRect();
const chartCoords = chart.getBoundingClientRect();
return [ elementCoords.x - chartCoords.x, elementCoords.y - chartCoords.y ];
};
export const drawLines = ( node, data, params ) => {
const series = node
.append( 'g' )
@ -424,10 +430,15 @@ export const drawLines = ( node, data, params ) => {
.attr( 'width', d => d.width )
.attr( 'height', params.height )
.attr( 'opacity', 0 )
.attr( 'tabindex', '0' )
.on( 'mouseover', ( d, i, nodes ) =>
handleMouseOverLineChart( d, i, nodes, node, data, params )
)
.on( 'mouseout', ( d, i, nodes ) => handleMouseOutLineChart( d, i, nodes, params ) );
.on( 'focus', ( d, i, nodes ) => {
const position = calculatePositionInChart( d3Event.target, node.node() );
handleMouseOverLineChart( d, i, nodes, node, data, params, position );
} )
.on( 'mouseout blur', ( d, i, nodes ) => handleMouseOutLineChart( d, i, nodes, params ) );
};
export const drawBars = ( node, data, params ) => {
@ -485,8 +496,13 @@ export const drawBars = ( node, data, params ) => {
.attr( 'width', params.xGroupScale.range()[ 1 ] )
.attr( 'height', params.height )
.attr( 'opacity', '0' )
.attr( 'tabindex', '0' )
.on( 'mouseover', ( d, i, nodes ) =>
handleMouseOverBarChart( d, i, nodes, node, data, params )
)
.on( 'mouseout', ( d, i, nodes ) => handleMouseOutBarChart( d, i, nodes, params ) );
.on( 'focus', ( d, i, nodes ) => {
const position = calculatePositionInChart( d3Event.target, node.node() );
handleMouseOverBarChart( d, i, nodes, node, data, params, position );
} )
.on( 'mouseout blur', ( d, i, nodes ) => handleMouseOutBarChart( d, i, nodes, params ) );
};