Skip to content
Merged
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
13 changes: 13 additions & 0 deletions .changeset/eager-walls-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@reown/appkit-react-native': patch
'@reown/appkit-ui-react-native': patch
'@reown/appkit-bitcoin-react-native': patch
'@reown/appkit-coinbase-react-native': patch
'@reown/appkit-common-react-native': patch
'@reown/appkit-core-react-native': patch
'@reown/appkit-ethers-react-native': patch
'@reown/appkit-solana-react-native': patch
'@reown/appkit-wagmi-react-native': patch
---

chore: round logo from qr code + added borderWidth 0 to card component
3 changes: 2 additions & 1 deletion packages/appkit/src/modal/w3m-modal/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { StyleSheet } from 'react-native';
export default StyleSheet.create({
card: {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0
borderBottomRightRadius: 0,
borderWidth: 0
}
});
11 changes: 10 additions & 1 deletion packages/appkit/src/partials/w3m-connecting-qrcode/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import styles from './styles';
import { ReownButton } from './components/ReownButton';
import { useWindowDimensions } from 'react-native';

const LOGO_SIZE = 60;
const LOGO_BORDER_RADIUS = 10;

export function ConnectingQrCode() {
const { height, width } = useWindowDimensions();
const windowSize = Math.min(height, width);
Expand Down Expand Up @@ -65,7 +68,13 @@ export function ConnectingQrCode() {
flexDirection={isPortrait ? 'column' : 'row'}
padding={['xl', 'xl', 'xs', 'xl']}
>
<QrCode size={qrSize} uri={wcUri} testID="qr-code" />
<QrCode
size={qrSize}
uri={wcUri}
testID="qr-code"
logoBorderRadius={LOGO_BORDER_RADIUS}
logoSize={LOGO_SIZE}
/>
<FlexView alignItems="center" margin="m">
<Text variant="paragraph-500">Scan this QR code with your phone</Text>
{showCopy ? (
Expand Down
9 changes: 4 additions & 5 deletions packages/ui/src/assets/svg/WalletConnect.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import Svg, { ClipPath, Defs, G, Path, type SvgProps } from 'react-native-svg';
const SvgWalletConnect = (props: SvgProps) => (
<Svg fill="none" viewBox="0 0 96 67" {...props}>
<Svg fill="none" viewBox="0 0 37 23" {...props}>
<Path
fill={props.fill ?? '#fff'}
d="M25.32 18.8a32.56 32.56 0 0 1 45.36 0l1.5 1.47c.63.62.63 1.61 0 2.22l-5.15 5.05c-.31.3-.82.3-1.14 0l-2.07-2.03a22.71 22.71 0 0 0-31.64 0l-2.22 2.18c-.31.3-.82.3-1.14 0l-5.15-5.05a1.55 1.55 0 0 1 0-2.22l1.65-1.62Zm56.02 10.44 4.59 4.5c.63.6.63 1.6 0 2.21l-20.7 20.26c-.62.61-1.63.61-2.26 0L48.28 41.83a.4.4 0 0 0-.56 0L33.03 56.21c-.63.61-1.64.61-2.27 0L10.07 35.95a1.55 1.55 0 0 1 0-2.22l4.59-4.5a1.63 1.63 0 0 1 2.27 0L31.6 43.63a.4.4 0 0 0 .57 0l14.69-14.38a1.63 1.63 0 0 1 2.26 0l14.69 14.38a.4.4 0 0 0 .57 0l14.68-14.38a1.63 1.63 0 0 1 2.27 0Z"
d="M26.6428 8.62163L29.8418 5.42265C22.6115 -1.80755 13.6277 -1.80755 6.39746 5.42265L9.59644 8.62163C15.0953 3.12281 21.1477 3.12281 26.6465 8.62163H26.6428Z"
/>
<Path
stroke="#000"
strokeOpacity=".1"
d="M25.67 19.15a32.06 32.06 0 0 1 44.66 0l1.5 1.48c.43.42.43 1.09 0 1.5l-5.15 5.05a.31.31 0 0 1-.44 0l-2.07-2.03a23.21 23.21 0 0 0-32.34 0l-2.22 2.18a.31.31 0 0 1-.44 0l-5.15-5.05a1.05 1.05 0 0 1 0-1.5l1.65-1.63ZM81 29.6l4.6 4.5c.42.41.42 1.09 0 1.5l-20.7 20.26c-.43.43-1.14.43-1.57 0L48.63 41.47a.9.9 0 0 0-1.26 0L32.68 55.85c-.43.43-1.14.43-1.57 0L10.42 35.6a1.05 1.05 0 0 1 0-1.5l4.59-4.5a1.13 1.13 0 0 1 1.57 0l14.68 14.38a.9.9 0 0 0 1.27 0l-.35-.35.35.35L47.22 29.6a1.13 1.13 0 0 1 1.56 0l14.7 14.38a.9.9 0 0 0 1.26 0L79.42 29.6a1.13 1.13 0 0 1 1.57 0Z"
fill={props.fill ?? '#fff'}
d="M25.5769 16.0749L18.1164 8.61435L10.6558 16.0749L3.19526 8.61435L0 11.8096L10.6558 22.4691L18.1164 15.0086L25.5769 22.4691L36.2328 11.8096L33.0375 8.61435L25.5769 16.0749Z"
/>
</Svg>
);
Expand Down
91 changes: 75 additions & 16 deletions packages/ui/src/composites/wui-qr-code/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { memo, useMemo } from 'react';
import { View, type StyleProp, type ViewStyle } from 'react-native';
import Svg from 'react-native-svg';
import Svg, { Circle, Line, Rect } from 'react-native-svg';
import { Icon } from '../../components/wui-icon';
import { Image } from '../../components/wui-image';
import { Shimmer } from '../../components/wui-shimmer';
Expand All @@ -17,17 +17,32 @@ export interface QrCodeProps {
testID?: string;
arenaClear?: boolean;
style?: StyleProp<ViewStyle>;
logoSize?: number;
logoBorderRadius?: number;
}

export function QrCode_({ size, uri, imageSrc, testID, arenaClear, icon, style }: QrCodeProps) {
export function QrCode_({
size,
uri,
imageSrc,
testID,
arenaClear,
icon,
style,
logoSize,
logoBorderRadius
}: QrCodeProps) {
const Theme = LightTheme;
const containerPadding = Spacing.l;
const qrSize = size - containerPadding * 2;
const logoSize = arenaClear ? 0 : qrSize / 4;
const _logoSize = arenaClear ? 0 : logoSize ?? qrSize / 4;

const dots = useMemo(
() => (uri ? QRCodeUtil.generate(uri, qrSize, logoSize) : []),
[uri, qrSize, logoSize]
const dotColor = Theme['inverse-000'];
const edgeColor = Theme['inverse-100'];

const qrData = useMemo(
() => (uri ? QRCodeUtil.generate(uri, qrSize, _logoSize, logoBorderRadius) : null),
[uri, qrSize, _logoSize, logoBorderRadius]
);

const logoTemplate = () => {
Expand All @@ -40,8 +55,12 @@ export function QrCode_({ size, uri, imageSrc, testID, arenaClear, icon, style }
<Image
source={imageSrc}
style={[
styles.icon,
{ height: qrSize / 4, width: qrSize / 4, borderRadius: qrSize / 16 }
{
position: 'absolute' as const,
height: _logoSize,
width: _logoSize,
borderRadius: logoBorderRadius
}
]}
/>
);
Expand All @@ -51,14 +70,18 @@ export function QrCode_({ size, uri, imageSrc, testID, arenaClear, icon, style }
<Icon
name={icon ?? 'walletConnect'}
color="accent-100"
height={qrSize / 3.5}
width={qrSize / 3.5}
style={styles.icon}
height={_logoSize}
width={_logoSize}
style={{ position: 'absolute' as const }}
/>
);
};

return uri ? (
if (!uri || !qrData) {
return <Shimmer width={size} height={size} borderRadius={BorderRadius.l} />;
}

return (
<View
style={[
styles.container,
Expand All @@ -68,19 +91,55 @@ export function QrCode_({ size, uri, imageSrc, testID, arenaClear, icon, style }
testID={testID}
>
<Svg height={qrSize} width={qrSize}>
{dots}
{/* Render rectangles */}
{qrData.rects.map(rect => (
<Rect
key={`rect_${rect.x}_${rect.y}`}
fill={rect.fillType === 'dot' ? dotColor : edgeColor}
height={rect.size}
rx={rect.size * 0.32}
ry={rect.size * 0.32}
width={rect.size}
x={rect.x}
y={rect.y}
/>
))}

{/* Render circles */}
{qrData.circles.map(circle => (
<Circle
key={`circle_${circle.cx}_${circle.cy}`}
cx={circle.cx}
cy={circle.cy}
fill={dotColor}
r={circle.r}
/>
))}

{/* Render lines */}
{qrData.lines.map(line => (
<Line
key={`line_${line.x1}_${line.y1}_${line.y2}`}
x1={line.x1}
x2={line.x2}
y1={line.y1}
y2={line.y2}
stroke={dotColor}
strokeWidth={line.strokeWidth}
strokeLinecap="round"
/>
))}
</Svg>
{logoTemplate()}
</View>
) : (
<Shimmer width={size} height={size} borderRadius={BorderRadius.l} />
);
}

export const QrCode = memo(QrCode_, (prevProps, nextProps) => {
return (
prevProps.size === nextProps.size &&
prevProps.uri === nextProps.uri &&
prevProps.style === nextProps.style
prevProps.style === nextProps.style &&
prevProps.logoBorderRadius === nextProps.logoBorderRadius
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Incomplete memo props cause stale QR codes.

The QrCode component's memo comparison is incomplete. It misses logoSize, imageSrc, icon, arenaClear, and testID props. Changes to these props won't trigger a re-render, which can lead to stale QR codes or incorrect logo display.

Fix in Cursor Fix in Web

);
});
Comment on lines 138 to 145
Copy link

Copilot AI Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The memo comparison function is missing checks for logoSize, imageSrc, icon, arenaClear, and testID props. This will cause the component to incorrectly skip re-renders when these props change, leading to stale UI. Either add all props to the comparison or remove the custom comparison function to use the default shallow comparison.

Copilot uses AI. Check for mistakes.
3 changes: 0 additions & 3 deletions packages/ui/src/composites/wui-qr-code/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,5 @@ export default StyleSheet.create({
borderRadius: BorderRadius.l,
padding: Spacing.l,
alignSelf: 'center'
},
icon: {
position: 'absolute'
}
});
Loading
Loading