Skip to content

Commit

Permalink
style(legend): align k7 design (opensearch-project#54)
Browse files Browse the repository at this point in the history
The legend respect the chart theme margins. The toggle is now moved to the bottom left of the
chart as in kibana new design.
Added the euiScrollBar on legend.
Refactored the use of classnames package using object for the conditional class

fix opensearch-project#34
  • Loading branch information
markov00 authored Feb 15, 2019
1 parent 80e66d3 commit 066dbb3
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 94 deletions.
93 changes: 57 additions & 36 deletions packages/osd-charts/src/components/_legend.scss
Original file line number Diff line number Diff line change
@@ -1,101 +1,122 @@
$euiChartLegendMaxWidth: $euiSize * 10 + $euiSize;
$euiChartLegendMaxHeight: $euiSize * 4 + $euiSize;
$elasticChartsLegendMaxWidth: $euiSize * 10 + $euiSize;
$elasticChartsLegendMaxHeight: $euiSize * 4 + $euiSize;

.euiChartLegend {
.elasticChartsLegend {
position: absolute;
display: flex;
align-items: flex-start;
flex-direction: row;
}
.euiChartLegend--collapsed {
.elasticChartsLegend--collapsed {
width: $euiSize * 2 !important;
height: $euiSize * 2 !important;
.euiChartLegendList {
.elasticChartsLegendList {
display: none;
}
}
.euiChartLegend--debug {
.elasticChartsLegend--debug {
background: red;
}
.euiChartLegend--top {
.elasticChartsLegend--top {
top: 0;
left: 0;
right: 0;
width: auto;
height: $euiChartLegendMaxHeight;
height: $elasticChartsLegendMaxHeight;
flex-direction: column;
order: 1;
.euiChartLegend__listItem {
.elasticChartsLegend__listItem {
min-height: 50%;
width: $euiChartLegendMaxWidth;
min-width: $euiChartLegendMaxWidth;
width: $elasticChartsLegendMaxWidth;
min-width: $elasticChartsLegendMaxWidth;
}
}
.euiChartLegend--bottom {
.elasticChartsLegend--bottom {
bottom: 0;
left: 0;
right: 0;
width: auto;
height: $euiChartLegendMaxHeight;
height: $elasticChartsLegendMaxHeight;
flex-direction: column;
.euiChartLegend__listItem {
.elasticChartsLegend__listItem {
min-height: 50%;
width: $euiChartLegendMaxWidth;
min-width: $euiChartLegendMaxWidth;
width: $elasticChartsLegendMaxWidth;
min-width: $elasticChartsLegendMaxWidth;
}
}
.euiChartLegend--left {
.elasticChartsLegend--left {
top: 0;
bottom: 0;
left: 0;
width: $euiChartLegendMaxWidth;
width: $elasticChartsLegendMaxWidth;
order: 1;
.euiChartLegend__listItem {
.elasticChartsLegend__listItem {
min-width: 100%;
}
}
.euiChartLegend--right {
.elasticChartsLegend--right {
top: 0;
bottom: 0;
right: 0;
width: $euiChartLegendMaxWidth;
.euiChartLegend__listItem {
width: $elasticChartsLegendMaxWidth;
.elasticChartsLegend__listItem {
min-width: 100%;
}
}


.euiChartLegendCollapser {
.elasticChartsLegendCollapser {
width: 2 * $euiSize;
height: 2 * $euiSize;
flex-shrink: 0;
flex-grow: 0;
}
.euiChartLegendCollapser--top {
.elasticChartsLegendCollapser--top {
order: 2;
}
.euiChartLegendCollapser--left {
.elasticChartsLegendCollapser--left {
order: 2;
}



.euiChartLegendListContainer {
.elasticChartsLegendListContainer {
overflow: hidden;
flex-shrink: 1;
flex-grow: 0;
}
.euiChartLegendList {
.elasticChartsLegendList {
overflow-y: auto;
overflow-x: hidden;
height: 100%;
@include euiScrollBar;
}
.euiChartLegendListItem__title {
width: $euiChartLegendMaxWidth - 4 * $euiSize;
max-width: $euiChartLegendMaxWidth - 4 * $euiSize;
}
.euiChartLegendList__item {

.elasticChartsLegendList__item {
&:hover {
text-decoration: underline;
}
}
}

.elasticChartsLegendListItem__title {
width: $elasticChartsLegendMaxWidth - 4 * $euiSize;
max-width: $elasticChartsLegendMaxWidth - 4 * $euiSize;
}

.elasticChartsLegend__toggle {
border-radius: $euiBorderRadius;
border-bottom-right-radius: 0;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
position: absolute;
bottom: 0;
left: 0;
opacity: 0;
background-color: $euiColorEmptyShade;
transition: opacity $euiAnimSpeedFast $euiAnimSlightResistance,
background-color $euiAnimSpeedFast $euiAnimSlightResistance $euiAnimSpeedExtraSlow;
&:focus {
box-shadow: none;
background-color: $euiFocusBackgroundColor !important;
}
}
.elasticChartsLegend__toggle--isOpen {
background-color: transparentize($euiColorDarkestShade, 0.9);
}
6 changes: 3 additions & 3 deletions packages/osd-charts/src/components/_tooltip.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.euiChartTooltip {
.elasticChartsTooltip {
@include euiBottomShadow($color: $euiColorFullShade);
@include euiFontSizeXS;
pointer-events: none;
Expand Down Expand Up @@ -28,12 +28,12 @@
}
}
}
.euiChartTooltip__label {
.elasticChartsTooltip__label {
// max-width: $euiSizeXL * 3;
font-weight: $euiFontWeightMedium;
color: shade($euiColorGhost, 20%);
}

.euiChartTooltip--hidden {
.elasticChartsTooltip--hidden {
opacity: 0;
}
4 changes: 3 additions & 1 deletion packages/osd-charts/src/components/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SpecsParser } from '../specs/specs_parser';
import { ChartStore } from '../state/chart_state';
import { ChartResizer } from './chart_resizer';
import { Legend } from './legend';
import { LegendButton } from './legend_button';
import { ReactiveChart as ReactChart } from './react_canvas/reactive_chart';
import { ReactiveChart as SVGChart } from './svg/reactive_chart';
import { Tooltips } from './tooltips';
Expand Down Expand Up @@ -36,7 +37,7 @@ export class Chart extends React.Component<ChartProps> {
} else {
containerStyle = {};
}
const chartClass = classNames('elasticcharts', className);
const chartClass = classNames('elasticCharts', className);
return (
<Provider chartStore={this.chartSpecStore}>
<Fragment>
Expand All @@ -47,6 +48,7 @@ export class Chart extends React.Component<ChartProps> {
{renderer === 'canvas' && <ReactChart />}
<Tooltips />
<Legend />
<LegendButton />
</div>
</Fragment>
</Provider>
Expand Down
82 changes: 32 additions & 50 deletions packages/osd-charts/src/components/legend.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,15 @@
import {
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiText,
} from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText } from '@elastic/eui';
import classNames from 'classnames';
import { inject, observer } from 'mobx-react';
import React from 'react';
import { isVertical } from '../lib/axes/axis_utils';
import { LegendItem } from '../lib/series/legend';
import { Position } from '../lib/series/specs';
import { ChartStore } from '../state/chart_state';

interface ReactiveChartProps {
chartStore?: ChartStore; // FIX until we find a better way on ts mobx
}

function getCollapseArrowType(
position: Position | undefined,
legendShown: boolean,
): 'arrowRight' | 'arrowLeft' | 'arrowDown' | 'arrowUp' {
switch (position) {
case Position.Left:
return legendShown ? 'arrowRight' : 'arrowLeft';
case Position.Bottom:
return legendShown ? 'arrowUp' : 'arrowDown';
case Position.Right:
return legendShown ? 'arrowLeft' : 'arrowRight';
case Position.Top:
return legendShown ? 'arrowDown' : 'arrowUp';
default:
return 'arrowRight';
}
}

class LegendComponent extends React.Component<ReactiveChartProps> {
static displayName = 'Legend';

Expand All @@ -49,45 +25,51 @@ class LegendComponent extends React.Component<ReactiveChartProps> {
showLegend,
legendCollapsed,
debug,
chartTheme,
} = this.props.chartStore!;

if (!showLegend.get() || !initialized.get() || legendItems.length === 0) {
if (
!showLegend.get() ||
!initialized.get() ||
legendItems.length === 0 ||
legendPosition === undefined
) {
return null;
}

const legendClasses = classNames(
'euiChartLegend',
`euiChartLegend--${legendPosition}`,
legendCollapsed.get() && 'euiChartLegend--collapsed',
debug && 'euiChartLegend--debug',
);

const legendCollapser = classNames(
'euiChartLegendCollapser',
`euiChartLegendCollapser--${legendPosition}`,
'elasticChartsLegend',
`elasticChartsLegend--${legendPosition}`,
{
'elasticChartsLegend--collapsed': legendCollapsed.get(),
'elasticChartsLegend--debug': debug,
},
);
const collapseArrowType = getCollapseArrowType(legendPosition, legendCollapsed.get());

let paddingStyle;
if (isVertical(legendPosition)) {
paddingStyle = {
paddingTop: chartTheme.chart.margins.top,
paddingBottom: chartTheme.chart.margins.bottom,
};
} else {
paddingStyle = {
paddingLeft: chartTheme.chart.margins.left,
paddingRight: chartTheme.chart.margins.right,
};
}
return (
<div className={legendClasses}>
<div className={legendCollapser}>
<EuiButtonIcon
onClick={this.onCollapseLegend}
iconType={collapseArrowType}
aria-label={legendCollapsed.get() ? 'Expand legend' : 'Collapse legend'}
/>
</div>
<div className="euiChartLegendList">
<div className={legendClasses} style={paddingStyle}>
<div className="elasticChartsLegendList">
<EuiFlexGroup
gutterSize="s"
wrap
className="euiChartLegendListContainer"
className="elasticChartsLegendListContainer"
responsive={false}
>
{legendItems.map((item, index) => {
const legendItemProps = {
key: index,
className: 'euiChartLegendList__item',
className: 'elasticChartsLegendList__item',
onMouseEnter: this.onLegendItemMouseover(index),
onMouseLeave: this.onLegendItemMouseout,
};
Expand Down Expand Up @@ -119,7 +101,7 @@ function LegendElement({ color, label }: Partial<LegendItem>) {
<EuiIcon type="dot" color={color} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexItem grow={true} className="euiChartLegendListItem__title" title={label}>
<EuiFlexItem grow={true} className="elasticChartsLegendListItem__title" title={label}>
<EuiText size="xs" className="eui-textTruncate">
{label}
</EuiText>
Expand Down
38 changes: 38 additions & 0 deletions packages/osd-charts/src/components/legend_button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { EuiButtonIcon } from '@elastic/eui';
import classNames from 'classnames';
import { inject, observer } from 'mobx-react';
import React from 'react';
import { ChartStore } from '../state/chart_state';

interface ReactiveChartProps {
chartStore?: ChartStore;
}

class LegendButtonComponent extends React.Component<ReactiveChartProps> {
static displayName = 'Legend';
onCollapseLegend = () => {
this.props.chartStore!.toggleLegendCollapsed();
}

render() {
const { initialized, legendItems, legendCollapsed, showLegend } = this.props.chartStore!;

if (!showLegend.get() || !initialized.get() || legendItems.length === 0) {
return null;
}
const isOpen = !legendCollapsed.get();
const className = classNames('elasticChartsLegend__toggle', {
'elasticChartsLegend__toggle--isOpen': isOpen,
});
return (
<EuiButtonIcon
className={className}
onClick={this.onCollapseLegend}
iconType="list"
aria-label={legendCollapsed.get() ? 'Expand legend' : 'Collapse legend'}
/>
);
}
}

export const LegendButton = inject('chartStore')(observer(LegendButtonComponent));
Loading

0 comments on commit 066dbb3

Please sign in to comment.