Skip to content

Commit a4bbe61

Browse files
authored
fix(perps): recent activity: only ">" is tappable (#42676)
<!-- 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** Fixes the Perps Recent activity affordance so the full header row is tappable on both the Perps tab and Perp market detail page. Previously only the arrow icon was inside the button target. ## **Changelog** CHANGELOG entry: Fixed a bug that made only the Recent activity arrow tappable in Perps. ## **Related issues** Fixes: [TAT-3077](https://consensyssoftware.atlassian.net/browse/TAT-3077) ## **Manual testing steps** 1. Open MetaMask and go to the Perps tab with recent activity. 2. Click the Recent activity header text, not just the arrow. 3. Confirm the Perps activity page opens. 4. Open a Perp market detail page with recent activity. 5. Click the Recent activity header text and confirm the Perps activity page opens. ## **Screenshots/Recordings** <table> <tr><td align="center" width="50%"><strong>Screenshots/evidence Ac1 Perps Recent Activity Row 1778746896456</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/evidence-ac1-perps-recent-activity-row-1778746896456.png" alt="Screenshots/evidence Ac1 Perps Recent Activity Row 1778746896456" width="400" /></td><td align="center" width="50%"><strong>Screenshots/evidence Ac1 Perps Recent Activity Row 1778747064138</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/evidence-ac1-perps-recent-activity-row-1778747064138.png" alt="Screenshots/evidence Ac1 Perps Recent Activity Row 1778747064138" width="400" /></td></tr> <tr><td align="center" width="50%"><strong>Screenshots/evidence Ac2 Market Recent Activity Row 1778746896956</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/evidence-ac2-market-recent-activity-row-1778746896956.png" alt="Screenshots/evidence Ac2 Market Recent Activity Row 1778746896956" width="400" /></td><td align="center" width="50%"><strong>Screenshots/evidence Ac2 Market Recent Activity Row 1778747064585</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/evidence-ac2-market-recent-activity-row-1778747064585.png" alt="Screenshots/evidence Ac2 Market Recent Activity Row 1778747064585" width="400" /></td></tr> <tr><td align="center" width="50%"><strong>Screenshots/long Position ETH 1778746895492</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/long-position-ETH-1778746895492.png" alt="Screenshots/long Position ETH 1778746895492" width="400" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td><td align="center" width="50%"><strong>Screenshots/long Position ETH 1778747063131</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/long-position-ETH-1778747063131.png" alt="Screenshots/long Position ETH 1778747063131" width="400" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td></tr> <tr><td align="center" width="50%"><strong>Screenshots/perps Tab 1778746896035</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/perps-tab-1778746896035.png" alt="Screenshots/perps Tab 1778746896035" width="400" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td><td align="center" width="50%"><strong>Screenshots/perps Tab 1778747063678</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/42676/screenshots/perps-tab-1778747063678.png" alt="Screenshots/perps Tab 1778747063678" width="400" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td></tr> </table> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/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. ## **Validation Recipe** <details><summary>recipe.json</summary> ```json { "title": "TAT-3077 — Recent activity header rows are fully tappable", "description": "Validates that the left side of the Recent activity header row is inside the tappable ButtonBase on the Perps tab and Perp market detail page.", "schema_version": 1, "validate": { "workflow": { "pre_conditions": ["wallet.unlocked", "perps.feature_enabled"], "entry": "setup-open-position", "nodes": { "setup-open-position": { "action": "call", "ref": "perps/open-long-position", "params": { "symbol": "ETH", "side": "long", "amount": "10" }, "next": "setup-nav-perps-tab" }, "setup-nav-perps-tab": { "action": "call", "ref": "perps/navigate-perps-tab", "next": "ac1-wait-recent-activity" }, "ac1-wait-recent-activity": { "action": "wait_for", "test_id": "perps-recent-activity-see-all", "timeout_ms": 10000, "next": "ac1-scroll-recent-activity" }, "ac1-scroll-recent-activity": { "action": "scroll", "test_id": "perps-recent-activity-see-all", "next": "ac1-assert-row-hit-target" }, "ac1-assert-row-hit-target": { "action": "eval_sync", "expression": "(function(){var testId='perps-recent-activity-see-all';var btn=document.querySelector('[data-testid=\"'+testId+'\"]');if(!btn){return JSON.stringify({ok:false,reason:'missing button'});}var parent=btn.parentElement||btn;var parentRect=parent.getBoundingClientRect();var btnRect=btn.getBoundingClientRect();var probeX=parentRect.left+Math.min(40,parentRect.width/4);var probeY=btnRect.top+(btnRect.height/2);var hit=document.elementFromPoint(probeX,probeY);var target=hit&&hit.closest('[data-testid=\"'+testId+'\"]');return JSON.stringify({ok:target===btn,buttonWidth:Math.round(btnRect.width),rowWidth:Math.round(parentRect.width),probeX:Math.round(probeX),probeY:Math.round(probeY),hitTestId:(target&&target.getAttribute('data-testid'))||(hit&&hit.getAttribute&&hit.getAttribute('data-testid'))||null});})()", "assert": { "operator": "eq", "field": "ok", "value": true }, "save_as": "ac1_hit_target", "next": "ac1-screenshot-recent-activity-row" }, "ac1-screenshot-recent-activity-row": { "action": "screenshot", "filename": "evidence-ac1-perps-recent-activity-row", "note": "AC1: Perps tab Recent activity header row is visible after hit-target assertion", "next": "setup-nav-market-detail" }, "setup-nav-market-detail": { "action": "call", "ref": "perps/navigate-to-market-detail", "params": { "symbol": "ETH" }, "next": "ac2-wait-recent-activity" }, "ac2-wait-recent-activity": { "action": "wait_for", "test_id": "perps-market-detail-view-all-activity", "timeout_ms": 10000, "next": "ac2-scroll-recent-activity" }, "ac2-scroll-recent-activity": { "action": "scroll", "test_id": "perps-market-detail-view-all-activity", "next": "ac2-assert-row-hit-target" }, "ac2-assert-row-hit-target": { "action": "eval_sync", "expression": "(function(){var testId='perps-market-detail-view-all-activity';var btn=document.querySelector('[data-testid=\"'+testId+'\"]');if(!btn){return JSON.stringify({ok:false,reason:'missing button'});}var parent=btn.parentElement||btn;var parentRect=parent.getBoundingClientRect();var btnRect=btn.getBoundingClientRect();var probeX=parentRect.left+Math.min(40,parentRect.width/4);var probeY=btnRect.top+(btnRect.height/2);var hit=document.elementFromPoint(probeX,probeY);var target=hit&&hit.closest('[data-testid=\"'+testId+'\"]');return JSON.stringify({ok:target===btn,buttonWidth:Math.round(btnRect.width),rowWidth:Math.round(parentRect.width),probeX:Math.round(probeX),probeY:Math.round(probeY),hitTestId:(target&&target.getAttribute('data-testid'))||(hit&&hit.getAttribute&&hit.getAttribute('data-testid'))||null});})()", "assert": { "operator": "eq", "field": "ok", "value": true }, "save_as": "ac2_hit_target", "next": "ac2-screenshot-recent-activity-row" }, "ac2-screenshot-recent-activity-row": { "action": "screenshot", "filename": "evidence-ac2-market-recent-activity-row", "note": "AC2: Market detail Recent activity header row is visible after hit-target assertion", "next": "teardown-done" }, "teardown-done": { "action": "end", "status": "pass" } } } } } ``` </details> ## **Recipe Workflow** <details><summary>workflow.mmd</summary> ```mermaid flowchart TD %% TAT-3077 — Recent activity header rows are fully tappable __entry__(["ENTRY"]) --> node_setup_open_position node_setup_open_position[["setup-open-position<br/>perps/open-long-position"]] node_setup_nav_perps_tab[["setup-nav-perps-tab<br/>perps/navigate-perps-tab"]] node_ac1_wait_recent_activity["ac1-wait-recent-activity<br/>wait_for"] node_ac1_scroll_recent_activity["ac1-scroll-recent-activity<br/>scroll"] node_ac1_assert_row_hit_target["ac1-assert-row-hit-target<br/>eval_sync"] node_ac1_screenshot_recent_activity_row["ac1-screenshot-recent-activity-row<br/>screenshot"] node_setup_nav_market_detail[["setup-nav-market-detail<br/>perps/navigate-to-market-detail"]] node_ac2_wait_recent_activity["ac2-wait-recent-activity<br/>wait_for"] node_ac2_scroll_recent_activity["ac2-scroll-recent-activity<br/>scroll"] node_ac2_assert_row_hit_target["ac2-assert-row-hit-target<br/>eval_sync"] node_ac2_screenshot_recent_activity_row["ac2-screenshot-recent-activity-row<br/>screenshot"] node_teardown_done(["teardown-done<br/>PASS"]) node_setup_open_position --> node_setup_nav_perps_tab node_setup_nav_perps_tab --> node_ac1_wait_recent_activity node_ac1_wait_recent_activity --> node_ac1_scroll_recent_activity node_ac1_scroll_recent_activity --> node_ac1_assert_row_hit_target node_ac1_assert_row_hit_target --> node_ac1_screenshot_recent_activity_row node_ac1_screenshot_recent_activity_row --> node_setup_nav_market_detail node_setup_nav_market_detail --> node_ac2_wait_recent_activity node_ac2_wait_recent_activity --> node_ac2_scroll_recent_activity node_ac2_scroll_recent_activity --> node_ac2_assert_row_hit_target node_ac2_assert_row_hit_target --> node_ac2_screenshot_recent_activity_row node_ac2_screenshot_recent_activity_row --> node_teardown_done ``` </details> [TAT-3077]: https://consensyssoftware.atlassian.net/browse/TAT-3077?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI-only change that wraps the header row in a single `ButtonBase` and updates tests; no business logic or data handling is modified. > > **Overview** > Fixes the Perps *Recent Activity* affordance by making the entire header row (text + arrow) a single clickable `ButtonBase` that navigates to `PERPS_ACTIVITY_ROUTE`, in both `PerpsRecentActivity` and `PerpsMarketRecentActivity`. > > Updates accessibility (`aria-label`) and styling to keep full-width button behavior (including explicit horizontal padding on the market detail header), and extends unit tests to assert header-text clicks navigate correctly (switching to `userEvent` where needed). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e58c33d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent ee2119a commit a4bbe61

4 files changed

Lines changed: 67 additions & 48 deletions

File tree

ui/components/app/perps/perps-market-recent-activity/perps-market-recent-activity.test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { fireEvent, screen } from '@testing-library/react';
3+
import userEvent from '@testing-library/user-event';
34
import { renderWithProvider } from '../../../../../test/lib/render-helpers-navigate';
45
import configureStore from '../../../../store/store';
56
import mockState from '../../../../../test/data/mock-state.json';
@@ -197,6 +198,9 @@ describe('PerpsMarketRecentActivity', () => {
197198
expect(
198199
screen.getByTestId('perps-market-detail-view-all-activity'),
199200
).toBeInTheDocument();
201+
expect(
202+
screen.getByTestId('perps-market-detail-view-all-activity'),
203+
).toHaveStyle({ paddingLeft: '0px', paddingRight: '0px' });
200204
});
201205

202206
it('"See All" navigates to PERPS_ACTIVITY_ROUTE', () => {
@@ -214,6 +218,21 @@ describe('PerpsMarketRecentActivity', () => {
214218
expect(mockNavigate).toHaveBeenCalledWith(PERPS_ACTIVITY_ROUTE);
215219
});
216220

221+
it('navigates to PERPS_ACTIVITY_ROUTE when the Recent Activity header text is clicked', async () => {
222+
const user = userEvent.setup();
223+
mockUsePerpsMarketFills.mockReturnValue({
224+
fills: [],
225+
isInitialLoading: false,
226+
});
227+
mockTransformFills.mockReturnValue([createTransaction('tx-1')]);
228+
229+
renderWithProvider(<PerpsMarketRecentActivity symbol="BTC" />, mockStore);
230+
231+
await user.click(screen.getByText(messages.perpsRecentActivity.message));
232+
233+
expect(mockNavigate).toHaveBeenCalledWith(PERPS_ACTIVITY_ROUTE);
234+
});
235+
217236
it('navigates to PERPS_ACTIVITY_ROUTE when a transaction row is tapped', () => {
218237
mockUsePerpsMarketFills.mockReturnValue({
219238
fills: [],

ui/components/app/perps/perps-market-recent-activity/perps-market-recent-activity.tsx

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import React, { useMemo } from 'react';
22
import {
33
Box,
44
BoxFlexDirection,
5-
BoxJustifyContent,
6-
BoxAlignItems,
75
Text,
86
TextVariant,
97
TextColor,
@@ -97,31 +95,30 @@ export const PerpsMarketRecentActivity: React.FC<
9795

9896
return (
9997
<>
100-
<Box
101-
flexDirection={BoxFlexDirection.Row}
102-
justifyContent={BoxJustifyContent.Between}
103-
alignItems={BoxAlignItems.Center}
104-
paddingTop={4}
105-
paddingBottom={2}
106-
>
107-
<Text variant={TextVariant.HeadingSm} fontWeight={FontWeight.Medium}>
108-
{t('perpsRecentActivity')}
109-
</Text>
110-
{hasTransactions && (
111-
<ButtonBase
112-
onClick={handleSeeAll}
113-
className="bg-transparent hover:bg-transparent active:bg-transparent p-0 min-w-0 h-auto"
114-
data-testid="perps-market-detail-view-all-activity"
115-
aria-label={t('perpsSeeAll')}
116-
>
117-
<Icon
118-
name={IconName.ArrowRight}
119-
size={IconSize.Sm}
120-
color={IconColor.IconAlternative}
121-
/>
122-
</ButtonBase>
123-
)}
124-
</Box>
98+
{hasTransactions ? (
99+
<ButtonBase
100+
onClick={handleSeeAll}
101+
className="w-full flex flex-row justify-between items-center pt-4 pb-2 bg-transparent rounded-none hover:bg-hover active:bg-pressed"
102+
style={{ paddingLeft: 0, paddingRight: 0 }}
103+
data-testid="perps-market-detail-view-all-activity"
104+
aria-label={`${t('perpsRecentActivity')}, ${t('perpsSeeAll')}`}
105+
>
106+
<Text variant={TextVariant.HeadingSm} fontWeight={FontWeight.Medium}>
107+
{t('perpsRecentActivity')}
108+
</Text>
109+
<Icon
110+
name={IconName.ArrowRight}
111+
size={IconSize.Sm}
112+
color={IconColor.IconAlternative}
113+
/>
114+
</ButtonBase>
115+
) : (
116+
<Box paddingTop={4} paddingBottom={2}>
117+
<Text variant={TextVariant.HeadingSm} fontWeight={FontWeight.Medium}>
118+
{t('perpsRecentActivity')}
119+
</Text>
120+
</Box>
121+
)}
125122
{showSkeleton && <RecentActivitySkeleton />}
126123
{!showSkeleton && !hasTransactions && <RecentActivityEmpty />}
127124
{!showSkeleton && hasTransactions && (

ui/components/app/perps/perps-recent-activity/perps-recent-activity.test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { fireEvent, screen } from '@testing-library/react';
3+
import userEvent from '@testing-library/user-event';
34
import { renderWithProvider } from '../../../../../test/lib/render-helpers-navigate';
45
import configureStore from '../../../../store/store';
56
import mockState from '../../../../../test/data/mock-state.json';
@@ -251,6 +252,18 @@ describe('PerpsRecentActivity', () => {
251252
expect(mockNavigate).toHaveBeenCalledWith(PERPS_ACTIVITY_ROUTE);
252253
});
253254

255+
it('navigates to activity route when the Recent Activity header text is clicked', async () => {
256+
const user = userEvent.setup();
257+
renderWithProvider(
258+
<PerpsRecentActivity transactions={mockTransactions} />,
259+
mockStore,
260+
);
261+
262+
await user.click(screen.getByText(messages.perpsRecentActivity.message));
263+
264+
expect(mockNavigate).toHaveBeenCalledWith(PERPS_ACTIVITY_ROUTE);
265+
});
266+
254267
it('calls onTransactionClick when a transaction is clicked', () => {
255268
const handleClick = jest.fn();
256269
renderWithProvider(

ui/components/app/perps/perps-recent-activity/perps-recent-activity.tsx

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -132,29 +132,19 @@ export const PerpsRecentActivity: React.FC<PerpsRecentActivityProps> = ({
132132
data-testid="perps-recent-activity"
133133
>
134134
{/* Section Header */}
135-
<Box
136-
flexDirection={BoxFlexDirection.Row}
137-
justifyContent={BoxJustifyContent.Between}
138-
alignItems={BoxAlignItems.Center}
139-
paddingLeft={4}
140-
paddingRight={4}
141-
paddingTop={4}
142-
marginBottom={2}
135+
<ButtonBase
136+
className="w-full flex flex-row justify-between items-center px-4 pt-4 mb-2 bg-transparent rounded-none hover:bg-hover active:bg-pressed"
137+
onClick={handleSeeAll}
138+
data-testid="perps-recent-activity-see-all"
139+
aria-label={`${t('perpsRecentActivity')}, ${t('perpsSeeAll')}`}
143140
>
144141
<Text fontWeight={FontWeight.Medium}>{t('perpsRecentActivity')}</Text>
145-
<ButtonBase
146-
onClick={handleSeeAll}
147-
className="bg-transparent hover:bg-transparent active:bg-transparent p-0 min-w-0 h-auto"
148-
data-testid="perps-recent-activity-see-all"
149-
aria-label={t('perpsSeeAll')}
150-
>
151-
<Icon
152-
name={IconName.ArrowRight}
153-
size={IconSize.Sm}
154-
color={IconColor.IconAlternative}
155-
/>
156-
</ButtonBase>
157-
</Box>
142+
<Icon
143+
name={IconName.ArrowRight}
144+
size={IconSize.Sm}
145+
color={IconColor.IconAlternative}
146+
/>
147+
</ButtonBase>
158148

159149
{/* Transaction List */}
160150
<Box flexDirection={BoxFlexDirection.Column}>

0 commit comments

Comments
 (0)