Skip to content

Commit 600e129

Browse files
TMHSDigitalclaude
andauthored
feat(gallery): browse controls and interaction feel (#303)
* feat(gallery): detail-page navigation, code ergonomics, image polish Detail pages were dead ends: a reader who finished one example had to go back to the grid to find the next. They now page within their own kind (prev/next, arrow keys), list their tags as links back to the filtered index, and end with three related entries chosen by shared topic tags. Source listings gain a line-number gutter and collapse past 120 lines; every code block gets a copy button with a non-secure-context fallback and a visible failure state; README headings get stable anchors. Card images carry intrinsic dimensions so the grid no longer shifts as they load, and the lightbox only closes on backdrop, button or Esc -- clicking the image toggles native size instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> * feat(gallery): browse controls and interaction feel Showcase pieces were reachable only through a "showcase" topic chip, one tag could be active at a time, and the grid had one fixed order. The index now has an All / Examples / Showcase switch, AND-combined topic chips, and a Gallery order / Name A-Z sort, all mirrored in the URL hash (k=, tag=a,b, s=). Legacy #tag=showcase links, the landing page's among them, resolve to the Showcase switch so no inbound link breaks. Search no longer rewrites the hash on every keystroke, card renders fade in once decoded, hover gets a restrained zoom that reduced-motion turns off (replacing a rule that disabled a transform nobody set), focus rings sit inside segmented controls instead of being clipped, README prose is capped at a readable measure, and the sticky bar packs tighter on phones. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> --------- Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 88e04c2 commit 600e129

91 files changed

Lines changed: 2416 additions & 542 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/gallery/anvil/index.html‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@
104104
.density-btn + .density-btn { border-left: 1px solid var(--border); }
105105
.density-btn:hover { color: var(--select); }
106106
.density-btn.active { background: var(--select); color: #1a1b1e; }
107+
/* Segmented groups clip overflow, so the ring has to sit inside. */
108+
.density-btn:focus-visible, .chip:focus-visible { outline-offset: -2px; }
109+
.sort select { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim);
110+
border-radius: var(--radius); padding: 0.3rem 0.5rem; cursor: pointer;
111+
font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; text-transform: uppercase; }
112+
.sort select:hover, .sort select:focus { color: var(--select); border-color: var(--select); outline: none; }
107113
.tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border);
108114
color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer;
109115
font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; }
@@ -123,6 +129,14 @@
123129
transition: color 0.15s, border-color 0.15s; }
124130
.chip:hover { color: var(--select); border-color: var(--select); }
125131
.chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); }
132+
@media (max-width: 559px) {
133+
.controls-inner { padding: 0.45rem 1rem 0.5rem; gap: 0.4rem; }
134+
.controls-row { gap: 0.4rem; }
135+
.searchwrap { flex-basis: 100%; }
136+
.count { position: absolute; width: 1px; height: 1px; overflow: hidden;
137+
clip: rect(0 0 0 0); white-space: nowrap; }
138+
.density-btn { padding: 0.36rem 0.5rem; }
139+
}
126140
@media (max-width: 719px) {
127141
html.js .tags-toggle { display: inline-block; }
128142
html.js .chips { display: none; }
@@ -160,8 +174,12 @@
160174
transition: outline-color 0.12s ease, border-color 0.12s ease; }
161175
.card:hover { border-color: var(--select); outline-color: var(--select); }
162176
.card.hidden { display: none; }
163-
.card-media { display: block; background: var(--bg2); line-height: 0; }
164-
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
177+
.card-media { display: block; background: var(--bg2); line-height: 0; overflow: hidden; }
178+
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
179+
transition: transform 0.35s ease, opacity 0.3s ease; }
180+
.card:hover .card-media img { transform: scale(1.03); }
181+
html.js .grid .card-media img { opacity: 0; }
182+
html.js .grid .card-media img.is-loaded { opacity: 1; }
165183
.card-body { padding: 1.15rem 1.4rem 1.45rem; display: flex; flex-direction: column; flex: 1 1 auto; }
166184
.card-body h2 { font-family: var(--font-mono); font-size: 1rem; font-weight: 400; margin-bottom: 0.5rem; }
167185
.card-body h2 a { color: var(--text); }
@@ -200,6 +218,7 @@
200218
.md h1, .md h2, .md h3 { letter-spacing: -0.01em; margin: 1.4rem 0 0.6rem; line-height: 1.25; }
201219
.md h1 { font-size: 1.35rem; } .md h2 { font-size: 1.15rem; } .md h3 { font-size: 1rem; }
202220
.md p { margin: 0.7rem 0; }
221+
.md > p, .md > ul, .md > ol, .md > h2, .md > h3 { max-width: 75ch; }
203222
.md ul, .md ol { margin: 0.7rem 0 0.7rem 1.4rem; }
204223
.md li { margin: 0.3rem 0; }
205224
.md .table-wrap { overflow-x: auto; margin: 0.9rem 0; }
@@ -306,8 +325,8 @@
306325
}
307326
@media (prefers-reduced-motion: reduce) {
308327
html { scroll-behavior: auto; }
309-
.card { transition: none; }
310-
.card:hover { transform: none; }
328+
.card, .card-media img { transition: none; }
329+
.card:hover .card-media img { transform: none; }
311330
.to-top { transition: none; }
312331
}
313332
</style>

