feat: add desktop variant for @selfxyz/qrcode#1734
Conversation
Update `main` 10/10/25
Release to Production - 2025-10-12
Release to Staging - 2025-10-24
Release to Production - 2025-10-26
Release to Staging - 2025-11-01
Release to Production - 2025-11-04
Release to Staging - 2025-11-07
Release to Staging - 2025-11-14
Release to Staging - 2025-11-20
Release to Staging - 2025-12-05
…allowing dynamic switching between iOS and Android during tests. This change improves test isolation and avoids hoisting issues with jest.mock.
Bugfix: Workaround Mobile CI tests flakiness
Release to Staging - 2025-12-12
Release alpha build for 2.9.5
Release to Staging - 2025-12-16
…nges. Added checks for 'circuits' in circuits.yml and 'contracts' or 'common' in contracts.yml to determine if tests should execute on dev branch. This avoids too wide changelist in trigger filter that is problematic
…in circuits.yml and contracts.yml. This change ensures that the full history is available for subsequent steps in the workflows.
… checks. Added error handling for git diff command in circuits.yml and contracts.yml to ensure robust execution and prevent workflow failures due to diff errors.
…tibility and performance across all CI configurations. This change replaces the previous version v4 in circuits, contracts, and other workflow files.
…pendency installation process.
…pha package.json for version checks.
SELF-1684: Ensure checks are run with pull requests to staging/main
Release to Production - 2025-12-07
Release to Staging - 2026-01-16
Release to Staging - 2026-01-22
Release to Staging - 2026-01-22
Release to Staging - 2026-01-22
Release to Staging - 2026-01-23
chore: fix circuits tests in staging
Release to Staging - 2026-01-30
Release to Staging - 2026-02-04
Prep for release 2.9.13 - 2026-02-04
Debug Android Release v2.9.13 - 2026-02-04
Debug 2.9.15 - 2026-02-04
Release to Staging - 2026-02-06
Release Build v2.9.15 - 2026-02-09
Release to Production - 2026-01-22
Add a new `variant="desktop"` option to SelfQRcode that renders a card-style layout with app branding, instruction steps, and status feedback — designed for desktop web integrations. Co-Authored-By: Claude Opus 4.6 <[email protected]>
📝 WalkthroughWalkthroughAdds a desktop rendering variant for QR code UI: new DesktopHeader, DesktopFooter, DesktopQRcode, icon set, desktop styles and text utilities; SelfQRcode gains a Changes
Sequence Diagram(s)(omitted — changes are UI additions and build/CI updates without multi-component runtime control-flow requiring sequence diagrams) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
This is the final PR Bugbot will review for you during this billing cycle
Your free Bugbot reviews will reset on February 17
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| } | ||
| }; | ||
|
|
||
| export const getDesktopStatusSubtitle = (): string => 'Verify the proof using the Self mobile app'; |
There was a problem hiding this comment.
Status subtitle is static across all proof states
Medium Severity
getDesktopStatusSubtitle always returns the static string "Verify the proof using the Self mobile app" regardless of proof state. This is misleading when the title reads "Proof Verified" or "Proof Failed" — the subtitle still instructs the user to verify. Unlike getDesktopStatusTitle, which correctly switches on proofStep, the subtitle function takes no arguments and never varies. The PR test plan specifically calls for verifying "proof status transitions update … footer state," which this doesn't fully satisfy.
Additional Locations (1)
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@sdk/qrcode/components/DesktopFooter.tsx`:
- Around line 86-89: getDesktopStatusSubtitle currently returns a static string
that is misleading in terminal states; update getDesktopStatusSubtitle (in
sdk/qrcode/utils/utils.ts) to accept the proofStep parameter (like
getDesktopStatusTitle) and return context-appropriate text: e.g., return a
neutral or empty string for PROOF_VERIFIED and a failure-specific message for
PROOF_GENERATION_FAILED, otherwise return the existing "Verify the proof using
the Self mobile app" for in-progress states; ensure the component call in
DesktopFooter passes proofStep into getDesktopStatusSubtitle.
In `@sdk/qrcode/components/DesktopQRcode.tsx`:
- Around line 1-8: The import order is violating simple-import-sort rules
because the type import "SelfApp" is placed before React and other module
imports; reorder imports to match the project's sorting convention (e.g., move
"import type { SelfApp } from '@selfxyz/sdk-common';" so it falls in the correct
group relative to React and local imports) or run the auto-fix (yarn
lint:imports --fix); update the imports in DesktopQRcode.tsx (references:
SelfApp, React, desktopCardStyle, DesktopFooter, DesktopHeader, QRCode) so the
linter passes.
In `@sdk/qrcode/utils/styles.ts`:
- Around line 69-245: Reorder the exported desktop style functions so they match
the project's expected export ordering (alphabetical by export name) to satisfy
the quality-checks CI; locate the functions such as desktopAppLogoStyle,
desktopCardStyle, desktopDescriptionStyle, desktopFooterStyle,
desktopHeaderStyle, desktopLogoRowStyle, desktopQrSectionStyle,
desktopQrWrapperStyle, desktopSelfLogoContainerStyle, desktopSelfLogoImgStyle,
desktopStepIconStyle, desktopStepInnerStyle, desktopStepStyle,
desktopStepTextStyle, desktopStatusFooterStyle, desktopStatusCardStyle,
desktopStatusContentStyle, desktopStatusIconStyle, desktopStatusTextStyle,
desktopStatusTitleStyle, and desktopStatusSubtitleStyle and rearrange their
export declarations into the correct sorted order.
In `@sdk/qrcode/utils/utils.ts`:
- Around line 42-54: The desktop title mapping in getDesktopStatusTitle
incorrectly groups QRcodeSteps.PROOF_GENERATED with the "Connecting to Self"
states; update getDesktopStatusTitle so QRcodeSteps.PROOF_GENERATED has its own
case that returns "Proof Generated" (matching getStatusText) instead of falling
through to "Connecting to Self", ensuring consistency between
getDesktopStatusTitle and getStatusText.
🧹 Nitpick comments (5)
sdk/qrcode/utils/styles.ts (2)
51-67:getDesktopBorderColorduplicatesgetBorderColorwith a single color difference.Consider extracting a shared helper parameterized by the verified-state color to avoid maintaining two near-identical switch statements.
♻️ Example consolidation
-const getBorderColor = (step: number): string => { - ... -}; - -const getDesktopBorderColor = (step: number): string => { - ... -}; +const makeBorderColorFn = (verifiedColor: string) => (step: number): string => { + switch (step) { + case QRcodeSteps.DISCONNECTED: + case QRcodeSteps.WAITING_FOR_MOBILE: + return '#E2E8F0'; + case QRcodeSteps.MOBILE_CONNECTED: + case QRcodeSteps.PROOF_GENERATION_STARTED: + case QRcodeSteps.PROOF_GENERATED: + return '#3B82F6'; + case QRcodeSteps.PROOF_GENERATION_FAILED: + return '#EF4444'; + case QRcodeSteps.PROOF_VERIFIED: + return verifiedColor; + default: + return '#E2E8F0'; + } +}; + +const getBorderColor = makeBorderColorFn('#01BFFF'); +const getDesktopBorderColor = makeBorderColorFn('#00FFB6');
69-245: Parameterless style functions create new object references on every render, defeatingReact.memo.Functions like
desktopCardStyle(),desktopHeaderStyle(), etc. return fresh objects each call. Since the desktop components are wrapped inmemo(), these always-new style objects will cause unnecessary re-renders of children that compare props by reference. Consider exporting them as constants instead of zero-arg functions.♻️ Example: convert zero-arg style functions to constants
-export const desktopCardStyle = (): React.CSSProperties => ({ +export const desktopCardStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', border: '1px solid `#E2E8F0`', borderRadius: '10px', backgroundColor: '#FFFFFF', overflow: 'hidden', width: '373px', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', -}); +};Apply the same pattern to all other zero-arg style functions. This also simplifies call sites (e.g.,
style={desktopCardStyle}instead ofstyle={desktopCardStyle()}).sdk/qrcode/components/SelfQRcode.tsx (1)
13-24: Consider documenting which props are ignored in desktop mode.
showBorderandshowStatusTexthave no effect whenvariant="desktop", which could surprise SDK consumers. A JSDoc comment on thevariantprop or on the ignored props noting this would improve the public API clarity.sdk/qrcode/components/icons.tsx (2)
16-46: Export order doesn't match the project's lint rules.Static analysis flagged that the named exports aren't in alphabetical order. The linter expects
BoltIconbeforeReturnIcon, andReturnIconbeforeSelfShieldIcon.♻️ Reorder exports alphabetically
-export const DotsIcon = ({ size = 18 }: IconProps) => ( - <img src={dotsIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); - -export const ScanIcon = ({ size = 24 }: IconProps) => ( - <img src={qrcodeIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); - -export const SelfShieldIcon = ({ size = 24 }: IconProps) => ( - <img src={shieldcheckIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); - -export const ReturnIcon = ({ size = 24 }: IconProps) => ( - <img src={squarecheckIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); - -export const BoltIcon = ({ size = 24 }: IconProps) => ( - <img src={shieldlightningIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); - -export const CheckIcon = ({ size = 24 }: IconProps) => ( - <img src={shieldcheck2Icon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); - -export const ExclamationIcon = ({ size = 24 }: IconProps) => ( - <img src={errorIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); - -export const WarningIcon = ({ size = 24 }: IconProps) => ( - <img src={warningIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> -); +export const BoltIcon = ({ size = 24 }: IconProps) => ( + <img src={shieldlightningIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +); + +export const CheckIcon = ({ size = 24 }: IconProps) => ( + <img src={shieldcheck2Icon} alt="" width={size} height={size} style={{ display: 'block' }} /> +); + +export const DotsIcon = ({ size = 18 }: IconProps) => ( + <img src={dotsIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +); + +export const ExclamationIcon = ({ size = 24 }: IconProps) => ( + <img src={errorIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +); + +export const ReturnIcon = ({ size = 24 }: IconProps) => ( + <img src={squarecheckIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +); + +export const ScanIcon = ({ size = 24 }: IconProps) => ( + <img src={qrcodeIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +); + +export const SelfShieldIcon = ({ size = 24 }: IconProps) => ( + <img src={shieldcheckIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +); + +export const WarningIcon = ({ size = 24 }: IconProps) => ( + <img src={warningIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +);
16-17: Emptyaltattributes on icons that convey status meaning.Using
alt=""is correct for purely decorative icons. However, some of these icons (e.g.,CheckIcon,ExclamationIcon,WarningIcon) are used inDesktopFooterto convey proof status — they carry semantic meaning. Consider accepting an optionalaltprop so consuming components can provide meaningful alternative text for screen readers when the icon isn't purely decorative.♻️ Accept optional alt prop
interface IconProps { size?: number; + alt?: string; } -export const BoltIcon = ({ size = 24 }: IconProps) => ( - <img src={shieldlightningIcon} alt="" width={size} height={size} style={{ display: 'block' }} /> +export const BoltIcon = ({ size = 24, alt = '' }: IconProps) => ( + <img src={shieldlightningIcon} alt={alt} width={size} height={size} style={{ display: 'block' }} /> );Apply the same pattern to the other icon components.
| <div style={desktopStatusTextStyle()}> | ||
| <p style={desktopStatusTitleStyle()}>{getDesktopStatusTitle(proofStep)}</p> | ||
| <p style={desktopStatusSubtitleStyle()}>{getDesktopStatusSubtitle()}</p> | ||
| </div> |
There was a problem hiding this comment.
Static subtitle may be contextually misleading for terminal states.
getDesktopStatusSubtitle() always returns "Verify the proof using the Self mobile app" — even when the proof is already verified or has failed. For PROOF_VERIFIED, the instruction to "verify the proof" is confusing; for PROOF_GENERATION_FAILED, it may mislead users into thinking they need to take action in the app when the flow has already errored out.
Consider making the subtitle dynamic based on proofStep (similar to getDesktopStatusTitle), or at minimum returning an empty string / different message for terminal states. The fix would be in sdk/qrcode/utils/utils.ts.
🤖 Prompt for AI Agents
In `@sdk/qrcode/components/DesktopFooter.tsx` around lines 86 - 89,
getDesktopStatusSubtitle currently returns a static string that is misleading in
terminal states; update getDesktopStatusSubtitle (in sdk/qrcode/utils/utils.ts)
to accept the proofStep parameter (like getDesktopStatusTitle) and return
context-appropriate text: e.g., return a neutral or empty string for
PROOF_VERIFIED and a failure-specific message for PROOF_GENERATION_FAILED,
otherwise return the existing "Verify the proof using the Self mobile app" for
in-progress states; ensure the component call in DesktopFooter passes proofStep
into getDesktopStatusSubtitle.
| import type { SelfApp } from '@selfxyz/sdk-common'; | ||
|
|
||
| import React, { memo } from 'react'; | ||
|
|
||
| import { desktopCardStyle, desktopQrSectionStyle, desktopQrWrapperStyle } from '../utils/styles.js'; | ||
| import DesktopFooter from './DesktopFooter.js'; | ||
| import DesktopHeader from './DesktopHeader.js'; | ||
| import QRCode from './QRCode.js'; |
There was a problem hiding this comment.
Import order is failing CI — pipeline blocker.
The simple-import-sort/imports lint rule requires imports to be sorted. The type import on Line 1 needs to be reordered.
🔧 Suggested fix
-import type { SelfApp } from '@selfxyz/sdk-common';
-
-import React, { memo } from 'react';
-
-import { desktopCardStyle, desktopQrSectionStyle, desktopQrWrapperStyle } from '../utils/styles.js';
-import DesktopFooter from './DesktopFooter.js';
-import DesktopHeader from './DesktopHeader.js';
-import QRCode from './QRCode.js';
+import React, { memo } from 'react';
+
+import type { SelfApp } from '@selfxyz/sdk-common';
+
+import { desktopCardStyle, desktopQrSectionStyle, desktopQrWrapperStyle } from '../utils/styles.js';
+import DesktopFooter from './DesktopFooter.js';
+import DesktopHeader from './DesktopHeader.js';
+import QRCode from './QRCode.js';Note: The exact expected order depends on the project's eslint-plugin-simple-import-sort config. Run yarn lint:imports --fix to auto-fix.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import type { SelfApp } from '@selfxyz/sdk-common'; | |
| import React, { memo } from 'react'; | |
| import { desktopCardStyle, desktopQrSectionStyle, desktopQrWrapperStyle } from '../utils/styles.js'; | |
| import DesktopFooter from './DesktopFooter.js'; | |
| import DesktopHeader from './DesktopHeader.js'; | |
| import QRCode from './QRCode.js'; | |
| import React, { memo } from 'react'; | |
| import type { SelfApp } from '@selfxyz/sdk-common'; | |
| import { desktopCardStyle, desktopQrSectionStyle, desktopQrWrapperStyle } from '../utils/styles.js'; | |
| import DesktopFooter from './DesktopFooter.js'; | |
| import DesktopHeader from './DesktopHeader.js'; | |
| import QRCode from './QRCode.js'; |
🧰 Tools
🪛 GitHub Actions: QRCode SDK CI
[error] 1-1: Run autofix to sort these imports! simple-import-sort/imports
🪛 GitHub Check: quality-checks
[failure] 1-1:
Run autofix to sort these imports!
🤖 Prompt for AI Agents
In `@sdk/qrcode/components/DesktopQRcode.tsx` around lines 1 - 8, The import order
is violating simple-import-sort rules because the type import "SelfApp" is
placed before React and other module imports; reorder imports to match the
project's sorting convention (e.g., move "import type { SelfApp } from
'@selfxyz/sdk-common';" so it falls in the correct group relative to React and
local imports) or run the auto-fix (yarn lint:imports --fix); update the imports
in DesktopQRcode.tsx (references: SelfApp, React, desktopCardStyle,
DesktopFooter, DesktopHeader, QRCode) so the linter passes.
| export const desktopCardStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'center', | ||
| border: '1px solid #E2E8F0', | ||
| borderRadius: '10px', | ||
| backgroundColor: '#FFFFFF', | ||
| overflow: 'hidden', | ||
| width: '373px', | ||
| fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', | ||
| }); | ||
|
|
||
| export const desktopHeaderStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'center', | ||
| gap: '10px', | ||
| paddingTop: '26px', | ||
| paddingLeft: '20px', | ||
| paddingRight: '20px', | ||
| width: '100%', | ||
| boxSizing: 'border-box', | ||
| }); | ||
|
|
||
| export const desktopLogoRowStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| gap: '10px', | ||
| }); | ||
|
|
||
| export const desktopAppLogoStyle = (): React.CSSProperties => ({ | ||
| width: '32px', | ||
| height: '32px', | ||
| borderRadius: '3px', | ||
| objectFit: 'contain', | ||
| }); | ||
|
|
||
| export const desktopSelfLogoContainerStyle = (): React.CSSProperties => ({ | ||
| width: '32px', | ||
| height: '32px', | ||
| borderRadius: '3px', | ||
| backgroundColor: '#000000', | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| overflow: 'hidden', | ||
| }); | ||
|
|
||
| export const desktopSelfLogoImgStyle = (): React.CSSProperties => ({ | ||
| width: '20px', | ||
| height: '20px', | ||
| }); | ||
|
|
||
| export const desktopDescriptionStyle = (): React.CSSProperties => ({ | ||
| fontSize: '16px', | ||
| lineHeight: 'normal', | ||
| color: '#000000', | ||
| textAlign: 'center', | ||
| margin: 0, | ||
| }); | ||
|
|
||
| export const desktopQrSectionStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| padding: '20px 10px', | ||
| width: '100%', | ||
| boxSizing: 'border-box', | ||
| }); | ||
|
|
||
| export const desktopQrWrapperStyle = (step: number): React.CSSProperties => ({ | ||
| display: 'inline-flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'center', | ||
| padding: '10px', | ||
| borderRadius: '10px', | ||
| border: `6px solid ${getDesktopBorderColor(step)}`, | ||
| backgroundColor: '#FFF', | ||
| transition: 'border-color 0.3s ease', | ||
| }); | ||
|
|
||
| export const desktopFooterStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| gap: '6px', | ||
| width: '100%', | ||
| padding: '20px', | ||
| borderTop: '1px solid #E2E8F0', | ||
| boxSizing: 'border-box', | ||
| }); | ||
|
|
||
| export const desktopStepStyle = (): React.CSSProperties => ({ | ||
| backgroundColor: '#F8FAFC', | ||
| borderRadius: '5px', | ||
| padding: '6px 10px', | ||
| width: '100%', | ||
| boxSizing: 'border-box', | ||
| }); | ||
|
|
||
| export const desktopStepInnerStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| gap: '10px', | ||
| padding: '8px 0', | ||
| width: '100%', | ||
| }); | ||
|
|
||
| export const desktopStepIconStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| width: '26px', | ||
| height: '26px', | ||
| flexShrink: 0, | ||
| }); | ||
|
|
||
| export const desktopStepTextStyle = (): React.CSSProperties => ({ | ||
| fontSize: '14px', | ||
| lineHeight: 'normal', | ||
| color: '#0F172A', | ||
| }); | ||
|
|
||
| export const desktopStatusFooterStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| width: '100%', | ||
| padding: '20px', | ||
| borderTop: '1px solid #E2E8F0', | ||
| boxSizing: 'border-box', | ||
| }); | ||
|
|
||
| export const desktopStatusCardStyle = (): React.CSSProperties => ({ | ||
| backgroundColor: '#F8FAFC', | ||
| borderRadius: '5px', | ||
| padding: '6px 10px', | ||
| width: '100%', | ||
| boxSizing: 'border-box', | ||
| }); | ||
|
|
||
| export const desktopStatusContentStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'center', | ||
| gap: '10px', | ||
| padding: '8px 0', | ||
| }); | ||
|
|
||
| export const desktopStatusIconStyle = (): React.CSSProperties => ({ | ||
| width: '34px', | ||
| height: '34px', | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| }); | ||
|
|
||
| export const desktopStatusTextStyle = (): React.CSSProperties => ({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| gap: '6px', | ||
| alignItems: 'center', | ||
| width: '100%', | ||
| textAlign: 'center', | ||
| }); | ||
|
|
||
| export const desktopStatusTitleStyle = (): React.CSSProperties => ({ | ||
| fontSize: '18px', | ||
| fontWeight: 500, | ||
| color: '#000000', | ||
| margin: 0, | ||
| }); | ||
|
|
||
| export const desktopStatusSubtitleStyle = (): React.CSSProperties => ({ | ||
| fontSize: '14px', | ||
| color: '#94A3B8', | ||
| margin: 0, | ||
| }); |
There was a problem hiding this comment.
Static analysis reports export ordering failures — this is blocking the pipeline.
The quality-checks CI step flags that exported desktop style functions are not in the expected sorted order (e.g., desktopCardStyle before qrWrapperStyle, desktopFooterStyle before desktopQrWrapperStyle, etc.). Please re-sort the exports to match the project's lint rules.
🧰 Tools
🪛 GitHub Check: quality-checks
[failure] 192-192:
Expected desktopStatusFooterStyle before desktopStepTextStyle
[failure] 177-177:
Expected desktopStepIconStyle before desktopStepInnerStyle
[failure] 169-169:
Expected desktopStepInnerStyle before desktopStepStyle
[failure] 151-151:
Expected desktopFooterStyle before desktopQrWrapperStyle
[failure] 122-122:
Expected desktopDescriptionStyle before desktopSelfLogoImgStyle
[failure] 99-99:
Expected desktopAppLogoStyle before desktopLogoRowStyle
[failure] 69-69:
Expected desktopCardStyle before qrWrapperStyle
🤖 Prompt for AI Agents
In `@sdk/qrcode/utils/styles.ts` around lines 69 - 245, Reorder the exported
desktop style functions so they match the project's expected export ordering
(alphabetical by export name) to satisfy the quality-checks CI; locate the
functions such as desktopAppLogoStyle, desktopCardStyle,
desktopDescriptionStyle, desktopFooterStyle, desktopHeaderStyle,
desktopLogoRowStyle, desktopQrSectionStyle, desktopQrWrapperStyle,
desktopSelfLogoContainerStyle, desktopSelfLogoImgStyle, desktopStepIconStyle,
desktopStepInnerStyle, desktopStepStyle, desktopStepTextStyle,
desktopStatusFooterStyle, desktopStatusCardStyle, desktopStatusContentStyle,
desktopStatusIconStyle, desktopStatusTextStyle, desktopStatusTitleStyle, and
desktopStatusSubtitleStyle and rearrange their export declarations into the
correct sorted order.
| export const getDesktopStatusTitle = (proofStep: number): string => { | ||
| switch (proofStep) { | ||
| case QRcodeSteps.MOBILE_CONNECTED: | ||
| case QRcodeSteps.PROOF_GENERATION_STARTED: | ||
| case QRcodeSteps.PROOF_GENERATED: | ||
| return 'Connecting to Self'; | ||
| case QRcodeSteps.PROOF_VERIFIED: | ||
| return 'Proof Verified'; | ||
| case QRcodeSteps.PROOF_GENERATION_FAILED: | ||
| return 'Proof Failed'; | ||
| default: | ||
| return 'An error occurred'; | ||
| } |
There was a problem hiding this comment.
PROOF_GENERATED step mapped to "Connecting to Self" seems semantically incorrect.
In getStatusText (Line 67-68), PROOF_GENERATED returns "Proof Generated", but here it falls through to "Connecting to Self". Once the proof is generated, the user isn't really "connecting" anymore. This could confuse users during the desktop flow. Was this intentional, or should PROOF_GENERATED have its own label (e.g., "Proof Generated") before the verified state?
🤖 Prompt for AI Agents
In `@sdk/qrcode/utils/utils.ts` around lines 42 - 54, The desktop title mapping in
getDesktopStatusTitle incorrectly groups QRcodeSteps.PROOF_GENERATED with the
"Connecting to Self" states; update getDesktopStatusTitle so
QRcodeSteps.PROOF_GENERATED has its own case that returns "Proof Generated"
(matching getStatusText) instead of falling through to "Connecting to Self",
ensuring consistency between getDesktopStatusTitle and getStatusText.
Release to Staging v2.9.16 - 2026-02-12
Release to Staging v2.9.16 - 2026-02-16
Release to Staging v2.9.16 - 2026-02-16
Release to Staging v2.9.16 - 2026-02-16
Release to Production v2.9.15 - 2026-02-15
Release to Staging v2.9.16 - 2026-02-20
Release to Production v2.9.16 - 2026-02-22
…de-desktop-variant
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 19414827 | Triggered | Generic Password | 12bdd72 | packages/mobile-sdk-alpha/ios/Frameworks/NFCPassportReader.xcframework/ios-arm64/NFCPassportReader.framework/Modules/NFCPassportReader.swiftmodule/arm64-apple-ios.swiftinterface | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
…e-desktop-variant
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/core-sdk-ci.yml (1)
151-152:⚠️ Potential issue | 🟠 MajorMissing CI fast-fail check for nested require() patterns before test execution.
The test job runs tests without first validating for nested
require()patterns that can cause out-of-memory pipeline failures. Theqrcode-sdk-ci.ymlworkflow correctly implements this check before running tests.🛡️ Proposed fix: Add nested require() check before tests
yarn workspace `@selfxyz/common` build yarn workspace `@selfxyz/core` build + - name: Check for nested require() in tests + run: | + # Check SDK tests for nested require patterns that cause OOM + if grep -rE "require\(['\"]react(-native)?['\"])" sdk/core/src/ sdk/core/tests/ 2>/dev/null; then + echo "❌ Found nested require() patterns that cause OOM in CI" + exit 1 + fi + echo "✅ No nested require() patterns found" - name: Run tests run: yarn workspace `@selfxyz/core` testBased on learnings: "Add a CI fast-fail check step that runs the validation script to detect nested require() patterns before test execution to prevent out-of-memory pipeline failures"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/core-sdk-ci.yml around lines 151 - 152, Insert a new CI step immediately before the existing step named "Run tests" to run the nested require() validation script (the same fast-fail check used in qrcode-sdk-ci.yml) and cause the job to fail on non-zero exit; specifically, add a step that invokes the validation command (e.g., the repo's validation script that detects nested require patterns) so the test job performs the fast-fail nested-require check before executing the "@selfxyz/core test" step.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In @.github/workflows/core-sdk-ci.yml:
- Around line 151-152: Insert a new CI step immediately before the existing step
named "Run tests" to run the nested require() validation script (the same
fast-fail check used in qrcode-sdk-ci.yml) and cause the job to fail on non-zero
exit; specifically, add a step that invokes the validation command (e.g., the
repo's validation script that detects nested require patterns) so the test job
performs the fast-fail nested-require check before executing the "@selfxyz/core
test" step.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.github/workflows/circuits.yml.github/workflows/contracts.yml.github/workflows/core-sdk-ci.yml.github/workflows/qrcode-sdk-ci.yml



Summary
variant="desktop"prop toSelfQRcodecomponent that renders a card-style layout with app branding, instruction steps, and proof status feedbackDesktopQRcode,DesktopHeader,DesktopFooter, and PNG-based icon set.pngloader support in tsup config and TypeScript declarations@selfxyz/qrcodeversion to 1.0.19Test plan
<SelfQRcode variant="desktop" />renders the card layout with header, QR code, and instruction stepsvariant="hybrid"still renders the original QR code layout unchangednpm run build🤖 Generated with Claude Code
Note
Low Risk
Primarily additive UI/packaging changes gated behind a new optional
variantprop; main risk is minor build/bundling regressions due to new PNG asset handling.Overview
Adds a new
variant="desktop"prop toSelfQRcode(defaulting tohybrid) that swaps the existing QR wrapper/status banner for a new card-styleDesktopQRcodelayout.The desktop variant introduces new header/footer components with app branding, step-by-step instructions, and proof-status feedback (icon/title/subtitle) along with dedicated desktop styling and border color logic per
QRcodeSteps.Build packaging is updated to support PNG-based icons (new
icons.tsx), including.pngloader support intsupand TypeScript module declarations, and the package version is bumped to1.0.19.Written by Cursor Bugbot for commit 181374a. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
New Features
Chores