Repository navigation
Expand file tree
/
Copy pathdemo.html
More file actions
112 lines (103 loc) · 6.4 KB
/
Copy pathdemo.html
File metadata and controls
112 lines (103 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sediment demo</title>
<link rel="stylesheet" href="sediment.css">
<style>
/* Demo-only chrome, not part of Sediment. */
body { margin: 0; padding: 32px; background: #3e332f; color: #edf3d7;
font-family: ui-monospace, "SF Mono", Menlo, monospace; }
h1 { font-size: 14px; font-weight: 400; opacity: 0.7; margin: 0 0 20px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
gap: 16px; max-width: 1100px; }
.card { position: relative; background: rgba(0,0,0,0.25); border-radius: 8px; padding: 20px 16px; }
.card h2 { font-size: 12px; font-weight: 400; margin: 0 0 10px; }
:root { --sediment-tip-bg: #edf3d7; --sediment-tip-ink: #3e332f; --sediment-tip-border: rgba(62,51,47,0.5); }
</style>
</head>
<body>
<h1>Sediment: a simple, accessible charting system for financial numbers.</h1>
<div class="grid">
<div class="card"><h2>Risk profile</h2><div id="dotPlot"></div></div>
<div class="card"><h2>Net worth</h2><div id="lineChart"></div></div>
<div class="card"><h2>Total assets</h2><div id="stackedArea"></div></div>
<div class="card"><h2>Monthly savings</h2><div id="columnChart"></div></div>
<div class="card"><h2>Holdings</h2><div id="segmentedBar"></div></div>
<div class="card"><h2>Invested vs value</h2><div id="barLineChart"></div></div>
<div class="card"><h2>Cash and shares</h2><div id="twoLines"></div></div>
<div class="card"><h2>Holdings over time</h2><div id="smallMultiples"></div></div>
</div>
<div id="tip" class="sediment-tip"></div>
<script src="sediment.js"></script>
<script>
const cream = "#edf3d7", choc = "#3e332f", border = "rgba(237,243,215,0.5)",
hair = "rgba(237,243,215,0.18)", surface = "rgba(0,0,0,0.25)",
pistachio = "#81bb8b", peach = "#e88b7d";
const TIP = Sediment.tip(document.getElementById("tip"));
const el = id => document.getElementById(id);
// Absurd, obviously-fictional confectionery money. Compact $Xm / $Xb labels.
const M = v => { if (v === 0) return "$0"; const a = Math.abs(v), s = v < 0 ? "-$" : "$";
return a >= 1e9 ? s + (a/1e9).toFixed(1) + "b" : s + Math.round(a/1e6) + "m"; };
const MO = ["Jan","Feb","Mar","Apr","May","Jun"];
const xs = MO.map((_, i) => Date.UTC(2026, i, 15));
const xLabel = t => MO[new Date(t).getUTCMonth()];
// Risk profile: funds on a shared risk axis, dot area = amount.
const L = ["cash","conservative","balanced","growth","aggressive"];
const funds = [["Cocoa Cash",0,24e6],["Marzipan Bonds",1,60e6],["Nougat Balanced",2,300e6],
["Pistachio Growth",3,140e6],["Ghost Pepper",4,40e6]];
const fundTotal = funds.reduce((a, r) => a + r[2], 0);
Sediment.dotPlot({ host: el("dotPlot"), axisPad: 40, levels: L, dotColor: cream,
tokens: { hair: border, fg: cream }, staggerLabels: true, tip: TIP,
avgPos: funds.reduce((a, r) => a + r[2] * r[1], 0) / fundTotal,
rows: funds.map(r => ({ pos: r[1], value: r[2], label: r[0], valueLabel: M(r[2]),
tipHTML: '<div class="t">' + r[0] + '</div>' })) });
// Net worth: a single line over time.
Sediment.lineChart({ host: el("lineChart"), xs,
series: [{ values: [120,150,190,240,300,380].map(v => v*1e6), color: cream }],
tokens: { axis: cream, hair, page: choc }, fmtK: M, xLabel,
endLabel: () => "net worth", annotateExtremes: true });
// Two lines, told apart by dash: each named at its end with its latest value,
// a target drawn as a reference, an event marked, and a missing month left blank.
Sediment.lineChart({ host: el("twoLines"), xs,
series: [{ values: [180,200,240,null,360,420].map(v => v && v*1e6), color: cream },
{ values: [20,22,24,25,26,26].map(v => v*1e6), color: cream }],
tokens: { axis: cream, hair, page: choc, ref: border }, fmtK: M,
fmtTick: (v, top) => top ? M(v) : M(v).replace("$", ""), xLabel, padR: 130,
endLabel: si => ["shares", "cash"][si], endValue: si => M([420e6, 26e6][si]),
refs: [{ value: 300e6, label: "target" }],
events: [{ t: xs[2], label: "rebalance" }] });
// Holdings over time: one panel each, on its own scale.
Sediment.smallMultiples({ host: el("smallMultiples"), xs, note: "each on its own scale",
tokens: { axis: cream, hair, page: choc }, fmtK: M, xLabel,
panels: [{ label: "Praline Partners", values: [480,500,470,510,515,520].map(v => v*1e6), color: cream },
{ label: "Macaron Mills", values: [120,140,170,150,175,180].map(v => v*1e6), color: cream },
{ label: "Fudge Factory", values: [70,66,61,null,58,60].map(v => v && v*1e6), color: cream }] });
// Total assets: stacked, texture-coded bands.
Sediment.stackedArea({ host: el("stackedArea"), xs, n: 4, padR: 150, ink: cream, bg: choc,
tokens: { surface, axis: cream, hair }, fmtK: M, fmtNZD: M, xLabel,
bands: [{ values: [20,22,24,25,26,26].map(v => v*1e6), ti: 0, label: "cash" },
{ values: [180,200,240,300,360,420].map(v => v*1e6), ti: 1, label: "shares" },
{ values: [400,410,430,470,520,560].map(v => v*1e6), ti: 2, label: "property" }] });
// Monthly savings: diverging columns with a target line.
const net = [6.2,8.1,-1.4,7.5,5.3,6.9].map(v => v*1e6);
Sediment.columnChart({ host: el("columnChart"), posColor: pistachio, negColor: peach, ink: cream,
tokens: { border }, target: 3e6, targetLabel: "goal", zeroLabel: "$0", tip: TIP,
bars: net.map((v, i) => ({ value: v, label: MO[i] })),
tipHTML: i => '<div class="row"><span>net</span><span>' + M(net[i]) + '</span></div>' });
// Holdings: proportional segments with connector labels.
const holds = [["Fudge Factory",60e6,0],["Macaron Mills",180e6,1],["Praline Partners",520e6,2],["Sorbet Co",90e6,3]];
const holdTotal = holds.reduce((a, r) => a + r[1], 0);
Sediment.segmentedBar({ host: el("segmentedBar"), n: 5, total: holdTotal, ink: cream,
tokens: { border, hair }, connectors: true, tip: TIP,
segments: holds.map(r => ({ label: r[0], value: r[1], ti: r[2],
tipHTML: '<div class="t">' + r[0] + '</div><div class="row"><span>' + M(r[1]) + '</span></div>' })) });
// Invested vs value: textured area under a value line.
Sediment.barLineChart({ host: el("barLineChart"), xs, ti: 1, ink: cream,
tokens: { axis: cream, hair, page: choc }, fmtK: M, xLabel, H: 250, padB: 44,
bars: [40,110,190,270,340,400].map(v => v*1e6),
line: [40,120,230,360,500,610].map(v => v*1e6) });
</script>
</body>
</html>