Feedback() — supabase Function Reference
Architecture documentation for the Feedback() function in Feedback.tsx from the supabase codebase.
Entity Profile
Dependency Diagram
graph TD db81693d_9a17_bf20_5e49_ea669c5037e3["Feedback()"] 4b70e582_d1b2_fa26_b397_618941837a63["useSendTelemetryEvent()"] db81693d_9a17_bf20_5e49_ea669c5037e3 -->|calls| 4b70e582_d1b2_fa26_b397_618941837a63 28b182b0_b6eb_ea43_788c_54be8711896a["useSendFeedbackMutation()"] db81693d_9a17_bf20_5e49_ea669c5037e3 -->|calls| 28b182b0_b6eb_ea43_788c_54be8711896a 4581944a_42ce_7bd1_a836_adcac492f56d["getSanitizedTabParams()"] db81693d_9a17_bf20_5e49_ea669c5037e3 -->|calls| 4581944a_42ce_7bd1_a836_adcac492f56d 06021ec0_94f4_72a6_9fd8_c3841210a444["getLinearTeam()"] db81693d_9a17_bf20_5e49_ea669c5037e3 -->|calls| 06021ec0_94f4_72a6_9fd8_c3841210a444 style db81693d_9a17_bf20_5e49_ea669c5037e3 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
apps/docs/components/Feedback/Feedback.tsx lines 75–236
function Feedback({ className }: { className?: string }) {
const [state, dispatch] = useReducer(reducer, initialState)
const [modalOpen, setModalOpen] = useState(false)
const feedbackButtonRef = useRef<HTMLButtonElement>(null)
const pathname = usePathname() ?? ''
const sendTelemetryEvent = useSendTelemetryEvent()
const { mutate: sendFeedbackComment } = useSendFeedbackMutation()
const supabase = useConstant(() =>
IS_PLATFORM
? createClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
: undefined
)
const unanswered = state.type === 'unanswered'
const isYes = 'response' in state && state.response === 'yes'
const isNo = 'response' in state && state.response === 'no'
const showYes = unanswered || isYes
const showNo = unanswered || isNo
async function sendFeedbackVote(response: Response) {
if (!supabase) return
const { error } = await supabase.from('feedback').insert({
vote: response,
page: pathname,
metadata: {
query: getSanitizedTabParams(),
},
})
if (error) console.error(error)
}
function handleVote(response: Response) {
sendTelemetryEvent({
action: 'docs_feedback_clicked',
properties: { response },
})
sendFeedbackVote(response)
dispatch({ event: 'VOTED', response })
// Focus so screen reader users are aware of the new element
setTimeout(() => {
feedbackButtonRef.current?.focus()
// Wait for element to show up first
}, 700)
}
function refocusButton() {
setTimeout(() => {
feedbackButtonRef.current?.focus()
// Wait for modal to disappear and button to become focusable again
}, 100)
}
async function handleSubmit({ page, comment, title }: FeedbackFields) {
sendFeedbackComment({
message: comment,
pathname: page,
title,
// @ts-expect-error -- can't click this button without having a state.response
isHelpful: state.response === 'yes',
team: getLinearTeam(pathname),
})
setModalOpen(false)
refocusButton()
}
return (
<section className={cn('@container', className)} aria-labelledby="feedback-title">
<h3 id="feedback-title" className="block font-mono text-xs text-foreground-light mb-3">
Is this helpful?
</h3>
<div className="relative flex flex-col gap-2 @[12rem]:gap-4 @[12rem]:flex-row @[12rem]:items-center">
<div
style={{ '--container-flex-gap': '0.5rem' } as CSSProperties}
className="relative flex gap-2 items-center"
>
<Button
type="outline"
rounded
className={cn(
'px-1 w-7 h-7',
'text-foreground-light',
'[transition-property:opacity,transform,color] [transition-duration:150ms,250ms,250ms]',
'motion-reduce:[transition-duration:150ms,1ms,300ms]',
'[transition-timing-function:cubic-bezier(.76,0,.23,1)]',
!isNo && 'hover:text-warning hover:border-warning-500',
isNo && `bg-warning text-warning-200 !border-warning disabled:opacity-100`,
!showNo && 'opacity-0 invisible'
)}
onClick={() => handleVote('no')}
disabled={state.type === StateType.Followup}
>
<X size={14} strokeWidth={2} className="text-current" />
<span className="sr-only">No</span>
</Button>
<Button
type="outline"
rounded
className={cn(
'px-1 w-7 h-7',
'text-foreground-light',
'[transition-property:opacity,transform,color] [transition-duration:150ms,250ms,250ms]',
'motion-reduce:[transition-duration:150ms,1ms,300ms]',
'[transition-timing-function:cubic-bezier(.76,0,.23,1)]',
!isYes && 'hover:text-brand-600 hover:border-brand-500',
isYes &&
'bg-brand text-brand-200 !border-brand disabled:opacity-100 -translate-x-[calc(100%+var(--container-inline-flex-gap,0.5rem))]',
!showYes && 'opacity-0 invisible'
)}
onClick={() => handleVote('yes')}
disabled={state.type === StateType.Followup}
>
<Check size={14} strokeWidth={2} />
<span className="sr-only">Yes</span>
</Button>
</div>
<div
className={cn(
'flex flex-col gap-0.5',
'@[12rem]:absolute @[12rem]:left-9',
'text-xs',
'opacity-0 invisible',
'text-left',
'-translate-x-2',
'[transition-property:opacity,transform]',
'[transition-duration:450ms,300ms]',
'[transition-delay:200ms,0ms]',
'[transition-timing-function:cubic-bezier(.76,0,.23,1)]',
'motion-reduce:[transition-duration:150ms,1ms]',
'!ease-out',
state.type === StateType.Followup && 'opacity-100 visible -translate-x-0'
)}
>
{state.type === StateType.Followup && (
<>
<span className="text-foreground-light">Thanks for your feedback!</span>
<FeedbackButton
ref={feedbackButtonRef}
onClick={() => setModalOpen(true)}
isYes={isYes}
visible={true}
/>
</>
)}
</div>
</div>
<FeedbackModal
visible={modalOpen}
page={pathname}
onCancel={() => {
setModalOpen(false)
refocusButton()
}}
onSubmit={handleSubmit}
/>
</section>
)
}
Domain
Subdomains
Source
Frequently Asked Questions
What does Feedback() do?
Feedback() is a function in the supabase codebase.
What does Feedback() call?
Feedback() calls 4 function(s): getLinearTeam, getSanitizedTabParams, useSendFeedbackMutation, useSendTelemetryEvent.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free