Skip to content

Numeric widget: add optional value title from API (#3282)#3337

Merged
tom2drum merged 3 commits intomainfrom
tom2drum/issue-3282
Apr 2, 2026
Merged

Numeric widget: add optional value title from API (#3282)#3337
tom2drum merged 3 commits intomainfrom
tom2drum/issue-3282

Conversation

@tom2drum
Copy link
Copy Markdown
Collaborator

@tom2drum tom2drum commented Apr 2, 2026

Description and Related Issue(s)

Resolves #3282

This change adds an optional valueTitlePath so address page third-party widgets can show an extra string from the API beside the widget title (for example a risk label such as "LOW" or "Honeypot"), similar to how valuePath selects the main value.

Proposed Changes

  • Added optional valueTitlePath to the widget config type, Yup schema, validator test asset, and docs/ENVS.md.
  • Updated useWidgetData to return both the formatted value and an optional title string from the response; Address3rdPartyWidgetCard shows Title: valueTitle when present and keeps title truncation with ellipsis.
  • Adjusted Playwright mocks and screenshot baselines for third-party widgets.

Breaking or Incompatible Changes

None. Widgets that omit valueTitlePath behave as before.

Additional Information

Environment variable changes

Variable / field Purpose
valueTitlePath (inside NEXT_PUBLIC_ADDRESS_3RD_PARTY_WIDGETS JSON) JSON path in the widget API response for optional text shown next to the widget title (e.g. status or risk label).

Checklist for PR author

  • I have tested these changes locally.
  • I added tests to cover any new functionality, following this guide
  • Whenever I fix a bug, I include a regression test to ensure that the bug does not reappear silently.
  • If I have added a feature or functionality that is not privacy-compliant (e.g., tracking, analytics, third-party services), I have disabled it for private mode.
  • If I have added, changed, renamed, or removed an environment variable
    • I updated the list of environment variables in the documentation
    • I made the necessary changes to the validator script according to the guide
    • I added "ENVs" label to this pull request

@tom2drum tom2drum added the ENVs label Apr 2, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

Important

Review skipped

Auto reviews are disabled on this repository. To trigger a review, include @coderabbitai review in the PR description. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a2acdbe4-130b-41ab-ac1a-7ae3c5f51c01

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
ui/address/Address3rdPartyWidgets.pw.tsx (1)

29-29: Consider extracting hardcoded mock value to the mocks file.

The valueTitle: 'Duck' is hardcoded here. Per project conventions, mock values should be imported from existing files in mocks/ rather than hardcoded in test files.

Suggested approach

Add to mocks/address/widgets.ts:

export const valueTitle = 'Duck';

Then update this file:

-      { value: widgetsMock.values[i], valueTitle: 'Duck' },
+      { value: widgetsMock.values[i], valueTitle: widgetsMock.valueTitle },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/address/Address3rdPartyWidgets.pw.tsx` at line 29, Replace the hardcoded
valueTitle 'Duck' in Address3rdPartyWidgets.pw.tsx with a mock import: add
export const valueTitle = 'Duck' to mocks/address/widgets.ts, import {
valueTitle } from 'mocks/address/widgets' in Address3rdPartyWidgets.pw.tsx, and
use valueTitle where the diff currently has valueTitle: 'Duck' (alongside
existing widgetsMock.values[i]).
ui/address/address3rdPartyWidgets/useWidgetData.ts (3)

37-37: Missing explicit return type annotation.

Per coding guidelines, top-level module functions should declare their return types.

Suggested change
-export default function useWidgetData({ name, valuePath, valueTitlePath, address, isLoading }: Props) {
+export default function useWidgetData({ name, valuePath, valueTitlePath, address, isLoading }: Props): ReturnType<typeof useApiQuery<typeof RESOURCE_NAME, unknown, Response | undefined>> {

Alternatively, extract the return type to a named type alias for readability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/address/address3rdPartyWidgets/useWidgetData.ts` at line 37, The function
useWidgetData lacks an explicit return type; add a clear return type annotation
to its declaration (e.g., useWidgetData(props: Props): <ReturnType> or define a
named type alias like WidgetDataResult and use useWidgetData(props: Props):
WidgetDataResult) and ensure the annotated type matches the actual returned
shape (include any promises, nullable fields, or unions used inside the
function). Locate the function named useWidgetData and update its signature to
include the chosen return type so it adheres to the top-level module function
guideline.

44-49: valueTitle may not be a string at runtime.

The get() function returns unknown, but valueTitle is assigned directly without validation. If the API returns a non-string value for the valueTitlePath, it could cause unexpected rendering behavior.

Consider adding type validation similar to how formatValue handles value:

Suggested fix
           const value = valuePath ? get(response, valuePath) : undefined;
-          const valueTitle = valueTitlePath ? get(response, valueTitlePath) : undefined;
+          const rawValueTitle = valueTitlePath ? get(response, valueTitlePath) : undefined;
+          const valueTitle = typeof rawValueTitle === 'string' ? rawValueTitle : undefined;
           return {
             value: formatValue(value),
             valueTitle,
           };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/address/address3rdPartyWidgets/useWidgetData.ts` around lines 44 - 49, In
useWidgetData (the mapping that computes value and valueTitle) validate and
coerce the result of get(response, valueTitlePath) before assigning to
valueTitle: treat non-string or null/undefined as undefined (or convert via
String(...) if intended), using a typeof check similar to formatValue for value,
so that valueTitle is guaranteed to be a string | undefined; update the logic
around get, valueTitlePath and formatValue usage to perform this runtime type
check and assignment.

24-35: Consider adding readonly modifiers to interface properties.

Per coding guidelines, interface properties should use readonly by default to prevent accidental mutation.

Suggested change
 interface Props {
-  name: string;
-  valuePath?: string;
-  valueTitlePath?: string;
-  address: string;
-  isLoading: boolean;
+  readonly name: string;
+  readonly valuePath?: string;
+  readonly valueTitlePath?: string;
+  readonly address: string;
+  readonly isLoading: boolean;
 }

 interface Response {
-  value: string | undefined;
-  valueTitle: string | undefined;
+  readonly value: string | undefined;
+  readonly valueTitle: string | undefined;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/address/address3rdPartyWidgets/useWidgetData.ts` around lines 24 - 35, The
Props and Response interfaces (Props and Response) should mark their properties
as readonly to prevent accidental mutation; update the interface declarations so
every property (name, valuePath, valueTitlePath, address, isLoading on Props and
value, valueTitle on Response) is prefixed with readonly while preserving
optional modifiers and types.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ui/address/Address3rdPartyWidgets.pw.tsx`:
- Line 29: Replace the hardcoded valueTitle 'Duck' in
Address3rdPartyWidgets.pw.tsx with a mock import: add export const valueTitle =
'Duck' to mocks/address/widgets.ts, import { valueTitle } from
'mocks/address/widgets' in Address3rdPartyWidgets.pw.tsx, and use valueTitle
where the diff currently has valueTitle: 'Duck' (alongside existing
widgetsMock.values[i]).

In `@ui/address/address3rdPartyWidgets/useWidgetData.ts`:
- Line 37: The function useWidgetData lacks an explicit return type; add a clear
return type annotation to its declaration (e.g., useWidgetData(props: Props):
<ReturnType> or define a named type alias like WidgetDataResult and use
useWidgetData(props: Props): WidgetDataResult) and ensure the annotated type
matches the actual returned shape (include any promises, nullable fields, or
unions used inside the function). Locate the function named useWidgetData and
update its signature to include the chosen return type so it adheres to the
top-level module function guideline.
- Around line 44-49: In useWidgetData (the mapping that computes value and
valueTitle) validate and coerce the result of get(response, valueTitlePath)
before assigning to valueTitle: treat non-string or null/undefined as undefined
(or convert via String(...) if intended), using a typeof check similar to
formatValue for value, so that valueTitle is guaranteed to be a string |
undefined; update the logic around get, valueTitlePath and formatValue usage to
perform this runtime type check and assignment.
- Around line 24-35: The Props and Response interfaces (Props and Response)
should mark their properties as readonly to prevent accidental mutation; update
the interface declarations so every property (name, valuePath, valueTitlePath,
address, isLoading on Props and value, valueTitle on Response) is prefixed with
readonly while preserving optional modifiers and types.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7a77f1c2-f6b1-4a87-a907-652615091da5

📥 Commits

Reviewing files that changed from the base of the PR and between d28767d and 6cd2785.

⛔ Files ignored due to path filters (3)
  • ui/address/__screenshots__/Address3rdPartyWidgets.pw.tsx_dark-color-mode_base-view-dark-mode-1.png is excluded by !**/*.png
  • ui/address/__screenshots__/Address3rdPartyWidgets.pw.tsx_default_base-view-dark-mode-1.png is excluded by !**/*.png
  • ui/address/__screenshots__/Address3rdPartyWidgets.pw.tsx_default_mobile-base-view-1.png is excluded by !**/*.png
📒 Files selected for processing (8)
  • deploy/tools/envs-validator/schemas/features/address3rdPartyWidgets.ts
  • deploy/tools/envs-validator/test/assets/configs/address_3rd_party_widgets_config.json
  • docs/ENVS.md
  • mocks/address/widgets.ts
  • types/views/address.ts
  • ui/address/Address3rdPartyWidgets.pw.tsx
  • ui/address/address3rdPartyWidgets/Address3rdPartyWidgetCard.tsx
  • ui/address/address3rdPartyWidgets/useWidgetData.ts

@tom2drum tom2drum merged commit f0c4053 into main Apr 2, 2026
3 checks passed
@tom2drum tom2drum deleted the tom2drum/issue-3282 branch April 2, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Numeric widget: add new value from API

1 participant