feat: add Bridge LPT menu option#705
Conversation
Add a "Bridge LPT" entry to the desktop nav popover (new-window link) and mobile drawer (embedded bridge.arbitrum.io iframe modal), letting users bridge LPT from Ethereum to Arbitrum One. Rename LlamaswapModal -> EmbedModal since it now hosts both the DefiLlama swap and the Arbitrum bridge embeds. Closes #704 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Adds a Bridge LPT entry to the app’s navigation so users can move L1 (Ethereum) LPT to Arbitrum One (staking network), matching the existing “Get LPT” behavior across desktop (new window link) and mobile (embedded modal).
Changes:
- Add “Bridge LPT” external link to the desktop “More” popover menu.
- Rename the shared embed dialog component to
EmbedModal. - Add “Bridge LPT” embedded iframe modal entry in the mobile drawer.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| layouts/main.tsx | Adds a “Bridge LPT” popover item that opens the Arbitrum bridge in a new window. |
| components/EmbedModal/index.tsx | Renames the generic embed dialog component to EmbedModal (default export). |
| components/Drawer/index.tsx | Replaces LlamaswapModal usage with EmbedModal and adds a new “Bridge LPT” embedded bridge modal. |
Comments suppressed due to low confidence (1)
components/Drawer/index.tsx:168
- The modal trigger is rendered as
Linkstyled component withas={Text}, which likely results in a non-interactive element (e.g.span) and makes the dialog inaccessible to keyboard users. Use a realbuttonelement (while keeping the same styling) so it is focusable and activates on Enter/Space.
<A
as={Text}
css={{
cursor: "pointer",
fontSize: "$2",
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Warning Review limit reached
More reviews will be available in 8 minutes and 6 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe PR renames ChangesBridge LPT Navigation Feature
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
components/Drawer/index.tsx (2)
178-186:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEmbedded third-party iframes are missing isolation attributes
Problem: On Line 178 and Line 205, external iframes are embedded without
sandboxand withoutreferrerPolicy(and notitle).Why it matters: Unsandboxed third-party content has broader capabilities than needed and increases security/privacy risk if the remote page is compromised or changes behavior.
Suggested fix: Add a restrictive
sandboxpolicy (allow only required capabilities),referrerPolicy="no-referrer"(or project standard), and a descriptivetitlefor each iframe.Also applies to: 205-213
🤖 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 `@components/Drawer/index.tsx` around lines 178 - 186, The iframe elements embedded in this component lack essential security and accessibility attributes. For each iframe element (including both occurrences in the file), add a restrictive sandbox attribute that permits only necessary capabilities (such as sandbox="allow-same-origin allow-scripts"), add referrerPolicy="no-referrer" to protect user privacy, and add a descriptive title attribute for accessibility. Apply these attributes to all iframe elements to prevent unsandboxed third-party content from having broader capabilities than needed and to reduce security and privacy risks if the remote content is compromised.
162-175:⚠️ Potential issue | 🟠 MajorUse an interactive element for modal triggers
Problem: Lines 164–175 and 191–201 use
<A as={Text}>forDialogTrigger asChild. This likely renders as a non-interactive element that cannot be keyboard-activated, breaking modal access for keyboard users. OtherDialogTrigger asChildusages in the codebase (e.g.,Search/index.tsx,EditProfile/index.tsx) correctly useButtonorIconButton.Why it matters: Keyboard users and screen reader users cannot open the "Get LPT" and "Bridge LPT" modals—a core accessibility failure.
Suggested fix: Replace
<A as={Text}>with<Button>or<A>(without theas={Text}override) soDialogTrigger asChildreceives a proper interactive element.🤖 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 `@components/Drawer/index.tsx` around lines 162 - 175, The EmbedModal and other DialogTrigger components are using `<A as={Text}>` as their trigger element, which renders as non-interactive text and blocks keyboard and screen reader access. Replace the `<A as={Text}>` elements used as triggers for the "Get LPT" and "Bridge LPT" modals with either `<Button>` or just `<A>` without the `as={Text}` prop override, so that DialogTrigger asChild receives a proper interactive element that supports keyboard activation and accessibility.
🤖 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.
Inline comments:
In `@layouts/main.tsx`:
- Around line 737-740: Extract the hardcoded Bridge URL that appears in the
PopoverLink component (the URL with
destinationChain=arbitrum-one&sourceChain=ethereum&token=0x58b6a8a3302369daec383334672404ee733ab239)
into a shared constant, such as BRIDGE_LPT_URL, in a common constants or config
module. Then replace the hardcoded URL string in the PopoverLink href attribute
with a reference to this constant. Additionally, locate the same hardcoded URL
in the Drawer component and replace it with the same shared constant reference
to ensure both locations stay in sync.
---
Outside diff comments:
In `@components/Drawer/index.tsx`:
- Around line 178-186: The iframe elements embedded in this component lack
essential security and accessibility attributes. For each iframe element
(including both occurrences in the file), add a restrictive sandbox attribute
that permits only necessary capabilities (such as sandbox="allow-same-origin
allow-scripts"), add referrerPolicy="no-referrer" to protect user privacy, and
add a descriptive title attribute for accessibility. Apply these attributes to
all iframe elements to prevent unsandboxed third-party content from having
broader capabilities than needed and to reduce security and privacy risks if the
remote content is compromised.
- Around line 162-175: The EmbedModal and other DialogTrigger components are
using `<A as={Text}>` as their trigger element, which renders as non-interactive
text and blocks keyboard and screen reader access. Replace the `<A as={Text}>`
elements used as triggers for the "Get LPT" and "Bridge LPT" modals with either
`<Button>` or just `<A>` without the `as={Text}` prop override, so that
DialogTrigger asChild receives a proper interactive element that supports
keyboard activation and accessibility.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: b9771bbd-de5e-4786-84fe-a546e0390f55
📒 Files selected for processing (3)
components/Drawer/index.tsxcomponents/EmbedModal/index.tsxlayouts/main.tsx
- Add title attributes to the Get LPT / Bridge LPT iframes. - Render modal triggers as real buttons so they are keyboard-focusable. - Extract the swap/bridge URLs into constants/links.ts to keep the desktop and mobile surfaces in sync. - Use portal.arbitrum.io for the bridge link (the embeddable Arbitrum portal; the earlier framing concern was a Cloudflare bot-challenge artifact, not the real app's headers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-Authored-By: Copilot <copilot@github.com> Co-Authored-By: coderabbitai[bot] <coderabbitai[bot]@users.noreply.github.com>
Summary
Adds a Bridge LPT option to the navigation menu, giving users an in-app path to move L1 (Ethereum) LPT to Arbitrum One, where staking happens. It sits alongside the existing Get LPT option and mirrors its behaviour:
The bridge URL pre-fills the LPT token and the Ethereum → Arbitrum One route:
https://bridge.arbitrum.io/?destinationChain=arbitrum-one&sourceChain=ethereum&token=0x58b6a8a3302369daec383334672404ee733ab239bridge.arbitrum.iosets noX-Frame-Options/frame-blocking CSP, so it embeds cleanly (verified locally). Note thatportal.arbitrum.io/bridgedoes block framing — this usesbridge.arbitrum.io.Cleanup
The shared modal
LlamaswapModalnow hosts both the DefiLlama swap and the Arbitrum bridge embeds, so it's renamed to a neutralEmbedModal.Testing
Closes #704
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Refactor