Skip to content

Commit d6fd3c4

Browse files
authored
fix(homepage): add dot separator between price and variation for token rows (TMCU-569) (#27449)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR adds a dot separator (•) between the price and variation text in token rows on the homepage, aligning with the `price • variation` format used in `TokenListItemV2`. **1. What is the reason for the change?** - Token rows in the Cash section and Popular Tokens section did not follow the same layout as token list items - `TokenListItemV2` displays price and variation as `$1.00 • +5.25%` (or similar) - The MUSD row in Cash and the Popular Token rows were missing this separator **2. What is the improvement/solution?** - Insert the Unicode bullet (`\u2022`) between the price and variation - Update `PopularTokenRow` so price and percentage display as `price • variation` - Update `CashGetMusdEmptyState` for the MUSD empty state - Adjust test assertions in `PopularTokenRow.test.tsx` to match the new format ## **Changelog** CHANGELOG entry: Fixed token row display on homepage to show price and variation separated by a dot for consistency with token list items ## **Related issues** Fixes: [TMCU-569](https://consensyssoftware.atlassian.net/browse/TMCU-569) ## **Manual testing steps** ```gherkin Feature: Homepage token row display consistency Scenario: user views token rows with price and variation Given the user is on the Homepage And the Cash section shows MUSD or Popular Tokens shows tokens with price/variation When the user views the token row Then price and variation are separated by a dot (•) And the layout matches TokenListItemV2 (e.g. "$1.00 • 3% bonus" or "$1,234.56 • +5.25%") ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="300" src="https://github.com/user-attachments/assets/b81022c5-6d85-4f86-9b74-f246503b8475" /> ### **After** <img width="300" src="https://github.com/user-attachments/assets/03c27fe4-07d0-49fa-947f-3fa1ca12efaa" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI-only change to text/layout formatting plus corresponding test updates; no data, auth, or navigation logic changes. > > **Overview** > Aligns homepage token rows with the `price • variation` display by inserting a Unicode bullet separator between the price and percentage/bonus text. > > Updates `PopularTokenRow` to render the separator *only when* a percentage value is present (and simplifies the layout), and tweaks `CashGetMusdEmptyState` to show the same separator for the mUSD row. Tests are updated to assert the new formatting and ensure no trailing bullet appears when variation is absent/invalid. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit dcda7cd. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 69f4c71 commit d6fd3c4

File tree

3 files changed

+37
-20
lines changed

3 files changed

+37
-20
lines changed

app/components/Views/Homepage/Sections/Cash/CashGetMusdEmptyState.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,12 @@ const CashGetMusdEmptyState = () => {
201201
>
202202
{MUSD_TOKEN.name}
203203
</Text>
204-
<Box twClassName="flex-row gap-2">
204+
<Box twClassName="flex-row gap-1">
205205
<Text
206206
variant={TextVariant.BodySm}
207207
color={TextColor.TextAlternative}
208208
>
209-
{musdPriceFormatted}
209+
{musdPriceFormatted} {'\u2022'}
210210
</Text>
211211
<Text
212212
variant={TextVariant.BodySm}

app/components/Views/Homepage/Sections/Tokens/components/PopularTokenRow.test.tsx

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,17 @@ describe('PopularTokenRow', () => {
8383

8484
renderWithProvider(<PopularTokenRow token={token} />);
8585

86-
// Price should be formatted with currency symbol
87-
expect(screen.getByText('$1,234.56')).toBeOnTheScreen();
86+
// Price is rendered with dot separator when percentage exists (e.g. "$1,234.56 • +5.25%")
87+
expect(screen.getByText(/\$1,234\.56/)).toBeOnTheScreen();
8888
});
8989

9090
it('renders dash when price is undefined', () => {
9191
const token = createMockToken({ price: undefined });
9292

9393
renderWithProvider(<PopularTokenRow token={token} />);
9494

95-
expect(screen.getByText('—')).toBeOnTheScreen();
95+
// Dash is rendered; with default percentage we get "— • +5.25%"
96+
expect(screen.getByText(//)).toBeOnTheScreen();
9697
});
9798

9899
it('renders positive percentage change with plus sign', () => {
@@ -124,8 +125,23 @@ describe('PopularTokenRow', () => {
124125

125126
renderWithProvider(<PopularTokenRow token={token} />);
126127

127-
// Use regex to match any text containing a percentage value (e.g. +5.25%, -3.50%)
128+
// No percentage should be shown
128129
expect(screen.queryByText(/[+-]?\d+\.\d+%/)).toBeNull();
130+
// Price only, no trailing bullet
131+
expect(screen.getByText('$100.50')).toBeOnTheScreen();
132+
});
133+
134+
it('does not render trailing bullet when percentage change is undefined', () => {
135+
const token = createMockToken({
136+
price: 99.99,
137+
priceChange1d: undefined,
138+
});
139+
140+
renderWithProvider(<PopularTokenRow token={token} />);
141+
142+
// Price without trailing bullet (no "•" after it)
143+
expect(screen.getByText('$99.99')).toBeOnTheScreen();
144+
expect(screen.queryByText(/\$\d+\.\d+\s+\s*$/)).toBeNull();
129145
});
130146

131147
it('renders description instead of price when provided', () => {
@@ -138,8 +154,8 @@ describe('PopularTokenRow', () => {
138154
renderWithProvider(<PopularTokenRow token={token} />);
139155

140156
expect(screen.getByText('Earn 3% bonus')).toBeOnTheScreen();
141-
// Price should not be rendered when description is present
142-
expect(screen.queryByText('$100.00')).not.toBeOnTheScreen();
157+
// Price and percentage should not be rendered when description is present
158+
expect(screen.queryByText(/\$100\.00/)).toBeNull();
143159
});
144160

145161
it('renders Buy button', () => {
@@ -293,17 +309,19 @@ describe('PopularTokenRow', () => {
293309

294310
renderWithProvider(<PopularTokenRow token={token} />);
295311

296-
// Should not render percentage for Infinity
297-
expect(screen.queryByText('Infinity%')).not.toBeOnTheScreen();
312+
// Should not render percentage for Infinity; price only, no trailing bullet
313+
expect(screen.queryByText('Infinity%')).toBeNull();
314+
expect(screen.getByText('$100.50')).toBeOnTheScreen();
298315
});
299316

300317
it('handles NaN price change gracefully', () => {
301318
const token = createMockToken({ priceChange1d: NaN });
302319

303320
renderWithProvider(<PopularTokenRow token={token} />);
304321

305-
// Should not render percentage for NaN
306-
expect(screen.queryByText('NaN%')).not.toBeOnTheScreen();
322+
// Should not render percentage for NaN; price only, no trailing bullet
323+
expect(screen.queryByText('NaN%')).toBeNull();
324+
expect(screen.getByText('$100.50')).toBeOnTheScreen();
307325
});
308326
});
309327
});

app/components/Views/Homepage/Sections/Tokens/components/PopularTokenRow.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,15 @@ const PopularTokenRow: React.FC<PopularTokenRowProps> = ({ token }) => {
222222
color={TextColor.Alternative}
223223
>
224224
{priceDisplay}
225+
{percentageChange.text ? ' \u2022 ' : ''}
225226
</Text>
226227
{percentageChange.text ? (
227-
<Box twClassName="ml-2">
228-
<Text
229-
variant={TextVariant.BodySMMedium}
230-
color={percentageChange.color}
231-
>
232-
{percentageChange.text}
233-
</Text>
234-
</Box>
228+
<Text
229+
variant={TextVariant.BodySMMedium}
230+
color={percentageChange.color}
231+
>
232+
{percentageChange.text}
233+
</Text>
235234
) : null}
236235
</Box>
237236
)}

0 commit comments

Comments
 (0)