Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions components/EmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ interface EmptyStateProps {
className?: string
}

/**
* Displays a centered empty-state panel with an icon, title, description, a small "Ready when you are!" hint, and an optional action control.
*
* @param icon - Material Symbols icon name to display inside the icon container.
* @param title - Primary heading text.
* @param description - Supporting descriptive text shown beneath the title.
* @param actionLabel - Label for the optional action control; when omitted no action is rendered.
* @param actionHref - If provided, renders the action as a client-side link targeting this href.
* @param onAction - If provided and `actionHref` is not, renders the action as a button that invokes this callback when clicked.
* @param className - Additional CSS classes to append to the root container.
* @returns The empty-state React element.
*/
export function EmptyState({
icon,
title,
Expand All @@ -23,15 +35,18 @@ export function EmptyState({
}: EmptyStateProps) {
return (
<div className={`flex flex-col items-center justify-center py-12 px-6 text-center animate-fade-in ${className}`}>
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-primary/10 text-primary mb-4 animate-scale-in">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-primary/10 text-primary mb-4 animate-scale-in transition-transform hover:scale-110">
<span className="material-symbols-outlined text-3xl">{icon}</span>
</div>
<h3 className="text-lg font-bold text-slate-900 dark:text-white mb-2">
{title}
</h3>
<p className="text-sm text-slate-500 dark:text-[#a69db9] max-w-sm mb-6">
<p className="text-sm text-slate-500 dark:text-[#a69db9] max-w-sm mb-2">
{description}
</p>
<p className="mt-2 text-xs font-semibold text-primary uppercase tracking-widest mb-6">
Ready when you are!
</p>
{actionLabel && (
actionHref ? (
<Link
Expand Down
13 changes: 11 additions & 2 deletions components/VoiceInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ interface VoiceInputProps {
disabled?: boolean
}

/**
* Render a microphone input UI that manages microphone permissions, records audio, and forwards the recorded audio blob to `onAudioSend`.
*
* The component handles secure-context checks, permission diagnostics, user-facing permission help, recording and processing states, and stops/releases the microphone after recording.
*
* @param onAudioSend - Callback invoked with the recorded audio `Blob` when recording stops; should return a Promise (errors will be caught and logged).
* @param disabled - If true, the microphone control is visually and functionally disabled.
* @returns The VoiceInput React element.
*/
export function VoiceInput({ onAudioSend, disabled }: VoiceInputProps) {
const [isRecording, setIsRecording] = useState(false)
const [isProcessing, setIsProcessing] = useState(false)
Expand Down Expand Up @@ -159,11 +168,11 @@ export function VoiceInput({ onAudioSend, disabled }: VoiceInputProps) {
<ul className="text-[11px] text-slate-500 dark:text-text-secondary space-y-2">
<li className="flex gap-2">
<span className="text-primary font-bold">1.</span>
<span>Click the **lock icon** 🔒 next to the URL and reset the Microphone permission to "Allow".</span>
<span>Click the **lock icon** 🔒 next to the URL and reset the Microphone permission to &quot;Allow&quot;.</span>
</li>
<li className="flex gap-2">
<span className="text-primary font-bold">2.</span>
<span>Check **Windows Settings &gt; Privacy &gt; Microphone** and ensure "Allow apps to access your microphone" is ON.</span>
<span>Check **Windows Settings &gt; Privacy &gt; Microphone** and ensure &quot;Allow apps to access your microphone&quot; is ON.</span>
</li>
<li className="flex gap-2">
<span className="text-primary font-bold">3.</span>
Expand Down