Skip to content

Commit 3fc0f44

Browse files
fix(user): render graveyard badge inline
Avoid showing raw alt text when the badge image fails to load, and improve wrapping for the copy row. Made-with: Cursor
1 parent 9fe9dbb commit 3fc0f44

2 files changed

Lines changed: 84 additions & 49 deletions

File tree

src/app/globals.css

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,13 @@ button {
345345
/* README badge preview block — shields badge + copy button grouped */
346346
.readme-badge-block {
347347
margin-top: 10px;
348-
background: var(--c-surface);
348+
width: 100%;
349+
background: transparent;
349350
}
350351
.readme-badge-row {
351352
display: flex;
352353
align-items: center;
353-
justify-content: center;
354+
justify-content: space-between;
354355
gap: 12px;
355356
flex-wrap: wrap;
356357
}
@@ -361,6 +362,11 @@ button {
361362
margin: 10px 0 0;
362363
}
363364

365+
.readme-badge-preview {
366+
width: 100%;
367+
max-width: 100%;
368+
}
369+
364370
.subpage-faq-cta {
365371
display: inline-flex;
366372
align-items: center;

src/components/ReadmeBadge.tsx

Lines changed: 76 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,58 +27,87 @@ export default function ReadmeBadge({ username }: Props) {
2727
}
2828

2929
return (
30-
<div style={{ width: '100%', marginBottom: '22px', display: 'flex', justifyContent: 'center' }}>
31-
<div
32-
className="record-card"
33-
style={{
34-
width: 'min(520px, 100%)',
35-
border: '2px solid #1a1a1a',
36-
borderRadius: '0px',
37-
boxShadow: '0 1px 4px rgba(0,0,0,0.05)',
38-
padding: '14px 16px',
39-
}}
40-
>
41-
{/* Badge preview — aspect-ratio wrapper prevents layout shift while loading */}
42-
<div style={{ width: '100%', aspectRatio: '440 / 96' }}>
43-
{/* eslint-disable-next-line @next/next/no-img-element */}
44-
<img
45-
src={`/api/badge?username=${username}&v=${BADGE_VERSION}`}
46-
alt={altText}
47-
loading="lazy"
48-
decoding="async"
30+
<div className="readme-badge-block" style={{ width: '100%', marginBottom: '22px' }}>
31+
{/* Badge preview — the SVG already has its own border; keep the wrapper borderless */}
32+
<div className="readme-badge-preview" style={{ width: '100%', aspectRatio: '440 / 96', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
33+
{svg ? (
34+
<div
35+
aria-label={altText}
36+
role="img"
4937
style={{ width: '100%', height: '100%', display: 'block' }}
38+
// SVG is generated by our own API route.
39+
dangerouslySetInnerHTML={{ __html: svg }}
5040
/>
51-
</div>
52-
53-
{/* Copy row */}
54-
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '12px', marginTop: '10px' }}>
55-
<p className="readme-badge-caption" style={{ fontFamily: MONO, margin: 0, textAlign: 'left' }}>
56-
↻ paste once — updates automatically
57-
</p>
58-
<button
59-
onClick={handleCopy}
60-
className="readme-copy-btn"
41+
) : (
42+
<div
43+
aria-label={altText}
44+
role="img"
6145
style={{
62-
fontFamily: MONO,
63-
fontSize: '10px',
64-
fontWeight: 700,
65-
letterSpacing: '0.06em',
66-
padding: '8px 14px',
67-
minHeight: '36px',
68-
background: copied ? '#2d7a3c' : 'transparent',
69-
color: copied ? '#fff' : '#4a4440',
70-
border: `2px solid ${copied ? '#2d7a3c' : '#cec6bb'}`,
71-
cursor: 'pointer',
72-
transition: 'all 0.15s',
73-
whiteSpace: 'nowrap',
74-
flexShrink: 0,
46+
width: '100%',
47+
height: '100%',
48+
border: '2px solid #1a1a1a',
49+
background: 'var(--c-bg)',
50+
display: 'flex',
51+
alignItems: 'center',
52+
justifyContent: 'center',
53+
padding: '10px',
54+
textAlign: 'center',
7555
}}
76-
onMouseEnter={e => { if (!copied) { e.currentTarget.style.borderColor = '#1a1a1a'; e.currentTarget.style.color = '#1a1a1a' } }}
77-
onMouseLeave={e => { if (!copied) { e.currentTarget.style.borderColor = '#cec6bb'; e.currentTarget.style.color = '#4a4440' } }}
7856
>
79-
{copied ? '✓ copied!' : '⎘ copy to readme'}
80-
</button>
81-
</div>
57+
<span
58+
style={{
59+
fontFamily: MONO,
60+
fontSize: '11px',
61+
fontWeight: 700,
62+
letterSpacing: '0.12em',
63+
textTransform: 'uppercase',
64+
color: svgError ? '#8B0000' : 'var(--c-muted)',
65+
}}
66+
>
67+
{svgError ? 'could not load graveyard badge' : 'loading graveyard badge…'}
68+
</span>
69+
</div>
70+
)}
71+
</div>
72+
73+
{/* Copy row */}
74+
<div className="readme-badge-row" style={{ marginTop: '10px', flexWrap: 'wrap', justifyContent: 'space-between' }}>
75+
<p className="readme-badge-caption" style={{ fontFamily: MONO, margin: 0, textAlign: 'left' }}>
76+
↻ paste once — updates automatically
77+
</p>
78+
<button
79+
onClick={handleCopy}
80+
className="readme-copy-btn"
81+
style={{
82+
fontFamily: MONO,
83+
fontSize: '10px',
84+
fontWeight: 700,
85+
letterSpacing: '0.06em',
86+
padding: '8px 14px',
87+
minHeight: '36px',
88+
background: copied ? '#2d7a3c' : 'transparent',
89+
color: copied ? '#fff' : '#4a4440',
90+
border: `2px solid ${copied ? '#2d7a3c' : '#cec6bb'}`,
91+
cursor: 'pointer',
92+
transition: 'all 0.15s',
93+
whiteSpace: 'nowrap',
94+
flexShrink: 0,
95+
}}
96+
onMouseEnter={e => {
97+
if (!copied) {
98+
e.currentTarget.style.borderColor = '#1a1a1a'
99+
e.currentTarget.style.color = '#1a1a1a'
100+
}
101+
}}
102+
onMouseLeave={e => {
103+
if (!copied) {
104+
e.currentTarget.style.borderColor = '#cec6bb'
105+
e.currentTarget.style.color = '#4a4440'
106+
}
107+
}}
108+
>
109+
{copied ? '✓ copied!' : '⎘ copy to readme'}
110+
</button>
82111
</div>
83112
</div>
84113
)

0 commit comments

Comments
 (0)