Skip to content

Commit

Permalink
adopt the new classes for plot's big numbers (#554)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
Fil and mbostock authored Jan 25, 2024
1 parent 67ee6fd commit a1cbe3d
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 117 deletions.
33 changes: 0 additions & 33 deletions examples/google-analytics/docs/components/bigNumber.js

This file was deleted.

4 changes: 2 additions & 2 deletions examples/google-analytics/docs/components/dailyPlot.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as d3 from "npm:d3";
import * as Plot from "npm:@observablehq/plot";
import * as d3 from "npm:d3";

export const today = d3.utcDay(d3.utcHour.offset(d3.utcHour(), -10));
export const start = d3.utcYear.offset(today, -2);
Expand All @@ -16,7 +16,7 @@ export function DailyPlot(data, {title, label = title, domain, width, height = 2
y: {
grid: true,
domain,
label: label
label
},
marks: [
Plot.axisY({
Expand Down
31 changes: 31 additions & 0 deletions examples/google-analytics/docs/components/trend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as d3 from "npm:d3";
import {html} from "npm:htl";

export function trend(
value /*: number */,
{
format = "+d",
positive = "green",
negative = "red",
base = "muted",
positiveSuffix = " ↗︎",
negativeSuffix = " ↘︎",
baseSuffix = ""
} = {} /*
as {
format: string | ((x: number) => string);
positive: string;
negative: string;
base: string;
positiveSuffix: string;
negativeSuffix: string;
baseSuffix: string;
}
*/
) /*: Node */ {
if (typeof format === "string") format = d3.format(format);
if (typeof format !== "function") throw new Error(`unsupported format ${format}`);
return html`<span class="small ${value > 0 ? positive : value < 0 ? negative : base}">${format(value)}${
value > 0 ? positiveSuffix : value < 0 ? negativeSuffix : baseSuffix
}`;
}
57 changes: 29 additions & 28 deletions examples/google-analytics/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ theme: dashboard
---

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

```js
// Imports
import {svg} from "npm:htl";
import {BigNumber} from "./components/bigNumber.js";
import {Marimekko} from "./components/marimekko.js";
import {trend} from "./components/trend.js";
```

```js
// Helpers
const bigPercent = d3.format(".0%");
const percent = d3.format(".2%");
const bigNumber = d3.format(".3s");
const date = d3.utcFormat("%m/%d/%Y");
const color = Plot.scale({
Expand Down Expand Up @@ -55,11 +51,10 @@ function getCompareValue(data, metric) {
```

```js
// Charts
function lineChart(data, {width, height, metric}) {
return Plot.plot({
width,
height: 97,
height: 94,
axis: null,
insetTop: 10,
insetLeft: -15,
Expand All @@ -78,11 +73,11 @@ function lineChart(data, {width, height, metric}) {
function areaChart(data, {width, height, metric}) {
return Plot.plot({
width,
height: 97,
height: 94,
axis: null,
insetTop: 10,
insetLeft: -15,
insetRight: -16.5,
insetRight: -17,
marks: [
Plot.ruleY([0]),
Plot.areaY(data, {
Expand Down Expand Up @@ -276,42 +271,48 @@ function worldMap(data, {width, height, title, caption}) {
}
```

<style>
.bigNumber {
overflow: hidden
}
</style>

# Google analytics

_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))}_

<div class="grid grid-cols-4" style="grid-auto-rows: 165px;">
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
${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}))}
<div class="card">
<h2>Rolling 28-day Active users</h2>
<span class="big">${summary[summary.length-1].active28d.toLocaleString("en-US")}</span>
${trend(getCompareValue(summary, 'active28d'))}
${resize((width) => areaChart(summary, {width, metric: 'active28d'}))}
</div>
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
${resize((width) => BigNumber(`${bigPercent(summary[summary.length-1].engagementRate)}`, {title: "Engagement Rate", plot: lineChart(summary, {width, metric: 'engagementRate'}), trend: getCompareValue(summary, 'engagementRate'), trendFormat: percent}))}
<div class="card">
<h2>Engagement Rate</h2>
<span class="big">${bigPercent(summary[summary.length-1].engagementRate)}</span>
${trend(getCompareValue(summary, "engagementRate"), {format: "+.2%"})}
${resize((width) => lineChart(summary, {width, metric: "engagementRate"}))}
</div>
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
${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}))}
<div class="card">
<h2>WAU to MAU ratio</h2>
<span class="big">${bigPercent(summary[summary.length-1].wauPerMau)}</span>
${trend(getCompareValue(summary, "wauPerMau"), {format: "+.2%"})}
${resize((width) => lineChart(summary, {width, metric: 'wauPerMau'}))}
</div>
<div class="card grid-colspan-1 grid-rowspan-1 bigNumber">
${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}))}
<div class="card">
<h2>Engaged Sessions</h2>
<span class="big">${summary[summary.length-1].engagedSessions.toLocaleString("en-US")}</span>
${trend(getCompareValue(summary, 'engagedSessions'))}
${resize((width) => areaChart(summary, {width, metric: 'engagedSessions'}))}
</div>
</div>

