home: back-to-top button (0.66.0)
- the home page is long now (hero -> flow -> features -> session preview -> activity -> footer); add a floating back-to-top button that fades in once you scroll past the hero and smooth-scrolls the home container to top - listens on the gm-home scroll container (not window); hidden by the persistent-home display:none when off-route; respects reduced-motion - verified live: hidden at top, shows after scroll, returns to top on click
This commit is contained in:
parent
e73dbbe186
commit
26030b0a13
@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0e0a14" />
|
||||
<meta name="description" content="amerc is the agent mercenary tavern — hire, run, publish, and remotely deliver AI agents across software boundaries. No infrastructure, just skills." />
|
||||
<meta name="version" content="0.65.0-instanthome" />
|
||||
<meta name="version" content="0.66.0-backtotop" />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="icon" href="/app-192.png" type="image/png" sizes="192x192" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "amerc-site",
|
||||
"version": "0.65.0-instanthome",
|
||||
"version": "0.66.0-backtotop",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@ -7,7 +7,7 @@ import Account from './Account.jsx';
|
||||
import TavernGame from './TavernGame.jsx';
|
||||
import { api } from './api.js';
|
||||
|
||||
const RELEASE = '0.65.0-instanthome';
|
||||
const RELEASE = '0.66.0-backtotop';
|
||||
|
||||
const NAV = [
|
||||
{ id: 'home', label: 'Tavern' },
|
||||
@ -100,9 +100,17 @@ function Reveal({ children, className = '', delay = 0, tag: Tag = 'div' }) {
|
||||
|
||||
function Home({ setRoute }) {
|
||||
const [stats, setStats] = useState(null);
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const homeRef = useRef(null);
|
||||
useEffect(() => { api('/agents/stats').then(setStats).catch(() => {}); }, []);
|
||||
useEffect(() => {
|
||||
const el = homeRef.current; if (!el) return;
|
||||
const onScroll = () => setScrolled(el.scrollTop > 500);
|
||||
el.addEventListener('scroll', onScroll, { passive: true });
|
||||
return () => el.removeEventListener('scroll', onScroll);
|
||||
}, []);
|
||||
return (
|
||||
<div className="gm-home">
|
||||
<div className="gm-home" ref={homeRef}>
|
||||
<div className="gm-hero">
|
||||
<div className="gm-stage"><TavernGame onHotspot={setRoute} stats={stats} /></div>
|
||||
<div className="gm-caption">
|
||||
@ -124,6 +132,7 @@ function Home({ setRoute }) {
|
||||
</div>
|
||||
<HomeFeatures setRoute={setRoute} />
|
||||
<Footer setRoute={setRoute} />
|
||||
<button className={`gm-totop${scrolled ? ' show' : ''}`} onClick={() => homeRef.current?.scrollTo({ top: 0, behavior: 'smooth' })} aria-label="Back to top" type="button">↑</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1449,3 +1449,11 @@ button {
|
||||
|
||||
/* persistent home host (0.65) — keeps the tavern mounted, hidden off-route */
|
||||
.route-host { flex: 1; min-height: 0; flex-direction: column; }
|
||||
|
||||
/* back-to-top button (0.66) */
|
||||
.gm-totop { position: fixed; right: 22px; bottom: 22px; width: 42px; height: 42px; border-radius: 50%; border: none; cursor: pointer;
|
||||
background: linear-gradient(180deg, #2aa7d8, #1f86c4); color: #fff; font-size: 20px; line-height: 1;
|
||||
box-shadow: 0 6px 18px rgba(0,0,0,0.45); opacity: 0; transform: translateY(10px); pointer-events: none; transition: opacity .2s, transform .2s, background .15s; z-index: 30; }
|
||||
.gm-totop.show { opacity: 0.92; transform: none; pointer-events: auto; }
|
||||
.gm-totop.show:hover { opacity: 1; background: linear-gradient(180deg, #46c8e0, #2aa7d8); }
|
||||
@media (prefers-reduced-motion: reduce) { .gm-totop { transition: opacity .2s; transform: none; } }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user