Skip to content

Commit a1cbe3d

Browse files
Filmbostock
andauthored
adopt the new classes for plot's big numbers (#554)
* adopt the new classes for plot's big numbers * fix padding and color, the hard way * Update examples/plot/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * Update examples/plot/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * quote attributes * link not muted, fix slag * Update examples/plot/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * remove redundant client-side html generation * a bit of clean-up in the google-analytics example * add a gap class * fix links * remove .gap * fix indentation, close div * trend function * Update examples/google-analytics/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * Update examples/google-analytics/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * Update examples/google-analytics/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * Update examples/google-analytics/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * Update examples/plot/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * Update examples/plot/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * Update examples/plot/docs/index.md Co-authored-by: Mike Bostock <[email protected]> * - trend as a (local) component - adopt toLocaleString * small --------- Co-authored-by: Mike Bostock <[email protected]>
1 parent 67ee6fd commit a1cbe3d

File tree

9 files changed

+135
-117
lines changed

9 files changed

+135
-117
lines changed

examples/google-analytics/docs/components/bigNumber.js

Lines changed: 0 additions & 33 deletions
This file was deleted.

examples/google-analytics/docs/components/dailyPlot.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as d3 from "npm:d3";
21
import * as Plot from "npm:@observablehq/plot";
2+
import * as d3 from "npm:d3";
33

