Conversation
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
📝 WalkthroughWalkthroughReplaces the single onboarding flow with a dual payout model (stablecoin vs bank account) in docs, adds autoplay-disable on user interaction to the image carousel component, and adds search and payout-method filtering to the supported-countries component. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
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: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@help/article/receiving-payouts.mdx`:
- Line 221: The sentence "Unlike platforms like [PartnerStack]..., where you
have to manually withdraw your earnings to your bank account – you do not need
to manually withdraw your earnings on Dub." uses bank-specific wording; update
it to be payout-method-neutral by replacing "bank account" with "connected
payout method" (or add a clarifying parenthetical like "(e.g., bank account or
stablecoin wallet)") and ensure any follow-up FAQ answers use "connected payout
method" instead of "bank" unless the text is specifically scoped to bank
payouts; look for this exact sentence in receiving-payouts.mdx and update the
wording accordingly.
- Around line 14-19: The "Fees" cell for the "Bank account" column currently
states "1% FX conversion fee" unconditionally; update the Fees row in the
comparison table so it matches the later bank-payout note by qualifying it
(e.g., "1% FX conversion fee for international / non‑US payouts; domestic bank
payouts may not incur this fee") so the table's Bank account fee mirrors the
later note about international/non‑US applicability.
- Around line 35-39: Change the incorrect subject-verb agreement in the intro
sentence that currently reads "Stablecoin payouts is the easiest and fastest
way..." to use plural agreement (e.g., "Stablecoin payouts are the easiest and
fastest way..." or rephrase to "Receiving payouts in stablecoins is the easiest
and fastest way..."); update the sentence in help/article/receiving-payouts.mdx
where the exact phrase "Stablecoin payouts is" appears so the copy is
grammatically correct and consistent with the surrounding list items.
In `@snippets/components/image-carousel.jsx`:
- Around line 9-17: The component initializes local state autoplayActive from
the autoplay prop but never syncs it after mount, so toggling autoplay from a
parent won't pause/resume the carousel; fix by making the autoplay prop
authoritative—either remove autoplayActive and reference autoplay directly
inside the useEffect condition, or add a syncing effect that calls
setAutoplayActive(autoplay) whenever the autoplay prop changes; update the
dependency list of the existing useEffect (which uses autoplayActive,
images.length, setCurrentIndex) accordingly to ensure the interval starts/stops
when autoplay changes.
In `@snippets/components/payout-supported-countries.jsx`:
- Around line 54-68: The segmented control rendering PAYOUT_METHODS should
expose its active state to assistive tech: wrap the buttons container (the div
surrounding the map over PAYOUT_METHODS) with role="group" and an appropriate
aria-label (e.g., "Payout method filter"), and add aria-pressed={payoutMethod
=== value} to each button rendered by the map (the elements using
setPayoutMethod and comparing payoutMethod === value) so screen readers can
announce which option is selected.
- Around line 86-101: The flag URL construction calls code.toLowerCase() without
guarding for a missing or non-string code, which can throw when a country row is
malformed; in the displayed.map callback (where displayed.map and the img tag
are defined) add a guard that ensures code is a non-empty string (or falls back
to a safe placeholder like 'unknown' or skips rendering the flag) before calling
code.toLowerCase(), and handle the fallback consistently so the component does
not crash when PAYOUT_METHODS or methods are present but code is invalid.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d5e50b78-8e9c-4a49-aac9-1f8d1bd92cee
⛔ Files ignored due to path filters (10)
images/payouts/connect-bank-account-1.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-2.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-3.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-4.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-5.pngis excluded by!**/*.pngimages/payouts/connect-stablecoin-wallet-1.pngis excluded by!**/*.pngimages/payouts/connect-stablecoin-wallet-2.pngis excluded by!**/*.pngimages/payouts/connect-stablecoin-wallet-3.pngis excluded by!**/*.pngimages/payouts/payout-settings-bank-account.pngis excluded by!**/*.pngimages/payouts/payout-settings-stablecoin.pngis excluded by!**/*.png
📒 Files selected for processing (3)
help/article/receiving-payouts.mdxsnippets/components/image-carousel.jsxsnippets/components/payout-supported-countries.jsx
| Stablecoin payouts is the easiest and fastest way to receive payouts on Dub (especially for non-US partners): | ||
|
|
||
| - **Get paid in USD** – instead of your local currency, you can receive payouts in USDC all around the world | ||
| - **Faster payouts** – payouts are sent within minutes instead of having to wait up to 15 business days for regular bank transfers | ||
| - **Lower fees** – 0.5% transaction fee vs 1% FX conversion fee for international payouts |
There was a problem hiding this comment.
Fix the stablecoin intro grammar.
"Stablecoin payouts is" should be "Stablecoin payouts are" (or equivalent). This is user-facing copy on a top-level docs page.
✏️ Proposed fix
-Stablecoin payouts is the easiest and fastest way to receive payouts on Dub (especially for non-US partners):
+Stablecoin payouts are the easiest and fastest way to receive payouts on Dub (especially for non-US partners):📝 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.
| Stablecoin payouts is the easiest and fastest way to receive payouts on Dub (especially for non-US partners): | |
| - **Get paid in USD** – instead of your local currency, you can receive payouts in USDC all around the world | |
| - **Faster payouts** – payouts are sent within minutes instead of having to wait up to 15 business days for regular bank transfers | |
| - **Lower fees** – 0.5% transaction fee vs 1% FX conversion fee for international payouts | |
| Stablecoin payouts are the easiest and fastest way to receive payouts on Dub (especially for non-US partners): | |
| - **Get paid in USD** – instead of your local currency, you can receive payouts in USDC all around the world | |
| - **Faster payouts** – payouts are sent within minutes instead of having to wait up to 15 business days for regular bank transfers | |
| - **Lower fees** – 0.5% transaction fee vs 1% FX conversion fee for international payouts |
🧰 Tools
🪛 GitHub Check: Mintlify Validation (dub) - vale-spellcheck
[warning] 35-35: help/article/receiving-payouts.mdx#L35
Did you really mean 'Stablecoin'?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@help/article/receiving-payouts.mdx` around lines 35 - 39, Change the
incorrect subject-verb agreement in the intro sentence that currently reads
"Stablecoin payouts is the easiest and fastest way..." to use plural agreement
(e.g., "Stablecoin payouts are the easiest and fastest way..." or rephrase to
"Receiving payouts in stablecoins is the easiest and fastest way..."); update
the sentence in help/article/receiving-payouts.mdx where the exact phrase
"Stablecoin payouts is" appears so the copy is grammatically correct and
consistent with the surrounding list items.
| ### Do I need to manually withdraw my earnings from Dub? | ||
|
|
||
| Unlike platforms like PartnerStack, where you have to manually withdraw your earnings to your bank account – you do not need to manually withdraw your earnings on Dub. | ||
| Unlike platforms like [PartnerStack](https://dub.co/compare/partnerstack), where you have to manually withdraw your earnings to your bank account – you do not need to manually withdraw your earnings on Dub. |
There was a problem hiding this comment.
Use payout-method-neutral wording in the withdrawal FAQs.
This section still says payouts land in a bank account, but the page now documents stablecoin wallets too. Please either scope these answers to bank payouts or rename the destination to the connected payout method where the rule applies to both.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@help/article/receiving-payouts.mdx` at line 221, The sentence "Unlike
platforms like [PartnerStack]..., where you have to manually withdraw your
earnings to your bank account – you do not need to manually withdraw your
earnings on Dub." uses bank-specific wording; update it to be
payout-method-neutral by replacing "bank account" with "connected payout method"
(or add a clarifying parenthetical like "(e.g., bank account or stablecoin
wallet)") and ensure any follow-up FAQ answers use "connected payout method"
instead of "bank" unless the text is specifically scoped to bank payouts; look
for this exact sentence in receiving-payouts.mdx and update the wording
accordingly.
| const [autoplayActive, setAutoplayActive] = useState(autoplay); | ||
|
|
||
| useEffect(() => { | ||
| if (!autoplay || images.length <= 1) return; | ||
| if (!autoplayActive || images.length <= 1) return; | ||
| const interval = setInterval(() => { | ||
| setCurrentIndex((prev) => (prev === images.length - 1 ? 0 : prev + 1)); | ||
| }, 3000); | ||
| return () => clearInterval(interval); | ||
| }, [autoplay, images.length]); | ||
| }, [autoplayActive, images.length]); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In React, does useState(initialProp)resync state wheninitialProp changes after the component mounts?
💡 Result:
No. useState(initialProp) uses initialProp only on the initial render—after the component mounts, that argument is ignored, so later changes to initialProp will not “resync” the state automatically. [1]
If you need state to follow a prop change, you must update it yourself (commonly with an effect), or reset the component (e.g., via a changing key). [2]
Sources
[1] https://react.dev/reference/react/useState
[2] https://stackoverflow.com/questions/54865764/react-usestate-does-not-reload-state-from-props
Keep the autoplay prop authoritative after mount.
autoplayActive is initialized from autoplay on line 9, but useState(initialValue) only reads the prop once at mount. After this change, a parent toggling autoplay later will not pause/resume the carousel, causing a regression in the existing prop API.
💡 Proposed fix
const [currentIndex, setCurrentIndex] = useState(0);
const [autoplayActive, setAutoplayActive] = useState(autoplay);
+ useEffect(() => {
+ setAutoplayActive(autoplay);
+ }, [autoplay]);
+
useEffect(() => {
if (!autoplayActive || images.length <= 1) return;📝 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.
| const [autoplayActive, setAutoplayActive] = useState(autoplay); | |
| useEffect(() => { | |
| if (!autoplay || images.length <= 1) return; | |
| if (!autoplayActive || images.length <= 1) return; | |
| const interval = setInterval(() => { | |
| setCurrentIndex((prev) => (prev === images.length - 1 ? 0 : prev + 1)); | |
| }, 3000); | |
| return () => clearInterval(interval); | |
| }, [autoplay, images.length]); | |
| }, [autoplayActive, images.length]); | |
| const [autoplayActive, setAutoplayActive] = useState(autoplay); | |
| useEffect(() => { | |
| setAutoplayActive(autoplay); | |
| }, [autoplay]); | |
| useEffect(() => { | |
| if (!autoplayActive || images.length <= 1) return; | |
| const interval = setInterval(() => { | |
| setCurrentIndex((prev) => (prev === images.length - 1 ? 0 : prev + 1)); | |
| }, 3000); | |
| return () => clearInterval(interval); | |
| }, [autoplayActive, images.length]); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@snippets/components/image-carousel.jsx` around lines 9 - 17, The component
initializes local state autoplayActive from the autoplay prop but never syncs it
after mount, so toggling autoplay from a parent won't pause/resume the carousel;
fix by making the autoplay prop authoritative—either remove autoplayActive and
reference autoplay directly inside the useEffect condition, or add a syncing
effect that calls setAutoplayActive(autoplay) whenever the autoplay prop
changes; update the dependency list of the existing useEffect (which uses
autoplayActive, images.length, setCurrentIndex) accordingly to ensure the
interval starts/stops when autoplay changes.
| <div className="flex flex-wrap md:flex-nowrap gap-2"> | ||
| {PAYOUT_METHODS.map(({ value, label }) => ( | ||
| <button | ||
| key={value} | ||
| type="button" | ||
| onClick={() => setPayoutMethod(value)} | ||
| className={`rounded-full px-4 py-1.5 text-sm whitespace-nowrap transition-colors ${ | ||
| payoutMethod === value | ||
| ? "bg-neutral-900 text-white dark:bg-neutral-100 dark:text-neutral-900" | ||
| : "border border-neutral-200 bg-white text-neutral-600 hover:bg-neutral-50 hover:text-neutral-900 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:hover:text-neutral-200" | ||
| }`} | ||
| > | ||
| {label} | ||
| </button> | ||
| ))} |
There was a problem hiding this comment.
Expose the active payout filter to assistive tech.
These buttons act like a segmented control, but the selected state is only visual today. Add aria-pressed (and ideally a group label) so screen-reader users can tell which filter is active.
♿ Proposed fix
- <div className="flex flex-wrap md:flex-nowrap gap-2">
+ <div
+ className="flex flex-wrap md:flex-nowrap gap-2"
+ role="group"
+ aria-label="Filter supported countries by payout method"
+ >
{PAYOUT_METHODS.map(({ value, label }) => (
<button
key={value}
type="button"
onClick={() => setPayoutMethod(value)}
+ aria-pressed={payoutMethod === value}
className={`rounded-full px-4 py-1.5 text-sm whitespace-nowrap transition-colors ${🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@snippets/components/payout-supported-countries.jsx` around lines 54 - 68, The
segmented control rendering PAYOUT_METHODS should expose its active state to
assistive tech: wrap the buttons container (the div surrounding the map over
PAYOUT_METHODS) with role="group" and an appropriate aria-label (e.g., "Payout
method filter"), and add aria-pressed={payoutMethod === value} to each button
rendered by the map (the elements using setPayoutMethod and comparing
payoutMethod === value) so screen readers can announce which option is selected.
| {displayed.map(({ code, name, methods = [] }) => { | ||
| const methodLabels = PAYOUT_METHODS.filter((m) => | ||
| methods.includes(m.value), | ||
| ) | ||
| .map((m) => m.label) | ||
| .join(" · "); | ||
| return ( | ||
| <div key={code} className="flex items-start gap-3"> | ||
| <img | ||
| src={`https://hatscripts.github.io/circle-flags/flags/${code.toLowerCase()}.svg`} | ||
| alt={code} | ||
| width={32} | ||
| height={32} | ||
| className="size-5 shrink-0 rounded-full border border-neutral-200 shadow-sm dark:border-neutral-700 mt-0.5" | ||
| draggable={false} | ||
| /> |
There was a problem hiding this comment.
Guard code before building the flag URL.
Line 95 calls code.toLowerCase() on API data, but the filtering logic above already treats code as optional. A single malformed country row will throw here and blank the whole list.
🛡️ Proposed fix
{displayed.map(({ code, name, methods = [] }) => {
+ const normalizedCode =
+ typeof code === "string" && code.length > 0
+ ? code.toLowerCase()
+ : null;
const methodLabels = PAYOUT_METHODS.filter((m) =>
methods.includes(m.value),
)
.map((m) => m.label)
.join(" · ");
return (
- <div key={code} className="flex items-start gap-3">
- <img
- src={`https://hatscripts.github.io/circle-flags/flags/${code.toLowerCase()}.svg`}
- alt={code}
+ <div key={code || name} className="flex items-start gap-3">
+ {normalizedCode ? (
+ <img
+ src={`https://hatscripts.github.io/circle-flags/flags/${normalizedCode}.svg`}
+ alt=""
+ aria-hidden="true"
width={32}
height={32}
className="size-5 shrink-0 rounded-full border border-neutral-200 shadow-sm dark:border-neutral-700 mt-0.5"
draggable={false}
- />
+ />
+ ) : null}
<div className="min-w-0 flex-1">📝 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.
| {displayed.map(({ code, name, methods = [] }) => { | |
| const methodLabels = PAYOUT_METHODS.filter((m) => | |
| methods.includes(m.value), | |
| ) | |
| .map((m) => m.label) | |
| .join(" · "); | |
| return ( | |
| <div key={code} className="flex items-start gap-3"> | |
| <img | |
| src={`https://hatscripts.github.io/circle-flags/flags/${code.toLowerCase()}.svg`} | |
| alt={code} | |
| width={32} | |
| height={32} | |
| className="size-5 shrink-0 rounded-full border border-neutral-200 shadow-sm dark:border-neutral-700 mt-0.5" | |
| draggable={false} | |
| /> | |
| {displayed.map(({ code, name, methods = [] }) => { | |
| const normalizedCode = | |
| typeof code === "string" && code.length > 0 | |
| ? code.toLowerCase() | |
| : null; | |
| const methodLabels = PAYOUT_METHODS.filter((m) => | |
| methods.includes(m.value), | |
| ) | |
| .map((m) => m.label) | |
| .join(" · "); | |
| return ( | |
| <div key={code || name} className="flex items-start gap-3"> | |
| {normalizedCode ? ( | |
| <img | |
| src={`https://hatscripts.github.io/circle-flags/flags/${normalizedCode}.svg`} | |
| alt="" | |
| aria-hidden="true" | |
| width={32} | |
| height={32} | |
| className="size-5 shrink-0 rounded-full border border-neutral-200 shadow-sm dark:border-neutral-700 mt-0.5" | |
| draggable={false} | |
| /> | |
| ) : null} | |
| <div className="min-w-0 flex-1"> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@snippets/components/payout-supported-countries.jsx` around lines 86 - 101,
The flag URL construction calls code.toLowerCase() without guarding for a
missing or non-string code, which can throw when a country row is malformed; in
the displayed.map callback (where displayed.map and the img tag are defined) add
a guard that ensures code is a non-empty string (or falls back to a safe
placeholder like 'unknown' or skips rendering the flag) before calling
code.toLowerCase(), and handle the fallback consistently so the component does
not crash when PAYOUT_METHODS or methods are present but code is invalid.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (6)
help/article/receiving-payouts.mdx (3)
35-35:⚠️ Potential issue | 🟡 MinorFix the stablecoin intro grammar.
“Stablecoin payouts is” should be plural here.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@help/article/receiving-payouts.mdx` at line 35, The sentence "Stablecoin payouts is the easiest and fastest way to receive payouts on Dub (especially for non-US partners):" uses a singular verb with a plural subject; change it to "Stablecoin payouts are the easiest and fastest way to receive payouts on Dub (especially for non-US partners):" to fix the grammar and ensure subject-verb agreement (locate the exact sentence starting "Stablecoin payouts is..." in receiving-payouts.mdx).
221-227:⚠️ Potential issue | 🟠 MajorUse payout-method-neutral wording in the withdrawal FAQs.
This section still says earnings are withdrawn or deposited to a bank account, which excludes the stablecoin flow introduced above. Use “connected payout method” unless the answer is intentionally bank-only.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@help/article/receiving-payouts.mdx` around lines 221 - 227, Update the payout wording to be payout-method-neutral: replace instances of "bank account", "withdrawn", and "deposited into your connected bank account" with "connected payout method" or "connected payout method (e.g., bank account or stablecoin)" in the FAQ section under the heading "What is the minimum withdrawal amount, and how does it work?" and the preceding paragraph comparing PartnerStack; ensure the sentence about automated payouts reads that earnings/payouts are "automatically sent to your connected payout method" and keep the $10 minimum wording intact.
14-19:⚠️ Potential issue | 🟠 MajorMake the bank-fee row match the later bank-payout note.
The table still states a 1% FX fee unconditionally, but Line 93 scopes that fee to international / non-US bank payouts. Please make these two sections consistent.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@help/article/receiving-payouts.mdx` around lines 14 - 19, Update the "Fees" row in the table so it matches the bank-payout note: change the bank account cell from an unconditional "1% FX conversion fee" to a scoped description such as "1% FX conversion fee (applies to international/non‑US bank payouts)" or add a parenthetical/link that points to the same bank-payout note referenced by the Supported countries anchor; modify the table's "Fees" row text accordingly so the wording for bank account fees is consistent with the bank-payout note.snippets/components/payout-supported-countries.jsx (2)
24-35:⚠️ Potential issue | 🟠 MajorNormalize API fields before using them in search and rendering.
The new filter assumes
nameandcodeare strings, and the row renderer still assumesmethodsis an array pluscodeis present. A single malformed country record can throw here and blank the whole widget.🛡️ Suggested hardening
const filtered = useMemo(() => { const q = searchQuery.trim().toLowerCase(); return countries.filter((c) => { + const name = typeof c.name === "string" ? c.name : ""; + const code = typeof c.code === "string" ? c.code : ""; + const methods = Array.isArray(c.methods) ? c.methods : []; const matchesSearch = !q || - (c.name || "").toLowerCase().includes(q) || - (c.code || "").toLowerCase().includes(q); - const methods = Array.isArray(c.methods) ? c.methods : []; + name.toLowerCase().includes(q) || + code.toLowerCase().includes(q); const matchesMethod = payoutMethod === "all" || methods.includes(payoutMethod); return matchesSearch && matchesMethod; @@ - {displayed.map(({ code, name, methods = [] }) => { - const methodLabels = PAYOUT_METHODS.filter((m) => - methods.includes(m.value), + {displayed.map(({ code, name, methods }) => { + const normalizedCode = + typeof code === "string" && code.length > 0 + ? code.toLowerCase() + : null; + const normalizedMethods = Array.isArray(methods) ? methods : []; + const methodLabels = PAYOUT_METHODS.filter((m) => + normalizedMethods.includes(m.value), ) .map((m) => m.label) .join(" · "); return ( - <div key={code} className="flex items-start gap-3"> - <img - src={`https://hatscripts.github.io/circle-flags/flags/${code.toLowerCase()}.svg`} - alt={code} + <div key={code || name} className="flex items-start gap-3"> + {normalizedCode ? ( + <img + src={`https://hatscripts.github.io/circle-flags/flags/${normalizedCode}.svg`} + alt="" + aria-hidden="true" width={32} height={32} className="size-5 shrink-0 rounded-full border border-neutral-200 shadow-sm dark:border-neutral-700 mt-0.5" draggable={false} - /> + /> + ) : null}Also applies to: 86-101
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/components/payout-supported-countries.jsx` around lines 24 - 35, The filter assumes country objects always have safe name/code/methods fields; normalize those fields first to avoid crashing on malformed records: inside the useMemo (and likewise in the row renderer referenced around lines 86-101) coerce c.name and c.code to strings (e.g., const name = String(c.name || "") and const code = String(c.code || "")) and ensure methods is an array (const methods = Array.isArray(c.methods) ? c.methods : []), then use name, code, and methods for searching and rendering instead of accessing c.name/c.code/c.methods directly; update references in the filtered computation and the row rendering to use these normalized variables.
54-68:⚠️ Potential issue | 🟡 MinorExpose the active payout filter to assistive tech.
The selected state is still visual only here. Add a group label on the container and
aria-pressedon each button so screen readers can announce which payout filter is active.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/components/payout-supported-countries.jsx` around lines 54 - 68, The payout filter is only visual; update the container wrapper (around where PAYOUT_METHODS is mapped) to expose an accessible group label (e.g., add role="group" and aria-label="Payout method filter" or aria-labelledby pointing to a visible heading) and set aria-pressed on each generated button (in the map where setPayoutMethod is called) to aria-pressed={payoutMethod === value} so assistive tech can announce the active filter; keep existing onClick and visual classes unchanged.snippets/components/image-carousel.jsx (1)
9-17:⚠️ Potential issue | 🟠 MajorKeep
autoplayauthoritative after mount.
autoplayActiveis still initialized fromautoplayonly once. If a parent togglesautoplaylater, the interval will not start or stop with the prop anymore, so this regresses the existing API.💡 Suggested fix
const [currentIndex, setCurrentIndex] = useState(0); const [autoplayActive, setAutoplayActive] = useState(autoplay); + useEffect(() => { + setAutoplayActive(autoplay); + }, [autoplay]); + useEffect(() => { if (!autoplayActive || images.length <= 1) return;In React, does useState(initialProp) resync local state when the prop changes after the component mounts?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@snippets/components/image-carousel.jsx` around lines 9 - 17, The component currently initializes autoplayActive from the autoplay prop only once, so later prop changes are ignored; update the component to keep the prop authoritative by syncing autoplay into local state—add an effect that runs when the autoplay prop changes and calls setAutoplayActive(autoplay) (or remove autoplayActive and use the autoplay prop directly if you don't need local toggling), and keep the existing interval effect using autoplayActive (or autoplay) so starting/stopping the interval follows prop updates; reference autoplayActive, setAutoplayActive, autoplay, and the existing useEffect that sets/clears the interval.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@help/article/receiving-payouts.mdx`:
- Around line 21-25: The Warning block and the FAQ in receiving-payouts.mdx give
conflicting guidance about the "Country" field; update the Warning element and
the FAQ section so they consistently state whether "Country" must reflect the
user's actual tax residency or the legal entity's country (choose one), and make
the wording explicit (e.g., "Country must reflect your legal tax residency" OR
"Country must reflect the legal entity's country for payouts") across both the
<Warning> block and the FAQ paragraph that tells unsupported-country users to
create a legal entity; also add a brief note describing acceptable exceptions
(if any) and where to get compliance help (support/contact) to avoid ambiguity.
---
Duplicate comments:
In `@help/article/receiving-payouts.mdx`:
- Line 35: The sentence "Stablecoin payouts is the easiest and fastest way to
receive payouts on Dub (especially for non-US partners):" uses a singular verb
with a plural subject; change it to "Stablecoin payouts are the easiest and
fastest way to receive payouts on Dub (especially for non-US partners):" to fix
the grammar and ensure subject-verb agreement (locate the exact sentence
starting "Stablecoin payouts is..." in receiving-payouts.mdx).
- Around line 221-227: Update the payout wording to be payout-method-neutral:
replace instances of "bank account", "withdrawn", and "deposited into your
connected bank account" with "connected payout method" or "connected payout
method (e.g., bank account or stablecoin)" in the FAQ section under the heading
"What is the minimum withdrawal amount, and how does it work?" and the preceding
paragraph comparing PartnerStack; ensure the sentence about automated payouts
reads that earnings/payouts are "automatically sent to your connected payout
method" and keep the $10 minimum wording intact.
- Around line 14-19: Update the "Fees" row in the table so it matches the
bank-payout note: change the bank account cell from an unconditional "1% FX
conversion fee" to a scoped description such as "1% FX conversion fee (applies
to international/non‑US bank payouts)" or add a parenthetical/link that points
to the same bank-payout note referenced by the Supported countries anchor;
modify the table's "Fees" row text accordingly so the wording for bank account
fees is consistent with the bank-payout note.
In `@snippets/components/image-carousel.jsx`:
- Around line 9-17: The component currently initializes autoplayActive from the
autoplay prop only once, so later prop changes are ignored; update the component
to keep the prop authoritative by syncing autoplay into local state—add an
effect that runs when the autoplay prop changes and calls
setAutoplayActive(autoplay) (or remove autoplayActive and use the autoplay prop
directly if you don't need local toggling), and keep the existing interval
effect using autoplayActive (or autoplay) so starting/stopping the interval
follows prop updates; reference autoplayActive, setAutoplayActive, autoplay, and
the existing useEffect that sets/clears the interval.
In `@snippets/components/payout-supported-countries.jsx`:
- Around line 24-35: The filter assumes country objects always have safe
name/code/methods fields; normalize those fields first to avoid crashing on
malformed records: inside the useMemo (and likewise in the row renderer
referenced around lines 86-101) coerce c.name and c.code to strings (e.g., const
name = String(c.name || "") and const code = String(c.code || "")) and ensure
methods is an array (const methods = Array.isArray(c.methods) ? c.methods : []),
then use name, code, and methods for searching and rendering instead of
accessing c.name/c.code/c.methods directly; update references in the filtered
computation and the row rendering to use these normalized variables.
- Around line 54-68: The payout filter is only visual; update the container
wrapper (around where PAYOUT_METHODS is mapped) to expose an accessible group
label (e.g., add role="group" and aria-label="Payout method filter" or
aria-labelledby pointing to a visible heading) and set aria-pressed on each
generated button (in the map where setPayoutMethod is called) to
aria-pressed={payoutMethod === value} so assistive tech can announce the active
filter; keep existing onClick and visual classes unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 741481da-e5d3-45e4-af43-63fc78750197
⛔ Files ignored due to path filters (10)
images/payouts/connect-bank-account-1.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-2.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-3.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-4.pngis excluded by!**/*.pngimages/payouts/connect-bank-account-5.pngis excluded by!**/*.pngimages/payouts/connect-stablecoin-wallet-1.pngis excluded by!**/*.pngimages/payouts/connect-stablecoin-wallet-2.pngis excluded by!**/*.pngimages/payouts/connect-stablecoin-wallet-3.pngis excluded by!**/*.pngimages/payouts/payout-settings-bank-account.pngis excluded by!**/*.pngimages/payouts/payout-settings-stablecoin.pngis excluded by!**/*.png
📒 Files selected for processing (3)
help/article/receiving-payouts.mdxsnippets/components/image-carousel.jsxsnippets/components/payout-supported-countries.jsx
| <Warning> | ||
| During onboarding, you must select the country where you legally reside for | ||
| tax purposes. Providing incorrect information may result in account | ||
| suspension, loss of payouts, and legal action. | ||
| </Warning> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find and read the file
find . -name "receiving-payouts.mdx" -type f | head -1Repository: dubinc/docs
Length of output: 91
🏁 Script executed:
#!/bin/bash
# Read the entire file to see full context
if [ -f "help/article/receiving-payouts.mdx" ]; then
wc -l "help/article/receiving-payouts.mdx"
fiRepository: dubinc/docs
Length of output: 93
🏁 Script executed:
#!/bin/bash
# Read the specific sections mentioned
if [ -f "help/article/receiving-payouts.mdx" ]; then
echo "=== Lines 15-30 (context around lines 21-25) ==="
sed -n '15,30p' "help/article/receiving-payouts.mdx"
echo ""
echo "=== Lines 170-195 (context around lines 178-186) ==="
sed -n '170,195p' "help/article/receiving-payouts.mdx"
fiRepository: dubinc/docs
Length of output: 1981
Reconcile conflicting country-selection guidance before publishing.
The warning (lines 21-25) states that you "must select the country where you legally reside for tax purposes" and warns that incorrect information may result in account suspension or legal action. However, the FAQ (lines 178-186) instructs unsupported-country users to create a legal entity in a supported country and set Country to that entity's location (e.g., "United States")—regardless of where they actually reside. This creates a compliance-sensitive conflict: users following the FAQ could appear to violate the warning's explicit requirement. Clarify whether Country should reflect actual tax residency or entity location, and update both sections consistently.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@help/article/receiving-payouts.mdx` around lines 21 - 25, The Warning block
and the FAQ in receiving-payouts.mdx give conflicting guidance about the
"Country" field; update the Warning element and the FAQ section so they
consistently state whether "Country" must reflect the user's actual tax
residency or the legal entity's country (choose one), and make the wording
explicit (e.g., "Country must reflect your legal tax residency" OR "Country must
reflect the legal entity's country for payouts") across both the <Warning> block
and the FAQ paragraph that tells unsupported-country users to create a legal
entity; also add a brief note describing acceptable exceptions (if any) and
where to get compliance help (support/contact) to avoid ambiguity.
Summary by CodeRabbit
New Features
Documentation