<div class="grid grid-cols-2" style="grid-auto-rows: 140px;">
<div class="card grid-colspan-1 grid-rowspan-4">
<div class="card grid-rowspan-4">
${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)}))}
</div>
<div class="card grid-colspan-1 grid-rowspan-3">
<div class="card grid-rowspan-2">
${resize((width, height) => worldMap(countryData, {width, height, title: "Active users by country", caption: 'Current rolling 28-day active users by country', lookup: countryLookup}))}
</div>
<div class="card grid-colspan-1 grid-rowspan-3">
${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}))}
<div class="card grid-rowspan-4">
${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}))}
</div>
<div class="card grid-colspan-1 grid-rowspan-2">
<div class="card grid-rowspan-2">
${resize((width, height) => Punchcard(hourly, {width, height, label: "active users"}))}
</div>
</div>
2 changes: 1 addition & 1 deletion examples/plot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The [`npm-downloads.csv.ts`](./docs/data/npm-downloads.csv.ts) loader retrieves

## Big numbers

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.
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.

## Charts

Expand Down
36 changes: 0 additions & 36 deletions examples/plot/docs/components/bigNumber.js

This file was deleted.

2 changes: 1 addition & 1 deletion examples/plot/docs/components/dailyPlot.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as d3 from "npm:d3";
import * as Plot from "npm:@observablehq/plot";
import * as d3 from "npm:d3";

export const today = d3.utcDay(d3.utcHour.offset(d3.utcHour(), -10));
export const start = d3.utcYear.offset(today, -2);
Expand Down
31 changes: 31 additions & 0 deletions examples/plot/docs/components/trend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as d3 from "npm:d3";
import {html} from "npm:htl";

export function trend(
value /*: number */,
{
format = "+d",
positive = "green",
negative = "red",
base = "muted",
positiveSuffix = " ↗︎",
negativeSuffix = " ↘︎",
baseSuffix = ""
} = {} /*
as {
format: string | ((x: number) => string);
positive: string;
negative: string;
base: string;
positiveSuffix: string;
negativeSuffix: string;
baseSuffix: string;
}
*/
) /*: Node */ {
if (typeof format === "string") format = d3.format(format);
if (typeof format !== "function") throw new Error(`unsupported format ${format}`);
return html`<span class="small ${value > 0 ? positive : value < 0 ? negative : base}">${format(value)}${
value > 0 ? positiveSuffix : value < 0 ? negativeSuffix : baseSuffix
}`;
}
56 changes: 40 additions & 16 deletions examples/plot/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ theme: dashboard
# Plot

```js
import {BigNumber} from "./components/bigNumber.js";
import {trend} from "./components/trend.js";
import {DailyPlot, today, start} from "./components/dailyPlot.js";
```

Expand Down Expand Up @@ -43,17 +43,29 @@ const burndown = issues
```
<div class="grid grid-cols-4" style="grid-auto-rows: 86px;">
<div class=card>${BigNumber(versions.at(-1).version, {
title: "Current release",
href: `https://github.com/observablehq/plot/releases/tag/v${versions.at(-1).version}`,
trend: d3.utcDay.count(versions.at(-1).date, Date.now()),
trendFormat: d => `${d === 0 ? "today" : d===1 ? "yesterday" : `${d} days ago`}`,
trendColor: "#888",
trendArrow: null
})}</div>
<div class=card>${BigNumber(stars.length, {title: "GitHub stars", trend: stars.filter((d) => d.starred_at >= lastWeek).length, trendFormat: "+", trendTitle: "Since last week"})}</div>
<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>
<div class=card>${BigNumber(d3.sum(downloads, (d) => d.value), {title: "Total npm downloads"})}</div>
<div class="card">
<h2>Current release</h2>
<span class="big">${versions.at(-1).version}</span>
<a href="https://github.com/observablehq/plot/releases" style="color: inherit;">
${((days) => days === 0 ? "today" : days === 1 ? "yesterday" : `${days} days ago`)(d3. utcDay.count(versions.at(-1).date, new Date()))}
</a>
</div>
<div class="card">
<h2>GitHub stars</h2>
<span class="big">${stars.length.toLocaleString("en-US")}</span>
${trend(d3.sum(stars, (d) => d.starred_at >= lastWeek))}</span>
</div>
<div class="card">
<h2>Daily npm downloads</h2>
<span class="big">${downloads[0].value.toLocaleString("en-US")}</span>
${trend(downloads[7].value
? (downloads[0].value - downloads[7].value) / downloads[7].value
: undefined, {format: "+.1%"})}
</div>
<div class="card">
<h2>Total npm downloads</h2>
<span class="big">${d3.sum(downloads, (d) => d.value).toLocaleString("en-US")}</span>
</div>
</div>
<div class="card grid grid-cols-1" style="grid-auto-rows: calc(260px + 2rem);">
Expand Down Expand Up @@ -100,10 +112,22 @@ const burndown = issues
</div>
<div class="grid grid-cols-4" style="grid-auto-rows: 86px;">
<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>
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.open >= lastMonth).length, {title: "Opened issues, 28d"})}</div>
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.close >= lastMonth).length, {title: "Closed issues, 28d"})}</div>
<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>
<div class="card">
<h2>Open issues</h2>
<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>
</div>
<div class="card">
<h2>Opened issues, 28d</h2>
<span class="big">${d3.sum(issues, (d) => !d.pull_request && d.open >= lastMonth).toLocaleString("en-US")}</span>
</div>
<div class="card">
<h2>Closed issues, 28d</h2>
<span class="big">${d3.sum(issues, (d) => !d.pull_request && d.close >= lastMonth).toLocaleString("en-US")}</span>
</div>
<div class="card">
<h2>Open PRs</h2>
<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>
</div>
</div>
<div class="grid grid-cols-2" style="grid-auto-rows: 276px;">
Expand Down

0 comments on commit a1cbe3d

Please sign in to comment.