‎docs/gallery/apothecary-shelf/index.html‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@
104104
.density-btn + .density-btn { border-left: 1px solid var(--border); }
105105
.density-btn:hover { color: var(--select); }
106106
.density-btn.active { background: var(--select); color: #1a1b1e; }
107+
/* Segmented groups clip overflow, so the ring has to sit inside. */
108+
.density-btn:focus-visible, .chip:focus-visible { outline-offset: -2px; }
109+
.sort select { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim);
110+
border-radius: var(--radius); padding: 0.3rem 0.5rem; cursor: pointer;
111+
font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; text-transform: uppercase; }
112+
.sort select:hover, .sort select:focus { color: var(--select); border-color: var(--select); outline: none; }
107113
.tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border);
108114
color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer;
109115
font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; }
@@ -123,6 +129,14 @@
123129
transition: color 0.15s, border-color 0.15s; }
124130
.chip:hover { color: var(--select); border-color: var(--select); }
125131
.chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); }
132+
@media (max-width: 559px) {
133+
.controls-inner { padding: 0.45rem 1rem 0.5rem; gap: 0.4rem; }
134+
.controls-row { gap: 0.4rem; }
135+
.searchwrap { flex-basis: 100%; }
136+
.count { position: absolute; width: 1px; height: 1px; overflow: hidden;
137+
clip: rect(0 0 0 0); white-space: nowrap; }
138+
.density-btn { padding: 0.36rem 0.5rem; }
139+
}
126140
@media (max-width: 719px) {
127141
html.js .tags-toggle { display: inline-block; }
128142
html.js .chips { display: none; }
@@ -160,8 +174,12 @@
160174
transition: outline-color 0.12s ease, border-color 0.12s ease; }
161175
.card:hover { border-color: var(--select); outline-color: var(--select); }
162176
.card.hidden { display: none; }
163-
.card-media { display: block; background: var(--bg2); line-height: 0; }
164-
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
177+
.card-media { display: block; background: var(--bg2); line-height: 0; overflow: hidden; }
178+
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
179+
transition: transform 0.35s ease, opacity 0.3s ease; }
180+
.card:hover .card-media img { transform: scale(1.03); }
181+
html.js .grid .card-media img { opacity: 0; }
182+
html.js .grid .card-media img.is-loaded { opacity: 1; }
165183
.card-body { padding: 1.15rem 1.4rem 1.45rem; display: flex; flex-direction: column; flex: 1 1 auto; }
166184
.card-body h2 { font-family: var(--font-mono); font-size: 1rem; font-weight: 400; margin-bottom: 0.5rem; }
167185
.card-body h2 a { color: var(--text); }
@@ -200,6 +218,7 @@
200218
.md h1, .md h2, .md h3 { letter-spacing: -0.01em; margin: 1.4rem 0 0.6rem; line-height: 1.25; }
201219
.md h1 { font-size: 1.35rem; } .md h2 { font-size: 1.15rem; } .md h3 { font-size: 1rem; }
202220
.md p { margin: 0.7rem 0; }
221+
.md > p, .md > ul, .md > ol, .md > h2, .md > h3 { max-width: 75ch; }
203222
.md ul, .md ol { margin: 0.7rem 0 0.7rem 1.4rem; }
204223
.md li { margin: 0.3rem 0; }
205224
.md .table-wrap { overflow-x: auto; margin: 0.9rem 0; }
@@ -306,8 +325,8 @@
306325
}
307326
@media (prefers-reduced-motion: reduce) {
308327
html { scroll-behavior: auto; }
309-
.card { transition: none; }
310-
.card:hover { transform: none; }
328+
.card, .card-media img { transition: none; }
329+
.card:hover .card-media img { transform: none; }
311330
.to-top { transition: none; }
312331
}
313332
</style>

