Skip to content

fix(widget): clean up icon fallbacks and pending action labels#531

Merged
petar-omni merged 3 commits into
mainfrom
fix/widget-dashboard-position-fallback-icons
Jun 10, 2026
Merged

fix(widget): clean up icon fallbacks and pending action labels#531
petar-omni merged 3 commits into
mainfrom
fix/widget-dashboard-position-fallback-icons

Conversation

@sandy-yield

@sandy-yield sandy-yield commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

BEFORE:
image

AFTER:
image

  • Render a grey circle with the chain initial when a network logo is missing or fails to load, on a white badge so dark chain logos (e.g. Ethereum) stay visible.
  • Use a white background with black text for the token icon monogram fallback.
  • Humanize unmapped pending action types (e.g. RWA actions) so the position details "Action required" card, action button, and review heading never render raw translation keys.

Added

Description of new functionality, feature, or content that has been added in this pull request.

Changed

Description of the modifications made to existing functionality, feature, or content in this pull request. This could include changes to code, CI, documentation, etc.

Summary by CodeRabbit

  • New Features

    • Improved pending-action labels across the UI with humanized fallbacks when translations are missing.
    • Network logo component now receives the network name to improve fallback initials when logos fail.
  • Style

    • Network icon container restyled with white background, reduced padding and a subtle ring shadow.
    • Monogram image background changed to a white circle with a light gray stroke for consistent appearance.

- Render a grey circle with the chain initial when a network logo is
  missing or fails to load, on a white badge so dark chain logos (e.g.
  Ethereum) stay visible.
- Use a white background with black text for the token icon monogram
  fallback.
- Humanize unmapped pending action types (e.g. RWA actions) so the
  position details "Action required" card, action button, and review
  heading never render raw translation keys.
@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 4d2d70b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Network logo components now accept and forward a networkName prop, container styles were refactored to a white background with subtle ring, monogram SVGs use a fixed white circle, and a new humanizePendingActionType formatter is added and wired as i18n fallback across position and reward token UIs.

Changes

Network Logo Fallback System

Layer / File(s) Summary
Network name prop wiring to logo consumers
packages/widget/src/components/atoms/token-icon/index.tsx, packages/widget/src/components/atoms/token-icon/provider-icon/index.tsx
TokenIcon and ProviderIcon pass networkName={token.network} to NetworkLogoImage.
NetworkLogoImage props and Image fallback wiring
packages/widget/src/components/atoms/token-icon/network-icon-image/index.tsx
NetworkLogoImageProps gains optional networkName; NetworkLogoImage forwards fallbackName={networkName} to Image.
Container style refactor for logo and fallback
packages/widget/src/components/atoms/token-icon/network-icon-image/style.css.ts
Adds baseContainer and refactors logoContainer to compose it, sets backgroundColor: #ffffff``, padding: "3px" and a subtle `boxShadow` ring.
Monogram SVG styling simplification
packages/widget/src/components/atoms/image/index.tsx
Removes getBackgroundColor import and uses a fixed white circle fill with light stroke for monogram SVG generation.

Pending Action Type Humanization

Layer / File(s) Summary
Humanize pending action type formatter
packages/widget/src/utils/formatters.ts
Adds exported humanizePendingActionType(type: string) to produce title-cased, space-separated fallback labels from underscore-delimited API types.
Position details pending action humanization
packages/widget/src/pages-dashboard/position-details/position-details-model.tsx, packages/widget/src/pages-dashboard/position-details/components/position-details-actions.tsx
Adds formatPendingActionLabel and updates getStatusSummary; button label now supplies defaultValue using humanizePendingActionType.
Static action block pending action humanization
packages/widget/src/pages/position-details/components/static-action-block.tsx
“Available to” interpolation and pending-action button label now use humanizePendingActionType(pendingActionDto.type) as defaultValue.
Reward token details pending action defaults
packages/widget/src/components/molecules/reward-token-details/index.tsx
Computes i18nDefaults when rest.type === "pendingAction" and passes it into Trans via the defaults prop.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • stakekit/widget#516: Earlier refactor touching the monogram-generating Image component and token/network logo fallback logic.

Suggested reviewers

  • jdomingos
  • dnehl

In code I nibble on the token names,
I paint white circles, not color games,
Pending actions speak in polished light,
The widget hops along, pleased and bright. 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description includes concrete details about the changes (icon fallbacks, pending action labels) with before/after images, but the 'Added' and 'Changed' template sections are left empty without substantive content. Fill in the 'Added' and 'Changed' sections with descriptions of the specific modifications made, such as details about the new humanizePendingActionType function or the updated styling for network logos.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly and concisely describes the main changes: cleaning up icon fallbacks and pending action labels.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/widget-dashboard-position-fallback-icons

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.

❤️ Share

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

@aws-amplify-eu-central-1

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-531.d2ribjy8evqo6h.amplifyapp.com

@aws-amplify-eu-central-1

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-531.df4xyoi0xyeak.amplifyapp.com

xhakti
xhakti previously approved these changes Jun 9, 2026

@xhakti xhakti 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.

LGTM

