Skip to content

Commit 9fb3c58

Browse files
authored
Axis styling (esnet#267)
Features and bug fixes: * Adds YAxis and TimeAxis styling of all elements * Horizontal grid lines (Fixes esnet#244) * Ability to add chart title (Fixes esnet#9) * TimeAxis and YAxis now updates to additional prop changes (Fixes esnet#259, Fixes esnet#255 ) * Ease required props on TimeRangeMarker (Fixes esnet#263)
1 parent eab405c commit 9fb3c58

File tree

16 files changed

+1618
-1322
lines changed

16 files changed

+1618
-1322
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"d3-scale": "^1.0.6",
4848
"d3-scale-chromatic": "^1.1.1",
4949
"d3-selection": "^1.1.0",
50+
"d3-selection-multi": "^1.0.1",
5051
"d3-shape": "^1.2.0",
5152
"d3-time": "^1.0.7",
5253
"d3-time-format": "^2.0.5",

packages/website/yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
# yarn lockfile v1
3+
4+

src/components/ChartContainer.js

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,23 @@ import Charts from "./Charts";
2424
import EventHandler from "./EventHandler";
2525
import TimeAxis from "./TimeAxis";
2626
import TimeMarker from "./TimeMarker";
27+
import Label from "./Label";
2728

2829
const defaultTimeAxisStyle = {
29-
label: {
30-
labelColor: "#8B7E7E", // Default label color
31-
labelWeight: 100,
32-
labelSize: 12
33-
},
34-
values: {
35-
valueColor: "#8B7E7E",
36-
valueWeight: 100,
37-
valueSize: 11
38-
},
3930
axis: {
40-
axisColor: "#C0C0C0",
41-
axisWidth: 1
31+
fill: "none",
32+
stroke: "#C0C0C0",
33+
pointerEvents: "none"
4234
}
4335
};
4436

37+
const defaultTitleStyle = {
38+
fontWeight: 100,
39+
fontSize: 14,
40+
font: '"Goudy Bookletter 1911", sans-serif"',
41+
fill: "#C0C0C0"
42+
};
43+
4544
/**
4645
* The `<ChartContainer>` is the outer most element of a chart and is
4746
* responsible for generating and arranging its sub-elements. Specifically,
@@ -118,8 +117,14 @@ export default class ChartContainer extends React.Component {
118117
//
119118

120119
render() {
121-
const { padding } = this.props;
120+
const { padding = 0 } = this.props;
122121
const { paddingLeft = padding, paddingRight = padding } = this.props;
122+
const { paddingTop = padding, paddingBottom = padding } = this.props;
123+
124+
let { titleHeight = 28 } = this.props;
125+
if (_.isUndefined(this.props.title)) {
126+
titleHeight = 0;
127+
}
123128

124129
const chartRows = [];
125130
const leftAxisWidths = [];
@@ -230,8 +235,34 @@ export default class ChartContainer extends React.Component {
230235
.domain(this.props.timeRange.toJSON())
231236
.range([0, timeAxisWidth]));
232237

238+
const chartsWidth = this.props.width - leftWidth - rightWidth - paddingLeft - paddingRight;
239+
233240
let i = 0;
234-
let yPosition = 0;
241+
let yPosition = paddingTop;
242+
243+
// Chart title
244+
const transform = `translate(${leftWidth + paddingLeft},${yPosition})`;
245+
const titleStyle = merge(
246+
true,
247+
defaultTitleStyle,
248+
this.props.titleStyle ? this.props.titleStyle : {}
249+
);
250+
const title = this.props.title ? (
251+
<g transform={transform}>
252+
<Label
253+
align="center"
254+
label={this.props.title}
255+
style={{ label: titleStyle, box: { fill: "none", stroke: "none" } }}
256+
width={chartsWidth}
257+
height={titleHeight}
258+
/>
259+
</g>
260+
) : (
261+
<g />
262+
);
263+
264+
//yPosition += titleHeight;
265+
let chartsHeight = 0;
235266
React.Children.forEach(this.props.children, child => {
236267
if (areComponentsEqual(child.type, ChartRow)) {
237268
const chartRow = child;
@@ -250,6 +281,7 @@ export default class ChartContainer extends React.Component {
250281
transition: this.props.transition,
251282
enablePanZoom: this.props.enablePanZoom,
252283
minDuration: this.props.minDuration,
284+
showGrid: this.props.showGrid,
253285
timeFormat: this.props.format,
254286
trackerShowTime: firstRow,
255287
trackerTime: this.props.trackerPosition,
@@ -265,15 +297,14 @@ export default class ChartContainer extends React.Component {
265297
</g>
266298
);
267299

268-
yPosition += parseInt(child.props.height, 10);
300+
const height = parseInt(child.props.height, 10);
301+
yPosition += height;
302+
chartsHeight += height;
269303
}
270304
}
271305
i += 1;
272306
});
273307

274-
const chartsHeight = yPosition;
275-
const chartsWidth = this.props.width - leftWidth - rightWidth - paddingLeft - paddingRight;
276-
277308
// Hover tracker line
278309
let tracker;
279310
if (
@@ -284,7 +315,7 @@ export default class ChartContainer extends React.Component {
284315
<g
285316
key="tracker-group"
286317
style={{ pointerEvents: "none" }}
287-
transform={`translate(${leftWidth + paddingLeft},0)`}
318+
transform={`translate(${leftWidth + paddingLeft},${paddingTop + titleHeight})`}
288319
>
289320
<TimeMarker
290321
width={chartsWidth}
@@ -305,27 +336,24 @@ export default class ChartContainer extends React.Component {
305336
// TimeAxis
306337
//
307338

308-
const axisStyle = merge(
339+
const timeAxisStyle = merge(
309340
true,
310341
defaultTimeAxisStyle.axis,
311342
this.props.timeAxisStyle.axis ? this.props.timeAxisStyle.axis : {}
312343
);
313344

314-
const xStyle = {
315-
stroke: axisStyle.axisColor,
316-
strokeWidth: axisStyle.axisWidth,
317-
fill: "none",
318-
pointerEvents: "none"
319-
};
320-
321345
const timeAxis = (
322-
<g transform={`translate(${leftWidth + paddingLeft},${chartsHeight})`}>
346+
<g
347+
transform={`translate(${leftWidth + paddingLeft},${paddingTop +
348+
titleHeight +
349+
chartsHeight})`}
350+
>
323351
<line
324352
x1={-leftWidth}
325353
y1={0.5}
326354
x2={chartsWidth + rightWidth}
327355
y2={0.5}
328-
style={xStyle}
356+
style={timeAxisStyle}
329357
/>
330358
<TimeAxis
331359
scale={timeScale}
@@ -345,7 +373,7 @@ export default class ChartContainer extends React.Component {
345373
//
346374

347375
const rows = (
348-
<g transform={`translate(${leftWidth + paddingLeft},${0})`}>
376+
<g transform={`translate(${leftWidth + paddingLeft},${paddingTop + titleHeight})`}>
349377
<EventHandler
350378
key="event-handler"
351379
width={chartsWidth}
@@ -372,17 +400,24 @@ export default class ChartContainer extends React.Component {
372400
//
373401

374402
const svgWidth = this.props.width;
375-
const svgHeight = yPosition + timeAxisHeight;
403+
const svgHeight = chartsHeight + timeAxisHeight + paddingTop + paddingBottom + titleHeight;
404+
405+
const svgStyle = merge(
406+
true,
407+
{ display: "block" },
408+
this.props.style ? this.props.style : {}
409+
);
376410

377411
return this.props.showGridPosition === "over" ? (
378412
<svg
379413
width={svgWidth}
380414
height={svgHeight}
381-
style={{ display: "block" }}
415+
style={svgStyle}
382416
ref={c => {
383417
this.svg = c;
384418
}}
385419
>
420+
{title}
386421
{rows}
387422
{tracker}
388423
{timeAxis}
@@ -396,6 +431,7 @@ export default class ChartContainer extends React.Component {
396431
this.svg = c;
397432
}}
398433
>
434+
{title}
399435
{timeAxis}
400436
{rows}
401437
{tracker}
@@ -532,10 +568,21 @@ ChartContainer.propTypes = {
532568
* };
533569
* ```
534570
*/
535-
timeAxisStyle: PropTypes.shape({
536-
label: PropTypes.object, // eslint-disable-line
571+
/**
572+
* Object specifying the CSS by which the Time Axis can be styled. The object can contain:
573+
* "values" (the time labels), "axis" (the main horizontal line) and "ticks" (which may
574+
* optionally extend the height of all chart rows using the `showGrid` prop. Each of these
575+
* is an inline CSS style applied to the axis label, axis values, axis line and ticks
576+
* respectively.
577+
*
578+
* Note that "ticks" and "values" are passed into d3's styles, so they are regular CSS property names
579+
* and not React's camel case names (e.g. "stroke-dasharray" not strokeDasharray). "axis" is a
580+
* regular React rendered SVG line, so it uses camel case.
581+
*/
582+
style: PropTypes.shape({
583+
axis: PropTypes.object,
537584
values: PropTypes.object,
538-
axis: PropTypes.object
585+
ticks: PropTypes.object
539586
}),
540587

541588
/**
@@ -563,8 +610,8 @@ ChartContainer.propTypes = {
563610
PropTypes.string,
564611
PropTypes.arrayOf(
565612
PropTypes.shape({
566-
label: PropTypes.string, // eslint-disable-line
567-
value: PropTypes.string // eslint-disable-line
613+
label: PropTypes.string,
614+
value: PropTypes.string
568615
})
569616
)
570617
]),

src/components/ChartRow.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export default class ChartRow extends React.Component {
223223
// Space used by columns on left and right of charts
224224
const leftWidth = _.reduce(this.props.leftAxisWidths, (a, b) => a + b, 0);
225225
const rightWidth = _.reduce(this.props.rightAxisWidths, (a, b) => a + b, 0);
226+
const chartWidth = this.props.width - leftWidth - rightWidth - paddingLeft - paddingRight;
226227

227228
posx = leftWidth;
228229
for (
@@ -241,6 +242,8 @@ export default class ChartRow extends React.Component {
241242
props = {
242243
width: colWidth,
243244
height: innerHeight,
245+
chartExtent: chartWidth,
246+
isInnerAxis: leftColumnIndex === 0,
244247
align: "left",
245248
scale: this.scaleMap[id].latestScale()
246249
};
@@ -257,7 +260,7 @@ export default class ChartRow extends React.Component {
257260
}
258261
}
259262

260-
posx = this.props.width - rightWidth;
263+
posx = this.props.width - rightWidth - paddingRight;
261264
for (
262265
let rightColumnIndex = 0;
263266
rightColumnIndex < this.props.rightAxisWidths.length;
@@ -273,6 +276,9 @@ export default class ChartRow extends React.Component {
273276
props = {
274277
width: colWidth,
275278
height: innerHeight,
279+
chartExtent: chartWidth,
280+
//showGrid: this.props.showGrid,
281+
isInnerAxis: rightColumnIndex === 0,
276282
align: "right",
277283
scale: this.scaleMap[id].latestScale()
278284
};
@@ -298,7 +304,6 @@ export default class ChartRow extends React.Component {
298304
// current value is stored in the component state.
299305
//
300306

301-
const chartWidth = this.props.width - leftWidth - rightWidth - paddingLeft - paddingRight;
302307
const chartTransform = `translate(${leftWidth + paddingLeft},0)`;
303308

304309
let keyCount = 0;
@@ -386,7 +391,13 @@ export default class ChartRow extends React.Component {
386391
const clipper = (
387392
<defs>
388393
<clipPath id={this.state.clipId}>
389-
<rect x="0" y="0" width={chartWidth} height={innerHeight} />
394+
<rect
395+
x="0"
396+
y="0"
397+
style={{ strokeOpacity: 0.0 }}
398+
width={chartWidth}
399+
height={innerHeight}
400+
/>
390401
</clipPath>
391402
</defs>
392403
);

src/components/EventHandler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ export default class EventHandler extends React.Component {
289289
ref={c => {
290290
this.eventRect = c;
291291
}}
292-
style={{ opacity: 0.0, cursor }}
292+
style={{ fill: "#000", opacity: 0.0, cursor }}
293293
x={0}
294294
y={0}
295295
width={this.props.width}

0 commit comments

Comments
 (0)