‎docs/gallery/armature-bend/index.html‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@
104104
.density-btn + .density-btn { border-left: 1px solid var(--border); }
105105
.density-btn:hover { color: var(--select); }
106106
.density-btn.active { background: var(--select); color: #1a1b1e; }
107+
/* Segmented groups clip overflow, so the ring has to sit inside. */
108+
.density-btn:focus-visible, .chip:focus-visible { outline-offset: -2px; }
109+
.sort select { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim);
110+
border-radius: var(--radius); padding: 0.3rem 0.5rem; cursor: pointer;
111+
font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; text-transform: uppercase; }
112+
.sort select:hover, .sort select:focus { color: var(--select); border-color: var(--select); outline: none; }
107113
.tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border);
108114
color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer;
109115
font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; }
@@ -123,6 +129,14 @@
123129
transition: color 0.15s, border-color 0.15s; }
124130
.chip:hover { color: var(--select); border-color: var(--select); }
125131
.chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); }
132+
@media (max-width: 559px) {
133+
.controls-inner { padding: 0.45rem 1rem 0.5rem; gap: 0.4rem; }
134+
.controls-row { gap: 0.4rem; }
135+
.searchwrap { flex-basis: 100%; }
136+
.count { position: absolute; width: 1px; height: 1px; overflow: hidden;
137+
clip: rect(0 0 0 0); white-space: nowrap; }
138+
.density-btn { padding: 0.36rem 0.5rem; }
139+
}
126140
@media (max-width: 719px) {
127141
html.js .tags-toggle { display: inline-block; }
128142
html.js .chips { display: none; }
@@ -160,8 +174,12 @@
160174
transition: outline-color 0.12s ease, border-color 0.12s ease; }
161175
.card:hover { border-color: var(--select); outline-color: var(--select); }
162176
.card.hidden { display: none; }
163-
.card-media { display: block; background: var(--bg2); line-height: 0; }
164-
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
177+
.card-media { display: block; background: var(--bg2); line-height: 0; overflow: hidden; }
178+
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
179+
transition: transform 0.35s ease, opacity 0.3s ease; }
180+
.card:hover .card-media img { transform: scale(1.03); }
181+
html.js .grid .card-media img { opacity: 0; }
182+
html.js .grid .card-media img.is-loaded { opacity: 1; }
165183
.card-body { padding: 1.15rem 1.4rem 1.45rem; display: flex; flex-direction: column; flex: 1 1 auto; }
166184
.card-body h2 { font-family: var(--font-mono); font-size: 1rem; font-weight: 400; margin-bottom: 0.5rem; }
167185
.card-body h2 a { color: var(--text); }
@@ -200,6 +218,7 @@
200218
.md h1, .md h2, .md h3 { letter-spacing: -0.01em; margin: 1.4rem 0 0.6rem; line-height: 1.25; }
201219
.md h1 { font-size: 1.35rem; } .md h2 { font-size: 1.15rem; } .md h3 { font-size: 1rem; }
202220
.md p { margin: 0.7rem 0; }
221+
.md > p, .md > ul, .md > ol, .md > h2, .md > h3 { max-width: 75ch; }
203222
.md ul, .md ol { margin: 0.7rem 0 0.7rem 1.4rem; }
204223
.md li { margin: 0.3rem 0; }
205224
.md .table-wrap { overflow-x: auto; margin: 0.9rem 0; }
@@ -306,8 +325,8 @@
306325
}
307326
@media (prefers-reduced-motion: reduce) {
308327
html { scroll-behavior: auto; }
309-
.card { transition: none; }
310-
.card:hover { transform: none; }
328+
.card, .card-media img { transition: none; }
329+
.card:hover .card-media img { transform: none; }
311330
.to-top { transition: none; }
312331
}
313332
</style>