@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 (1)
packages/widget/src/pages-dashboard/position-details/position-details-model.tsx (1)

632-641: Align pending-action label fallback with humanizePendingActionType (match existing files; it’s slightly more defensive).

formatEnumValue and humanizePendingActionType are equivalent for current pending-action strings (both split on _ and capitalize segments). The difference is humanizePendingActionType filters out empty segments (filter(Boolean)), which avoids odd spacing if the API ever includes double/trailing underscores.

🔄 Proposed fix to use consistent formatter
+import { humanizePendingActionType } from "../../utils/formatters";
 import {
   formatCooldownDays,
-  formatEnumValue,
   formatMinStake,
   formatNetworkName,
   formatOptionalDays,
   formatRewardClaiming,
   formatRewardRateLabel,
   formatRewardTokenLabel,
 } from "../overview/earn-details/earn-details-formatters";
 const formatPendingActionLabel = (
   type: YieldPendingActionDto["type"],
   t: TFunction
 ) =>
   t(`position_details.pending_action.${type.toLowerCase()}`, {
-    defaultValue: formatEnumValue(type),
+    defaultValue: humanizePendingActionType(type),
   });
🤖 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
`@packages/widget/src/pages-dashboard/position-details/position-details-model.tsx`
around lines 632 - 641, Replace the use of formatEnumValue in
formatPendingActionLabel with humanizePendingActionType so the fallback matches
other files and defensively filters out empty segments; update the import/usage
in the formatPendingActionLabel function (referencing
YieldPendingActionDto["type"], formatPendingActionLabel,
humanizePendingActionType, and formatEnumValue) so the t(...) defaultValue calls
humanizePendingActionType(type) instead of formatEnumValue(type).
🤖 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
`@packages/widget/src/pages-dashboard/position-details/position-details-model.tsx`:
- Around line 632-641: Replace the use of formatEnumValue in
formatPendingActionLabel with humanizePendingActionType so the fallback matches
other files and defensively filters out empty segments; update the import/usage
in the formatPendingActionLabel function (referencing
YieldPendingActionDto["type"], formatPendingActionLabel,
humanizePendingActionType, and formatEnumValue) so the t(...) defaultValue calls
humanizePendingActionType(type) instead of formatEnumValue(type).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2df8c815-e4db-4a91-9fa9-fa095d72599d

📥 Commits

Reviewing files that changed from the base of the PR and between 2468076 and ebe34bd.

📒 Files selected for processing (10)
  • packages/widget/src/components/atoms/image/index.tsx
  • packages/widget/src/components/atoms/token-icon/index.tsx
  • packages/widget/src/components/atoms/token-icon/network-icon-image/index.tsx
  • packages/widget/src/components/atoms/token-icon/network-icon-image/style.css.ts
  • packages/widget/src/components/atoms/token-icon/provider-icon/index.tsx
  • packages/widget/src/components/molecules/reward-token-details/index.tsx
  • packages/widget/src/pages-dashboard/position-details/components/position-details-actions.tsx
  • packages/widget/src/pages-dashboard/position-details/position-details-model.tsx
  • packages/widget/src/pages/position-details/components/static-action-block.tsx
  • packages/widget/src/utils/formatters.ts

const backgroundColor = getBackgroundColor(name);

const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"><circle cx="50" cy="50" r="50" fill="${backgroundColor}" /><text x="50" y="50" fill="#FFFFFF" font-family="Arial, sans-serif" font-size="48" font-weight="700" text-anchor="middle" dominant-baseline="central">${initial}</text></svg>`;
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"><circle cx="50" cy="50" r="49" fill="#FFFFFF" stroke="rgba(0,0,0,0.08)" stroke-width="2" /><text x="50" y="50" fill="#000000" font-family="Arial, sans-serif" font-size="48" font-weight="700" text-anchor="middle" dominant-baseline="central">${initial}</text></svg>`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hm, with this we have white fallbacks on white background. why not color backgrounds?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it's the shared monogram used standalone in token/provider/validator icons (no container behind them), so the white circle's needed there. The badge just reuses it now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

here is with this change - is this expected? @sandy-yield

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

image

Yes, those are expected. If we don't have the image, it shows the initial letter of the coin.

Comment on lines +18 to +31
const [erroredUri, setErroredUri] = useState<string | null>(null);

const hasError = erroredUri === networkLogoUri;

