| author | |
| committer | |
| log | 9b2d04317c68233782e0630464ac86d77d0686f3 |
| tree | f53842d3df8b705d7185b508febbe0d23b75eec2 |
| parent | e9c4775e8738381140af4e5248507b15fc1cd491 |
| signature | Signed by PGP key B5690EEEBB952194 |
5 files changed, 39 insertions(+), 50 deletions(-)
apps/mobile/package.json-1| ... | ... | @@ -45,7 +45,6 @@ |
| 45 | 45 | "typecheck": "tsc --noEmit" |
| 46 | 46 | }, |
| 47 | 47 | "dependencies": { |
| 48 | "@callstack/liquid-glass": "^0.7.1", | |
| 49 | 48 | "@clerk/expo": "catalog:", |
| 50 | 49 | "@effect/atom-react": "catalog:", |
| 51 | 50 | "@expo-google-fonts/dm-sans": "^0.4.2", |
apps/mobile/src/features/threads/GitActionProgressOverlay.tsx+9-8| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | import * as Haptics from "expo-haptics"; |
| 2 | import { isLiquidGlassSupported, LiquidGlassView } from "@callstack/liquid-glass"; | |
| 2 | import { GlassView } from "expo-glass-effect"; | |
| 3 | 3 | import { SymbolView } from "../../components/AppSymbol"; |
| 4 | 4 | import { useCallback, useEffect, useRef } from "react"; |
| 5 | 5 | import { ActivityIndicator, Pressable, StyleSheet, useColorScheme, View } from "react-native"; |
| ... | ... | @@ -11,11 +11,12 @@ import { APP_BAR_HEIGHT } from "../../lib/layoutMetrics"; |
| 11 | 11 | import { themeColorWithAlpha } from "../../lib/mobileTheme"; |
| 12 | 12 | import { tryOpenExternalUrl } from "../../lib/openExternalUrl"; |
| 13 | 13 | import { useUniwindTheme } from "../../lib/useUniwindTheme"; |
| 14 | import { NATIVE_LIQUID_GLASS_SUPPORTED } from "../../native/native-glass"; | |
| 14 | 15 | import type { GitActionProgress } from "../../state/use-vcs-action-state"; |
| 15 | 16 | |
| 16 | 17 | const OVERLAY_LAYOUT_TRANSITION = LinearTransition.duration(220); |
| 17 | 18 | const OVERLAY_TOP_GAP = 8; |
| 18 | const AnimatedLiquidGlassView = Animated.createAnimatedComponent(LiquidGlassView); | |
| 19 | const AnimatedGlassView = Animated.createAnimatedComponent(GlassView); | |
| 19 | 20 | |
| 20 | 21 | export function GitActionProgressOverlay(props: { |
| 21 | 22 | readonly progress: GitActionProgress; |
| ... | ... | @@ -52,7 +53,7 @@ export function GitActionProgressOverlay(props: { |
| 52 | 53 | |
| 53 | 54 | return ( |
| 54 | 55 | <Animated.View |
| 55 | entering={isLiquidGlassSupported ? undefined : FadeIn.duration(200)} | |
| 56 | entering={NATIVE_LIQUID_GLASS_SUPPORTED ? undefined : FadeIn.duration(200)} | |
| 56 | 57 | exiting={FadeOut.duration(150)} |
| 57 | 58 | className="absolute inset-x-3 z-[100]" |
| 58 | 59 | style={{ top: insets.top + APP_BAR_HEIGHT + OVERLAY_TOP_GAP }} |
| ... | ... | @@ -102,7 +103,7 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) { |
| 102 | 103 | </> |
| 103 | 104 | ); |
| 104 | 105 | |
| 105 | if (isLiquidGlassSupported) { | |
| 106 | if (NATIVE_LIQUID_GLASS_SUPPORTED) { | |
| 106 | 107 | return ( |
| 107 | 108 | <Animated.View |
| 108 | 109 | layout={OVERLAY_LAYOUT_TRANSITION} |
| ... | ... | @@ -116,10 +117,10 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) { |
| 116 | 117 | shadowRadius: 18, |
| 117 | 118 | }} |
| 118 | 119 | > |
| 119 | <AnimatedLiquidGlassView | |
| 120 | <AnimatedGlassView | |
| 120 | 121 | colorScheme={isDarkMode ? "dark" : "light"} |
| 121 | effect="regular" | |
| 122 | interactive | |
| 122 | glassEffectStyle="regular" | |
| 123 | isInteractive | |
| 123 | 124 | layout={OVERLAY_LAYOUT_TRANSITION} |
| 124 | 125 | tintColor={glassTint} |
| 125 | 126 | style={{ |
| ... | ... | @@ -136,7 +137,7 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) { |
| 136 | 137 | > |
| 137 | 138 | {content} |
| 138 | 139 | </Animated.View> |
| 139 | </AnimatedLiquidGlassView> | |
| 140 | </AnimatedGlassView> | |
| 140 | 141 | </Animated.View> |
| 141 | 142 | ); |
| 142 | 143 | } |
apps/mobile/src/features/threads/floating-working-control.tsx+28-25| ... | ... | @@ -1,8 +1,4 @@ |
| 1 | import { | |
| 2 | isLiquidGlassSupported, | |
| 3 | LiquidGlassContainerView, | |
| 4 | LiquidGlassView, | |
| 5 | } from "@callstack/liquid-glass"; | |
| 1 | import { GlassContainer, GlassView } from "expo-glass-effect"; | |
| 6 | 2 | import { useEffect, useState } from "react"; |
| 7 | 3 | import { Text as SystemText, View } from "react-native"; |
| 8 | 4 | import Animated, { |
| ... | ... | @@ -18,6 +14,7 @@ import { withUniwind } from "uniwind"; |
| 18 | 14 | |
| 19 | 15 | import { AppText as Text } from "../../components/AppText"; |
| 20 | 16 | import { ControlPill } from "../../components/ControlPill"; |
| 17 | import { NATIVE_LIQUID_GLASS_SUPPORTED } from "../../native/native-glass"; | |
| 21 | 18 | |
| 22 | 19 | const CONTROL_HEIGHT = 44; |
| 23 | 20 | const CONTROL_COMPOSER_GAP = 8; |
| ... | ... | @@ -31,9 +28,15 @@ const CONTROL_TIMING = { |
| 31 | 28 | } as const; |
| 32 | 29 | const CONTROL_SEPARATION = (16 + CONTROL_HEIGHT) / 2; |
| 33 | 30 | |
| 34 | const UniwindLiquidGlassView = withUniwind(LiquidGlassView); | |
| 35 | const UniwindLiquidGlassContainerView = withUniwind(LiquidGlassContainerView); | |
| 36 | const AnimatedLiquidGlassView = Animated.createAnimatedComponent(UniwindLiquidGlassView); | |
| 31 | // Expo reapplies glass after native layout and window reattachment, when UIKit | |
| 32 | // can otherwise leave the label visible but lose the material behind it. | |
| 33 | const UniwindGlassView = withUniwind(GlassView, { | |
| 34 | style: { fromClassName: "className" }, | |
| 35 | }); | |
| 36 | const UniwindGlassContainer = withUniwind(GlassContainer, { | |
| 37 | style: { fromClassName: "className" }, | |
| 38 | }); | |
| 39 | const AnimatedGlassView = Animated.createAnimatedComponent(UniwindGlassView); | |
| 37 | 40 | |
| 38 | 41 | export const FLOATING_WORKING_CONTROL_COVERAGE = CONTROL_HEIGHT + CONTROL_COMPOSER_GAP; |
| 39 | 42 | |
| ... | ... | @@ -68,29 +71,29 @@ export function FloatingWorkingControl(props: { |
| 68 | 71 | pointerEvents="box-none" |
| 69 | 72 | className="absolute left-0 right-0 z-20 items-center" |
| 70 | 73 | style={{ top: -FLOATING_WORKING_CONTROL_COVERAGE }} |
| 71 | entering={isLiquidGlassSupported ? undefined : CONTROL_ENTERING} | |
| 72 | exiting={isLiquidGlassSupported ? undefined : CONTROL_EXITING} | |
| 74 | entering={NATIVE_LIQUID_GLASS_SUPPORTED ? undefined : CONTROL_ENTERING} | |
| 75 | exiting={NATIVE_LIQUID_GLASS_SUPPORTED ? undefined : CONTROL_EXITING} | |
| 73 | 76 | > |
| 74 | {props.startedAt !== null && isLiquidGlassSupported ? ( | |
| 75 | <UniwindLiquidGlassContainerView | |
| 77 | {props.startedAt !== null && NATIVE_LIQUID_GLASS_SUPPORTED ? ( | |
| 78 | <UniwindGlassContainer | |
| 76 | 79 | spacing={GLASS_MERGE_SPACING} |
| 77 | 80 | pointerEvents="box-none" |
| 78 | 81 | className="flex-row items-center gap-4" |
| 79 | 82 | > |
| 80 | <AnimatedLiquidGlassView | |
| 83 | <AnimatedGlassView | |
| 81 | 84 | colorScheme={props.colorScheme} |
| 82 | effect="regular" | |
| 85 | glassEffectStyle="regular" | |
| 83 | 86 | pointerEvents="none" |
| 84 | 87 | className="h-11 justify-center overflow-hidden rounded-full" |
| 85 | 88 | style={timerStyle} |
| 86 | 89 | > |
| 87 | 90 | <WorkingDuration startedAt={props.startedAt} /> |
| 88 | </AnimatedLiquidGlassView> | |
| 91 | </AnimatedGlassView> | |
| 89 | 92 | |
| 90 | <AnimatedLiquidGlassView | |
| 93 | <AnimatedGlassView | |
| 91 | 94 | colorScheme={props.colorScheme} |
| 92 | effect="regular" | |
| 93 | interactive | |
| 95 | glassEffectStyle="regular" | |
| 96 | isInteractive | |
| 94 | 97 | pointerEvents={props.showScrollToEnd ? "auto" : "none"} |
| 95 | 98 | accessibilityElementsHidden={!props.showScrollToEnd} |
| 96 | 99 | importantForAccessibility={props.showScrollToEnd ? "auto" : "no-hide-descendants"} |
| ... | ... | @@ -100,8 +103,8 @@ export function FloatingWorkingControl(props: { |
| 100 | 103 | <Animated.View style={arrowContentStyle}> |
| 101 | 104 | <ScrollToEndButton disabled={!props.showScrollToEnd} onPress={props.onScrollToEnd} /> |
| 102 | 105 | </Animated.View> |
| 103 | </AnimatedLiquidGlassView> | |
| 104 | </UniwindLiquidGlassContainerView> | |
| 106 | </AnimatedGlassView> | |
| 107 | </UniwindGlassContainer> | |
| 105 | 108 | ) : props.startedAt !== null ? ( |
| 106 | 109 | <View pointerEvents="box-none" className="flex-row items-center gap-4"> |
| 107 | 110 | <Animated.View |
| ... | ... | @@ -128,15 +131,15 @@ export function FloatingWorkingControl(props: { |
| 128 | 131 | /> |
| 129 | 132 | </Animated.View> |
| 130 | 133 | </View> |
| 131 | ) : isLiquidGlassSupported ? ( | |
| 132 | <UniwindLiquidGlassView | |
| 134 | ) : NATIVE_LIQUID_GLASS_SUPPORTED ? ( | |
| 135 | <UniwindGlassView | |
| 133 | 136 | colorScheme={props.colorScheme} |
| 134 | effect="regular" | |
| 135 | interactive | |
| 137 | glassEffectStyle="regular" | |
| 138 | isInteractive | |
| 136 | 139 | className="h-11 w-11 items-center justify-center overflow-hidden rounded-full" |
| 137 | 140 | > |
| 138 | 141 | <ScrollToEndButton onPress={props.onScrollToEnd} /> |
| 139 | </UniwindLiquidGlassView> | |
| 142 | </UniwindGlassView> | |
| 140 | 143 | ) : ( |
| 141 | 144 | <ControlPill |
| 142 | 145 | accessibilityLabel="Scroll to end" |
docs/user/mobile-appearance.md+2-2| ... | ... | @@ -4,8 +4,8 @@ T3 Code Mobile includes the T3 Code, T3 Chat, Grove, Ocean, Ember, and Iris them |
| 4 | 4 | light and dark colors that apply throughout the app, including code reviews, file previews, the |
| 5 | 5 | terminal, native headers, and sheets. |
| 6 | 6 | |
| 7 | On supported iOS versions, the new-task and thread composers use the system glass material. | |
| 8 | Other platforms use a themed background. | |
| 7 | On supported iOS versions, the new-task and thread composers, working timer, and scroll-to-end | |
| 8 | button use the system glass material. Other platforms use a themed background. | |
| 9 | 9 | |
| 10 | 10 | To change themes: |
| 11 | 11 |
pnpm-lock.yaml-14| ... | ... | @@ -211,9 +211,6 @@ importers: |
| 211 | 211 | |
| 212 | 212 | apps/mobile: |
| 213 | 213 | dependencies: |
| 214 | '@callstack/liquid-glass': | |
| 215 | specifier: ^0.7.1 | |
| 216 | version: 0.7.1(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) | |
| 217 | 214 | '@clerk/expo': |
| 218 | 215 | specifier: 4.2.0 |
| 219 | 216 | version: 4.2.0(patch_hash=72e426f44fc1cde16fc2cbba3d1e96cdca7c6d957faa73d0fe6b43948608a6c1)(1fcd0592788ddcf326eeeb90d875ed47) |
| ... | ... | @@ -1700,12 +1697,6 @@ packages: |
| 1700 | 1697 | cpu: [x64] |
| 1701 | 1698 | os: [win32] |
| 1702 | 1699 | |
| 1703 | '@callstack/liquid-glass@0.7.1': | |
| 1704 | resolution: {integrity: sha512-N2rzs8g3kneI5G/98AZdVtjc6OUFBBFwPxVGVMoXUEI7QiioB4+aWwbImg5h8Z3Vb/T+fgLYWmmNhi27wHwE4g==} | |
| 1705 | peerDependencies: | |
| 1706 | react: '*' | |
| 1707 | react-native: '*' | |
| 1708 | ||
| 1709 | 1700 | '@capsizecss/unpack@4.0.1': |
| 1710 | 1701 | resolution: {integrity: sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==} |
| 1711 | 1702 | engines: {node: '>=18'} |
| ... | ... | @@ -11398,11 +11389,6 @@ snapshots: |
| 11398 | 11389 | '@bruits/satteri-win32-x64-msvc@0.9.3': |
| 11399 | 11390 | optional: true |
| 11400 | 11391 | |
| 11401 | '@callstack/liquid-glass@0.7.1(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)': | |
| 11402 | dependencies: | |
| 11403 | react: 19.2.3 | |
| 11404 | react-native: 0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6) | |
| 11405 | ||
| 11406 | 11392 | '@capsizecss/unpack@4.0.1': |
| 11407 | 11393 | dependencies: |
| 11408 | 11394 | fontkitten: 1.0.3 |