-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Program marketplace promo banner + sidebar card #3209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds a Program Marketplace promo flow: a dismissible banner on the partners dashboard, a promo card in the sidebar, animated marketplace logos, a persisted promo-status hook, a Tailwind "float" animation, a minor sidebar style tweak, and updated program-marketplace announcement email content. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
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 |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (3)
apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx (1)
3-73: Sprite-based logos layout and animation look solid; consider minor a11y & style tweaksImplementation is sound: positions, rotation, scaling, and animation are all computed cleanly from
LOGOS, and using a single sprite URL is efficient.Two small, non-blocking suggestions:
- Since these logos are purely decorative, consider hiding the whole block from assistive tech (e.g.
aria-hidden="true"on the outer<div>or arole="presentation"wrapper) to avoid announcing meaningless content.- You could simplify the loop by iterating directly over
LOGOSinstead ofArray(LOGO_COUNT)(e.g.LOGOS.map((logo, index) => ...)), which removes the need to index back into the array inside the map.apps/web/ui/partners/program-marketplace/use-program-marketplace-promo.tsx (1)
3-19: Promo status hook is robust; easy to extend if a “hidden” state is neededThe hook correctly constrains the returned
statusto"banner" | "card"and safely falls back to"banner"if local storage contains an unexpected value, which is nice for forward/backward compatibility.If product later wants the card to be dismissible as well, this structure will extend naturally (e.g. add
"hidden"tomarketplacePromoStatusesand wire new UI to callsetStatus("hidden")), so no changes are required now.apps/web/ui/layout/sidebar/partners-sidebar-nav.tsx (1)
29-35: Confirm intended bottom content behavior across routesWith this change, the sidebar bottom now behaves as:
- On enrolled program pages (
isEnrolledProgramPage === true): only<ProgramHelpSupport />is shown;PayoutStatsis no longer rendered there.- On all other partner pages (e.g.
/programs,/payouts,/messages,/profile):<ProgramMarketplaceCard />is shown above<PayoutStats />.If the goal is to always keep payout stats visible, even on program detail pages, you may want to render both
ProgramHelpSupportandPayoutStatsin the enrolled branch, or movePayoutStatsoutside the conditional. If this split is intentional, the current structure is fine.Also applies to: 327-361
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/page-client.tsx(2 hunks)apps/web/tailwind.config.ts(2 hunks)apps/web/ui/layout/sidebar/partners-sidebar-nav.tsx(2 hunks)apps/web/ui/layout/sidebar/payout-stats.tsx(1 hunks)apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx(1 hunks)apps/web/ui/partners/program-marketplace/program-marketplace-card.tsx(1 hunks)apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx(1 hunks)apps/web/ui/partners/program-marketplace/use-program-marketplace-promo.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-details-form.tsx:180-189
Timestamp: 2025-09-24T15:50:16.414Z
Learning: TWilson023 prefers to keep security vulnerability fixes separate from refactoring PRs when the vulnerable code is existing and was only moved/relocated rather than newly introduced.
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx
📚 Learning: 2025-10-15T01:05:43.266Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx:432-457
Timestamp: 2025-10-15T01:05:43.266Z
Learning: In apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx, defer refactoring the custom MenuItem component (lines 432-457) to use the shared dub/ui MenuItem component to a future PR, as requested by steven-tey.
Applied to files:
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/page-client.tsx
📚 Learning: 2025-09-24T16:10:37.349Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/ui/partners/partner-about.tsx:11-11
Timestamp: 2025-09-24T16:10:37.349Z
Learning: In the Dub codebase, the team prefers to import Icon as a runtime value from "dub/ui" and uses Icon as both a type and variable name in component props, even when this creates shadowing. This is their established pattern and should not be suggested for refactoring.
Applied to files:
apps/web/ui/layout/sidebar/partners-sidebar-nav.tsx
📚 Learning: 2025-11-24T16:36:36.196Z
Learnt from: CR
Repo: dubinc/dub PR: 0
File: packages/hubspot-app/CLAUDE.md:0-0
Timestamp: 2025-11-24T16:36:36.196Z
Learning: Applies to packages/hubspot-app/app/cards/**/*.{js,jsx,ts,tsx} : Only components exported from the `hubspot/ui-extensions` npm package can be used in card components
Applied to files:
apps/web/ui/layout/sidebar/partners-sidebar-nav.tsxapps/web/ui/partners/program-marketplace/program-marketplace-card.tsx
📚 Learning: 2025-11-24T16:36:36.196Z
Learnt from: CR
Repo: dubinc/dub PR: 0
File: packages/hubspot-app/CLAUDE.md:0-0
Timestamp: 2025-11-24T16:36:36.196Z
Learning: Applies to packages/hubspot-app/app/cards/**/*.{js,jsx,ts,tsx} : Card components cannot use `window.fetch`; must use `hubspot.fetch` function from `hubspot/ui-extensions` npm package and add URLs to `config.permittedUrls.fetch` in the app component's hsmeta.json
Applied to files:
apps/web/ui/partners/program-marketplace/program-marketplace-card.tsx
📚 Learning: 2025-07-09T20:52:56.592Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.592Z
Learning: In apps/web/ui/partners/design/previews/lander-preview.tsx, the ellipsis wave animation delay calculation `3 - i * -0.15` is intentionally designed to create negative delays that offset each dot's animation cycle. This pattern works correctly for the intended ellipsis effect and should not be changed to positive incremental delays.
Applied to files:
apps/web/tailwind.config.ts
🧬 Code graph analysis (3)
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx (4)
apps/web/ui/partners/program-marketplace/use-program-marketplace-promo.tsx (1)
useProgramMarketplacePromo(6-20)apps/web/lib/network/get-discoverability-requirements.ts (1)
partnerCanViewMarketplace(34-51)apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx (1)
ProgramMarketplaceLogos(32-74)packages/ui/src/button.tsx (1)
buttonVariants(7-28)
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/page-client.tsx (1)
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx (1)
ProgramMarketplaceBanner(13-105)
apps/web/ui/layout/sidebar/partners-sidebar-nav.tsx (2)
apps/web/ui/partners/program-marketplace/program-marketplace-card.tsx (1)
ProgramMarketplaceCard(13-76)apps/web/ui/layout/sidebar/payout-stats.tsx (1)
PayoutStats(19-97)
🔇 Additional comments (3)
apps/web/ui/layout/sidebar/payout-stats.tsx (1)
26-29: Visual-only border tone change looks goodSwitching to
border-border-subtlekeeps structure intact and aligns with the softer border treatment used elsewhere. No behavioral impact.apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/page-client.tsx (1)
6-24: Banner integration into programs page is straightforward and safeImporting and rendering
<ProgramMarketplaceBanner />at the top ofPageWidthWrappercleanly composes the promo without touching enrollment fetching or list logic; visibility is fully controlled inside the banner component.apps/web/tailwind.config.ts (1)
18-35: Float animation matches logo usage and is well-scopedThe new
"float"animation and keyframes are self-contained, reuse the existing custom-property pattern (var(--r, 5%)), and line up with theanimate-floatclass used inProgramMarketplaceLogos. No issues with the transform sequence from a CSS standpoint.Also applies to: 84-98
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx (1)
86-102: Fix misleading comment and consider accessibility for icon-only buttons.
The comment on line 86 says
> mobile close buttonbut this button is the desktop version (hidden sm:flex). The mobile button is correctly labeled below.Both icon-only close buttons lack accessible names. Screen reader users won't know what these buttons do.
{/* > mobile close button */} + {/* Desktop close button */} <Button variant="outline" icon={<X className="size-4" />} className="hidden size-8 rounded-lg bg-black/5 p-0 hover:bg-black/10 sm:flex" onClick={() => setStatus("card")} + aria-label="Dismiss banner" /> </div> </div> {/* Mobile close button */} <Button variant="outline" icon={<X className="size-4" />} className="absolute right-2 top-2 size-8 rounded-lg bg-black/5 p-0 hover:bg-black/10 sm:hidden" onClick={() => setStatus("card")} + aria-label="Dismiss banner" />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx(1 hunks)apps/web/ui/partners/program-marketplace/program-marketplace-card.tsx(1 hunks)apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/ui/partners/program-marketplace/program-marketplace-card.tsx
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-details-form.tsx:180-189
Timestamp: 2025-09-24T15:50:16.414Z
Learning: TWilson023 prefers to keep security vulnerability fixes separate from refactoring PRs when the vulnerable code is existing and was only moved/relocated rather than newly introduced.
📚 Learning: 2025-07-30T15:29:54.131Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/rewards-logic.tsx:268-275
Timestamp: 2025-07-30T15:29:54.131Z
Learning: In apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward condition, dependent fields (attribute, operator, value) should be reset rather than preserved because different entities (customer vs sale) have different available attributes. Maintaining existing fields when the entity changes would create invalid state combinations and confusing UX.
Applied to files:
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx
📚 Learning: 2025-11-12T22:23:10.414Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 3098
File: apps/web/lib/actions/partners/message-program.ts:49-58
Timestamp: 2025-11-12T22:23:10.414Z
Learning: In apps/web/lib/actions/partners/message-program.ts, when checking if a partner can continue messaging after messaging is disabled, the code intentionally requires `senderPartnerId: null` (program-initiated messages) to prevent partners from continuing to send junk messages. Only conversations started by the program should continue after messaging is disabled, as a spam prevention mechanism.
Applied to files:
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx
📚 Learning: 2025-10-15T01:52:37.048Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx:270-303
Timestamp: 2025-10-15T01:52:37.048Z
Learning: In React components with dropdowns or form controls that show modals for confirmation (e.g., role selection, delete confirmation), local state should be reverted to match the prop value when the modal is cancelled. This prevents the UI from showing an unconfirmed change. The solution is to either: (1) pass an onClose callback to the modal that resets the local state, or (2) observe modal visibility state and reset on close. Example context: RoleCell component in apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/members/page-client.tsx where role dropdown should revert to user.role when UpdateUserModal is cancelled.
Applied to files:
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx
📚 Learning: 2025-11-24T09:10:12.536Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3089
File: apps/web/lib/api/fraud/fraud-rules-registry.ts:17-25
Timestamp: 2025-11-24T09:10:12.536Z
Learning: In apps/web/lib/api/fraud/fraud-rules-registry.ts, the fraud rules `partnerCrossProgramBan` and `partnerDuplicatePayoutMethod` intentionally have stub implementations that return `{ triggered: false }` because they are partner-scoped rules handled separately during partner application/onboarding flows (e.g., in detect-record-fraud-application.ts), rather than being evaluated per conversion event like other rules in the registry. The stubs exist only to satisfy the `Record<FraudRuleType, ...>` type constraint.
Applied to files:
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx
🧬 Code graph analysis (1)
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx (5)
apps/web/lib/swr/use-partner-profile.ts (1)
usePartnerProfile(6-30)apps/web/ui/partners/program-marketplace/use-program-marketplace-promo.tsx (1)
useProgramMarketplacePromo(6-20)apps/web/lib/network/get-discoverability-requirements.ts (1)
partnerCanViewMarketplace(34-51)apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx (1)
ProgramMarketplaceLogos(32-73)packages/ui/src/button.tsx (1)
buttonVariants(7-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (5)
apps/web/ui/partners/program-marketplace/program-marketplace-logos.tsx (2)
4-29: LGTM on the logo configuration data structure.The layout configuration is clean and well-organized. Minor note: the comments on lines 13 and 21 (
// S?and// X?) suggest uncertainty about which logos these represent. Consider clarifying these comments for future maintainability, or removing them if the specific identity doesn't matter.
32-73: Well-structured decorative component.The animation staggering with alternating directions creates visual interest. The sprite sheet approach is efficient for loading multiple logos.
One consideration: if the sprite image fails to load, users will see empty boxes. You might want to add a background color fallback or ensure the parent handles this gracefully, though for a promotional element this is likely acceptable.
apps/web/ui/partners/program-marketplace/program-marketplace-banner.tsx (3)
14-24: Previous issue resolved: visibility gating now correct.The
partnerCanViewMarketplace({ partner, programEnrollments })call now matches the expected function signature. Good fix!
37-50: Visually appealing background treatment.The layered gradient and grid pattern create a polished promotional appearance. The mask-image fade is a nice touch for the grid.
52-84: Good responsive layout and accessibility consideration.The
titleattribute on the truncated text (line 64) is a nice touch for users who hover. The CTA is clear and the link destination is appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/email/src/templates/program-marketplace-announcement.tsx(5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-details-form.tsx:180-189
Timestamp: 2025-09-24T15:50:16.414Z
Learning: TWilson023 prefers to keep security vulnerability fixes separate from refactoring PRs when the vulnerable code is existing and was only moved/relocated rather than newly introduced.
🧬 Code graph analysis (1)
packages/email/src/templates/program-marketplace-announcement.tsx (1)
packages/email/src/react-email.d.ts (7)
Preview(18-18)Img(13-13)Hr(17-17)Section(8-8)Link(14-14)Heading(16-16)Text(15-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (4)
packages/email/src/templates/program-marketplace-announcement.tsx (4)
7-7: LGTM!The
Hrimport is correctly added and used as a visual divider between the marketplace and payouts sections.
94-94: LGTM!The marketplace link is consistently updated to match the link at Line 64, maintaining uniformity across the email template.
111-159: Both $10M payouts announcement URLs are live and accessible.The announcement link (
https://ship.dub.co/10m-x) and image asset (https://assets.dub.co/cms/10m-payouts.jpg) are both returning HTTP 200. The section maintains consistent styling with the marketplace announcement above it, includes proper alt text for the image, and responsive design is preserved.
64-68: The updated marketplace link and image URLs are correctly configured and accessible.The marketplace link has been migrated from
partners.dub.co/programs/marketplacetoship.dub.co/marketplace, and the header image from an animated GIF to a static JPG atassets.dub.co/misc/program-marketplace-email-header.jpg. Both new URLs return HTTP 200 status and are functioning properly.
Summary by CodeRabbit
New Features
Style
Content
✏️ Tip: You can customize this high-level summary in your review settings.