‎docs/gallery/attribute-domain-shear/index.html‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@
104104
.density-btn + .density-btn { border-left: 1px solid var(--border); }
105105
.density-btn:hover { color: var(--select); }
106106
.density-btn.active { background: var(--select); color: #1a1b1e; }
107+
/* Segmented groups clip overflow, so the ring has to sit inside. */
108+
.density-btn:focus-visible, .chip:focus-visible { outline-offset: -2px; }
109+
.sort select { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim);
110+
border-radius: var(--radius); padding: 0.3rem 0.5rem; cursor: pointer;
111+
font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; text-transform: uppercase; }
112+
.sort select:hover, .sort select:focus { color: var(--select); border-color: var(--select); outline: none; }
107113
.tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border);
108114
color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer;
109115
font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; }
@@ -123,6 +129,14 @@
123129
transition: color 0.15s, border-color 0.15s; }
124130
.chip:hover { color: var(--select); border-color: var(--select); }
125131
.chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); }
132+
@media (max-width: 559px) {
133+
.controls-inner { padding: 0.45rem 1rem 0.5rem; gap: 0.4rem; }
134+
.controls-row { gap: 0.4rem; }
135+
.searchwrap { flex-basis: 100%; }
136+
.count { position: absolute; width: 1px; height: 1px; overflow: hidden;
137+
clip: rect(0 0 0 0); white-space: nowrap; }
138+
.density-btn { padding: 0.36rem 0.5rem; }
139+
}
126140
@media (max-width: 719px) {
127141
html.js .tags-toggle { display: inline-block; }
128142
html.js .chips { display: none; }
@@ -160,8 +174,12 @@
160174
transition: outline-color 0.12s ease, border-color 0.12s ease; }
161175
.card:hover { border-color: var(--select); outline-color: var(--select); }
162176
.card.hidden { display: none; }
163-
.card-media { display: block; background: var(--bg2); line-height: 0; }
164-
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
177+
.card-media { display: block; background: var(--bg2); line-height: 0; overflow: hidden; }
178+
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
179+
transition: transform 0.35s ease, opacity 0.3s ease; }
180+
.card:hover .card-media img { transform: scale(1.03); }
181+
html.js .grid .card-media img { opacity: 0; }
182+
html.js .grid .card-media img.is-loaded { opacity: 1; }
165183
.card-body { padding: 1.15rem 1.4rem 1.45rem; display: flex; flex-direction: column; flex: 1 1 auto; }
166184
.card-body h2 { font-family: var(--font-mono); font-size: 1rem; font-weight: 400; margin-bottom: 0.5rem; }
167185
.card-body h2 a { color: var(--text); }
@@ -200,6 +218,7 @@
200218
.md h1, .md h2, .md h3 { letter-spacing: -0.01em; margin: 1.4rem 0 0.6rem; line-height: 1.25; }
201219
.md h1 { font-size: 1.35rem; } .md h2 { font-size: 1.15rem; } .md h3 { font-size: 1rem; }
202220
.md p { margin: 0.7rem 0; }
221+
.md > p, .md > ul, .md > ol, .md > h2, .md > h3 { max-width: 75ch; }
203222
.md ul, .md ol { margin: 0.7rem 0 0.7rem 1.4rem; }
204223
.md li { margin: 0.3rem 0; }
205224
.md .table-wrap { overflow-x: auto; margin: 0.9rem 0; }
@@ -306,8 +325,8 @@
306325
}
307326
@media (prefers-reduced-motion: reduce) {
308327
html { scroll-behavior: auto; }
309-
.card { transition: none; }
310-
.card:hover { transform: none; }
328+
.card, .card-media img { transition: none; }
329+
.card:hover .card-media img { transform: none; }
311330
.to-top { transition: none; }
312331
}
313332
</style>

