Skip to content

Commit 6f201ff

Browse files
TMHSDigitalclaude
andauthored
docs: facelift the examples gallery + enrich landing meta (#25)
Gallery page (this-repo-owned, generated from gallery.json): - Add light/dark/auto theme with a toggle synced to the landing page's localStorage 'theme' key, so a visitor's choice carries across pages (was hardcoded dark, inconsistent with the landing). - Full meta/SEO/social: canonical, og:*, twitter card, theme-color, favicon. - Visual polish: sticky top bar, fluid type scale, refined cards with hover lift, :focus-visible states, skip link, prefers-reduced-motion guard. - Responsive 1->2 columns at 720px; heroes kept uncropped (align-items:start). Landing (via existing site.json template hooks -- no template edit, no fleet blast radius): favicon, canonical, and a this-repo og:image (was the meta-repo default logo), plus Claude Code + cross-platform compatibility badges. Add assets/favicon.svg (shared by both pages; build_site copies assets/ -> docs/assets/). Capture the design direction in docs/gallery/DESIGN_NOTES.md as the prototype for the Option-2 fleet facelift. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 427fde6 commit 6f201ff

6 files changed

Lines changed: 336 additions & 100 deletions

File tree

assets/favicon.svg

Lines changed: 10 additions & 0 deletions
Loading

docs/gallery/DESIGN_NOTES.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Gallery design direction — prototype for the Option-2 fleet facelift
2+
3+
This local gallery (`docs/gallery/`, generated by `scripts/build_gallery.py` from
4+
`examples/gallery.json`) is the **deliberate prototype** for the eventual shared-template
5+
facelift tracked in [Developer-Tools-Directory#86](https://github.com/TMHSDigital/Developer-Tools-Directory/issues/86)
6+
and the ROADMAP "Fleet Pages examples support" candidate. The markup here is throwaway on
7+
migration; the **data** (`gallery.json`) and the **visual direction** below are what carry over.
8+
9+
## Tokens (aligned to the fleet landing page so the two never clash)
10+
11+
| Token | Dark | Light | Notes |
12+
| --- | --- | --- | --- |
13+
| `--bg` | `#0d1117` | `#f6f8fa` | matches landing's GitHub-dark base |
14+
| `--surface` | `#161b22` | `#ffffff` | card background |
15+
| `--surface-2` | `#1c2128` | `#f0f2f5` | toggle / inline code |
16+
| `--border` | `#30363d` | `#d0d7de` | |
17+
| `--text` | `#e6edf3` | `#1f2328` | |
18+
| `--text-dim` | `#8b949e` | `#656d76` | secondary text |
19+
| `--accent` / `--accent-light` | `#7c3aed` / `#a78bfa` | same | from `site.json`; shared with landing |
20+
| `--radius` / `--radius-lg` | `8px` / `12px` || cards use `-lg` |
21+
| font | `'Inter', system-ui…` || landing ships the Inter webfont; the prototype uses the same stack and falls back to system sans (no coupling to the fleet font files) |
22+
23+
## Type scale
24+
- Page title `h1`: `clamp(1.9rem, 4vw, 2.6rem)`, `letter-spacing: -0.02em` — fluid hero.
25+
- Card title `h2`: `1.22rem`.
26+
- Body: `1rem` / `line-height: 1.6`; secondary `0.9rem`; tag `0.68rem` uppercase.
27+
28+
## Layout
29+
- Container `max-width: 1080px`, centered, `1.25rem` side padding.
30+
- Grid: **1 column** mobile → **2 columns at ≥720px**, `align-items: start` (cards don't stretch to a shared row height — heroes have mixed aspect ratios, e.g. the 8:3 swatch panorama vs 16:9 stills, and must not be cropped).
31+
- Card: hero image (full-bleed, natural aspect, never cropped) above a body block; hover lifts `-3px` with an accent-tinted border and soft shadow.
32+
33+
## Theme
34+
- Tri-state **auto / light / dark** mirroring the landing: `data-theme` on `<html>`, persisted in `localStorage['theme']`**the same key the landing uses**, so a visitor's choice carries across both pages.
35+
- FOUC guard runs before first paint. `theme-color` meta per scheme. Toggle cycles auto→light→dark with a sun/moon glyph and an accurate `aria-label`.
36+
37+
## Accessibility
38+
- Skip-to-content link; `:focus-visible` outlines (accent, 2px); `prefers-reduced-motion` disables hover transform + smooth scroll; descriptive `alt` per hero ("`<name> — <what it teaches>`"); single `h1`, card titles as `h2`.
39+
40+
## What the fleet template should adopt (not the markup, the direction)
41+
1. The token set above as CSS variables, light/dark parity with the existing landing palette.
42+
2. An **Examples grid** section reading `gallery.json` (per-entry `name/dir/teaches/witnessesFix/hero/preview`), cards styled as here.
43+
3. A **nav link to the gallery** (closes the landing→gallery cross-link gap — impossible today without a template edit).
44+
4. Keep heroes uncropped (`align-items: start`, natural aspect) — cropping loses content like the swatch panorama's outer spheres.

docs/gallery/index.html

Lines changed: 118 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,89 +5,168 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1" />
66
<title>Examples Gallery — Blender Developer Tools</title>
77
<meta name="description" content="Runnable, smoke-gated Blender Python examples — each executed headless on Blender 4.5 LTS and 5.1, so every render reflects code that actually runs." />
8+
<link rel="canonical" href="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/" />
9+
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml" />
10+
<meta name="theme-color" content="#0d1117" media="(prefers-color-scheme: dark)" />
11+
<meta name="theme-color" content="#f6f8fa" media="(prefers-color-scheme: light)" />
12+
<meta property="og:type" content="website" />
13+
<meta property="og:title" content="Examples Gallery — Blender Developer Tools" />
14+
<meta property="og:description" content="Runnable, smoke-gated Blender Python examples — each executed headless on Blender 4.5 LTS and 5.1, so every render reflects code that actually runs." />
15+
<meta property="og:url" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/" />
16+
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/swatch-grid-hero.webp" />
17+
<meta name="twitter:card" content="summary_large_image" />
18+
<meta name="twitter:title" content="Examples Gallery — Blender Developer Tools" />
19+
<meta name="twitter:description" content="Runnable, smoke-gated Blender Python examples — each executed headless on Blender 4.5 LTS and 5.1, so every render reflects code that actually runs." />
20+
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/swatch-grid-hero.webp" />
21+
<!-- FOUC guard: apply the saved theme before first paint. Shares the 'theme'
22+
key with the fleet landing page, so a visitor's choice carries across. -->
23+
<script>(function(){try{var t=localStorage.getItem('theme');if(t==='light'||t==='dark')document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
824
<style>
925
:root {
26+
--bg: #0d1117; --bg2: #161b22; --surface: #161b22; --surface-2: #1c2128;
27+
--border: #30363d; --text: #e6edf3; --text-dim: #8b949e;
1028
--accent: #7c3aed; --accent-light: #a78bfa;
11-
--bg: #0d1117; --bg2: #161b22; --card: #161b22;
12-
--text: #e6edf3; --text-dim: #9da7b3; --border: #30363d;
29+
--radius: 8px; --radius-lg: 12px; --maxw: 1080px;
30+
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
31+
}
32+
/* auto mode: follow the OS unless the user forced dark */
33+
@media (prefers-color-scheme: light) {
34+
:root:not([data-theme="dark"]) {
35+
--bg: #f6f8fa; --bg2: #ffffff; --surface: #ffffff; --surface-2: #f0f2f5;
36+
--border: #d0d7de; --text: #1f2328; --text-dim: #656d76;
37+
}
38+
}
39+
/* explicit override */
40+
[data-theme="light"] {
41+
--bg: #f6f8fa; --bg2: #ffffff; --surface: #ffffff; --surface-2: #f0f2f5;
42+
--border: #d0d7de; --text: #1f2328; --text-dim: #656d76;
1343
}
1444
* { box-sizing: border-box; margin: 0; padding: 0; }
15-
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
16-
background: linear-gradient(180deg, var(--bg), var(--bg2)); color: var(--text);
17-
line-height: 1.6; min-height: 100vh; }
45+
html { scroll-behavior: smooth; }
46+
body { font-family: var(--font-sans); background: var(--bg); color: var(--text);
47+
line-height: 1.6; min-height: 100vh; -webkit-font-smoothing: antialiased; }
1848
a { color: var(--accent-light); text-decoration: none; }
1949
a:hover { text-decoration: underline; }
20-
header { max-width: 1100px; margin: 0 auto; padding: 3rem 1.5rem 1.5rem; }
21-
.back { font-size: 0.875rem; color: var(--text-dim); }
22-
h1 { font-size: 2rem; margin: 0.75rem 0 0.5rem; }
23-
header p { color: var(--text-dim); max-width: 60ch; }
24-
main { max-width: 1100px; margin: 0 auto; padding: 1.5rem; display: grid;
25-
grid-template-columns: 1fr; gap: 1.5rem; }
26-
.card { background: var(--card); border: 1px solid var(--border); border-radius: 12px;
27-
overflow: hidden; display: flex; flex-direction: column; }
28-
.card-media { display: block; background: #0b0e13; }
50+
:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; border-radius: 3px; }
51+
.skip { position: absolute; left: -999px; top: 0; background: var(--accent); color: #fff;
52+
padding: 0.5rem 1rem; border-radius: var(--radius); z-index: 10; }
53+
.skip:focus { left: 0.5rem; top: 0.5rem; }
54+
55+
.topbar { position: sticky; top: 0; z-index: 5; display: flex; align-items: center;
56+
justify-content: space-between; gap: 1rem; padding: 0.75rem 1.25rem;
57+
background: color-mix(in srgb, var(--bg) 88%, transparent);
58+
backdrop-filter: blur(10px); border-bottom: 1px solid var(--border); }
59+
.topbar .back { color: var(--text-dim); font-size: 0.9rem; font-weight: 500; }
60+
.topbar .back:hover { color: var(--accent-light); }
61+
.theme-toggle { background: var(--surface-2); border: 1px solid var(--border);
62+
color: var(--text); border-radius: var(--radius); padding: 0.35rem 0.6rem;
63+
font-size: 0.95rem; cursor: pointer; line-height: 1; transition: border-color 0.15s, background 0.15s; }
64+
.theme-toggle:hover { border-color: var(--accent-light); }
65+
66+
header.hero { max-width: var(--maxw); margin: 0 auto; padding: 3rem 1.25rem 1.5rem; }
67+
header.hero h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); letter-spacing: -0.02em; line-height: 1.15; }
68+
header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.6rem; font-size: 1.02rem; }
69+
70+
main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem;
71+
display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: start; }
72+
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
73+
overflow: hidden; display: flex; flex-direction: column;
74+
transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease; }
75+
.card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
76+
box-shadow: 0 8px 28px rgba(0,0,0,0.28); }
77+
.card-media { display: block; background: var(--bg2); line-height: 0; }
2978
.card-media img { display: block; width: 100%; height: auto; }
30-
.card-body { padding: 1.25rem 1.5rem 1.5rem; }
31-
.card-body h2 { font-size: 1.25rem; margin-bottom: 0.5rem; }
79+
.card-body { padding: 1.15rem 1.4rem 1.45rem; }
80+
.card-body h2 { font-size: 1.22rem; letter-spacing: -0.01em; margin-bottom: 0.5rem; }
3281
.card-body h2 a { color: var(--text); }
33-
.teaches { color: var(--text); margin-bottom: 0.6rem; }
34-
.witnesses { color: var(--text-dim); font-size: 0.9rem; margin-bottom: 0.9rem; }
35-
.tag { display: inline-block; font-size: 0.72rem; text-transform: uppercase;
36-
letter-spacing: 0.05em; color: var(--accent-light); border: 1px solid var(--accent);
37-
border-radius: 999px; padding: 0.05rem 0.5rem; margin-right: 0.35rem; }
38-
.card-link { font-weight: 500; }
39-
footer { max-width: 1100px; margin: 0 auto; padding: 2rem 1.5rem 3rem;
82+
.card-body h2 a:hover { color: var(--accent-light); text-decoration: none; }
83+
.teaches { color: var(--text); margin-bottom: 0.7rem; }
84+
.witnesses { color: var(--text-dim); font-size: 0.9rem; margin-bottom: 1rem; }
85+
.tag { display: inline-block; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em;
86+
color: var(--accent-light); border: 1px solid color-mix(in srgb, var(--accent) 60%, transparent);
87+
border-radius: 999px; padding: 0.08rem 0.55rem; margin-right: 0.4rem; vertical-align: 1px; }
88+
.card-link { font-weight: 600; font-size: 0.95rem; }
89+
90+
footer { max-width: var(--maxw); margin: 0 auto; padding: 2rem 1.25rem 3rem;
4091
color: var(--text-dim); font-size: 0.85rem; border-top: 1px solid var(--border); }
41-
@media (min-width: 720px) {
42-
main { grid-template-columns: 1fr 1fr; }
92+
footer code { background: var(--surface-2); padding: 0.1rem 0.35rem; border-radius: 4px; font-size: 0.82rem; }
93+
94+
@media (min-width: 720px) { main { grid-template-columns: 1fr 1fr; gap: 1.75rem; } }
95+
@media (prefers-reduced-motion: reduce) {
96+
html { scroll-behavior: auto; }
97+
.card, .theme-toggle { transition: none; }
98+
.card:hover { transform: none; }
4399
}
44100
</style>
45101
</head>
46102
<body>
47-
<header>
48-
<a class="back" href="../">&larr; Blender Developer Tools</a>
103+
<a class="skip" href="#main">Skip to content</a>
104+
<div class="topbar">
105+
<a class="back" href="../"><span aria-hidden="true">&larr;</span> Blender Developer Tools</a>
106+
<button class="theme-toggle" id="themeToggle" type="button" aria-label="Theme: auto (click to change)">&#9788;</button>
107+
</div>
108+
<header class="hero">
49109
<h1>Examples Gallery</h1>
50-
<p>Runnable, smoke-gated demos. Each is executed headless on Blender 4.5 LTS and 5.1 by the
51-
<code>blender-smoke</code> workflow, so every render reflects code that actually runs.</p>
110+
<p>Runnable, smoke-gated Blender Python examples — each executed headless on Blender 4.5 LTS and 5.1, so every render reflects code that actually runs.</p>
52111
</header>
53-
<main>
112+
<main id="main">
54113
<article class="card">
55-
<a class="card-media" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/swatch-grid">
56-
<img src="assets/swatch-grid-hero.webp" alt="swatch-grid — Procedural Principled materials — metal and dielectric, the emission pattern, and the cross-version set_specular shim" loading="lazy" width="1280" />
114+
<a class="card-media" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/swatch-grid" aria-label="swatch-grid example on GitHub">
115+
<img src="assets/swatch-grid-hero.webp" alt="swatch-grid — Procedural Principled materials — metal and dielectric, the emission pattern, and the cross-version set_specular shim" loading="lazy" decoding="async" />
57116
</a>
58117
<div class="card-body">
59118
<h2><a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/swatch-grid">swatch-grid</a></h2>
60119
<p class="teaches">Procedural Principled materials — metal and dielectric, the emission pattern, and the cross-version set_specular shim.</p>
61120
<p class="witnesses"><span class="tag">witnesses</span> EEVEE engine-id mapping: BLENDER_EEVEE on 5.x, BLENDER_EEVEE_NEXT on 4.2–4.5.</p>
62-
<a class="card-link" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/swatch-grid">View example &rarr;</a>
121+
<a class="card-link" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/swatch-grid">View example <span aria-hidden="true">&rarr;</span></a>
63122
</div>
64123
</article>
65124
<article class="card">
66-
<a class="card-media" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/turntable">
67-
<img src="assets/turntable-hero.webp" alt="turntable — A slotted-actions Z-rotation turntable keyed through the cross-version channelbag path (get_channelbag_for_slot)" loading="lazy" width="1280" />
125+
<a class="card-media" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/turntable" aria-label="turntable example on GitHub">
126+
<img src="assets/turntable-hero.webp" alt="turntable — A slotted-actions Z-rotation turntable keyed through the cross-version channelbag path (get_channelbag_for_slot)" loading="lazy" decoding="async" />
68127
</a>
69128
<div class="card-body">
70129
<h2><a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/turntable">turntable</a></h2>
71130
<p class="teaches">A slotted-actions Z-rotation turntable keyed through the cross-version channelbag path (get_channelbag_for_slot).</p>
72131
<p class="witnesses"><span class="tag">witnesses</span> Slotted-actions boundary: ensure-helper channelbag on 5.x, strip.channelbag on 4.4/4.5.</p>
73-
<a class="card-link" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/turntable">View example &rarr;</a>
132+
<a class="card-link" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/turntable">View example <span aria-hidden="true">&rarr;</span></a>
74133
</div>
75134
</article>
76135
<article class="card">
77-
<a class="card-media" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/gn-sdf-remesh">
78-
<img src="assets/gn-sdf-remesh-hero.webp" alt="gn-sdf-remesh — A Geometry Nodes SDF remesh (MeshToSDFGrid → GridToMesh at the SDF zero-level), with a Set Material node carrying the material through the remesh" loading="lazy" width="1280" />
136+
<a class="card-media" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/gn-sdf-remesh" aria-label="gn-sdf-remesh example on GitHub">
137+
<img src="assets/gn-sdf-remesh-hero.webp" alt="gn-sdf-remesh — A Geometry Nodes SDF remesh (MeshToSDFGrid → GridToMesh at the SDF zero-level), with a Set Material node carrying the material through the remesh" loading="lazy" decoding="async" />
79138
</a>
80139
<div class="card-body">
81140
<h2><a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/gn-sdf-remesh">gn-sdf-remesh</a></h2>
82141
<p class="teaches">A Geometry Nodes SDF remesh (MeshToSDFGrid → GridToMesh at the SDF zero-level), with a Set Material node carrying the material through the remesh.</p>
83142
<p class="witnesses"><span class="tag">witnesses</span> An SDF grid is meshed with Grid to Mesh, not Volume to Mesh; GN geometry needs Set Material or it renders untextured.</p>
84-
<a class="card-link" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/gn-sdf-remesh">View example &rarr;</a>
143+
<a class="card-link" href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/gn-sdf-remesh">View example <span aria-hidden="true">&rarr;</span></a>
85144
</div>
86145
</article>
87146
</main>
88147
<footer>
89148
Generated from <code>examples/gallery.json</code> by <code>scripts/build_gallery.py</code>.
90149
&nbsp;&bull;&nbsp; CC-BY-NC-ND-4.0
91150
</footer>
151+
<script>
152+
(function () {
153+
var btn = document.getElementById('themeToggle');
154+
var root = document.documentElement;
155+
var order = ['auto', 'light', 'dark'];
156+
var glyph = { auto: '\u263C', light: '\u2600', dark: '\u263D' };
157+
function get() { try { return localStorage.getItem('theme') || 'auto'; } catch (e) { return 'auto'; } }
158+
function apply(state) {
159+
if (state === 'light' || state === 'dark') root.setAttribute('data-theme', state);
160+
else root.removeAttribute('data-theme');
161+
try { if (state === 'auto') localStorage.removeItem('theme'); else localStorage.setItem('theme', state); } catch (e) {}
162+
btn.innerHTML = glyph[state]; btn.setAttribute('aria-label', 'Theme: ' + state + ' (click to change)');
163+
}
164+
apply(get());
165+
btn.addEventListener('click', function () {
166+
var next = order[(order.indexOf(get()) + 1) % order.length];
167+
apply(next);
168+
});
169+
})();
170+
</script>
92171
</body>
93172
</html>

0 commit comments

Comments
 (0)