Skip to content

Commit 9c1d900

Browse files
authored
Rework the 'Why UltraPlot?' page with before/after comparison cards (#788)
* docs: rework Why UltraPlot page with before/after comparison cards * Replace why-page SVG figures with source plots * Use supported UltraPlot figsize arguments in Why page plot sources * Left-align why docs cards and standardize figure shape * Standardize why page matplotlib figure sizes to match UltraPlot dimensions * Add before/after slider UI for Why page figure comparisons * finalizing touches
1 parent c4665a9 commit 9c1d900

5 files changed

Lines changed: 854 additions & 619 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ docs/_build
2222
docs/_static/ultraplotrc
2323
docs/_static/rctable.rst
2424
docs/_static/*
25+
!docs/_static/why_plots/
2526
*.html
2627
docs/gallery/
2728
docs/sg_execution_times.rst

docs/_static/custom.css

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,3 +1250,213 @@ body.wy-body-for-nav
12501250
max-width: 100%;
12511251
height: auto;
12521252
}
1253+
1254+
/* Why UltraPlot page: before/after comparison cards */
1255+
.uplt-why {
1256+
border: 1px solid var(--uplt-color-border-muted);
1257+
border-radius: 0.8rem;
1258+
background: linear-gradient(
1259+
180deg,
1260+
var(--uplt-color-white) 0%,
1261+
var(--uplt-color-sidebar-bg) 100%
1262+
);
1263+
box-shadow: 0 4px 14px var(--uplt-color-shadow);
1264+
overflow: hidden;
1265+
}
1266+
1267+
.uplt-why-mpl {
1268+
border-top: 4px solid #b45309;
1269+
}
1270+
1271+
.uplt-why-uplt {
1272+
border-top: 4px solid #178f84;
1273+
}
1274+
1275+
.uplt-why img {
1276+
width: 100%;
1277+
height: auto;
1278+
border-radius: 0.45rem;
1279+
background: var(--uplt-color-panel-bg);
1280+
}
1281+
1282+
.uplt-why-compare {
1283+
margin-bottom: 0.75rem;
1284+
}
1285+
1286+
.uplt-why-compare .sd-card-body {
1287+
padding: 0.75rem;
1288+
display: flex;
1289+
flex-direction: column;
1290+
gap: 0.5rem;
1291+
}
1292+
1293+
.uplt-why-compare .uplt-compare-labels {
1294+
display: flex;
1295+
justify-content: space-between;
1296+
gap: 0.6rem;
1297+
padding: 0.4rem 0.75rem 0;
1298+
font-weight: 700;
1299+
font-size: 0.85rem;
1300+
text-transform: uppercase;
1301+
letter-spacing: 0.05em;
1302+
}
1303+
1304+
.uplt-why-compare .uplt-compare-labels .uplt-label {
1305+
background: var(--uplt-color-panel-bg);
1306+
border: 1px solid var(--uplt-color-border-muted);
1307+
border-radius: 9999px;
1308+
padding: 0.1rem 0.6rem;
1309+
}
1310+
1311+
.uplt-why-compare .uplt-compare-labels .uplt-label-mpl {
1312+
color: #b45309;
1313+
}
1314+
1315+
.uplt-why-compare .uplt-compare-labels .uplt-label-uplt {
1316+
color: #178f84;
1317+
}
1318+
1319+
.uplt-compare-frame {
1320+
position: relative;
1321+
width: 100%;
1322+
max-width: 100%;
1323+
overflow: hidden;
1324+
border-radius: 0.45rem;
1325+
border: 1px solid var(--uplt-color-border-muted);
1326+
background: var(--uplt-color-panel-bg);
1327+
--uplt-compare-position: 50%;
1328+
}
1329+
1330+
.uplt-compare-frame .uplt-compare-side {
1331+
position: relative;
1332+
width: 100%;
1333+
overflow: hidden;
1334+
}
1335+
1336+
.uplt-compare-frame .uplt-compare-side .sd-card-body {
1337+
margin: 0;
1338+
padding: 0.75rem;
1339+
color: inherit;
1340+
}
1341+
1342+
.uplt-compare-frame .uplt-compare-side .sd-card-body figure {
1343+
width: 100%;
1344+
margin: 0;
1345+
}
1346+
1347+
.uplt-compare-frame .uplt-compare-side .sd-card-body figure.align-default {
1348+
text-align: left;
1349+
}
1350+
1351+
.uplt-compare-frame .uplt-compare-side .sd-card-body figure img {
1352+
width: 100%;
1353+
height: auto;
1354+
display: block;
1355+
margin: 0;
1356+
}
1357+
1358+
.uplt-compare-frame .uplt-compare-side.uplt-compare-uplt {
1359+
position: relative;
1360+
z-index: 1;
1361+
clip-path: inset(0 0 0 var(--uplt-compare-position));
1362+
}
1363+
1364+
.uplt-compare-frame .uplt-compare-side.uplt-compare-mpl {
1365+
position: absolute;
1366+
inset: 0;
1367+
clip-path: inset(0 calc(100% - var(--uplt-compare-position)) 0 0);
1368+
z-index: 2;
1369+
}
1370+
1371+
.uplt-compare-frame .uplt-compare-handle {
1372+
position: absolute;
1373+
top: 0;
1374+
left: var(--uplt-compare-position);
1375+
transform: translateX(-50%);
1376+
width: 2px;
1377+
height: 100%;
1378+
background: var(--uplt-color-text-secondary);
1379+
opacity: 0.95;
1380+
pointer-events: none;
1381+
z-index: 3;
1382+
}
1383+
1384+
.uplt-compare-slider {
1385+
display: block;
1386+
width: 100%;
1387+
}
1388+
1389+
.uplt-compare-slider input[type="range"] {
1390+
width: 100%;
1391+
margin: 0;
1392+
}
1393+
1394+
.uplt-compare-label-btn {
1395+
appearance: none;
1396+
border: 1px solid var(--uplt-color-border-muted);
1397+
border-radius: 9999px;
1398+
background: var(--uplt-color-panel-bg);
1399+
color: inherit;
1400+
padding: 0.1rem 0.6rem;
1401+
margin: 0;
1402+
font: inherit;
1403+
font-weight: 700;
1404+
font-size: 0.85rem;
1405+
letter-spacing: 0.05em;
1406+
line-height: 1.2;
1407+
text-transform: uppercase;
1408+
cursor: pointer;
1409+
}
1410+
1411+
.uplt-compare-label-btn:focus-visible {
1412+
outline: 2px solid var(--uplt-color-accent);
1413+
outline-offset: 2px;
1414+
}
1415+
1416+
.uplt-compare-col {
1417+
grid-column: 1 / -1;
1418+
}
1419+
1420+
.uplt-why-compare-row {
1421+
align-items: stretch;
1422+
}
1423+
1424+
.uplt-why-compare-row .uplt-why-compare-col,
1425+
.uplt-why-compare-row .uplt-why-compare-col.sd-col {
1426+
flex: 0 0 100% !important;
1427+
width: 100% !important;
1428+
max-width: 100% !important;
1429+
grid-column: 1 / -1;
1430+
}
1431+
1432+
.uplt-why-compare-row .uplt-why-compare-hide-col {
1433+
display: none !important;
1434+
}
1435+
1436+
1437+
.uplt-why .sd-card-body > p:first-child {
1438+
font-weight: 700;
1439+
font-size: 0.9rem;
1440+
letter-spacing: 0.06em;
1441+
text-transform: uppercase;
1442+
}
1443+
1444+
.uplt-why-mpl .sd-card-body > p:first-child strong {
1445+
color: #b45309;
1446+
}
1447+
1448+
.uplt-why-uplt .sd-card-body > p:first-child strong {
1449+
color: #178f84;
1450+
}
1451+
1452+
.uplt-why .sd-card-body > p:last-child {
1453+
margin-top: auto;
1454+
padding-top: 0.35rem;
1455+
color: var(--uplt-color-text-secondary);
1456+
}
1457+
1458+
html.dark .uplt-why,
1459+
html.dark-theme .uplt-why,
1460+
[data-color-mode="dark"] .uplt-why {
1461+
background: linear-gradient(180deg, #252525 0%, #1f1f1f 100%);
1462+
}

docs/_static/custom.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,128 @@ function getCodeDetailsBlocks() {
3838
return Array.from(document.querySelectorAll("details.uplt-code-details"));
3939
}
4040

41+
function initWhyCompareSliders() {
42+
const isWhyPage = /\/why(?:\.html)?$|\/why\.htm$/.test(
43+
(window.location.pathname || "").toLowerCase(),
44+
);
45+
if (!isWhyPage) return;
46+
47+
const cards = Array.from(document.querySelectorAll(".sd-card.uplt-why"));
48+
for (let i = 0; i < cards.length - 1; i += 1) {
49+
const mplCard = cards[i];
50+
const upltCard = cards[i + 1];
51+
if (
52+
!mplCard ||
53+
!upltCard ||
54+
!mplCard.classList.contains("uplt-why-mpl") ||
55+
!upltCard.classList.contains("uplt-why-uplt")
56+
) {
57+
continue;
58+
}
59+
i += 1;
60+
61+
const mplBody = mplCard.querySelector(".sd-card-body");
62+
const upltBody = upltCard.querySelector(".sd-card-body");
63+
if (!mplBody || !upltBody) {
64+
continue;
65+
}
66+
67+
const slider = document.createElement("div");
68+
slider.className = "uplt-why-compare";
69+
70+
const body = document.createElement("div");
71+
body.className = "sd-card-body";
72+
slider.appendChild(body);
73+
74+
const labels = document.createElement("div");
75+
labels.className = "uplt-compare-labels";
76+
const leftLabel = document.createElement("button");
77+
leftLabel.type = "button";
78+
leftLabel.className = "uplt-label uplt-label-mpl uplt-compare-label-btn";
79+
leftLabel.textContent = "Matplotlib";
80+
leftLabel.addEventListener("click", () => {
81+
sliderInput.value = "100";
82+
onInput();
83+
});
84+
85+
const rightLabel = document.createElement("button");
86+
rightLabel.type = "button";
87+
rightLabel.className = "uplt-label uplt-label-uplt uplt-compare-label-btn";
88+
rightLabel.textContent = "UltraPlot";
89+
rightLabel.addEventListener("click", () => {
90+
sliderInput.value = "0";
91+
onInput();
92+
});
93+
labels.appendChild(leftLabel);
94+
labels.appendChild(rightLabel);
95+
body.appendChild(labels);
96+
97+
const frame = document.createElement("div");
98+
frame.className = "uplt-compare-frame";
99+
frame.setAttribute(
100+
"aria-label",
101+
"Matplotlib and UltraPlot before/after comparison",
102+
);
103+
104+
const mplLayer = document.createElement("div");
105+
mplLayer.className = "uplt-compare-side uplt-compare-mpl";
106+
mplLayer.appendChild(mplBody.cloneNode(true));
107+
frame.appendChild(mplLayer);
108+
109+
const upltLayer = document.createElement("div");
110+
upltLayer.className = "uplt-compare-side uplt-compare-uplt";
111+
upltLayer.appendChild(upltBody.cloneNode(true));
112+
frame.appendChild(upltLayer);
113+
114+
const handle = document.createElement("div");
115+
handle.className = "uplt-compare-handle";
116+
frame.appendChild(handle);
117+
118+
const sliderInput = document.createElement("input");
119+
sliderInput.className = "uplt-compare-slider";
120+
sliderInput.type = "range";
121+
sliderInput.min = "0";
122+
sliderInput.max = "100";
123+
sliderInput.value = "50";
124+
sliderInput.setAttribute("aria-label", "Comparison reveal amount");
125+
126+
const onInput = () => {
127+
frame.style.setProperty("--uplt-compare-position", `${sliderInput.value}%`);
128+
};
129+
sliderInput.addEventListener("input", onInput);
130+
onInput();
131+
132+
body.appendChild(frame);
133+
body.appendChild(sliderInput);
134+
135+
mplCard.className = "sd-card uplt-why uplt-why-compare";
136+
mplCard.replaceChildren();
137+
mplCard.appendChild(body);
138+
139+
const compareCol = mplCard.closest(".sd-col");
140+
if (compareCol) {
141+
compareCol.classList.add("uplt-why-compare-col");
142+
compareCol.style.width = "100%";
143+
compareCol.style.maxWidth = "100%";
144+
compareCol.style.flex = "0 0 100%";
145+
}
146+
147+
const compareRow = mplCard.closest(".sd-row");
148+
if (compareRow) {
149+
compareRow.classList.add("uplt-why-compare-row");
150+
compareRow.style.display = "block";
151+
}
152+
153+
const upltCol = upltCard.closest(".sd-col");
154+
if (upltCol) {
155+
upltCol.classList.add("uplt-why-compare-hide-col");
156+
upltCol.style.display = "none";
157+
}
158+
159+
upltCard.style.display = "none";
160+
}
161+
}
162+
41163
function initScrollChromeFade() {
42164
const topBar = document.querySelector(".sy-head");
43165
const leftBar = document.querySelector(".sy-lside");
@@ -711,6 +833,7 @@ document.addEventListener("DOMContentLoaded", function () {
711833

712834
// Re-sync right TOC controls now that code wrappers exist.
713835
initShibuyaRightToc();
836+
initWhyCompareSliders();
714837

715838
const navLinks = document.querySelectorAll(
716839
".wy-menu-vertical a.reference.internal",

docs/conf.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,10 @@ def _reset_ultraplot(gallery_conf, fname):
427427
"}",
428428
]
429429

430+
# Prefer vector graphics for sphinx ``plot`` directives so plots stay sharp
431+
# without high-DPI raster scaling.
432+
plot_formats = ["svg"]
433+
430434
# Control notebook execution from env for predictable local/CI builds.
431435
# Use values: auto, always, never.
432436
nbsphinx_execute = os.environ.get("UPLT_DOCS_EXECUTE", "auto").strip().lower()

0 commit comments

Comments
 (0)