diff --git a/mintlify/docs.json b/mintlify/docs.json index b3d256383..108d41e1c 100644 --- a/mintlify/docs.json +++ b/mintlify/docs.json @@ -79,6 +79,7 @@ "group": "Overview", "pages": [ "global-accounts/index", + "global-accounts/demo", "global-accounts/implementation-overview" ] }, diff --git a/mintlify/global-accounts/demo.mdx b/mintlify/global-accounts/demo.mdx new file mode 100644 index 000000000..7c18b00ab --- /dev/null +++ b/mintlify/global-accounts/demo.mdx @@ -0,0 +1,12 @@ +--- +title: "Playground" +description: "Create a Grid Global Account and watch the API calls fire in real time" +icon: "/images/icons/phone.svg" +"og:image": "/images/og/og-global-accounts.webp" +--- + +import { WalletDemoEmbed } from '/snippets/global-accounts/wallet-demo-embed.mdx'; + +
+ + diff --git a/mintlify/images/icons/phone.svg b/mintlify/images/icons/phone.svg new file mode 100644 index 000000000..726523bbf --- /dev/null +++ b/mintlify/images/icons/phone.svg @@ -0,0 +1,3 @@ + + + diff --git a/mintlify/snippets/global-accounts/wallet-demo-embed.mdx b/mintlify/snippets/global-accounts/wallet-demo-embed.mdx new file mode 100644 index 000000000..ebb527225 --- /dev/null +++ b/mintlify/snippets/global-accounts/wallet-demo-embed.mdx @@ -0,0 +1,87 @@ +export const WalletDemoEmbed = () => { + React.useEffect(() => { + const isLocal = ['localhost', '127.0.0.1'].includes(window.location.hostname); + const base = isLocal ? 'http://localhost:4000' : 'https://grid-wallet-demo.vercel.app'; + const isDark = () => document.documentElement.classList.contains('dark'); + + let host = document.getElementById('wallet-demo-host'); + if (!host) { + host = document.createElement('div'); + host.id = 'wallet-demo-host'; + host.style.cssText = 'position:fixed;z-index:1;overflow:hidden;'; + const iframe = document.createElement('iframe'); + iframe.id = 'wallet-demo-iframe'; + iframe.src = base + '/?embed=true&theme=' + (isDark() ? 'dark' : 'light'); + iframe.title = 'Grid Global Accounts — live demo'; + iframe.setAttribute('allow', 'publickey-credentials-create *; publickey-credentials-get *; clipboard-write'); + iframe.style.cssText = 'width:100%;height:100%;border:0;display:block;'; + host.appendChild(iframe); + document.body.appendChild(host); + } + if (window.__wdHideTimer) { clearTimeout(window.__wdHideTimer); window.__wdHideTimer = null; } + host.style.display = 'block'; + + let raf = 0; + let last = { left: -1, top: -1, width: -1, height: -1 }; + const sync = () => { + const el = document.getElementById('wallet-demo-container'); + if (el && host) { + const r = el.getBoundingClientRect(); + if (r.left !== last.left || r.top !== last.top || r.width !== last.width || r.height !== last.height) { + host.style.left = r.left + 'px'; + host.style.top = r.top + 'px'; + host.style.width = r.width + 'px'; + host.style.height = r.height + 'px'; + last = { left: r.left, top: r.top, width: r.width, height: r.height }; + } + } + raf = requestAnimationFrame(sync); + }; + raf = requestAnimationFrame(sync); + + let ignoreNextMutation = false; + const sendTheme = () => { + const t = isDark() ? 'dark' : 'light'; + const iframe = document.getElementById('wallet-demo-iframe'); + if (iframe && iframe.contentWindow) { + iframe.contentWindow.postMessage({ type: 'theme-sync', theme: t }, '*'); + } + }; + + const handleMessage = (e) => { + if (e.data && e.data.type === 'theme-request') { + sendTheme(); + return; + } + if (e.data && e.data.type === 'theme-sync') { + const wantsDark = e.data.theme === 'dark'; + if (isDark() !== wantsDark) { + ignoreNextMutation = true; + document.documentElement.classList.toggle('dark'); + } + } + }; + window.addEventListener('message', handleMessage); + + const obs = new MutationObserver(() => { + if (ignoreNextMutation) { ignoreNextMutation = false; return; } + sendTheme(); + }); + obs.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); + + sendTheme(); + requestAnimationFrame(sendTheme); + + return () => { + cancelAnimationFrame(raf); + window.removeEventListener('message', handleMessage); + obs.disconnect(); + window.__wdHideTimer = setTimeout(() => { + const h = document.getElementById('wallet-demo-host'); + if (h) h.style.display = 'none'; + }, 150); + }; + }, []); + + return null; +}; diff --git a/mintlify/style.css b/mintlify/style.css index 69d88540f..59d2cf034 100644 --- a/mintlify/style.css +++ b/mintlify/style.css @@ -4076,3 +4076,134 @@ html.dark:has(#flow-builder-container) #navbar button[class*="h-14"][class*="tex color: var(--ls-gray-700); } + +/* =========================================== + Wallet demo page (global-accounts/demo) + Docs sidebar stays; content column is iframe-only, edge-to-edge. + =========================================== */ + +#content-container:has(#wallet-demo-container) { + max-width: none !important; + width: 100% !important; + margin: 0 !important; + padding: 0 !important; +} + +/* Mintlify wraps content in max-w-5xl (1024px) — bust it for the demo */ +#content-container:has(#wallet-demo-container) > div.max-w-5xl, +#content-container:has(#wallet-demo-container) > div[class*="max-w-5xl"] { + max-width: none !important; + width: 100% !important; + margin-left: 0 !important; + margin-right: 0 !important; + gap: 0 !important; +} + +#content-area:has(#wallet-demo-container) { + width: 100% !important; + flex: 1 1 auto !important; + min-width: 0 !important; + contain: none !important; + display: flex !important; + flex-direction: column !important; + padding: 0 !important; + overflow: hidden !important; + /* navbar (64px bar + 48px tabs = 112px) */ + min-height: calc(100dvh - 112px) !important; +} + +/* Hide everything in the content column except the embed */ +#content-area:has(#wallet-demo-container) > header#header, +#content-area:has(#wallet-demo-container) > #pagination, +#content-area:has(#wallet-demo-container) > footer#footer, +#content-area:has(#wallet-demo-container) > div.sticky { + display: none !important; + height: 0 !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + visibility: hidden !important; +} + +#content-container:has(#wallet-demo-container) #content-side-layout { + display: none !important; +} + +#content-area:has(#wallet-demo-container) > #content { + flex: 1 1 auto !important; + width: 100% !important; + margin: 0 !important; + padding: 0 !important; + max-width: none !important; + min-height: 0 !important; + contain: none !important; +} + +#content:has(#wallet-demo-container) .prose, +.prose:has(#wallet-demo-container) { + max-width: none !important; + margin: 0 !important; + padding: 0 !important; +} + +/* Placeholder that defines the embed's box. The actual iframe lives in + #wallet-demo-host on (so theme toggles don't reload it) and is glued + to this box's position by the embed script. */ +#wallet-demo-container { + width: 100%; + height: calc(100dvh - 112px); + margin: 0; + padding: 0; + line-height: 0; + background: var(--ls-gray-100); +} + +html.dark #wallet-demo-container { + background: var(--ls-gray-975); +} + +/* Persistent iframe host — body-mounted, positioned over the placeholder. */ +#wallet-demo-host { + background: var(--ls-gray-100); +} + +html.dark #wallet-demo-host { + background: var(--ls-gray-975); +} + +#wallet-demo-iframe { + width: 100% !important; + height: 100% !important; + min-height: 0 !important; + border: none !important; + display: block !important; + aspect-ratio: unset !important; +} + +/* Flatten Mintlify's iframe aspect-ratio wrapper */ +#wallet-demo-container > div, +#wallet-demo-container > [style*="aspect-ratio"] { + aspect-ratio: unset !important; + width: 100% !important; + height: 100% !important; + max-width: none !important; + margin: 0 !important; + padding: 0 !important; +} + +@media (max-width: 1023px) { + #content-area:has(#wallet-demo-container) { + min-height: calc(100dvh - 120px) !important; + } + + #wallet-demo-container { + height: calc(100dvh - 120px); + } +} + +/* Prevent outer page scroll when the wallet demo is present */ +html:has(#wallet-demo-container), +html:has(#wallet-demo-container) body { + overflow: hidden !important; +} +