Skip to content

feat: add clipboard paste shortcut with Stellar address validation to…#36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGit avatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes #3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit avatGit requested a review from MJ-RWA as a code owner June 22, 2026 23:19
@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s) Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check ✅ Passed All core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
           <AddressInput 
             value={destination} 
             onChange={setDestination} 
             placeholder="G..."
             className="font-mono text-sm"
-          />           
-           </div>
+          />
+        </div>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
     } catch (error) {
-      //
       toast.error("Clipboard access permission denied");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
     } catch (error) {
-      toast.error("Clipboard access permission denied");
+      toast.error("Unable to access clipboard");
       console.error("Clipboard Error: ", error);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.

In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue #1 — Add clipboard paste button on address input fields

1 participant