feat(builder): basic tally feedback form (#7725)
parent
60d25135e6
commit
31dbb543a2
|
@ -6,3 +6,5 @@ docs/_javascript/** linguist-vendored
|
|||
|
||||
# Exclude VCR cassettes from stats
|
||||
forge/tests/vcr_cassettes/**/**.y*ml linguist-generated
|
||||
|
||||
* text=auto
|
|
@ -6,6 +6,7 @@ import { NavBar } from "@/components/NavBar";
|
|||
import { cn } from "@/lib/utils";
|
||||
|
||||
import "./globals.css";
|
||||
import TallyPopupSimple from "@/components/TallyPopup";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
|
@ -32,6 +33,7 @@ export default function RootLayout({
|
|||
<div className="flex flex-col min-h-screen ">
|
||||
<NavBar />
|
||||
<main className="flex-1 p-4 overflow-hidden">{children}</main>
|
||||
<TallyPopupSimple />
|
||||
</div>
|
||||
</Providers>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
"use client";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Button } from "./ui/button";
|
||||
import { Megaphone } from "lucide-react";
|
||||
|
||||
const TallyPopupSimple = () => {
|
||||
const [isFormVisible, setIsFormVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Load Tally script
|
||||
const script = document.createElement("script");
|
||||
script.src = "https://tally.so/widgets/embed.js";
|
||||
script.async = true;
|
||||
document.head.appendChild(script);
|
||||
|
||||
// Setup event listeners for Tally events
|
||||
const handleTallyMessage = (event: MessageEvent) => {
|
||||
if (typeof event.data === "string") {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.event === "Tally.FormLoaded") {
|
||||
setIsFormVisible(true);
|
||||
} else if (data.event === "Tally.PopupClosed") {
|
||||
setIsFormVisible(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error parsing Tally message:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("message", handleTallyMessage);
|
||||
|
||||
return () => {
|
||||
document.head.removeChild(script);
|
||||
window.removeEventListener("message", handleTallyMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (isFormVisible) {
|
||||
return null; // Hide the button when the form is visible
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-6 right-6 p-3 transition-all duration-300 ease-in-out z-50">
|
||||
<Button
|
||||
variant="default"
|
||||
data-tally-open="3yx2L0"
|
||||
data-tally-emoji-text="👋"
|
||||
data-tally-emoji-animation="wave"
|
||||
>
|
||||
<Megaphone />
|
||||
<span className="sr-only">Reach Out</span>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TallyPopupSimple;
|
|
@ -135,6 +135,8 @@ export const FlowRunsTimeline = ({
|
|||
</ResponsiveContainer>
|
||||
);
|
||||
|
||||
export default FlowRunsTimeline;
|
||||
|
||||
const ScrollableLegend: React.FC<
|
||||
DefaultLegendContentProps & { className?: string }
|
||||
> = ({ payload, className }) => {
|
||||
|
|
Loading…
Reference in New Issue