if (!networkLogoUri || hasError) {
const initial = networkName?.trim()?.[0]?.toUpperCase() ?? "?";

return (
<Box className={fallbackContainer} data-rk="token-network-logo-fallback">
<Box hw={tokenNetworkLogoHw} display="flex">
<ChainInitial initial={initial} />
</Box>
</Box>
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we already have image error handling with Image component
e.g. <Image fallbackName={networkName} />

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

dropped the custom error state + SVG, now using . Removed the unused coin icon too.

Comment on lines +3 to +12
const baseContainer = {
position: "absolute",
bottom: -2,
right: -2,
borderRadius: "50%",
padding: "4px",
backgroundColor: "rgba(37,37,37, 0.95)",
padding: "3px",
display: "flex",
alignItems: "center",
justifyContent: "center",
} as const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this loses style type safety. compose styles with style utility. e.g.

const base = style({ padding: 12 });

const primary = style([base, { background: 'blue' }]);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done — now style([baseContainer, { ... }]).

Drop the manual error state and ChainInitial SVG in NetworkLogoImage in
favor of the Image component's built-in fallbackName monogram. Compose
network-icon styles with the style() utility for type safety, and remove
the now-unused coin icon.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/widget/src/components/atoms/token-icon/network-icon-image/index.tsx (1)

12-23: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle empty networkLogoUri as missing so fallback always works.

On Line 19, src={networkLogoUri} can pass "", which does not trigger the src ?? generatedFallbackSrc path in Image. If upstream returns empty strings for missing logos, the monogram fallback may not render reliably. Normalize empty values to undefined before passing src.

Proposed fix
 export const NetworkLogoImage = ({
   networkLogoUri,
   networkName,
   tokenNetworkLogoHw = "3",
-}: NetworkLogoImageProps) => (
+}: NetworkLogoImageProps) => {
+  const normalizedNetworkLogoUri = networkLogoUri.trim() || undefined;
+
+  return (
   <Box className={logoContainer} data-rk="token-network-logo">
     <Image
-      src={networkLogoUri}
+      src={normalizedNetworkLogoUri}
       fallbackName={networkName}
       wrapperProps={{ hw: tokenNetworkLogoHw }}
       imgProps={{ hw: tokenNetworkLogoHw, className: logoImage }}
     />
   </Box>
-);
+  );
+};
🤖 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 `@packages/widget/src/components/atoms/token-icon/network-icon-image/index.tsx`
around lines 12 - 23, The NetworkLogoImage component passes networkLogoUri
directly to Image.src which can be an empty string and bypass Image's fallback
logic; update NetworkLogoImage to normalize empty string values (networkLogoUri)
to undefined before passing to the Image component (i.e., compute a local src
value from networkLogoUri that sets "" to undefined) so the Image component's
fallbackName/monogram behavior always triggers when the logo URI is missing.
🤖 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.

Outside diff comments:
In
`@packages/widget/src/components/atoms/token-icon/network-icon-image/index.tsx`:
- Around line 12-23: The NetworkLogoImage component passes networkLogoUri
directly to Image.src which can be an empty string and bypass Image's fallback
logic; update NetworkLogoImage to normalize empty string values (networkLogoUri)
to undefined before passing to the Image component (i.e., compute a local src
value from networkLogoUri that sets "" to undefined) so the Image component's
fallbackName/monogram behavior always triggers when the logo URI is missing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 58db955b-ee2d-4a7a-89c7-ffc2fd933a22

📥 Commits

Reviewing files that changed from the base of the PR and between ebe34bd and 325829f.

📒 Files selected for processing (2)
  • packages/widget/src/components/atoms/token-icon/network-icon-image/index.tsx
  • packages/widget/src/components/atoms/token-icon/network-icon-image/style.css.ts

@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 (1)
packages/widget/src/utils/index.ts (1)

46-52: Remove the commented-out getBackgroundColor block (unused)

  • getBackgroundColor (and colorsTuple) appear only in the commented-out code in packages/widget/src/utils/index.ts; no imports/usages remain.
🧹 Proposed fix to remove commented code
-// const colorsTuple = ["`#6B69D6`", "`#F1C40F`", "`#1ABC9C`", "`#E74C3C`"];
-
-// export const getBackgroundColor = (stringInput: string) => {
-//   const char = stringInput.charCodeAt(0);
-
-//   return colorsTuple[char % colorsTuple.length] ?? colorsTuple[0];
-// };
-
🤖 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 `@packages/widget/src/utils/index.ts` around lines 46 - 52, Remove the unused
commented-out block containing colorsTuple and getBackgroundColor from
packages/widget/src/utils/index.ts; locate the commented lines that define
colorsTuple and the getBackgroundColor function and delete them, and then run a
quick grep/TS search for symbols colorsTuple and getBackgroundColor to confirm
there are no remaining usages before committing.
🤖 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 `@packages/widget/src/utils/index.ts`:
- Around line 46-52: Remove the unused commented-out block containing
colorsTuple and getBackgroundColor from packages/widget/src/utils/index.ts;
locate the commented lines that define colorsTuple and the getBackgroundColor
function and delete them, and then run a quick grep/TS search for symbols
colorsTuple and getBackgroundColor to confirm there are no remaining usages
before committing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dea573d2-c115-40fe-8069-c9c4fd1b2ee2

📥 Commits

Reviewing files that changed from the base of the PR and between 325829f and 4d2d70b.

📒 Files selected for processing (1)
  • packages/widget/src/utils/index.ts

@sandy-yield sandy-yield requested a review from xhakti June 10, 2026 09:47

@xhakti xhakti 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.

LGTM

@petar-omni petar-omni merged commit 9ffe4db into main Jun 10, 2026
8 checks passed
@petar-omni petar-omni deleted the fix/widget-dashboard-position-fallback-icons branch June 10, 2026 09:50
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.

3 participants