Skip to content

Commit

Permalink
Resolver/node svg 2 html (elastic#62958) (elastic#63282)
Browse files Browse the repository at this point in the history
* Remove some SVG in Resolver nodes and replace with HTML
  • Loading branch information
bkimmel committed Apr 10, 2020
1 parent e768ac0 commit 1d4706f
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import React, { memo } from 'react';
import { saturate, lighten } from 'polished';
import { saturate } from 'polished';

import {
htmlIdGenerator,
Expand Down Expand Up @@ -79,8 +79,6 @@ const idGenerator = htmlIdGenerator();
* Ids of paint servers to be referenced by fill and stroke attributes
*/
export const PaintServerIds = {
runningProcess: idGenerator('psRunningProcess'),
runningTrigger: idGenerator('psRunningTrigger'),
runningProcessCube: idGenerator('psRunningProcessCube'),
runningTriggerCube: idGenerator('psRunningTriggerCube'),
terminatedProcessCube: idGenerator('psTerminatedProcessCube'),
Expand All @@ -93,46 +91,6 @@ export const PaintServerIds = {
*/
const PaintServers = memo(() => (
<>
<linearGradient
id={PaintServerIds.runningProcess}
x1="0"
y1="0"
x2="1"
y2="0"
spreadMethod="reflect"
gradientUnits="objectBoundingBox"
>
<stop
offset="0%"
stopColor={saturate(0.7, lighten(0.05, NamedColors.runningProcessStart))}
stopOpacity="1"
/>
<stop
offset="100%"
stopColor={saturate(0.7, lighten(0.05, NamedColors.runningProcessEnd))}
stopOpacity="1"
/>
</linearGradient>
<linearGradient
id={PaintServerIds.runningTrigger}
x1="0"
y1="0"
x2="1"
y2="0"
spreadMethod="reflect"
gradientUnits="objectBoundingBox"
>
<stop
offset="0%"
stopColor={saturate(0.7, lighten(0.05, NamedColors.runningTriggerStart))}
stopOpacity="1"
/>
<stop
offset="100%"
stopColor={saturate(0.7, lighten(0.05, NamedColors.runningTriggerEnd))}
stopOpacity="1"
/>
</linearGradient>
<linearGradient
id={PaintServerIds.terminatedProcessCube}
x1="-381.23752"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { htmlIdGenerator, EuiKeyboardAccessible } from '@elastic/eui';
import { useSelector } from 'react-redux';
import { applyMatrix3 } from '../lib/vector2';
import { Vector2, Matrix3, AdjacentProcessMap, ResolverProcessType } from '../types';
import { SymbolIds, NamedColors, PaintServerIds } from './defs';
import { SymbolIds, NamedColors } from './defs';
import { ResolverEvent } from '../../../../common/types';
import { useResolverDispatch } from './use_resolver_dispatch';
import * as eventModel from '../../../../common/models/event';
Expand All @@ -21,31 +21,31 @@ import * as selectors from '../store/selectors';
const nodeAssets = {
runningProcessCube: {
cubeSymbol: `#${SymbolIds.runningProcessCube}`,
labelFill: `url(#${PaintServerIds.runningProcess})`,
labelBackground: NamedColors.fullLabelBackground,
descriptionFill: NamedColors.empty,
descriptionText: i18n.translate('xpack.endpoint.resolver.runningProcess', {
defaultMessage: 'Running Process',
}),
},
runningTriggerCube: {
cubeSymbol: `#${SymbolIds.runningTriggerCube}`,
labelFill: `url(#${PaintServerIds.runningTrigger})`,
labelBackground: NamedColors.fullLabelBackground,
descriptionFill: NamedColors.empty,
descriptionText: i18n.translate('xpack.endpoint.resolver.runningTrigger', {
defaultMessage: 'Running Trigger',
}),
},
terminatedProcessCube: {
cubeSymbol: `#${SymbolIds.terminatedProcessCube}`,
labelFill: NamedColors.fullLabelBackground,
labelBackground: NamedColors.fullLabelBackground,
descriptionFill: NamedColors.empty,
descriptionText: i18n.translate('xpack.endpoint.resolver.terminatedProcess', {
defaultMessage: 'Terminated Process',
}),
},
terminatedTriggerCube: {
cubeSymbol: `#${SymbolIds.terminatedTriggerCube}`,
labelFill: NamedColors.fullLabelBackground,
labelBackground: NamedColors.fullLabelBackground,
descriptionFill: NamedColors.empty,
descriptionText: i18n.translate('xpack.endpoint.resolver.terminatedTrigger', {
defaultMessage: 'Terminated Trigger',
Expand Down Expand Up @@ -114,14 +114,21 @@ export const ProcessEventDot = styled(
[left, magFactorX, top]
);

/**
* Type in non-SVG components scales as follows:
* (These values were adjusted to match the proportions in the comps provided by UX/Design)
* 18.75 : The smallest readable font size at which labels/descriptions can be read. Font size will not scale below this.
* 12.5 : A 'slope' at which the font size will scale w.r.t. to zoom level otherwise
*/
const minimumFontSize = 18.75;
const slopeOfFontScale = 12.5;
const fontSizeAdjustmentForScale = magFactorX > 1 ? slopeOfFontScale * (magFactorX - 1) : 0;
const scaledTypeSize = minimumFontSize + fontSizeAdjustmentForScale;

const markerBaseSize = 15;
const markerSize = markerBaseSize;
const markerPositionOffset = -markerBaseSize / 2;

const labelYOffset = markerPositionOffset + 0.25 * markerSize - 0.5;

const labelYHeight = markerSize / 1.7647;

/**
* An element that should be animated when the node is clicked.
*/
Expand All @@ -136,9 +143,7 @@ export const ProcessEventDot = styled(
})
| null;
} = React.createRef();
const { cubeSymbol, labelFill, descriptionFill, descriptionText } = nodeAssets[
nodeType(event)
];
const { cubeSymbol, labelBackground, descriptionText } = nodeAssets[nodeType(event)];
const resolverNodeIdGenerator = useMemo(() => htmlIdGenerator('resolverNode'), []);

const nodeId = useMemo(() => resolverNodeIdGenerator(selfId), [
Expand All @@ -154,7 +159,7 @@ export const ProcessEventDot = styled(
const dispatch = useResolverDispatch();

const handleFocus = useCallback(
(focusEvent: React.FocusEvent<SVGSVGElement>) => {
(focusEvent: React.FocusEvent<HTMLDivElement>) => {
dispatch({
type: 'userFocusedOnResolverNode',
payload: {
Expand All @@ -166,7 +171,7 @@ export const ProcessEventDot = styled(
);

const handleClick = useCallback(
(clickEvent: React.MouseEvent<SVGSVGElement, MouseEvent>) => {
(clickEvent: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
if (animationTarget.current !== null) {
(animationTarget.current as any).beginElement();
}
Expand All @@ -179,14 +184,15 @@ export const ProcessEventDot = styled(
},
[animationTarget, dispatch, nodeId]
);

/* eslint-disable jsx-a11y/click-events-have-key-events */
/**
* Key event handling (e.g. 'Enter'/'Space') is provisioned by the `EuiKeyboardAccessible` component
*/
return (
<EuiKeyboardAccessible>
<svg
<div
data-test-subj={'resolverNode'}
className={className + ' kbn-resetFocusState'}
viewBox="-15 -15 90 30"
preserveAspectRatio="xMidYMid meet"
role="treeitem"
aria-level={adjacentNodeMap.level}
aria-flowto={
Expand All @@ -203,81 +209,100 @@ export const ProcessEventDot = styled(
onFocus={handleFocus}
tabIndex={-1}
>
<g>
<use
xlinkHref={`#${SymbolIds.processCubeActiveBacking}`}
x={-11.35}
y={-11.35}
width={markerSize * 1.5}
height={markerSize * 1.5}
className="backing"
/>
<rect x="7" y="-12.75" width="15" height="10" fill={NamedColors.resolverBackground} />
<use
role="presentation"
xlinkHref={cubeSymbol}
x={markerPositionOffset}
y={markerPositionOffset}
width={markerSize}
height={markerSize}
opacity="1"
className="cube"
>
<animateTransform
attributeType="XML"
attributeName="transform"
type="scale"
values="1 1; 1 .83; 1 .8; 1 .83; 1 1"
dur="0.2s"
begin="click"
repeatCount="1"
className="squish"
ref={animationTarget}
<svg
viewBox="-15 -15 90 30"
preserveAspectRatio="xMidYMid meet"
style={{
display: 'block',
width: '100%',
height: '100%',
position: 'absolute',
top: '0',
left: '0',
}}
>
<g>
<use
xlinkHref={`#${SymbolIds.processCubeActiveBacking}`}
x={-11.35}
y={-11.35}
width={markerSize * 1.5}
height={markerSize * 1.5}
className="backing"
/>
</use>
<use
role="presentation"
xlinkHref={`#${SymbolIds.processNodeLabel}`}
x={markerPositionOffset + markerSize - 0.5}
y={labelYOffset}
width={(markerSize / 1.7647) * 5}
height={markerSize / 1.7647}
opacity="1"
fill={labelFill}
/>
<text
x={markerPositionOffset + 0.7 * markerSize + 50 / 2}
y={labelYOffset + labelYHeight / 2}
textAnchor="middle"
dominantBaseline="middle"
fontSize="3.75"
fontWeight="bold"
fill={NamedColors.empty}
paintOrder="stroke"
tabIndex={-1}
style={{ letterSpacing: '-0.02px' }}
id={labelId}
>
{eventModel.eventName(event)}
</text>
<text
x={markerPositionOffset + markerSize}
y={labelYOffset - 1}
textAnchor="start"
dominantBaseline="middle"
fontSize="2.67"
fill={descriptionFill}
<use
role="presentation"
xlinkHref={cubeSymbol}
x={markerPositionOffset}
y={markerPositionOffset}
width={markerSize}
height={markerSize}
opacity="1"
className="cube"
>
<animateTransform
attributeType="XML"
attributeName="transform"
type="scale"
values="1 1; 1 .83; 1 .8; 1 .83; 1 1"
dur="0.2s"
begin="click"
repeatCount="1"
className="squish"
ref={animationTarget}
/>
</use>
</g>
</svg>
<div
style={{
left: '25%',
top: '30%',
position: 'absolute',
width: '50%',
color: 'white',
fontSize: `${scaledTypeSize}px`,
lineHeight: '140%',
}}
>
<div
id={descriptionId}
paintOrder="stroke"
fontWeight="bold"
style={{ textTransform: 'uppercase', letterSpacing: '-0.01px' }}
style={{
textTransform: 'uppercase',
letterSpacing: '-0.01px',
backgroundColor: NamedColors.resolverBackground,
lineHeight: '1.2',
fontWeight: 'bold',
fontSize: '.5em',
width: '100%',
margin: '0 0 .05em 0',
textAlign: 'left',
padding: '0',
}}
>
{descriptionText}
</text>
</g>
</svg>
</div>
<div
data-test-subject="nodeLabel"
id={labelId}
style={{
backgroundColor: labelBackground,
padding: '.15em 0',
textAlign: 'center',
maxWidth: '100%',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
contain: 'content',
}}
>
{eventModel.eventName(event)}
</div>
</div>
</div>
</EuiKeyboardAccessible>
);
/* eslint-enable jsx-a11y/click-events-have-key-events */
}
)
)`
Expand Down

0 comments on commit 1d4706f

Please sign in to comment.