44
export const today = d3.utcDay(d3.utcHour.offset(d3.utcHour(), -10));
55
export const start = d3.utcYear.offset(today, -2);
@@ -16,7 +16,7 @@ export function DailyPlot(data, {title, label = title, domain, width, height = 2
1616
y: {
1717
grid: true,
1818
domain,
19-
label: label
19+
label
2020
},
2121
marks: [
2222
Plot.axisY({
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as d3 from "npm:d3";
2+
import {html} from "npm:htl";
3+
4+
export function trend(
5+
value /*: number */,
6+
{
7+
format = "+d",
8+
positive = "green",
9+
negative = "red",
10+
base = "muted",
11+
positiveSuffix = " ↗︎",
12+
negativeSuffix = " ↘︎",
13+
baseSuffix = ""
14+
} = {} /*
15+
as {
16+
format: string | ((x: number) => string);
17+
positive: string;
18+
negative: string;
19+
base: string;
20+
positiveSuffix: string;
21+
negativeSuffix: string;
22+
baseSuffix: string;
23+
}
24+
*/
25+
) /*: Node */ {
26+
if (typeof format === "string") format = d3.format(format);
27+
if (typeof format !== "function") throw new Error(`unsupported format ${format}`);
28+
return html`<span class="small ${value > 0 ? positive : value < 0 ? negative : base}">${format(value)}${
29+
value > 0 ? positiveSuffix : value < 0 ? negativeSuffix : baseSuffix
30+
}`;
31+
}

examples/google-analytics/docs/index.md

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ theme: dashboard
33
---
44

55
```js
6-
// Data
76
const summary = FileAttachment("data/google-analytics-summary.csv").csv({typed: true});
87
const hourly = FileAttachment("data/google-analytics-time-of-day.csv").csv({typed: true});
98
const channels = FileAttachment("data/google-analytics-channels.csv").csv({typed: true});
@@ -13,16 +12,13 @@ const world = FileAttachment("data/countries-110m.json").json();
1312
```
1413

1514
```js
16-
// Imports
1715
import {svg} from "npm:htl";
18-
import {BigNumber} from "./components/bigNumber.js";
1916
import {Marimekko} from "./components/marimekko.js";
17+
import {trend} from "./components/trend.js";
2018
```
2119

2220
```js
23-
// Helpers
2421
const bigPercent = d3.format(".0%");
25-
const percent = d3.format(".2%");
2622
const bigNumber = d3.format(".3s");
2723
const date = d3.utcFormat("%m/%d/%Y");
2824
const color = Plot.scale({
@@ -55,11 +51,10 @@ function getCompareValue(data, metric) {
5551
```
5652

5753
```js
58-
// Charts
5954
function lineChart(data, {width, height, metric}) {
6055
return Plot.plot({
6156
width,
62-
height: 97,
57+
height: 94,
6358
axis: null,
6459
insetTop: 10,
6560
insetLeft: -15,
@@ -78,11 +73,11 @@ function lineChart(data, {width, height, metric}) {
7873
function areaChart(data, {width, height, metric}) {
7974
return Plot.plot({
8075
width,
81-
height: 97,
76+
height: 94,
8277
axis: null,
8378
insetTop: 10,
8479
insetLeft: -15,
85-
insetRight: -16.5,
80+
insetRight: -17,
8681
marks: [
8782
Plot.ruleY([0]),
8883
Plot.areaY(data, {
@@ -276,42 +271,48 @@ function worldMap(data, {width, height, title, caption}) {
276271
}
277272
```
278273

279-
<style>
280-
.bigNumber {
281-
overflow: hidden
282-
}
283-
</style>
284-
285274
# Google analytics
286275

287276
_Summary of metrics from the [Google Analytics Data API](https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries), pulled on ${date(d3.max(summary, d => d.date))}_
288277

289278
<div class="grid grid-cols-4" style="grid-auto-rows: 165px;">
290-
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
291-
${resize((width) => BigNumber(`${summary[summary.length-1].active28d.toLocaleString("en-US")}`, {title: "Rolling 28-day Active users", plot: areaChart(summary, {width, metric: 'active28d'}), trend: getCompareValue(summary, 'active28d'), trendFormat: bigNumber}))}
279+
<div class="card">
280+
<h2>Rolling 28-day Active users</h2>
281+
<span class="big">${summary[summary.length-1].active28d.toLocaleString("en-US")}</span>
282+
${trend(getCompareValue(summary, 'active28d'))}
283+
${resize((width) => areaChart(summary, {width, metric: 'active28d'}))}
292284
</div>
293-
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
294-
${resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].engagementRate)}`, {title: "Engagement Rate", plot: lineChart(summary, {width, metric: 'engagementRate'}), trend: getCompareValue(summary, 'engagementRate'), trendFormat: percent}))}
285+
<div class="card">
286+
<h2>Engagement Rate</h2>
287+
<span class="big">${bigPercent(summary[summary.length-1].engagementRate)}</span>
288+
${trend(getCompareValue(summary, "engagementRate"), {format: "+.2%"})}
289+
${resize((width) => lineChart(summary, {width, metric: "engagementRate"}))}
295290
</div>
296-
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
297-
${resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].wauPerMau)}`, {title: "WAU to MAU ratio", plot: lineChart(summary, {width, metric: 'wauPerMau'}), trend: getCompareValue(summary, 'wauPerMau'), trendFormat: percent}))}
291+
<div class="card">
292+
<h2>WAU to MAU ratio</h2>
293+
<span class="big">${bigPercent(summary[summary.length-1].wauPerMau)}</span>
294+
${trend(getCompareValue(summary, "wauPerMau"), {format: "+.2%"})}
295+
${resize((width) => lineChart(summary, {width, metric: 'wauPerMau'}))}
298296
</div>
299-
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
300-
${resize((width) => BigNumber(`${summary[summary.length-1].engagedSessions.toLocaleString("en-US")}`, {title: "Engaged Sessions", plot: areaChart(summary, {width, metric: 'engagedSessions'}), trend: getCompareValue(summary, 'engagedSessions'), trendFormat: bigNumber}))}
297+
<div class="card">
298+
<h2>Engaged Sessions</h2>
299+
<span class="big">${summary[summary.length-1].engagedSessions.toLocaleString("en-US")}</span>
300+
${trend(getCompareValue(summary, 'engagedSessions'))}
301+
${resize((width) => areaChart(summary, {width, metric: 'engagedSessions'}))}
301302
</div>
302303
</div>
303304

