Skip to content

Commit cc8f290

Browse files
authored
feat: use UICornerConfiguration for borders (#26)
1 parent 6976ed8 commit cc8f290

File tree

6 files changed

+3592
-2761
lines changed

6 files changed

+3592
-2761
lines changed

example/ios/LiquidGlassExample.xcodeproj/project.pbxproj

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,10 @@
191191
inputFileListPaths = (
192192
"${PODS_ROOT}/Target Support Files/Pods-LiquidGlassExample/Pods-LiquidGlassExample-frameworks-${CONFIGURATION}-input-files.xcfilelist",
193193
);
194-
inputPaths = (
195-
);
196194
name = "[CP] Embed Pods Frameworks";
197195
outputFileListPaths = (
198196
"${PODS_ROOT}/Target Support Files/Pods-LiquidGlassExample/Pods-LiquidGlassExample-frameworks-${CONFIGURATION}-output-files.xcfilelist",
199197
);
200-
outputPaths = (
201-
);
202198
runOnlyForDeploymentPostprocessing = 0;
203199
shellPath = /bin/sh;
204200
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LiquidGlassExample/Pods-LiquidGlassExample-frameworks.sh\"\n";
@@ -234,14 +230,10 @@
234230
inputFileListPaths = (
235231
"${PODS_ROOT}/Target Support Files/Pods-LiquidGlassExample/Pods-LiquidGlassExample-resources-${CONFIGURATION}-input-files.xcfilelist",
236232
);
237-
inputPaths = (
238-
);
239233
name = "[CP] Copy Pods Resources";
240234
outputFileListPaths = (
241235
"${PODS_ROOT}/Target Support Files/Pods-LiquidGlassExample/Pods-LiquidGlassExample-resources-${CONFIGURATION}-output-files.xcfilelist",
242236
);
243-
outputPaths = (
244-
);
245237
runOnlyForDeploymentPostprocessing = 0;
246238
shellPath = /bin/sh;
247239
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LiquidGlassExample/Pods-LiquidGlassExample-resources.sh\"\n";

example/ios/Podfile.lock

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
PODS:
2+
- ComputableLayout (0.7.0):
3+
- DGSwiftUtilities (~> 0.11)
4+
- ContextMenuAuxiliaryPreview (0.5.2):
5+
- DGSwiftUtilities (~> 0.29)
6+
- DGSwiftUtilities (0.47.0)
27
- FBLazyVector (0.81.4)
38
- hermes-engine (0.81.4):
49
- hermes-engine/Pre-built (= 0.81.4)
510
- hermes-engine/Pre-built (0.81.4)
6-
- LiquidGlass (0.3.0):
11+
- LiquidGlass (0.4.2):
712
- hermes-engine
813
- RCTRequired
914
- RCTTypeSafety
@@ -1304,6 +1309,62 @@ PODS:
13041309
- React-RCTFBReactNativeSpec
13051310
- ReactCommon/turbomodule/core
13061311
- ReactNativeDependencies
1312+
- react-native-ios-context-menu (3.2.1):
1313+
- ContextMenuAuxiliaryPreview (~> 0.5)
1314+
- DGSwiftUtilities
1315+
- hermes-engine
1316+
- RCTRequired
1317+
- RCTTypeSafety
1318+
- React-Core
1319+
- React-Core-prebuilt
1320+
- React-debug
1321+
- React-Fabric
1322+
- React-featureflags
1323+
- React-graphics
1324+
- React-ImageManager
1325+
- React-jsi
1326+
- React-jsinspector
1327+
- React-jsinspectortracing
1328+
- react-native-ios-utilities
1329+
- React-NativeModulesApple
1330+
- React-RCTAppDelegate
1331+
- React-RCTFabric
1332+
- React-renderercss
1333+
- React-rendererdebug
1334+
- React-utils
1335+
- ReactCodegen
1336+
- ReactCommon/turbomodule/bridging
1337+
- ReactCommon/turbomodule/core
1338+
- ReactNativeDependencies
1339+
- Yoga
1340+
- react-native-ios-utilities (5.2.0):
1341+
- ComputableLayout (~> 0.7)
1342+
- DGSwiftUtilities (~> 0.46)
1343+
- hermes-engine
1344+
- RCTRequired
1345+
- RCTTypeSafety
1346+
- React-Core
1347+
- React-Core-prebuilt
1348+
- React-debug
1349+
- React-Fabric
1350+
- React-featureflags
1351+
- React-graphics
1352+
- React-ImageManager
1353+
- React-jsi
1354+
- React-jsinspector
1355+
- React-jsinspectortracing
1356+
- React-jsitooling
1357+
- React-NativeModulesApple
1358+
- React-RCTAppDelegate
1359+
- React-RCTFabric
1360+
- React-renderercss
1361+
- React-rendererdebug
1362+
- React-utils
1363+
- ReactCodegen
1364+
- ReactCommon/turbomodule/bridging
1365+
- ReactCommon/turbomodule/core
1366+
- ReactNativeDependencies
1367+
- Yoga
13071368
- react-native-safe-area-context (5.6.1):
13081369
- hermes-engine
13091370
- RCTRequired
@@ -1808,6 +1869,8 @@ DEPENDENCIES:
18081869
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
18091870
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
18101871
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
1872+
- react-native-ios-context-menu (from `../node_modules/react-native-ios-context-menu`)
1873+
- react-native-ios-utilities (from `../node_modules/react-native-ios-utilities`)
18111874
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
18121875
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
18131876
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
@@ -1843,6 +1906,12 @@ DEPENDENCIES:
18431906
- ReactNativeDependencies (from `../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)
18441907
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
18451908

1909+
SPEC REPOS:
1910+
trunk:
1911+
- ComputableLayout
1912+
- ContextMenuAuxiliaryPreview
1913+
- DGSwiftUtilities
1914+
18461915
EXTERNAL SOURCES:
18471916
FBLazyVector:
18481917
:path: "../node_modules/react-native/Libraries/FBLazyVector"
@@ -1917,6 +1986,10 @@ EXTERNAL SOURCES:
19171986
:path: "../node_modules/react-native/ReactCommon"
19181987
React-microtasksnativemodule:
19191988
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
1989+
react-native-ios-context-menu:
1990+
:path: "../node_modules/react-native-ios-context-menu"
1991+
react-native-ios-utilities:
1992+
:path: "../node_modules/react-native-ios-utilities"
19201993
react-native-safe-area-context:
19211994
:path: "../node_modules/react-native-safe-area-context"
19221995
react-native-slider:
@@ -1987,9 +2060,12 @@ EXTERNAL SOURCES:
19872060
:path: "../node_modules/react-native/ReactCommon/yoga"
19882061

19892062
SPEC CHECKSUMS:
2063+
ComputableLayout: c50faffac4ed9f8f05b0ce5e6f3a60df1f6042c8
2064+
ContextMenuAuxiliaryPreview: 20be0be795b783b68f8792732eed4bed9f202c1c
2065+
DGSwiftUtilities: 567f8d5ee618f0b7afb185b17aa45ff356315a0f
19902066
FBLazyVector: 9e0cd874afd81d9a4d36679daca991b58b260d42
19912067
hermes-engine: 35c763d57c9832d0eef764316ca1c4d043581394
1992-
LiquidGlass: 2684e8e6ef8a1d206c6009f98271f1d42d42a3dc
2068+
LiquidGlass: 6937b48f2c38c97bc4f512aad93f582e86cd7afa
19932069
RCTDeprecation: 7487d6dda857ccd4cb3dd6ecfccdc3170e85dcbc
19942070
RCTRequired: 54128b7df8be566881d48c7234724a78cb9b6157
19952071
RCTTypeSafety: d2b07797a79e45d7b19e1cd2f53c79ab419fe217
@@ -2023,6 +2099,8 @@ SPEC CHECKSUMS:
20232099
React-logger: 7b234de35acb469ce76d6bbb0457f664d6f32f62
20242100
React-Mapbuffer: fbe1da882a187e5898bdf125e1cc6e603d27ecae
20252101
React-microtasksnativemodule: 76905804171d8ccbe69329fc84c57eb7934add7f
2102+
react-native-ios-context-menu: 9f23509b5722166590c4c53180991319cc44e286
2103+
react-native-ios-utilities: 14afbb6d64f67dce464df5e4bf09d3e80334adde
20262104
react-native-safe-area-context: 42a1b4f8774b577d03b53de7326e3d5757fe9513
20272105
react-native-slider: 8c562583722c396a3682f451f0b6e68e351ec3b9
20282106
React-NativeModulesApple: a9464983ccc0f66f45e93558671f60fc7536e438

example/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
"@react-native/new-app-screen": "0.81.4",
1515
"react": "19.1.0",
1616
"react-native": "0.81.4",
17-
"react-native-safe-area-context": "^5.5.2"
17+
"react-native-ios-context-menu": "3.2.1",
18+
"react-native-ios-utilities": "5.2.0",
19+
"react-native-safe-area-context": "^5.5.2",
20+
"zeego": "^3.0.6"
1821
},
1922
"devDependencies": {
2023
"@babel/core": "^7.25.2",

example/src/App.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable react-native/no-inline-styles */
21
import {
32
ScrollView,
43
StyleSheet,
@@ -8,6 +7,7 @@ import {
87
Animated,
98
View,
109
Pressable,
10+
PlatformColor,
1111
} from 'react-native';
1212
import {
1313
LiquidGlassView,
@@ -16,6 +16,40 @@ import {
1616
type LiquidGlassViewProps,
1717
} from '@callstack/liquid-glass';
1818
import { useEffect, useState } from 'react';
19+
import * as DropdownMenu from 'zeego/dropdown-menu';
20+
21+
function DropdownMenuButton({ title }: { title?: string }) {
22+
return (
23+
<DropdownMenu.Root>
24+
<DropdownMenu.Trigger>
25+
<Text style={styles.dropdownTrigger}>{title}</Text>
26+
</DropdownMenu.Trigger>
27+
<DropdownMenu.Content>
28+
<DropdownMenu.Item key="first">
29+
<DropdownMenu.ItemTitle>First</DropdownMenu.ItemTitle>
30+
</DropdownMenu.Item>
31+
<DropdownMenu.Item key="second">
32+
<DropdownMenu.ItemTitle>Second</DropdownMenu.ItemTitle>
33+
</DropdownMenu.Item>
34+
<DropdownMenu.Item key="third">
35+
<DropdownMenu.ItemTitle>Third</DropdownMenu.ItemTitle>
36+
</DropdownMenu.Item>
37+
</DropdownMenu.Content>
38+
</DropdownMenu.Root>
39+
);
40+
}
41+
42+
function LiquidToolBar() {
43+
return (
44+
<LiquidGlassView style={styles.toolbar}>
45+
<DropdownMenuButton title="File" />
46+
<DropdownMenuButton title="Edit" />
47+
<DropdownMenuButton title="View" />
48+
<DropdownMenuButton title="Window" />
49+
<DropdownMenuButton title="Help" />
50+
</LiquidGlassView>
51+
);
52+
}
1953

2054
const AnimatedLiquidGlassView =
2155
Animated.createAnimatedComponent(LiquidGlassView);
@@ -42,6 +76,7 @@ export default function App() {
4276
<Button />
4377
<MergingCircles />
4478
</ScrollView>
79+
<LiquidToolBar />
4580
</>
4681
);
4782
}
@@ -252,4 +287,21 @@ const styles = StyleSheet.create({
252287
flexDirection: 'row',
253288
gap: 10,
254289
},
290+
toolbar: {
291+
flexDirection: 'row',
292+
gap: 10,
293+
padding: 10,
294+
position: 'absolute',
295+
borderRadius: 40,
296+
bottom: 50,
297+
left: 20,
298+
right: 20,
299+
justifyContent: 'center',
300+
},
301+
dropdownTrigger: {
302+
padding: 10,
303+
color: PlatformColor('labelColor'),
304+
fontFamily: 'System',
305+
fontWeight: '600',
306+
},
255307
});

ios/LiquidGlassView.mm

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ @interface LiquidGlassView () <RCTLiquidGlassViewViewProtocol>
2323

2424
@implementation LiquidGlassView {
2525
LiquidGlassViewImpl * _view;
26+
BOOL _needsInvalidateLayer;
2627
}
2728

2829
+ (ComponentDescriptorProvider)componentDescriptorProvider
@@ -102,9 +103,10 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
102103
needsSetup = YES;
103104
}
104105

105-
if (oldViewProps.borderRadii != newViewProps.borderRadii) {
106-
_view.layer.cornerRadius = self.layer.cornerRadius;
107-
_view.layer.cornerCurve = self.layer.cornerCurve;
106+
// `border`
107+
if (oldViewProps.borderStyles != newViewProps.borderStyles || oldViewProps.borderRadii != newViewProps.borderRadii ||
108+
oldViewProps.borderColors != newViewProps.borderColors) {
109+
_needsInvalidateLayer = YES;
108110
}
109111

110112
if (needsSetup) {
@@ -114,6 +116,28 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
114116
[super updateProps:props oldProps:oldProps];
115117
}
116118

119+
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
120+
[super finalizeUpdates:updateMask];
121+
122+
if (!_needsInvalidateLayer) {
123+
return;
124+
}
125+
126+
_needsInvalidateLayer = NO;
127+
128+
if (@available(iOS 26.0, *)) {
129+
const auto borderMetrics = _props->resolveBorderMetrics(_layoutMetrics);
130+
131+
if (!borderMetrics.borderRadii.isUniform()) {
132+
// TODO: Handle non uniform border radius
133+
NSLog(@"[@callstack/liquid-glass] Using uneven border radius is not yet supported on glass elements.");
134+
}
135+
136+
// Use topLeft.horizontal same as React Native RCTViewComponentView implementation: https://github.com/facebook/react-native/blob/b823b26a3765cbf4506df0981e3350e0bae3ad62/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm#L988C26-L988C80
137+
_view.cornerConfiguration = [UICornerConfiguration configurationWithRadius:[UICornerRadius fixedRadius:borderMetrics.borderRadii.topLeft.horizontal]];
138+
}
139+
}
140+
117141
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
118142
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
119143
{

0 commit comments

Comments
 (0)