Files
SnapOtter/apps/demo/src/demo-banner.tsx
T
SnapOtter 228f70d011 feat: add static demo site at demo.snapotter.com
- New apps/demo/ that reuses apps/web components with mocked API layer
- Full UI shell: login, change password, analytics consent, dashboard, all tool pages
- Stateful mock tracks session flow (password change, analytics consent)
- Demo banner with link to GitHub repo
- Processing attempts show info message with GitHub link
- Deployed to Cloudflare Pages as static site (no backend)

Also links demo across all surfaces:
- README: "Live Demo" badge
- Landing navbar: "Try Demo" CTA button (replaces "Book a Demo")
- Landing hero: "No sign-ups. No credit card." tagline
- Docs getting-started: "Try before installing" tip box

Other changes:
- Docs: move NVIDIA GPU section above GHCR, demote GHCR to collapsed details
- Fix before-after slider checkerboard background for transparency
- Fix remove-bg preview reset when no effects applied
2026-05-17 09:25:12 +08:00

33 lines
941 B
TypeScript

import { useState } from "react";
export function DemoBanner() {
const [dismissed, setDismissed] = useState(false);
if (dismissed) return null;
return (
<div className="relative z-[9999] flex items-center justify-center gap-3 bg-blue-600 px-4 py-2 text-sm text-white">
<span>
This is a live demo. Processing is disabled.{" "}
<a
href="https://github.com/snapotter-hq/SnapOtter"
target="_blank"
rel="noopener noreferrer"
className="font-semibold underline underline-offset-2 hover:text-blue-100"
>
Self-host SnapOtter
</a>{" "}
for full functionality.
</span>
<button
type="button"
onClick={() => setDismissed(true)}
className="ms-2 shrink-0 rounded px-1.5 py-0.5 text-xs font-medium hover:bg-blue-700"
aria-label="Dismiss banner"
>
Dismiss
</button>
</div>
);
}