Commit 2373d09
feat(perps): chart improvements with volume and fullscreen view (MetaMask#22843)
## **Description**
This PR implements volume histogram and fullscreen chart mode for Perps
trading, addressing the lack of volume data visualization and limited
screen real estate for chart analysis on mobile.
### What is the reason for the change?
The current Perps chart lacks essential trading features:
- No volume data visualization (critical for confirming price movements)
- No fullscreen/landscape mode for detailed chart analysis
- Limited screen space forces traders to use external platforms
(TradingView, CEX apps)
### What is the improvement/solution?
**Volume Histogram**
- USD notional volume bars (volume × price) displayed below candlesticks
- Smart formatting with K/M/B/T suffixes (e.g., "120M" vs "120,000,000")
- Color-coded bars (green/red) matching candle direction
- Clean presentation with hidden Y-axis labels and transparent separator
**Fullscreen Chart Modal**
- Immersive chart experience with minimized UI chrome
- Auto-unlock device orientation (follows rotation in fullscreen, locks
to portrait when closed)
- Cross-platform safe area handling (iOS notch + Android navigation bar)
- OHLCV data bar shows Open/High/Low/Close/Volume values
**Key Changes**
- Added `PerpsChartFullscreenModal` component with orientation
management
- Added `PerpsOHLCVBar` component for real-time OHLC/volume display
- Enhanced `TradingViewChartTemplate` with multi-pane architecture (80%
candlesticks / 20% volume)
- Added `expo-screen-orientation` dependency for native orientation
control
- Updated Android/iOS config to support landscape orientation in
fullscreen only
## **Changelog**
CHANGELOG entry: Added fullscreen chart mode with landscape orientation
support and volume histogram for Perps trading
## **Related issues**
Relates to: Mobile Perps charting UX v2 PRD - Chart Foundations (P0)
## **Manual testing steps**
```gherkin
Feature: Fullscreen chart with volume histogram
Scenario: User views volume bars in market detail view
Given user is on Perps market detail screen
When user scrolls to chart section
Then volume histogram bars are visible below candlesticks
And volume values are formatted with K/M/B suffixes
And volume bars use green/red colors matching candle direction
Scenario: User enters fullscreen chart mode
Given user is on Perps market detail screen
When user taps fullscreen icon in chart header
Then chart expands to fullscreen modal
And header shows interval selector and close button
And volume bars are always visible
And device orientation unlocks to follow device rotation
Scenario: User rotates device in fullscreen
Given user is in fullscreen chart mode (portrait)
When user rotates device to landscape
Then chart automatically follows orientation change
And volume bars properly rescale to new dimensions
When user rotates device back to portrait
Then chart returns to portrait orientation
And volume bars rescale appropriately
Scenario: User exits fullscreen mode
Given user is in fullscreen chart mode (any orientation)
When user taps Close button (X icon)
Then chart exits fullscreen
And device orientation locks back to portrait
And user returns to market detail view
Scenario: Cross-platform safe area handling
Given user is on iOS device with notch
When user enters fullscreen chart mode
Then header content avoids notch area
And chart content avoids bottom safe area
```
## **Screenshots/Recordings**
### **Before**
- No volume data visible on chart
- No fullscreen/landscape mode
- Limited chart analysis capability on mobile
### **After**
**Volume Histogram in Market Detail View:**
- Volume bars visible below candlesticks with USD notional values
- Smart formatting: "120M" instead of "120,000,000"
- Color-coded green (up) / red (down)
**Fullscreen Modal - Portrait:**
- Clean fullscreen interface with minimal chrome
- Header: Interval selector (left), Close button (right)
- Volume bars always visible
- OHLCV data bar with proper padding
- Safe area handling for iOS notch and Android status bar
**Fullscreen Modal - Landscape:**
- Maximum screen real estate for chart analysis
- Volume bars automatically rescale after rotation
- Orientation locks back to portrait when exiting
https://github.com/user-attachments/assets/f9582cfa-fa5c-449b-a5de-d9750e0da05d
## **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]
> Adds a fullscreen Perps chart with device rotation handling,
introduces volume histogram and an OHLCV bar, upgrades the chart engine,
and wires in expo-screen-orientation with config and tests.
>
> - **Perps UI**:
> - Add `PerpsChartFullscreenModal` with orientation lock/unlock, header
controls, safe area handling, and tests.
> - Add `PerpsOHLCVBar` and render it in `PerpsMarketDetailsView` and
fullscreen modal.
> - Update `PerpsMarketHeader` to include a fullscreen button; minor
styles; make interval selector horizontally scrollable.
> - Enhance `PerpsMarketDetailsView`: integrate new components, skeleton
fallback, auto-zoom on interval change, improved error logging.
> - **Chart Engine**:
> - Extend `TradingViewChart` and template: volume histogram in separate
pane, OHLCV callbacks, overlay/volume toggles, pane sizing/resizing,
improved time/price formatting, and ref methods; expose `OhlcData`
types.
> - Adjust TPSL line styling/colors and add skeleton/error handling;
comprehensive unit tests added.
> - **Config/Dependencies**:
> - Add `expo-screen-orientation` (plugin, mock, Jest mapping); enable
landscape orientations in `ios/MetaMask/Info.plist`; register in
`app.config.js`; update Pods/Yarn.
> - **Logging/Services**:
> - Replace `console.error` with `Logger.error` in Perps flows; add
error logging in `HyperLiquidSubscriptionService` unsubscriptions.
> - **Selectors/i18n**:
> - Add E2E selectors for OHLCV bar and fullscreen modal; add i18n
strings for OHLC labels.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5032204. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Nicholas Smith <nick.smith@consensys.net>1 parent 7fd610b commit 2373d09
31 files changed
Lines changed: 2295 additions & 170 deletions
File tree
- app
- __mocks__
- components/UI/Perps
- Views/PerpsMarketDetailsView
- components
- PerpsCandlestickChartIntervalSelector
- PerpsChartFullscreenModal
- PerpsMarketHeader
- PerpsOHLCVBar
- TradingViewChart
- constants
- providers
- services
- utils
- e2e/selectors/Perps
- ios
- MetaMask
- locales/languages
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
33 | 39 | | |
34 | 40 | | |
35 | 41 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
Lines changed: 120 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
22 | 41 | | |
23 | 42 | | |
24 | 43 | | |
| |||
59 | 78 | | |
60 | 79 | | |
61 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
62 | 95 | | |
63 | 96 | | |
64 | 97 | | |
| |||
1428 | 1461 | | |
1429 | 1462 | | |
1430 | 1463 | | |
1431 | | - | |
1432 | | - | |
| 1464 | + | |
1433 | 1465 | | |
1434 | 1466 | | |
1435 | 1467 | | |
| |||
1449 | 1481 | | |
1450 | 1482 | | |
1451 | 1483 | | |
1452 | | - | |
| 1484 | + | |
1453 | 1485 | | |
1454 | | - | |
1455 | | - | |
| 1486 | + | |
1456 | 1487 | | |
| 1488 | + | |
| 1489 | + | |
| 1490 | + | |
| 1491 | + | |
1457 | 1492 | | |
1458 | 1493 | | |
| 1494 | + | |
| 1495 | + | |
1459 | 1496 | | |
1460 | | - | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
| 1513 | + | |
| 1514 | + | |
| 1515 | + | |
| 1516 | + | |
| 1517 | + | |
| 1518 | + | |
| 1519 | + | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
| 1551 | + | |
| 1552 | + | |
| 1553 | + | |
| 1554 | + | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
1461 | 1575 | | |
1462 | 1576 | | |
1463 | 1577 | | |
| |||
0 commit comments