304305
<div class="grid grid-cols-2" style="grid-auto-rows: 140px;">
305-
<div class="card grid-colspan-1 grid-rowspan-4">
306+
<div class="card grid-rowspan-4">
306307
${resize((width, height) => horizonChart(channels, {width, height, metric:'active28d', title: 'Active users by channel', caption: 'Rolling 28-day active users', format: 's', z: 'channelGroup', color, order: color.domain.slice(1)}))}
307308
</div>
308-
<div class="card grid-colspan-1 grid-rowspan-3">
309+
<div class="card grid-rowspan-2">
309310
${resize((width, height) => worldMap(countryData, {width, height, title: "Active users by country", caption: 'Current rolling 28-day active users by country', lookup: countryLookup}))}
310311
</div>
311-
<div class="card grid-colspan-1 grid-rowspan-3">
312-
${resize((width, height) => marrimekoChart(filteredChannelBreakdown, {width, height, metric:'active28d', title: 'New vs. returning users by channel', caption: 'Rolling 28-day active users by channel and split by new vs. returning', format: '%', yDim: 'channelGroup', xDim: 'type', color}))}
312+
<div class="card grid-rowspan-4">
313+
${resize((width, height) => marrimekoChart(filteredChannelBreakdown, {width, height: height - 12, metric:'active28d', title: 'New vs. returning users by channel', caption: 'Rolling 28-day active users by channel and split by new vs. returning', format: '%', yDim: 'channelGroup', xDim: 'type', color}))}
313314
</div>
314-
<div class="card grid-colspan-1 grid-rowspan-2">
315+
<div class="card grid-rowspan-2">
315316
${resize((width, height) => Punchcard(hourly, {width, height, label: "active users"}))}
316317
</div>
317318
</div>

examples/plot/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ The [`npm-downloads.csv.ts`](./docs/data/npm-downloads.csv.ts) loader retrieves
2626

2727
## Big numbers
2828

29-
Key performance indicators are displayed as “big numbers” with, in some cases, a trend indicating growth over one week. See the components/bigNumber.js file.
29+
Key performance indicators are displayed as “big numbers” with, in some cases, a trend indicating growth over one week. Their layout is using the convenience CSS classes _big_, _red_ etc.
3030

3131
## Charts
3232

examples/plot/docs/components/bigNumber.js

Lines changed: 0 additions & 36 deletions
This file was deleted.

examples/plot/docs/components/dailyPlot.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as d3 from "npm:d3";
21
import * as Plot from "npm:@observablehq/plot";
2+
import * as d3 from "npm:d3";
33

44
export const today = d3.utcDay(d3.utcHour.offset(d3.utcHour(), -10));
55
export const start = d3.utcYear.offset(today, -2);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as d3 from "npm:d3";
2+
import {html} from "npm:htl";
3+
4+
export function trend(
5+
value /*: number */,
6+
{
7+
format = "+d",
8+
positive = "green",
9+
negative = "red",
10+
base = "muted",
11+
positiveSuffix = " ↗︎",
12+
negativeSuffix = " ↘︎",
13+
baseSuffix = ""
14+
} = {} /*
15+
as {
16+
format: string | ((x: number) => string);
17+
positive: string;
18+
negative: string;
19+
base: string;
20+
positiveSuffix: string;
21+
negativeSuffix: string;
22+
baseSuffix: string;
23+
}
24+
*/
25+
) /*: Node */ {
26+
if (typeof format === "string") format = d3.format(format);
27+
if (typeof format !== "function") throw new Error(`unsupported format ${format}`);
28+
return html`<span class="small ${value > 0 ? positive : value < 0 ? negative : base}">${format(value)}${
29+
value > 0 ? positiveSuffix : value < 0 ? negativeSuffix : baseSuffix
30+
}`;
31+
}

examples/plot/docs/index.md

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ theme: dashboard
66
# Plot
77

88
```js
9-
import {BigNumber} from "./components/bigNumber.js";
9+
import {trend} from "./components/trend.js";
1010
import {DailyPlot, today, start} from "./components/dailyPlot.js";
1111
```
1212

