diff --git a/packages/app/src/components/dictation-controls.tsx b/packages/app/src/components/dictation-controls.tsx
index 525bc571e..8cf726bb7 100644
--- a/packages/app/src/components/dictation-controls.tsx
+++ b/packages/app/src/components/dictation-controls.tsx
@@ -1,3 +1,4 @@
+import { useMemo } from "react";
import { View, Text, Pressable, ActivityIndicator } from "react-native";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { X, ArrowUp, RefreshCcw, Check, Mic, Pencil } from "lucide-react-native";
@@ -47,6 +48,23 @@ export function DictationControls({
const actionsDisabled = isProcessing;
const handleCancel = isFailed && onDiscard ? onDiscard : onCancel;
+ const micButtonStyle = useMemo(
+ () => [styles.micButton, disabled && styles.buttonDisabled],
+ [disabled],
+ );
+ const timerTextStyle = useMemo(
+ () => [styles.timerText, { color: theme.colors.foreground }],
+ [theme.colors.foreground],
+ );
+ const cancelButtonStyle = useMemo(
+ () => [
+ styles.actionButton,
+ styles.actionButtonCancel,
+ actionsDisabled && !isFailed ? styles.buttonDisabled : undefined,
+ ],
+ [actionsDisabled, isFailed],
+ );
+
if (!showActiveState) {
return (
@@ -66,19 +84,13 @@ export function DictationControls({
-
- {formatDuration(duration)}
-
+ {formatDuration(duration)}
@@ -90,7 +102,7 @@ export function DictationControls({
@@ -99,14 +111,14 @@ export function DictationControls({
@@ -140,21 +152,43 @@ export function DictationOverlay({
const actionsDisabled = isProcessing;
const handleCancel = isFailed && onDiscard ? onDiscard : onCancel;
+ const containerStyle = useMemo(
+ () => [overlayStyles.container, { backgroundColor: theme.colors.accent }],
+ [theme.colors.accent],
+ );
+ const overlayCancelButtonStyle = useMemo(
+ () => [
+ overlayStyles.cancelButton,
+ actionsDisabled && !isFailed && overlayStyles.buttonDisabled,
+ ],
+ [actionsDisabled, isFailed],
+ );
+ const overlayTimerTextStyle = useMemo(
+ () => [overlayStyles.timerText, { color: theme.colors.palette.white }],
+ [theme.colors.palette.white],
+ );
+ const overlayTranscriptTextStyle = useMemo(
+ () => [overlayStyles.transcriptText, { color: theme.colors.palette.white, opacity: 0.95 }],
+ [theme.colors.palette.white],
+ );
+ const overlayRetryButtonStyle = useMemo(
+ () => [overlayStyles.actionButton, { backgroundColor: theme.colors.palette.white }],
+ [theme.colors.palette.white],
+ );
+ const overlayConfirmButtonStyle = overlayRetryButtonStyle;
+
if (!showActiveState) {
return null;
}
return (
-
+
@@ -168,18 +202,10 @@ export function DictationOverlay({
orientation="horizontal"
color={theme.colors.palette.white}
/>
-
- {formatDuration(duration)}
-
+ {formatDuration(duration)}
{isFailed ? (
-
+
{errorText ? `Dictation failed: ${errorText}` : "Dictation failed. Tap retry."}
) : null}
@@ -195,7 +221,7 @@ export function DictationOverlay({
onPress={onRetry}
accessibilityRole="button"
accessibilityLabel="Retry dictation"
- style={[overlayStyles.actionButton, { backgroundColor: theme.colors.palette.white }]}
+ style={overlayRetryButtonStyle}
>
@@ -205,7 +231,7 @@ export function DictationOverlay({
onPress={onAccept}
accessibilityRole="button"
accessibilityLabel="Insert transcription"
- style={[overlayStyles.actionButton, { backgroundColor: "rgba(255, 255, 255, 0.25)" }]}
+ style={OVERLAY_ACCEPT_BUTTON_STYLE}
>
@@ -364,3 +390,8 @@ const overlayStyles = StyleSheet.create((theme) => ({
justifyContent: "center",
},
}));
+
+const ACTION_CONFIRM_STYLE = [styles.actionButton, styles.actionButtonConfirm];
+const ACTION_SECONDARY_STYLE = [styles.actionButton, styles.actionButtonSecondary];
+const OVERLAY_ACCEPT_BUTTON_BG = { backgroundColor: "rgba(255, 255, 255, 0.25)" };
+const OVERLAY_ACCEPT_BUTTON_STYLE = [overlayStyles.actionButton, OVERLAY_ACCEPT_BUTTON_BG];