‎docs/gallery/bake-normal-high-to-low/index.html‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@
104104
.density-btn + .density-btn { border-left: 1px solid var(--border); }
105105
.density-btn:hover { color: var(--select); }
106106
.density-btn.active { background: var(--select); color: #1a1b1e; }
107+
/* Segmented groups clip overflow, so the ring has to sit inside. */
108+
.density-btn:focus-visible, .chip:focus-visible { outline-offset: -2px; }
109+
.sort select { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim);
110+
border-radius: var(--radius); padding: 0.3rem 0.5rem; cursor: pointer;
111+
font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; text-transform: uppercase; }
112+
.sort select:hover, .sort select:focus { color: var(--select); border-color: var(--select); outline: none; }
107113
.tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border);
108114
color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer;
109115
font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; }
@@ -123,6 +129,14 @@
123129
transition: color 0.15s, border-color 0.15s; }
124130
.chip:hover { color: var(--select); border-color: var(--select); }
125131
.chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); }
132+
@media (max-width: 559px) {
133+
.controls-inner { padding: 0.45rem 1rem 0.5rem; gap: 0.4rem; }
134+
.controls-row { gap: 0.4rem; }
135+
.searchwrap { flex-basis: 100%; }
136+
.count { position: absolute; width: 1px; height: 1px; overflow: hidden;
137+
clip: rect(0 0 0 0); white-space: nowrap; }
138+
.density-btn { padding: 0.36rem 0.5rem; }
139+
}
126140
@media (max-width: 719px) {
127141
html.js .tags-toggle { display: inline-block; }
128142
html.js .chips { display: none; }
@@ -160,8 +174,12 @@
160174
transition: outline-color 0.12s ease, border-color 0.12s ease; }
161175
.card:hover { border-color: var(--select); outline-color: var(--select); }
162176
.card.hidden { display: none; }
163-
.card-media { display: block; background: var(--bg2); line-height: 0; }
164-
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
177+
.card-media { display: block; background: var(--bg2); line-height: 0; overflow: hidden; }
178+
.card-media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
179+
transition: transform 0.35s ease, opacity 0.3s ease; }
180+
.card:hover .card-media img { transform: scale(1.03); }
181+
html.js .grid .card-media img { opacity: 0; }
182+
html.js .grid .card-media img.is-loaded { opacity: 1; }
165183
.card-body { padding: 1.15rem 1.4rem 1.45rem; display: flex; flex-direction: column; flex: 1 1 auto; }
166184
.card-body h2 { font-family: var(--font-mono); font-size: 1rem; font-weight: 400; margin-bottom: 0.5rem; }
167185
.card-body h2 a { color: var(--text); }
@@ -200,6 +218,7 @@
200218
.md h1, .md h2, .md h3 { letter-spacing: -0.01em; margin: 1.4rem 0 0.6rem; line-height: 1.25; }
201219
.md h1 { font-size: 1.35rem; } .md h2 { font-size: 1.15rem; } .md h3 { font-size: 1rem; }
202220
.md p { margin: 0.7rem 0; }
221+
.md > p, .md > ul, .md > ol, .md > h2, .md > h3 { max-width: 75ch; }
203222
.md ul, .md ol { margin: 0.7rem 0 0.7rem 1.4rem; }
204223
.md li { margin: 0.3rem 0; }
205224
.md .table-wrap { overflow-x: auto; margin: 0.9rem 0; }
@@ -306,8 +325,8 @@
306325
}
307326
@media (prefers-reduced-motion: reduce) {
308327
html { scroll-behavior: auto; }
309-
.card { transition: none; }
310-
.card:hover { transform: none; }
328+
.card, .card-media img { transition: none; }
329+
.card:hover .card-media img { transform: none; }
311330
.to-top { transition: none; }
312331
}
313332
</style>

0 commit comments

Comments
 (0)