@@ -43,17 +43,29 @@ const burndown = issues
4343
```
4444
4545
<div class="grid grid-cols-4" style="grid-auto-rows: 86px;">
46-
<div class=card>${BigNumber(versions.at(-1).version, {
47-
title: "Current release",
48-
href: `https://github.com/observablehq/plot/releases/tag/v${versions.at(-1).version}`,
49-
trend: d3.utcDay.count(versions.at(-1).date, Date.now()),
50-
trendFormat: d => `${d === 0 ? "today" : d===1 ? "yesterday" : `${d} days ago`}`,
51-
trendColor: "#888",
52-
trendArrow: null
53-
})}</div>
54-
<div class=card>${BigNumber(stars.length, {title: "GitHub stars", trend: stars.filter((d) => d.starred_at >= lastWeek).length, trendFormat: "+", trendTitle: "Since last week"})}</div>
55-
<div class=card>${BigNumber(downloads[0].value, {title: "Daily npm downloads", trend: downloads[7].value ? (downloads[0].value - downloads[7].value) / downloads[7].value : undefined, trendTitle: "Compared to last week"})}</div>
56-
<div class=card>${BigNumber(d3.sum(downloads, (d) => d.value), {title: "Total npm downloads"})}</div>
46+
<div class="card">
47+
<h2>Current release</h2>
48+
<span class="big">${versions.at(-1).version}</span>
49+
<a href="https://github.com/observablehq/plot/releases" style="color: inherit;">
50+
${((days) => days === 0 ? "today" : days === 1 ? "yesterday" : `${days} days ago`)(d3. utcDay.count(versions.at(-1).date, new Date()))}
51+
</a>
52+
</div>
53+
<div class="card">
54+
<h2>GitHub stars</h2>
55+
<span class="big">${stars.length.toLocaleString("en-US")}</span>
56+
${trend(d3.sum(stars, (d) => d.starred_at >= lastWeek))}</span>
57+
</div>
58+
<div class="card">
59+
<h2>Daily npm downloads</h2>
60+
<span class="big">${downloads[0].value.toLocaleString("en-US")}</span>
61+
${trend(downloads[7].value
62+
? (downloads[0].value - downloads[7].value) / downloads[7].value
63+
: undefined, {format: "+.1%"})}
64+
</div>
65+
<div class="card">
66+
<h2>Total npm downloads</h2>
67+
<span class="big">${d3.sum(downloads, (d) => d.value).toLocaleString("en-US")}</span>
68+
</div>
5769
</div>
5870
5971
<div class="card grid grid-cols-1" style="grid-auto-rows: calc(260px + 2rem);">
@@ -100,10 +112,22 @@ const burndown = issues
100112
</div>
101113
102114
<div class="grid grid-cols-4" style="grid-auto-rows: 86px;">
103-
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.state === "open").length, {title: "Open issues", href: "https://github.com/observablehq/plot/issues"})}</div>
104-
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.open >= lastMonth).length, {title: "Opened issues, 28d"})}</div>
105-
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.close >= lastMonth).length, {title: "Closed issues, 28d"})}</div>
106-
<div class=card>${BigNumber(issues.filter((d) => d.pull_request && d.state === "open" && !d.draft).length, {title: "Open PRs", href: "https://github.com/observablehq/plot/pulls?q=is%3Apr+is%3Aopen+draft%3Afalse"})}</div>
115+
<div class="card">
116+
<h2>Open issues</h2>
117+
<a href="https://github.com/observablehq/plot/issues" class="big" style="color: inherit;">${d3.sum(issues, (d) => !d.pull_request && d.state === "open").toLocaleString("en-US")}</a>
118+
</div>
119+
<div class="card">
120+
<h2>Opened issues, 28d</h2>
121+
<span class="big">${d3.sum(issues, (d) => !d.pull_request && d.open >= lastMonth).toLocaleString("en-US")}</span>
122+
</div>
123+
<div class="card">
124+
<h2>Closed issues, 28d</h2>
125+
<span class="big">${d3.sum(issues, (d) => !d.pull_request && d.close >= lastMonth).toLocaleString("en-US")}</span>
126+
</div>
127+
<div class="card">
128+
<h2>Open PRs</h2>
129+
<a class="big" href="https://github.com/observablehq/plot/pulls?q=is%3Apr+is%3Aopen+draft%3Afalse" style="color: inherit;">${d3.sum(issues, (d) => d.pull_request && d.state === "open" && !d.draft).toLocaleString("en-US")}</a>
130+
</div>
107131
</div>
108132
109133
<div class="grid grid-cols-2" style="grid-auto-rows: 276px;">

0 commit comments

Comments
 (0)