Skip to content

Commit 028e96c

Browse files
thebuilderclaude
andcommitted
fix(docs): rebalance the Open Graph card layout
The card was unbalanced: the logo floated alone top-left over a large void while the instrument spanned nearly the full height on the right, and the headline sat low, centred in the gap. - Group the logo lockup with the headline and subline into one left "message" column so the brand anchors the column instead of floating. - Match the instrument's height to that column (align stretch + the panel distributes its rows) so the two columns share top and bottom edges, and centre the whole band as a unit for equal top/bottom margins. - Give the viewport field purpose: a threshold line with a target chip sitting on it (echoing the page's instrument), replacing the empty box and the near-invisible progress bar. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 344c95a commit 028e96c

2 files changed

Lines changed: 62 additions & 43 deletions

File tree

‎apps/docs/public/og-home.png‎

-1.49 KB
Loading

‎apps/docs/scripts/generate-og.mjs‎

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ const ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
3636
</svg>`;
3737
const ICON_URI = `data:image/svg+xml;base64,${Buffer.from(ICON).toString("base64")}`;
3838

39+
// A crosshair for the "target" chip, echoing the page's instrument.
40+
const TARGET = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
41+
stroke="#c9b8ff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
42+
<circle cx="12" cy="12" r="7"/><circle cx="12" cy="12" r="2.6"/>
43+
<path d="M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3"/></svg>`;
44+
const TARGET_URI = `data:image/svg+xml;base64,${Buffer.from(TARGET).toString("base64")}`;
45+
3946
async function loadFonts() {
4047
try {
4148
const subsets = await googleFonts([
@@ -94,6 +101,7 @@ function instrument(mono) {
94101
display: "flex",
95102
flexDirection: "column",
96103
gap: 22,
104+
justifyContent: "space-between",
97105
padding: 32,
98106
width: 424,
99107
},
@@ -127,115 +135,128 @@ function instrument(mono) {
127135
}),
128136
],
129137
}),
130-
// Target chip on a viewport field with a threshold line
138+
// Viewport field: a threshold line the target chip sits on.
131139
container({
132140
style: {
133141
alignItems: "center",
134142
backgroundColor: "#0a0a11",
135143
border: `1px solid rgb(255 255 255 / 0.08)`,
136144
borderRadius: 14,
137145
display: "flex",
138-
height: 150,
146+
height: 152,
139147
justifyContent: "center",
148+
overflow: "hidden",
140149
position: "relative",
141150
},
142151
children: [
143152
container({
144153
style: {
145-
backgroundColor: "rgb(167 139 250 / 0.16)",
154+
backgroundColor: "rgb(167 139 250 / 0.45)",
155+
height: 1,
156+
left: 0,
157+
position: "absolute",
158+
top: 97,
159+
width: "100%",
160+
},
161+
}),
162+
container({
163+
style: { position: "absolute", right: 16, top: 74 },
164+
children: [
165+
text("threshold", {
166+
color: "rgb(200 188 245 / 0.85)",
167+
fontFamily: mono,
168+
fontSize: 15,
169+
}),
170+
],
171+
}),
172+
container({
173+
style: {
174+
alignItems: "center",
175+
backgroundColor: "rgb(167 139 250 / 0.18)",
146176
border: `1px solid ${VLINE}`,
147177
borderRadius: 10,
178+
display: "flex",
179+
gap: 8,
148180
paddingBottom: 10,
149-
paddingLeft: 16,
181+
paddingLeft: 14,
150182
paddingRight: 16,
151183
paddingTop: 10,
184+
position: "relative",
152185
},
153186
children: [
187+
image({ src: TARGET_URI, width: 18, height: 18 }),
154188
text("Hero", { color: FG, fontFamily: mono, fontSize: 22 }),
155189
],
156190
}),
157191
],
158192
}),
159193
readout("intersectionRatio", "1.00", mono, FG),
160194
readout("inView", "true", mono, EMERALD),
161-
// Full progress bar
162-
container({
163-
style: {
164-
backgroundColor: "rgb(255 255 255 / 0.08)",
165-
borderRadius: 999,
166-
height: 8,
167-
width: "100%",
168-
},
169-
children: [
170-
container({
171-
style: {
172-
backgroundColor: VIOLET,
173-
borderRadius: 999,
174-
height: 8,
175-
width: "100%",
176-
},
177-
}),
178-
],
179-
}),
180195
],
181196
});
182197
}
183198

184199
async function main() {
185200
const f = await loadFonts();
186201

187-
const header = container({
188-
style: { alignItems: "center", display: "flex", gap: 22 },
202+
// Brand lockup anchors the top of the message column instead of floating
203+
// alone as a header, so the left and right columns share a vertical extent.
204+
const brand = container({
205+
style: { alignItems: "center", display: "flex", gap: 18, marginBottom: 42 },
189206
children: [
190-
image({ src: ICON_URI, width: 76, height: 76 }),
207+
image({ src: ICON_URI, width: 60, height: 60 }),
191208
text("React Intersection Observer", {
192209
color: FG,
193210
fontFamily: f.display,
194-
fontSize: 38,
211+
fontSize: 30,
195212
fontWeight: 600,
196213
letterSpacing: "-0.01em",
197214
}),
198215
],
199216
});
200217

201-
const copy = container({
218+
const message = container({
202219
style: {
203220
display: "flex",
204221
flexDirection: "column",
205-
flexGrow: 1,
206-
maxWidth: 560,
207-
paddingRight: 56,
222+
maxWidth: 566,
223+
paddingRight: 40,
208224
},
209225
children: [
226+
brand,
210227
text("Know the moment an element meets the viewport.", {
211228
color: FG,
212229
fontFamily: f.display,
213-
fontSize: 60,
230+
fontSize: 58,
214231
fontWeight: 700,
215232
letterSpacing: "-0.03em",
216-
lineHeight: 1.04,
233+
lineHeight: 1.05,
217234
}),
218235
text(
219236
"A tiny, fully-typed React adapter for the Intersection Observer API.",
220237
{
221238
color: MUTED,
222239
fontFamily: f.body,
223-
fontSize: 27,
240+
fontSize: 26,
224241
lineHeight: 1.4,
225-
marginTop: 28,
242+
marginTop: 24,
243+
maxWidth: 468,
226244
},
227245
),
228246
],
229247
});
230248

231-
const middle = container({
249+
// The two-column band, centred as a unit so top and bottom margins match.
250+
// `stretch` matches the instrument's height to the message column so their
251+
// tops and bottoms align; the panel distributes its rows to fill.
252+
const band = container({
232253
style: {
233-
alignItems: "center",
254+
alignItems: "stretch",
234255
display: "flex",
235-
flexGrow: 1,
256+
justifyContent: "space-between",
236257
width: "100%",
237258
},
238-
children: [copy, instrument(f.mono)],
259+
children: [message, instrument(f.mono)],
239260
});
240261

241262
const root = container({
@@ -246,15 +267,13 @@ async function main() {
246267
color: FG,
247268
display: "flex",
248269
flexDirection: "column",
249-
gap: 8,
250270
height: HEIGHT,
251-
paddingBottom: 72,
271+
justifyContent: "center",
252272
paddingLeft: 72,
253273
paddingRight: 72,
254-
paddingTop: 68,
255274
width: WIDTH,
256275
},
257-
children: [header, middle],
276+
children: [band],
258277
});
259278

260279
const png = await render(root, {

0 commit comments

Comments
 (0)