Skip to content

Commit 73489ce

Browse files
igalklebanovclaude
andauthored
feat(site): explain the proof gauge behind a (?) on the production wall (#1977)
A help-circle button beside "in production at": hover peeks the explainer, click pins it open, outside click or Escape dismisses. The panel anchors to the caption row so it never overflows narrow viewports, and the button's padded hit area serves touch without growing the 13px glyph. Copy: "Every logo links to public proof and is graded on age and code over words." Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent a757ea0 commit 73489ce

2 files changed

Lines changed: 128 additions & 2 deletions

File tree

site/src/pages/index.module.css

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,13 +314,74 @@ a.stat:hover .statValue {
314314
font-family: var(--ifm-font-family-monospace);
315315
font-size: 12px;
316316
letter-spacing: 0.1em;
317+
position: relative;
317318
text-transform: uppercase;
318319
}
319320

320321
.productionCaption:not(:first-child) {
321322
margin-top: 10px;
322323
}
323324

325+
/* The (?) beside "in production at": hover peeks the gauge explainer,
326+
click pins it open. The panel anchors to the caption row (not the icon)
327+
so it never overflows narrow viewports. */
328+
.proofHelp {
329+
color: var(--kl-faint);
330+
display: inline-block;
331+
margin-left: 7px;
332+
vertical-align: -2px;
333+
}
334+
335+
/* Padding grows the tap target to ~29px; the negative margin keeps the
336+
13px glyph optically in place. */
337+
.proofHelpButton {
338+
color: inherit;
339+
cursor: help;
340+
display: block;
341+
margin: -8px;
342+
padding: 8px;
343+
}
344+
345+
.proofHelpButton svg {
346+
display: block;
347+
height: 13px;
348+
width: 13px;
349+
}
350+
351+
.proofHelp:hover,
352+
.proofHelpOpen {
353+
color: var(--kl-mut);
354+
}
355+
356+
.proofHelpPanel {
357+
background: var(--kl-panel);
358+
border: 1px solid var(--kl-line);
359+
border-radius: 8px;
360+
box-shadow: 0 8px 24px var(--kl-shadow);
361+
color: var(--kl-text2);
362+
font-family: var(--ifm-font-family-base);
363+
font-size: 12.5px;
364+
left: 0;
365+
letter-spacing: normal;
366+
line-height: 1.6;
367+
opacity: 0;
368+
padding: 10px 12px;
369+
pointer-events: none;
370+
position: absolute;
371+
text-transform: none;
372+
top: calc(100% + 8px);
373+
transition: opacity 0.15s ease;
374+
width: 320px;
375+
max-width: 80vw;
376+
z-index: 10;
377+
}
378+
379+
.proofHelp:hover .proofHelpPanel,
380+
.proofHelpOpen .proofHelpPanel {
381+
opacity: 1;
382+
pointer-events: auto;
383+
}
384+
324385
.productionNames {
325386
align-items: stretch;
326387
display: flex;

site/src/pages/index.tsx

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { JSX, useEffect, useState } from 'react'
1+
import React, { JSX, useEffect, useRef, useState } from 'react'
22
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
33
import Layout from '@theme/Layout'
44
import clsx from 'clsx'
@@ -391,12 +391,77 @@ const LOGO_WITH_NAME = new Set([
391391
])
392392

393393
function SectionProduction() {
394+
const [helpOpen, setHelpOpen] = useState(false)
395+
const helpRef = useRef<HTMLSpanElement>(null)
396+
397+
// Hover peeks the explainer; a click pins it open until a click lands
398+
// outside or Escape is pressed.
399+
useEffect(() => {
400+
if (!helpOpen) {
401+
return
402+
}
403+
404+
const onClick = (event: MouseEvent) => {
405+
if (!helpRef.current?.contains(event.target as Node)) {
406+
setHelpOpen(false)
407+
}
408+
}
409+
const onKeyDown = (event: KeyboardEvent) => {
410+
if (event.key === 'Escape') {
411+
setHelpOpen(false)
412+
}
413+
}
414+
415+
document.addEventListener('click', onClick)
416+
document.addEventListener('keydown', onKeyDown)
417+
return () => {
418+
document.removeEventListener('click', onClick)
419+
document.removeEventListener('keydown', onKeyDown)
420+
}
421+
}, [helpOpen])
422+
394423
return (
395424
<section className={styles.production}>
396425
<div className={clsx('container', styles.productionInner)}>
397426
{PROOF_GROUPS.map(({ group, caption }) => (
398427
<React.Fragment key={group}>
399-
<span className={styles.productionCaption}>{caption}</span>
428+
<span className={styles.productionCaption}>
429+
{caption}
430+
{group === 'production' && (
431+
<span
432+
ref={helpRef}
433+
className={clsx(
434+
styles.proofHelp,
435+
helpOpen && styles.proofHelpOpen,
436+
)}
437+
>
438+
<button
439+
aria-expanded={helpOpen}
440+
aria-label="How proof is graded"
441+
className={clsx('clean-btn', styles.proofHelpButton)}
442+
onClick={() => setHelpOpen((open) => !open)}
443+
type="button"
444+
>
445+
<svg
446+
fill="none"
447+
stroke="currentColor"
448+
strokeLinecap="round"
449+
strokeLinejoin="round"
450+
strokeWidth="2"
451+
viewBox="0 0 24 24"
452+
>
453+
<circle cx="12" cy="12" r="10" />
454+
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
455+
<path d="M12 17h.01" />
456+
</svg>
457+
</button>
458+
<span role="tooltip" className={styles.proofHelpPanel}>
459+
Every logo links to public proof and is graded on age and
460+
code over words.
461+
</span>
462+
</span>
463+
)}
464+
</span>
400465
<span className={styles.productionNames}>
401466
{proofEntries
402467
.filter((entry) => entry.group === group)

0 commit comments

Comments
 (0)