From 4fdfeebcbf88876e6b6a520f851709a2f3d55eb0 Mon Sep 17 00:00:00 2001 From: morepriyam Date: Sat, 15 Aug 2026 02:14:40 +0530 Subject: [PATCH] feat(ui): extend Liquid Glass to the remaining over-video chrome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converts the last flat-scrim overlays to GlassPill (Liquid Glass on iOS 26+, the usual dark scrim elsewhere), completing the glass system: glass = chrome floating over video, themed screens stay flat. - export: ▶ play badge goes glass and grows 56→64pt / 28pt glyph to match the recorder preview card; clip-count · duration meta pill goes glass; caption badge goes glass and grows 30→40pt with a 20pt icon (48pt effective target with hitSlop — it had the same sub-HIG tap target problem as the preview card badges), split into placement + surface so the spinner and pressable variants share the surface - subtitles: ▶ play badge goes glass, keeping the 48pt / 32pt-compact text-mode sizing - recorder: the top timer sits in a small glass pill next to the glass close button; the text shadow is dropped — the pill's dimming layer does that job now The export/subtitles close buttons deliberately stay flat: dark-pinned glass over a light themed background turns nearly transparent, and the glass rule reserves glass for chrome over video anyway. Closes #168 --- src/app/export.tsx | 44 ++++++++++++++++++++++++------------------- src/app/recorder.tsx | 14 ++++++++++---- src/app/subtitles.tsx | 7 ++++--- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/app/export.tsx b/src/app/export.tsx index d2f7a18..e46be02 100644 --- a/src/app/export.tsx +++ b/src/app/export.tsx @@ -12,6 +12,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { ThemedText } from '@/components/themed-text'; import { ThemedView } from '@/components/themed-view'; +import { GlassPill } from '@/components/glass-pill'; import { CloseButton } from '@/features/recorder/close-button'; import { Spacing } from '@/constants/theme'; import { useTheme } from '@/hooks/use-theme'; @@ -605,33 +606,35 @@ function MergedPreview({ {!isPlaying && ( - - - + + + )} - + {meta} - + {working && ( - + - + )} {actionable && ( 0 ? 'Edit captions' : 'Add captions' } style={styles.captionBadge}> - + + + )} @@ -661,11 +664,12 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, + // Shape only — GlassPill owns the surface (Liquid Glass on iOS 26+, dark scrim fallback). + // Matches the recorder preview card's ▶; paddingLeft optically centers the glyph. playBadge: { - width: 56, - height: 56, - borderRadius: 28, - backgroundColor: 'rgba(0,0,0,0.45)', + width: 64, + height: 64, + borderRadius: 32, alignItems: 'center', justifyContent: 'center', paddingLeft: 4, @@ -694,7 +698,6 @@ const styles = StyleSheet.create({ paddingHorizontal: Spacing.two, paddingVertical: 4, borderRadius: 12, - backgroundColor: 'rgba(0,0,0,0.55)', }, metaText: { color: '#fff', @@ -704,15 +707,18 @@ const styles = StyleSheet.create({ letterSpacing: 0.3, }, // Small tappable badge in the top-right of the merged preview — edit/add captions, or a - // spinner while transcribing/downloading. White glyph on a translucent scrim over the video. + // spinner while transcribing/downloading. Placement here; the glass surface (sized to a + // 48pt effective target with hitSlop, like the recorder preview card's badges) is split + // out so the Pressable variant can own the position while GlassPill owns the surface. captionBadge: { position: 'absolute', top: Spacing.two, right: Spacing.two, - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: 'rgba(0,0,0,0.55)', + }, + captionSurface: { + width: 40, + height: 40, + borderRadius: 20, alignItems: 'center', justifyContent: 'center', }, diff --git a/src/app/recorder.tsx b/src/app/recorder.tsx index 89788c1..35fb314 100644 --- a/src/app/recorder.tsx +++ b/src/app/recorder.tsx @@ -12,6 +12,7 @@ import { } from 'react-native-vision-camera'; import { ThemedView } from '@/components/themed-view'; +import { GlassPill } from '@/components/glass-pill'; import { Spacing } from '@/constants/theme'; import { CameraControls } from '@/features/recorder/camera-controls'; import { CloseButton } from '@/features/recorder/close-button'; @@ -444,7 +445,9 @@ export default function RecorderScreen() { { paddingTop: insets.top + Spacing.two, paddingHorizontal: Spacing.three }, ]}> - {formatDurationPadded(totalMs)} + + {formatDurationPadded(totalMs)} + {/* Mirrors the CloseButton's width so the timer stays optically centered. */} @@ -585,15 +588,18 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'space-between', }, + // Shape only — GlassPill owns the surface; ties the top bar to the glass close button. + timerPill: { + paddingHorizontal: Spacing.two, + paddingVertical: 4, + borderRadius: 14, + }, timerText: { color: '#fff', fontSize: 16, fontWeight: '600', fontVariant: ['tabular-nums'], letterSpacing: 0.5, - textShadowColor: 'rgba(0,0,0,0.6)', - textShadowOffset: { width: 0, height: 1 }, - textShadowRadius: 3, }, topBarSpacer: { width: 40 }, previewArea: { flex: 1, alignItems: 'center', justifyContent: 'center' }, diff --git a/src/app/subtitles.tsx b/src/app/subtitles.tsx index 8a2bd85..6074389 100644 --- a/src/app/subtitles.tsx +++ b/src/app/subtitles.tsx @@ -2,6 +2,7 @@ import { useEvent } from 'expo'; import { useLiveQuery } from 'drizzle-orm/expo-sqlite'; import { useLocalSearchParams, router } from 'expo-router'; import { Icon, type IconName } from '@/components/icon'; +import { GlassPill } from '@/components/glass-pill'; import { useVideoPlayer, VideoView } from 'expo-video'; import { useEffect, useMemo, useRef, useState } from 'react'; import { @@ -334,9 +335,9 @@ function Editor({ {!isPlaying && ( - + - + )} @@ -513,11 +514,11 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, + // Shape only — GlassPill owns the surface. paddingLeft optically centers the ▶ glyph. playBadge: { width: 48, height: 48, borderRadius: 24, - backgroundColor: 'rgba(0,0,0,0.45)', alignItems: 'center', justifyContent: 'center', paddingLeft: 3,