This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
"use client"
|
||||
|
||||
// The notes page's way into the feedback survey (feedback.guide.ts): a button that asks the guides
|
||||
// module to start `notes.feedback` through the shared surface coordinator (`guides.start`, joint
|
||||
// contract §12), the same command the support chat's help offers send. It shows only while the guides
|
||||
// module serves that command, so an app without guides renders nothing here; `kit template:prune
|
||||
// --without guides` removes it with this folder.
|
||||
|
||||
import type { SurfaceCoordinator } from "@conusai-kit/core"
|
||||
import { useSurfaceCoordinator } from "@conusai-kit/ui"
|
||||
import { type ReactElement, useState, useSyncExternalStore } from "react"
|
||||
import type { FeedbackButtonLabels } from "./feedback-labels.js"
|
||||
|
||||
const never = () => () => undefined
|
||||
|
||||
export function FeedbackButton({ labels }: { labels: FeedbackButtonLabels }): ReactElement | null {
|
||||
const coordinator = useSurfaceCoordinator<SurfaceCoordinator>()
|
||||
const served = useSyncExternalStore(
|
||||
coordinator ? (listener) => coordinator.subscribe(listener) : never,
|
||||
() => coordinator?.serves("guides.start") ?? false,
|
||||
() => false,
|
||||
)
|
||||
const [unavailable, setUnavailable] = useState(false)
|
||||
if (!coordinator || !served) return null
|
||||
const start = async () => {
|
||||
const result = await coordinator.dispatch({
|
||||
version: 1,
|
||||
requestId: globalThis.crypto.randomUUID(),
|
||||
type: "guides.start",
|
||||
guideKey: "notes.feedback",
|
||||
})
|
||||
setUnavailable(result.status !== "ok")
|
||||
}
|
||||
return (
|
||||
<p>
|
||||
<button type="button" onClick={() => void start()}>
|
||||
{labels.open}
|
||||
</button>{" "}
|
||||
<span role="status">{unavailable ? labels.unavailable : ""}</span>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user