Skip to content

feat(LineChart): add React Native support - #3718

Merged
rohitr-raz merged 20 commits into
masterfrom
feat/blade-rn/LineChart
Jul 15, 2026
Merged

feat(LineChart): add React Native support#3718
rohitr-raz merged 20 commits into
masterfrom
feat/blade-rn/LineChart

Conversation

@rohitr-raz

@rohitr-raz rohitr-raz commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds React Native support for LineChart via a new LineChart.native.tsx implementation:

  • SVG-based native line rendering
  • Tap-to-stay scrub tooltip on a single responder surface
  • Reference lines with label placement matching web
  • Opaque tooltip styled to match the web appearance

Also includes native unit tests + snapshots and a minor story tweak.

Screen.Recording.2026-07-15.at.2.16.38.PM.mov

Test plan

  • Native unit tests pass (LineChart.native.test.tsx)
  • Typecheck clean
  • Verified on iOS simulator: line rendering, tap-to-stay scrub tooltip, and reference-line label placement

Made with Cursor

Add SVG-based `LineChart.native.tsx` implementation with:
- native line rendering
- tap-to-stay scrub tooltip on a single responder surface
- reference lines with web-matching label placement
- opaque tooltip matching the web appearance

Includes native unit tests and snapshots, plus a story tweak.

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot

changeset-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c5ad72e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@razorpay/blade Minor

Not sure what this means? Click here to learn what changesets are.

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

@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@rzpcibot

rzpcibot commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

🛡️ Coverage Report

Summary


=============================== Coverage summary ===============================
Statements   : 81.74% ( 10743/13142 )
Branches     : 68.19% ( 6717/9850 )
Functions    : 81.01% ( 2471/3050 )
Lines        : 82.63% ( 10482/12684 )
================================================================================
Full Coverage Details
---------------------------------------|---------|----------|---------|---------|-------------------
File                                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------------------------------|---------|----------|---------|---------|-------------------
All files                              |   81.74 |    68.19 |   81.01 |   82.63 |                   
 blade                                 |     100 |      100 |     100 |     100 |                   
  jestStyledComponentsSerializer.js    |     100 |      100 |     100 |     100 |                   
 ...odemods/brand-refresh/transformers |    89.1 |     89.6 |   98.85 |   88.99 |                   
  index.ts                             |   88.23 |    84.37 |     100 |   88.23 | ...15,144,179,215 
  migrate-actionlist-and-table.ts      |      75 |      100 |     100 |      75 | 23                
  migrate-amount.ts                    |   86.48 |       75 |     100 |   86.48 | 27-31,101,133,164 
  migrate-badge.ts                     |      75 |      100 |     100 |      75 | 21                
  migrate-card.ts                      |    87.5 |      100 |     100 |    87.5 | 36                
  ...te-contrast-intent-color-props.ts |   89.83 |      100 |     100 |   89.65 | ...28,153,245,291 
  migrate-divider.ts                   |   83.33 |      100 |     100 |   83.33 | 31                
  migrate-dropdown.ts                  |   91.66 |      100 |     100 |   91.66 | 72                
  migrate-typography.ts                |    90.9 |    88.13 |   96.96 |   90.82 | ...34,245,325,355 
  utils.ts                             |     100 |      100 |     100 |     100 |                   
 ...migrate-motion-tokens/transformers |    87.5 |       50 |     100 |    87.5 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  migrate-motion.ts                    |    87.5 |       50 |     100 |    87.5 | 18                
 ...s/migrate-progressbar/transformers |   78.26 |       75 |     100 |   78.26 |                   
  index.ts                             |   78.26 |       75 |     100 |   78.26 | 9,39,64-68,78     
 blade/src/components/Accordion        |    87.5 |    69.29 |   95.83 |   89.83 |                   
  Accordion.tsx                        |     100 |      100 |     100 |     100 |                   
  AccordionButton.web.tsx              |   93.33 |    68.75 |     100 |    92.3 | 41                
  AccordionContext.tsx                 |   85.71 |       50 |     100 |   85.71 | 29,42             
  AccordionItem.tsx                    |   88.23 |       88 |     100 |   88.23 | 98,112            
  AccordionItemBody.tsx                |     100 |    58.33 |     100 |     100 | 58-61             
  AccordionItemHeader.tsx              |      68 |    45.45 |      75 |   80.95 | 21-22,63,70       
  AccordionSurface.web.tsx             |     100 |      100 |     100 |     100 |                   
  StyledAccordionButton.web.tsx        |   82.35 |    77.77 |     100 |   81.25 | 24-30             
  commonStyles.ts                      |     100 |      100 |     100 |     100 |                   
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  styles.web.ts                        |     100 |      100 |     100 |     100 |                   
 blade/src/components/ActionList       |   70.41 |    53.47 |   69.35 |   70.56 |                   
  ActionList.tsx                       |     100 |      100 |     100 |     100 |                   
  ActionListBox.web.tsx                |   67.08 |    40.47 |   73.68 |   67.08 | ...00,243,318-326 
  ActionListItem.tsx                   |   67.12 |    47.54 |      55 |   68.05 | ...19,361,392,414 
  ActionListItemAsset.web.tsx          |     100 |      100 |     100 |     100 |                   
  ActionListNoResults.tsx              |     100 |      100 |     100 |     100 |                   
  actionListUtils.ts                   |   63.63 |    50.94 |   69.23 |   63.07 | ...09,223,240,247 
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  getA11yRoles.ts                      |   82.14 |    80.95 |      80 |   82.14 | 33,48-52,81       
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/ActionList/styles |     100 |      100 |     100 |     100 |                   
  StyledListBoxWrapper.web.tsx         |     100 |      100 |     100 |     100 |                   
  getBaseListBoxWrapperStyles.ts       |     100 |      100 |     100 |     100 |                   
 blade/src/components/Alert            |   80.55 |    75.96 |     100 |      80 |                   
  Alert.tsx                            |   77.04 |     73.5 |     100 |   76.27 | ...91,264-266,305 
  StyledAlert.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  styles.ts                            |     100 |      100 |     100 |     100 |                   
 blade/src/components/Amount           |    87.8 |    70.43 |   81.81 |    88.6 |                   
  Amount.tsx                           |   87.17 |    70.43 |   81.81 |      88 | ...16,350,416-417 
  amountTokens.ts                      |     100 |      100 |     100 |     100 |                   
  index.tsx                            |       0 |        0 |       0 |       0 |                   
 ...src/components/AnimateInteractions |   76.92 |    28.57 |   55.55 |      80 |                   
  AnimateInteractions.web.tsx          |   71.42 |      100 |   33.33 |   71.42 | 43-46             
  AnimateInteractionsProvider.tsx      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useFocusWithin.ts                    |   73.33 |    16.66 |      60 |   78.57 | 17,22-23          
 .../src/components/AnnouncementBanner |     100 |      100 |     100 |     100 |                   
  AnnouncementBanner.tsx               |     100 |      100 |     100 |     100 |                   
  StyledAnnouncementBanner.tsx         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  styles.ts                            |     100 |      100 |     100 |     100 |                   
 blade/src/components/AppBar           |   97.22 |     86.2 |     100 |   97.22 |                   
  AppBar.web.tsx                       |   96.15 |     86.2 |     100 |   96.15 | 253               
  AppBarContext.tsx                    |     100 |      100 |     100 |     100 |                   
  appBarTokens.ts                      |     100 |      100 |     100 |     100 |                   
 blade/src/components/Avatar           |   94.44 |    80.61 |    90.9 |   94.44 |                   
  Avatar.web.tsx                       |   95.83 |    76.31 |     100 |   95.83 | 74                
  AvatarButton.tsx                     |     100 |    88.88 |     100 |     100 | 19-21             
  AvatarGroup.web.tsx                  |   93.33 |    81.25 |     100 |   93.33 | 43                
  AvatarGroupContext.tsx               |     100 |      100 |     100 |     100 |                   
  StyledAvatar.tsx                     |     100 |      100 |     100 |     100 |                   
  StyledAvatarButton.tsx               |     100 |    69.23 |     100 |     100 | 11-13,25          
  StyledAvatarGroup.tsx                |     100 |      100 |     100 |     100 |                   
  TrustedBadgeIcon.web.tsx             |   33.33 |      100 |       0 |   33.33 | 6-7               
  avatarTokens.ts                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Badge            |     100 |     91.3 |     100 |     100 |                   
  Badge.tsx                            |     100 |     91.3 |     100 |     100 | 112,152           
  StyledBadge.web.tsx                  |     100 |      100 |     100 |     100 |                   
  badgeTokens.ts                       |     100 |      100 |     100 |     100 |                   
  getStyledBadgeStyles.ts              |     100 |      100 |     100 |     100 |                   
  index.tsx                            |       0 |        0 |       0 |       0 |                   
 blade/src/components/BaseHeaderFooter |   94.11 |    79.31 |      90 |   94.11 |                   
  BaseFooter.tsx                       |     100 |    85.71 |     100 |     100 | 34                
  BaseHeader.tsx                       |   93.75 |    78.75 |   88.88 |   93.75 | 340,383,421       
 blade/src/components/BaseMenu         |     100 |      100 |     100 |     100 |                   
  BaseMenuContext.ts                   |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
 ...c/components/BaseMenu/BaseMenuItem |     100 |    85.18 |     100 |     100 |                   
  BaseMenuItem.tsx                     |     100 |    84.21 |     100 |     100 | 69,109,121        
  StyledMenuItemContainer.web.tsx      |     100 |      100 |     100 |     100 |                   
  getBaseMenuItemStyles.ts             |     100 |       50 |     100 |     100 | 11                
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
 blade/src/components/BaseMotion       |   97.43 |    91.42 |     100 |   97.43 |                   
  BaseMotion.tsx                       |     100 |     91.3 |     100 |     100 | 101,127           
  baseMotionUtils.ts                   |   94.44 |    91.66 |     100 |   94.44 | 33                
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/BladeProvider    |   91.17 |       75 |   83.33 |    90.9 |                   
  BladeProvider.web.tsx                |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  stylisCSSHigherSpecificity.ts        |     100 |      100 |     100 |     100 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
  useBladeProvider.ts                  |     100 |     87.5 |     100 |     100 | 32                
  useTheme.ts                          |      70 |       50 |      50 |      70 | 21,28,34          
 blade/src/components/BottomNav        |   94.44 |    78.26 |     100 |   94.44 |                   
  BottomNav.web.tsx                    |   94.44 |    78.26 |     100 |   94.44 | 76                
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/BottomSheet      |   83.33 |    75.43 |   79.72 |   83.62 |                   
  BottomSheet.web.tsx                  |   81.21 |    68.04 |   89.65 |   81.25 | ...76-382,389-396 
  BottomSheetBackdrop.web.tsx          |     100 |      100 |     100 |     100 |                   
  BottomSheetBody.web.tsx              |   94.73 |    93.75 |     100 |     100 | 35                
  BottomSheetCommon.tsx                |    87.5 |    83.33 |     100 |    87.5 | 59                
  BottomSheetContext.ts                |     100 |      100 |      25 |     100 |                   
  BottomSheetFooter.web.tsx            |     100 |      100 |     100 |     100 |                   
  BottomSheetGrabHandle.web.tsx        |     100 |      100 |     100 |     100 |                   
  BottomSheetHeader.web.tsx            |   93.33 |    94.73 |     100 |     100 | 38                
  BottomSheetStack.tsx                 |   92.85 |      100 |   71.42 |   91.66 | 17-19             
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  getBottomSheetGrabHandleStyles.ts    |     100 |       75 |     100 |     100 | 38                
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
  utils.ts                             |   16.66 |    14.28 |      50 |   16.66 | 11-25             
 blade/src/components/Box              |   96.42 |    78.57 |     100 |   96.42 |                   
  Box.tsx                              |   96.42 |    78.57 |     100 |   96.42 | 239               
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Box/BaseBox      |   94.38 |    94.31 |     100 |   94.31 |                   
  BaseBox.web.tsx                      |     100 |      100 |     100 |     100 |                   
  baseBoxStyles.ts                     |    98.3 |    96.96 |     100 |   98.27 | 308               
  getResponsiveValue.web.ts            |      90 |    92.85 |     100 |      90 | 67                
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useMemoizedStyles.web.ts             |      80 |        0 |     100 |      80 | 22-30             
 ...e/src/components/Box/BaseBox/types |     100 |      100 |     100 |     100 |                   
  propsTypes.ts                        |     100 |      100 |     100 |     100 |                   
 blade/src/components/Box/styledProps  |     100 |      100 |     100 |     100 |                   
  getStyledProps.ts                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useStyledProps.ts                    |     100 |      100 |     100 |     100 |                   
 blade/src/components/Breadcrumb       |     100 |       72 |     100 |     100 |                   
  Breadcrumb.web.tsx                   |     100 |     92.3 |     100 |     100 | 20                
  BreadcrumbContext.tsx                |     100 |      100 |     100 |     100 |                   
  BreadcrumbItem.web.tsx               |     100 |       50 |     100 |     100 | 25-53             
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Button           |       0 |        0 |       0 |       0 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Button/BaseButton |   77.32 |    78.08 |      90 |   79.14 |                   
  AnimatedButtonContent.web.tsx        |     100 |      100 |     100 |     100 |                   
  BaseButton.tsx                       |    73.1 |    76.96 |   86.36 |      75 | ...05-329,616-621 
  StyledBaseButton.web.tsx             |     100 |    76.47 |     100 |     100 | 25,45-56,70       
  buttonTokens.ts                      |     100 |      100 |     100 |     100 |                   
  getStyledBaseButtonStyles.ts         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Button/Button    |     100 |      100 |     100 |     100 |                   
  Button.tsx                           |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Button/IconButton |    91.3 |    70.73 |     100 |    91.3 |                   
  IconButton.tsx                       |     100 |      100 |     100 |     100 |                   
  StyledIconButton.web.tsx             |    87.5 |    69.23 |     100 |    87.5 | 41-45             
  index.ts                             |       0 |        0 |       0 |       0 |                   
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
 blade/src/components/ButtonGroup      |   88.46 |       72 |     100 |   88.46 |                   
  ButtonGroup.web.tsx                  |   81.25 |    66.66 |     100 |   81.25 | 31-39             
  ButtonGroupContext.tsx               |     100 |      100 |     100 |     100 |                   
  StyledButtonGroup.tsx                |     100 |       80 |     100 |     100 | 8                 
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Card             |   59.58 |    41.44 |   44.44 |   61.47 |                   
  Card.tsx                             |   92.59 |    80.85 |     100 |     100 | 278-288,324-337   
  CardContext.tsx                      |     100 |       75 |     100 |     100 | 9                 
  CardFooter.tsx                       |     100 |    63.82 |     100 |     100 | ...49-158,172-174 
  CardHeader.tsx                       |   82.97 |       80 |      60 |   82.97 | ...72,79-81,95-97 
  CardInfoSurface.tsx                  |      25 |        0 |       0 |      25 | 35-38             
  CardRoot.web.tsx                     |   81.81 |    77.27 |   71.42 |   89.47 | 96-97             
  CardSurface.web.tsx                  |     100 |    33.33 |     100 |     100 | 14-20             
  CardTicketSurface.web.tsx            |   14.58 |        0 |       0 |   15.21 | ...,84-86,125-181 
  InfoCard.tsx                         |      50 |        0 |       0 |      50 | 59-90             
  LinkOverlay.web.tsx                  |     100 |      100 |     100 |     100 |                   
  TicketCard.tsx                       |      50 |        0 |       0 |      50 | 59-90             
  constants.ts                         |     100 |      100 |     100 |     100 |                   
  createSectionedCardSlot.tsx          |      75 |      100 |      50 |      75 | 18                
  index.ts                             |       0 |        0 |       0 |       0 |                   
  sectionedCardConstants.ts            |     100 |      100 |     100 |     100 |                   
  splitSectionedCardChildren.ts        |    7.14 |        0 |       0 |    7.14 | 23-50             
  useSectionedCardState.ts             |    5.55 |        0 |       0 |    6.25 | 43-71             
 blade/src/components/Carousel         |    71.5 |    64.74 |   61.11 |   74.13 |                   
  Carousel.web.tsx                     |    67.7 |    66.15 |   56.25 |   70.46 | ...75,489,545-565 
  CarouselContext.tsx                  |   83.33 |       50 |     100 |   83.33 | 30                
  CarouselItem.web.tsx                 |     100 |    58.33 |     100 |     100 | 44-53,76-77       
  constants.ts                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
  utils.ts                             |     100 |      100 |     100 |     100 |                   
 ...src/components/Carousel/Indicators |   74.35 |     40.9 |   55.55 |   76.31 |                   
  CircularIndicatorButton.web.tsx      |   57.89 |        0 |       0 |   61.11 | 29,64-76          
  IndicatorButton.tsx                  |     100 |      100 |     100 |     100 |                   
  Indicators.web.tsx                   |   81.81 |       50 |   66.66 |   81.81 | 26,40             
  StyledIndicatorButton.web.tsx        |     100 |      100 |     100 |     100 |                   
  getIndicatorButtonStyles.ts          |     100 |     87.5 |     100 |     100 | 32                
 ...mponents/Carousel/NavigationButton |   80.76 |    55.55 |      80 |   80.76 |                   
  NavigationButton.tsx                 |   61.53 |       60 |   66.66 |   61.53 | 23-28,34-37       
  StyledNavigationButton.web.tsx       |     100 |      100 |     100 |     100 |                   
  getNavigationButtonStyles.ts         |     100 |       50 |     100 |     100 | 11-70             
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Charts           |       0 |        0 |       0 |       0 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Charts/AreaChart |   91.48 |    72.97 |   88.88 |    91.3 |                   
  AreaChart.web.tsx                    |    91.3 |    72.97 |   88.88 |   91.11 | 193-197           
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Charts/BarChart  |   89.39 |    64.44 |   78.57 |   89.06 |                   
  BarChart.web.tsx                     |    87.5 |    64.44 |   76.92 |   87.27 | ...49-253,288-291 
  BarChartContext.ts                   |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
 ...nents/Charts/CommonChartComponents |   74.45 |    61.72 |   82.22 |   74.42 |                   
  CommonChartComponents.web.tsx        |      80 |    64.18 |   85.36 |      80 | ...94-810,839-840 
  CommonChartComponentsContext.tsx     |      60 |      100 |   33.33 |      60 | 6-9               
  index.ts                             |       0 |        0 |       0 |       0 |                   
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
  utils.ts                             |   36.11 |    35.71 |     100 |   35.29 | 45-82             
 ...e/src/components/Charts/DonutChart |   79.88 |    66.38 |   77.77 |    82.2 |                   
  DonutChart.web.tsx                   |   79.04 |    66.38 |   77.77 |   81.41 | ...75,513,562-565 
  index.ts                             |       0 |        0 |       0 |       0 |                   
  tokens.tsx                           |     100 |      100 |     100 |     100 |                   
 blade/src/components/Charts/LineChart |   83.33 |    80.43 |    61.9 |   82.35 |                   
  LineChart.web.tsx                    |   83.58 |    80.43 |   63.15 |   82.81 | ...07,235-239,270 
  LineChartContext.tsx                 |      75 |      100 |      50 |   66.66 | 10                
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../src/components/Charts/SankeyChart |   91.16 |    72.51 |   97.72 |   92.02 |                   
  SankeyChart.web.tsx                  |    92.1 |     72.8 |   97.67 |   93.25 | ...21,505-507,735 
  humanizeIndian.ts                    |   63.63 |    66.66 |     100 |   63.63 | 5-6,9-10          
  index.ts                             |       0 |        0 |       0 |       0 |                   
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
 blade/src/components/Charts/utils     |   78.57 |    73.91 |     100 |   78.57 |                   
  getHighestColorInRange.ts            |   73.33 |    66.66 |     100 |   73.33 | 22-23,50-53       
  index.tsx                            |       0 |        0 |       0 |       0 |                   
  isSequentialColor.tsx                |      50 |       50 |     100 |      50 | 25-31             
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
  useColorTheme.tsx                    |   93.75 |    83.33 |     100 |   93.75 | 47                
 ...harts/utils/assignDataColorMapping |     100 |      100 |     100 |     100 |                   
  assignDataColorMapping.ts            |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...onents/Charts/utils/sanitizeString |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  sanitizeString.ts                    |     100 |      100 |     100 |     100 |                   
 blade/src/components/ChatInput        |   70.28 |    63.04 |   67.56 |   74.38 |                   
  ChatInput.web.tsx                    |   82.75 |    71.42 |   66.66 |   82.14 | ...62,194-195,317 
  ChatInputActionBar.tsx               |     100 |    71.42 |     100 |     100 | 21-34             
  ChatInputGhostSuggestion.tsx         |      80 |       75 |     100 |     100 | 20                
  chatInputTokens.ts                   |     100 |      100 |     100 |     100 |                   
  getChatInputSubmitDisabled.ts        |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useChatInput.web.ts                  |   61.11 |    52.08 |   59.09 |   65.78 | ...96-198,205-219 
 blade/src/components/ChatMessage      |   39.42 |    32.57 |   23.33 |   41.83 |                   
  ChatMessage.web.tsx                  |     100 |    84.84 |     100 |     100 | 32,64,70,112      
  DefaultMessageBubble.web.tsx         |     100 |     40.9 |     100 |     100 | 30-71             
  ReasoningTraces.web.tsx              |    12.5 |        0 |       0 |      14 | ...79,114,163-273 
  Rotate.web.tsx                       |     100 |      100 |     100 |     100 |                   
  SelfMessageBubble.web.tsx            |     100 |       80 |     100 |     100 | 30                
  ThumbnailPreview.web.tsx             |   26.31 |        0 |       0 |   26.31 | 23,33-37,55-106   
  token.ts                             |     100 |      100 |     100 |     100 |                   
  utils.ts                             |     100 |      100 |     100 |     100 |                   
 blade/src/components/Checkbox         |   90.76 |    89.61 |     100 |   92.18 |                   
  Checkbox.tsx                         |     100 |    94.23 |     100 |     100 | 151,158,238       
  checkboxTokens.ts                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useCheckbox.ts                       |      80 |       80 |     100 |   82.75 | 58,72-74,112      
 .../components/Checkbox/CheckboxGroup |   85.36 |    77.14 |   86.66 |   86.48 |                   
  CheckboxGroup.tsx                    |     100 |    95.23 |     100 |     100 | 166               
  CheckboxGroupContext.ts              |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useCheckboxGroup.ts                  |   76.92 |       50 |   83.33 |   77.27 | 60-64,71,79       
 ...c/components/Checkbox/CheckboxIcon |     100 |    96.42 |     100 |     100 |                   
  CheckboxIcon.tsx                     |     100 |      100 |     100 |     100 |                   
  CheckboxIconWrapper.web.tsx          |     100 |      100 |     100 |     100 |                   
  CheckboxIconWrapperStyles.ts         |     100 |    91.66 |     100 |     100 | 31                
  Fade.web.tsx                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Chip             |   91.24 |    82.94 |     100 |   94.53 |                   
  AnimatedChip.web.tsx                 |     100 |      100 |     100 |     100 |                   
  Chip.tsx                             |   91.37 |    81.48 |     100 |   98.14 | 74                
  ChipGroup.tsx                        |   83.33 |    91.17 |     100 |   83.33 | 59,65             
  ChipGroupContext.tsx                 |    87.5 |       50 |     100 |    87.5 | 12                
  StyledChipWrapper.web.tsx            |     100 |    88.88 |     100 |     100 | 10                
  chipTokens.ts                        |     100 |       50 |     100 |     100 | 163               
  getAnimatedChipStyles.ts             |     100 |    33.33 |     100 |     100 | 11-29             
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useChipGroup.ts                      |    87.5 |    85.71 |     100 |   88.88 | 64,75,78          
 blade/src/components/Collapsible      |   88.18 |    75.67 |   86.66 |   87.61 |                   
  Collapsible.tsx                      |   94.44 |    92.85 |     100 |   94.44 | 130               
  CollapsibleBody.tsx                  |     100 |      100 |     100 |     100 |                   
  CollapsibleBodyContent.web.tsx       |   76.47 |       50 |      70 |   76.47 | 69,109-119        
  CollapsibleButton.tsx                |     100 |       50 |     100 |     100 | 51                
  CollapsibleChevronIcon.web.tsx       |     100 |      100 |     100 |     100 |                   
  CollapsibleContext.ts                |   85.71 |       50 |     100 |   85.71 | 19                
  CollapsibleLink.tsx                  |     100 |      100 |     100 |     100 |                   
  CollapsibleText.web.tsx              |   72.72 |    71.42 |   66.66 |   72.72 | 35-37             
  commonStyles.ts                      |     100 |       75 |     100 |     100 | 23-24             
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  styles.web.ts                        |     100 |      100 |     100 |     100 |                   
 blade/src/components/Counter          |     100 |    84.21 |     100 |     100 |                   
  Counter.tsx                          |     100 |    84.21 |     100 |     100 | 56-57,122         
  StyledCounter.web.tsx                |     100 |      100 |     100 |     100 |                   
  counterTokens.ts                     |     100 |      100 |     100 |     100 |                   
  getStyledCounterStyles.ts            |     100 |      100 |     100 |     100 |                   
  index.tsx                            |       0 |        0 |       0 |       0 |                   
 blade/src/components/CounterInput     |      90 |    77.63 |      96 |      95 |                   
  CounterInput.web.tsx                 |   88.75 |    77.63 |   95.65 |   94.28 | 149-154           
  CounterInputContext.tsx              |     100 |      100 |     100 |     100 |                   
  StyledCounterInput.tsx               |     100 |      100 |     100 |     100 |                   
  token.ts                             |     100 |      100 |     100 |     100 |                   
 blade/src/components/DatePicker       |   56.07 |    44.06 |   66.91 |   56.22 |                   
  BaseDatePicker.web.tsx               |      60 |    59.79 |   56.25 |   60.25 | ...11,449,530-564 
  Calendar.web.tsx                     |   61.01 |    78.57 |    37.5 |   61.81 | ...42-146,161-179 
  CalendarFooter.web.tsx               |    87.5 |       75 |     100 |     100 | 27,33,42-44       
  CalendarHeader.web.tsx               |   54.54 |    54.54 |      50 |   54.54 | ...09-120,172-181 
  CalendarStyles.web.tsx               |     100 |     77.5 |     100 |     100 | 171-306           
  DateInput.web.tsx                    |   69.76 |    45.63 |   84.61 |   70.58 | ...51,304,310,515 
  DatePicker.web.tsx                   |     100 |      100 |     100 |     100 |                   
  DatePickerContext.tsx                |     100 |      100 |     100 |     100 |                   
  constants.ts                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  shiftTimezone.tsx                    |      65 |    64.28 |      75 |   63.15 | 10-13,29-33       
  useControlledDates.ts                |   34.78 |       16 |     100 |   34.78 | 42-73             
  useDatesState.ts                     |      50 |    52.94 |   78.57 |      50 | ...32-133,143,158 
  usePopup.ts                          |   94.73 |    58.33 |     100 |   94.73 | 46                
  utils.ts                             |   35.71 |    21.55 |   77.27 |   34.35 | ...81-421,484-710 
 ...ts/DatePicker/FilterChipDatePicker |   16.66 |        0 |       0 |   16.66 |                   
  DatePickerFilterChip.web.tsx         |   13.63 |        0 |       0 |   13.63 | 15-38,64-95       
  FilterChipDatePicker.web.tsx         |      50 |      100 |       0 |      50 | 5                 
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...mponents/DatePicker/QuickSelection |   41.66 |    20.75 |   17.64 |   44.44 |                   
  PresetSideBar.web.tsx                |   23.07 |    16.66 |   16.66 |   18.18 | 18-65             
  QuickSelectionItem.web.tsx           |      50 |        0 |       0 |      50 | 14                
  renderPresetDropdown.web.tsx         |   16.66 |        0 |       0 |   16.66 | 14-29             
  usePresetState.ts                    |   57.57 |    34.48 |   33.33 |   61.29 | ...36,57,69,86-96 
  utils.ts                             |   16.66 |        0 |       0 |      25 | 8-11              
 blade/src/components/Divider          |     100 |       90 |     100 |     100 |                   
  Divider.tsx                          |     100 |       90 |     100 |     100 | 80                
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Drawer           |    92.3 |       80 |   77.77 |    92.3 |                   
  Drawer.web.tsx                       |   88.23 |    76.74 |      80 |   88.23 | 135-136,217-218   
  DrawerContext.ts                     |     100 |      100 |       0 |     100 |                   
  DrawerSubcomponents.web.tsx          |   95.45 |      100 |   83.33 |   95.45 | 49                
  StackProvider.tsx                    |      95 |       50 |      80 |      95 | 37                
  drawerComponentIds.ts                |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Dropdown         |   65.53 |    57.29 |   55.33 |   67.33 |                   
  Dropdown.tsx                         |   96.72 |    78.26 |     100 |   96.66 | 136,158           
  DropdownButton.tsx                   |     100 |      100 |     100 |     100 |                   
  DropdownHeaderFooter.tsx             |   78.57 |       50 |      75 |   78.57 | 49-52             
  DropdownIconButton.tsx               |   22.22 |        0 |       0 |   22.22 | 38-70             
  DropdownLink.tsx                     |   77.77 |    83.33 |      75 |   77.77 | 79-81             
  DropdownOverlay.web.tsx              |     100 |    96.55 |     100 |     100 | 136               
  FilterChipGroup.web.tsx              |    9.09 |        0 |       0 |      10 | 17-28             
  FilterChipGroupContext.web.tsx       |     100 |      100 |   66.66 |     100 |                   
  FilterChipSelectInput.web.tsx        |   54.36 |    48.68 |      40 |    57.6 | ...89,196-207,231 
  InputDropdownButton.web.tsx          |   46.42 |     30.3 |   33.33 |      52 | 184,206-225       
  StyledDropdownOverlay.tsx            |     100 |       75 |     100 |     100 | 18                
  dropdownComponentIds.ts              |     100 |      100 |     100 |     100 |                   
  dropdownUtils.ts                     |   54.28 |    53.27 |   53.33 |   54.45 | ...73-276,292-307 
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
  useDropdown.ts                       |   69.56 |    66.66 |   58.82 |   70.78 | ...19-438,463,468 
 blade/src/components/Elevate          |     100 |      100 |     100 |     100 |                   
  Elevate.web.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/EmptyState       |     100 |      100 |     100 |     100 |                   
  EmptyState.web.tsx                   |     100 |      100 |     100 |     100 |                   
  emptyStateTokens.ts                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Fade             |     100 |       60 |     100 |     100 |                   
  Fade.web.tsx                         |     100 |       60 |     100 |     100 | 41-61             
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/FileUpload       |   51.42 |    55.65 |    37.5 |   54.87 |                   
  FileUpload.web.tsx                   |   43.28 |    51.67 |   25.71 |   47.89 | ...20-227,374-460 
  FileUploadItem.tsx                   |   69.23 |    68.75 |   42.85 |   69.23 | 110-122,150-156   
  FileUploadItemIcon.tsx               |   40.62 |    30.76 |     100 |   40.62 | 42-61,72-75       
  StyledFileUploadItemWrapper.web.tsx  |     100 |       75 |     100 |     100 | 18-32             
  StyledFileUploadWrapper.web.tsx      |     100 |      100 |     100 |     100 |                   
  fileUploadTokens.ts                  |     100 |      100 |     100 |     100 |                   
  isFileAccepted.tsx                   |   78.57 |    58.33 |     100 |   78.57 | 19,24-27          
 blade/src/components/FilterChip       |   85.71 |    63.63 |   77.77 |   85.71 |                   
  BaseFilterChip.web.tsx               |      85 |    63.63 |   77.77 |      85 | 92,145-177        
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
 blade/src/components/Form             |   96.07 |    84.61 |     100 |   96.07 |                   
  FormHint.tsx                         |     100 |       88 |     100 |     100 | 30-35,114         
  FormHintWrapper.web.tsx              |     100 |      100 |     100 |     100 |                   
  FormLabel.tsx                        |   88.88 |     82.5 |     100 |   88.88 | 106,163           
  formTokens.ts                        |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useFormId.ts                         |     100 |      100 |     100 |     100 |                   
 ...c/components/Form/CharacterCounter |     100 |      100 |     100 |     100 |                   
  CharacterCounter.tsx                 |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Form/Selector    |   96.87 |    71.87 |     100 |     100 |                   
  SelectorGroupField.tsx               |   88.88 |    66.66 |     100 |     100 | 33-45             
  SelectorInput.web.tsx                |     100 |      100 |     100 |     100 |                   
  SelectorLabel.web.tsx                |     100 |      100 |     100 |     100 |                   
  SelectorSupportText.tsx              |     100 |       50 |     100 |     100 | 24-29             
  SelectorTitle.tsx                    |     100 |    66.66 |     100 |     100 | 7                 
 blade/src/components/GenUI            |   82.18 |    73.77 |   88.64 |   82.22 |                   
  GenUIComponents.web.tsx              |      90 |    78.01 |   94.73 |   89.68 | ...1303,1332,1691 
  GenUIContext.web.tsx                 |     100 |      100 |     100 |     100 |                   
  GenUIProvider.web.tsx                |     100 |      100 |     100 |     100 |                   
  GenUISchemaRenderer.web.tsx          |   85.71 |    80.76 |   76.92 |   86.76 | ...17-218,226-233 
  GenUISpacing.ts                      |     100 |    91.66 |     100 |     100 | 33,52             
  rehypeAnimate.ts                     |   18.33 |    15.78 |    9.09 |   19.29 | ...0,44-63,89-119 
 blade/src/components/Icons            |       0 |        0 |       0 |       0 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
 ...nts/Icons/AcceptPaymentsFilledIcon |     100 |      100 |     100 |     100 |                   
  AcceptPaymentsFilledIcon.tsx         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...omponents/Icons/AcceptPaymentsIcon |     100 |      100 |     100 |     100 |                   
  AcceptPaymentsIcon.tsx               |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../src/components/Icons/ActivityIcon |     100 |      100 |     100 |     100 |                   
  ActivityIcon.tsx                     |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...c/components/Icons/AddressBookIcon |     100 |      100 |     100 |     100 |                   
  AddressBookIcon.tsx                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ents/Icons/AffordabilityFilledIcon |     100 |      100 |     100 |     100 |                   
  AffordabilityFilledIcon.tsx          |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...components/Icons/AffordabilityIcon |     100 |      100 |     100 |     100 |                   
  AffordabilityIcon.tsx                |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...c/components/Icons/AgentStudioIcon |     100 |      100 |     100 |     100 |                   
  AgentStudioIcon.tsx                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Icons/AirplayIcon |     100 |      100 |     100 |     100 |                   
  AirplayIcon.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...c/components/Icons/AlertCircleIcon |     100 |      100 |     100 |     100 |                   
  AlertCircleIcon.tsx                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../components/Icons/AlertOctagonIcon |     100 |      100 |     100 |     100 |                   
  AlertOctagonIcon.tsx                 |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...src/components/Icons/AlertOnlyIcon |     100 |      100 |     100 |     100 |                   
  AlertOnlyIcon.tsx                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...components/Icons/AlertTriangleIcon |     100 |      100 |     100 |     100 |                   
  AlertTriangleIcon.tsx                |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...c/components/Icons/AlignCenterIcon |     100 |      100 |     100 |     100 |                   
  AlignCenterIcon.tsx                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../components/Icons/AlignJustifyIcon |     100 |      100 |     100 |     100 |                   
  AlignJustifyIcon.tsx                 |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...src/components/Icons/AlignLeftIcon |     100 |      100 |     100 |     100 |                   
  AlignLeftIcon.tsx                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...rc/components/Icons/AlignRightIcon |     100 |      100 |     100 |     100 |                   
  AlignRightIcon.tsx                   |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/AnchorIcon |     100 |      100 |     100 |     100 |                   
  AnchorIcon.tsx                       |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Icons/AndroidIcon |     100 |      100 |     100 |     100 |                   
  AndroidIcon.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../components/Icons/AnnouncementIcon |     100 |      100 |     100 |     100 |                   
  AnnouncementIcon.tsx                 |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../src/components/Icons/ApertureIcon |     100 |      100 |     100 |     100 |                   
  ApertureIcon.tsx                     |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../src/components/Icons/AppStoreIcon |     100 |      100 |     100 |     100 |                   
  AppStoreIcon.tsx                     |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/AppleIcon  |     100 |      100 |     100 |     100 |                   
  AppleIcon.tsx                        |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...src/components/Icons/ArrowDownIcon |     100 |      100 |     100 |     100 |                   
  ArrowDownIcon.tsx                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...components/Icons/ArrowDownLeftIcon |     100 |      100 |     100 |     100 |                   
  ArrowDownLeftIcon.tsx                |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...omponents/Icons/ArrowDownRightIcon |     100 |      100 |     100 |     100 |                   
  ArrowDownRightIcon.tsx               |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...src/components/Icons/ArrowLeftIcon |     100 |      100 |     100 |     100 |                   
  ArrowLeftIcon.tsx                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...rc/components/Icons/ArrowRightIcon |     100 |      100 |     100 |     100 |                   
  ArrowRightIcon.tsx                   |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...mponents/Icons/ArrowSquareDownIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareDownIcon.tsx              |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ents/Icons/ArrowSquareDownLeftIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareDownLeftIcon.tsx          |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...nts/Icons/ArrowSquareDownRightIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareDownRightIcon.tsx         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...mponents/Icons/ArrowSquareLeftIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareLeftIcon.tsx              |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ponents/Icons/ArrowSquareRightIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareRightIcon.tsx             |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...components/Icons/ArrowSquareUpIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareUpIcon.tsx                |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...onents/Icons/ArrowSquareUpLeftIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareUpLeftIcon.tsx            |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...nents/Icons/ArrowSquareUpRightIcon |     100 |      100 |     100 |     100 |                   
  ArrowSquareUpRightIcon.tsx           |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Icons/ArrowUpIcon |     100 |      100 |     100 |     100 |                   
  ArrowUpIcon.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...c/components/Icons/ArrowUpLeftIcon |     100 |      100 |     100 |     100 |                   
  ArrowUpLeftIcon.tsx                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../components/Icons/ArrowUpRightIcon |     100 |      100 |     100 |     100 |                   
  ArrowUpRightIcon.tsx                 |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/AtSignIcon |     100 |      100 |     100 |     100 |                   
  AtSignIcon.tsx                       |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...rc/components/Icons/AttachmentIcon |     100 |      100 |     100 |     100 |                   
  AttachmentIcon.tsx                   |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...nents/Icons/AutomateAccountingIcon |     100 |      100 |     100 |     100 |                   
  AutomateAccountingIcon.tsx           |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ts/Icons/AutomatePayrollFilledIcon |     100 |      100 |     100 |     100 |                   
  AutomatePayrollFilledIcon.tsx        |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...mponents/Icons/AutomatePayrollIcon |     100 |      100 |     100 |     100 |                   
  AutomatePayrollIcon.tsx              |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/AwardIcon  |     100 |      100 |     100 |     100 |                   
  AwardIcon.tsx                        |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../BankAccountVerificationFilledIcon |     100 |      100 |     100 |     100 |                   
  ...AccountVerificationFilledIcon.tsx |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../Icons/BankAccountVerificationIcon |     100 |      100 |     100 |     100 |                   
  BankAccountVerificationIcon.tsx      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BankIcon   |     100 |      100 |     100 |     100 |                   
  BankIcon.tsx                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...c/components/Icons/BarChartAltIcon |     100 |      100 |     100 |     100 |                   
  BarChartAltIcon.tsx                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../src/components/Icons/BarChartIcon |     100 |      100 |     100 |     100 |                   
  BarChartIcon.tsx                     |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Icons/BarCodeIcon |     100 |      100 |     100 |     100 |                   
  BarCodeIcon.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...onents/Icons/Battery100PercentIcon |     100 |      100 |     100 |     100 |                   
  Battery100PercentIcon.tsx            |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ponents/Icons/Battery20PercentIcon |     100 |      100 |     100 |     100 |                   
  Battery20PercentIcon.tsx             |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ponents/Icons/Battery40PercentIcon |     100 |      100 |     100 |     100 |                   
  Battery40PercentIcon.tsx             |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ponents/Icons/Battery60PercentIcon |     100 |      100 |     100 |     100 |                   
  Battery60PercentIcon.tsx             |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...ponents/Icons/Battery80PercentIcon |     100 |      100 |     100 |     100 |                   
  Battery80PercentIcon.tsx             |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...mponents/Icons/BatteryChargingIcon |     100 |      100 |     100 |     100 |                   
  BatteryChargingIcon.tsx              |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Icons/BatteryIcon |     100 |      100 |     100 |     100 |                   
  BatteryIcon.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BellIcon   |     100 |      100 |     100 |     100 |                   
  BellIcon.tsx                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...e/src/components/Icons/BellOffIcon |     100 |      100 |     100 |     100 |                   
  BellOffIcon.tsx                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...rc/components/Icons/BfsiFilledIcon |     100 |      100 |     100 |     100 |                   
  BfsiFilledIcon.tsx                   |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BfsiIcon   |     100 |      100 |     100 |     100 |                   
  BfsiIcon.tsx                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BillIcon   |     100 |      100 |     100 |     100 |                   
  BillIcon.tsx                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../components/Icons/BillMeFilledIcon |     100 |      100 |     100 |     100 |                   
  BillMeFilledIcon.tsx                 |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BillMeIcon |     100 |      100 |     100 |     100 |                   
  BillMeIcon.tsx                       |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...src/components/Icons/BluetoothIcon |     100 |      100 |     100 |     100 |                   
  BluetoothIcon.tsx                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BoldIcon   |     100 |      100 |     100 |     100 |                   
  BoldIcon.tsx                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BookIcon   |     100 |      100 |     100 |     100 |                   
  BookIcon.tsx                         |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../src/components/Icons/BookmarkIcon |     100 |      100 |     100 |     100 |                   
  BookmarkIcon.tsx                     |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BoxIcon    |     100 |      100 |     100 |     100 |                   
  BoxIcon.tsx                          |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...src/components/Icons/BriefcaseIcon |     100 |      100 |     100 |     100 |                   
  BriefcaseIcon.tsx                    |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Icons/BugIcon    |     100 |      100 |     100 |     100 |                   
  BugIcon.tsx                          |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 .../src/components/Icons/BuildingIcon |     100 |      100 |     100 |     100 |                   
  BuildingIcon.tsx                     |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...onents/Icons/BulkPayoutsFilledIcon |     100 |      100 |     100 |     100 |                   
  BulkPayoutsFilledIcon.tsx            |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...c/components/Icons/BulkPayoutsIcon |     100 |      100 |     100 |     100 |                   
  BulkPayoutsIcon.tsx                  |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 ...mponents/Icons/BusinessBankingIcon |     100 |      100 |     100 |     100 |                   
  BusinessBankingI...*[Comment body truncated]*

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash PR Healer has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

Usage

import {
  ChartLine,
  ChartLineWrapper,
  ChartXAxis,
  ChartYAxis,
  ChartCartesianGrid,
  ChartTooltip,
  ChartLegend,
  ChartReferenceLine,
} from '@razorpay/blade/components';

<ChartLineWrapper data={data}>
  <ChartCartesianGrid />
  <ChartXAxis dataKey="name" />
  <ChartYAxis />
  <ChartTooltip />
  <ChartLegend />
  <ChartLine dataKey="sales" name="Sales" />
</ChartLineWrapper>

Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Co-authored-by: admin <admin>
@rzp-slash-public

Copy link
Copy Markdown
Contributor

Slash PR Healer

Fixed the following CI failures:

  1. @typescript-eslint/no-unnecessary-type-assertion (line 146) — Removed redundant as string | undefined type assertion on props.name (already string | undefined from ChartLineProps).
  2. @typescript-eslint/no-unnecessary-type-assertion (line 192) — Removed redundant as string | number | undefined type assertion on props.x (already string | number | undefined from ChartReferenceLineProps).
  3. prefer-template (line 221) — Converted string concatenation (+) to template literal in buildLinearPath.

Also added:

  • Missing changeset (.changeset/line-chart-react-native-support.md) with minor bump type for the new React Native LineChart feature.

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@rzp-slash-public

Copy link
Copy Markdown
Contributor

Fixed in branch fix/linechart-native-negative-y-domain.

Changes:

  • Added niceFloor() counterpart to niceCeil() for rounding negative values to nice tick boundaries
  • Track both dataMin and dataMax; compute domain as [niceFloor(dataMin), niceCeil(dataMax)] when negatives are present (falls back to [0, yMax] for all-positive data, preserving existing behavior)
  • Updated y-coordinate formula from value / yMax to (value - yMin) / (yMax - yMin) in line geometries, grid lines, y-axis ticks, and reference lines
  • Updated y-tick generation to span the full [yMin, yMax] domain
  • Updated reference line bounds check from refLine.y < 0 to refLine.y < yMin
  • Added test case for negative data values (profit/loss scenario)

[resolved by agent]

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

UI Review

⏭️ 1 skipped

Usage

import { ChartLineWrapper, ChartLine, ChartXAxis, ChartYAxis, ChartLegend, ChartTooltip, ChartCartesianGrid, ChartReferenceLine } from '@razorpay/blade/components';

<ChartLineWrapper data={data} testID="line-chart" colorTheme="categorical">
  <ChartXAxis dataKey="name" />
  <ChartYAxis />
  <ChartLegend />
  <ChartTooltip />
  <ChartLine dataKey="sales" name="Sales" type="monotone" />
  <ChartLine dataKey="profit" name="Profit" strokeStyle="dashed" />
</ChartLineWrapper>

Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
…e-level eslint-disable with targeted per-line disables [resolved by agent]

Co-authored-by: admin <admin>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash PR Healer has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

rzp-slash-public[bot]
rzp-slash-public Bot previously approved these changes Jul 14, 2026

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

Status: Approved ✅

Usage

import { ChartLineWrapper, ChartLine } from '@razorpay/blade/components';

<ChartLineWrapper data={data}>
  <ChartLine dataKey="sales" name="Sales" />
</ChartLineWrapper>

@rzp-slash-public rzp-slash-public Bot added the rcore:eligible-for-auto-approval PR is approved by slash label Jul 14, 2026

@rohankokane-dev rohankokane-dev left a comment

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.

✨ Agentic PR Review ✨

Usage

import {
  ChartLineWrapper,
  ChartLine,
  ChartXAxis,
  ChartYAxis,
  ChartCartesianGrid,
  ChartTooltip,
  ChartLegend,
  ChartReferenceLine,
} from '@razorpay/blade/components';

<ChartLineWrapper data={data} colorTheme="categorical" testID="revenue-chart">
  <ChartCartesianGrid />
  <ChartXAxis dataKey="month" />
  <ChartYAxis label="Revenue" />
  <ChartTooltip />
  <ChartLegend />
  <ChartLine dataKey="revenue" name="Revenue" type="monotone" strokeStyle="solid" />
  <ChartReferenceLine y={100} label="Target" />
</ChartLineWrapper>

Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Co-authored-by: admin <admin>
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

Skip null/undefined cells when computing the y-domain, show a placeholder for missing tooltip values, and clamp yMax to 0 for all-negative data instead of niceCeil's fallback of 1.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

rzp-slash-public[bot]
rzp-slash-public Bot previously approved these changes Jul 15, 2026

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

Status: Approved ✅

UI Review

✅ 5 passed

Passing checks (5)
Check Screenshot
LineChart SimpleLineChart
LineChart LineChartConnectNulls
LineChart LineChartWithLargeLabels
LineChart LineChartWithLargeLabelsAndSecondary
LineChart ForecastLineChart

Usage

import { ChartLineWrapper, ChartLine, ChartXAxis, ChartYAxis, ChartTooltip, ChartLegend, ChartReferenceLine, ChartCartesianGrid } from '@razorpay/blade/components';

<ChartLineWrapper data={salesData} colorTheme="categorical" testID="line-chart">
  <ChartCartesianGrid />
  <ChartXAxis dataKey="month" />
  <ChartYAxis />
  <ChartTooltip />
  <ChartLegend />
  <ChartReferenceLine y={4000} label="Target" />
  <ChartLine dataKey="sales" name="Sales" type="monotone" strokeStyle="solid" />
  <ChartLine dataKey="profit" name="Profit" connectNulls />
</ChartLineWrapper>

…l blocking

- Fix buildStepPath: 'step' type now uses midpoint stepping (d3 curveStep)
  instead of being treated identically to 'stepAfter'
- Fix touch responder: remove onStartShouldSetResponder that blocked vertical
  scrolling in parent ScrollViews; follow AreaChart.native.tsx pattern with
  onMoveShouldSetResponder horizontal threshold + onTouchStart/onTouchEnd
- Update tests to use touchStart/touchEnd for tap interactions
- Update snapshots for new View prop structure

Co-authored-by: admin <admin>
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

…tance conflicts [resolved by agent]

Co-authored-by: admin <admin>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash PR Healer has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

CI Run Tests failed after the clip-path ID fix removed LineChart.native.test.tsx.snap; regenerate the 12 native snapshots.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

UI Review

✅ 10 passed · ❌ 7 failed

Check Problem Screenshot
LineChartWithManyLines (Legend alignment) Legend align prop is ignored — legend is always centered. If a user sets align='left' or align='right' on ChartLegend, it has no effect on native. AreaChart.native.tsx correctly handles this prop.

Suggestion: Add the same justifyContent logic as AreaChart: justifyContent: slots.legend.align === 'left' ? 'flex-start' : slots.legend.align === 'right' ? 'flex-end' : 'center'
LineChartWithManyLines (Legend vertical layout) Vertical legend layout uses flexWrap: 'wrap' and alignItems: 'center' instead of flexWrap: 'nowrap' and alignItems: 'flex-start'. On narrow screens, vertical legend items may wrap into multiple columns unexpectedly.

Suggestion: Apply conditional logic like AreaChart: flexWrap: slots.legend.layout === 'vertical' ? 'nowrap' : 'wrap' and alignItems: slots.legend.layout === 'vertical' ? 'flex-start' : 'center'
LineChartWithBenchmarkAndSinglePoint (Reference Line - Vertical) Vertical reference line label chip is not clamped to plot bounds. When the reference line is at the first or last data point, the chip will overflow off the edge of the SVG, becoming clipped or invisible.

Suggestion: Clamp the chip x position like AreaChart: use x={Math.max(0, Math.min(x - chipWidth / 2, plotWidth - chipWidth))} for the Rect, and adjust the SvgText x to match.
Reference Line Label Truncation Reference line labels have no max width cap. A long label will create a chip wider than the entire chart, overflowing the SVG.

Suggestion: Add a REF_LABEL_MAX_WIDTH constant (e.g., 200) and truncate long labels with ellipsis, matching AreaChart's approach.
Reference Line Chip Height Consistency Reference line label chip height is 20px in LineChart but 30px in AreaChart. Visual inconsistency when both chart types are used together.

Suggestion: Use chipHeight=30 to match AreaChart for visual consistency across chart types.
Legend Accessibility Legend items lack accessibility props. No accessibilityRole or accessibilityLabel is set, so screen reader users cannot interact with or understand the legend toggle buttons.

Suggestion: Add accessibilityRole="button" and accessibilityLabel with selection state to each legend Pressable, matching AreaChart.
CI: Snapshot Tests 12 snapshot tests are failing in CI. The snapshots need to be updated to match the new LineChart.native.tsx output.

Suggestion: Run yarn test:react-native -u to update the snapshots, then commit the updated snapshot files.
Passing checks (10)
Check Screenshot
SimpleLineChart
LineChartWithLargeLabels
LineChartWithLargeLabelsAndSecondary
LineChartConnectNulls
LineChartWithCartesianGrid
ForecastLineChart
SteppedLineChart
LineChartWithMultiLineXAxis
LineChartWithXAndYAxisLabels
LineChartWithSequentialColors

Usage

import {
  ChartLineWrapper,
  ChartLine,
  ChartXAxis,
  ChartYAxis,
  ChartCartesianGrid,
  ChartTooltip,
  ChartLegend,
  ChartReferenceLine,
} from '@razorpay/blade/components';

const data = [
  { name: 'Jan', sales: 4000, profit: 2000 },
  { name: 'Feb', sales: 3000, profit: 1500 },
  { name: 'Mar', sales: 2000, profit: 1000 },
];

<ChartLineWrapper data={data} colorTheme="categorical">
  <ChartCartesianGrid />
  <ChartXAxis dataKey="name" />
  <ChartYAxis />
  <ChartTooltip />
  <ChartLegend />
  <ChartLine dataKey="sales" name="Sales" />
  <ChartLine dataKey="profit" name="Profit" strokeStyle="dashed" />
</ChartLineWrapper>

Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

UI Review

✅ 8 passed

Passing checks (8)
Check Screenshot
Simple Line Chart
Line Chart (Connect Nulls)
Line Chart with Large Labels
Line Chart with Large Labels and Secondary
Tiny Line Chart (regression check)
Stepped Line Chart (regression check)
Line Chart with many lines (regression check)
Forecast Line Chart (regression check)

Usage

import {
  ChartLine,
  ChartLineWrapper,
  ChartXAxis,
  ChartYAxis,
  ChartCartesianGrid,
  ChartTooltip,
  ChartLegend,
  ChartReferenceLine,
} from '@razorpay/blade/components';

<ChartLineWrapper data={data} colorTheme="categorical" testID="my-chart">
  <ChartCartesianGrid />
  <ChartXAxis dataKey="month" secondaryDataKey="year" />
  <ChartYAxis label="Revenue" tickFormatter={formatCurrency} />
  <ChartTooltip filterNull={false} />
  <ChartLegend
    selectedDataKeys={['sales']}
    onSelectedDataKeysChange={({ dataKey, selectedKeysArray }) => {}}
  />
  <ChartLine dataKey="sales" name="Sales" type="monotone" strokeStyle="dashed" dot={true} connectNulls />
  <ChartLine dataKey="profit" name="Profit" color="data.background.categorical.blue.moderate" />
  <ChartReferenceLine y={4000} label="Target" />
  <ChartReferenceLine x="Feb" label="Launch" />
</ChartLineWrapper>

Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx Outdated
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
… YAxis domain/tickCount, legend align/layout/accessibility, color assertion, shadow token, __DEV__ warning, scrub terminate [resolved by agent]

Co-authored-by: admin <admin>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🤖 Slash PR Healer has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

…t native [resolved by agent]

Co-authored-by: admin <admin>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

_(Review Cancelled - Superseded by a new run)_~~

_(Review Cancelled - Superseded by a new run)_

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

UI Review

⏭️ 7 skipped

Usage

import {
  ChartLineWrapper,
  ChartLine,
  ChartXAxis,
  ChartYAxis,
  ChartCartesianGrid,
  ChartTooltip,
  ChartLegend,
  ChartReferenceLine,
} from '@razorpay/blade/components';

const data = [
  { month: 'Jan', sales: 4000, profit: 2000 },
  { month: 'Feb', sales: 3000, profit: 1500 },
  { month: 'Mar', sales: 5000, profit: 2500 },
];

<ChartLineWrapper data={data} colorTheme="categorical" testID="my-line-chart">
  <ChartCartesianGrid />
  <ChartXAxis dataKey="month" />
  <ChartYAxis label="Revenue" />
  <ChartTooltip />
  <ChartLegend />
  <ChartLine dataKey="sales" name="Sales" />
  <ChartLine dataKey="profit" name="Profit" strokeStyle="dashed" />
  <ChartReferenceLine y={4000} label="Target" />
</ChartLineWrapper>

if (!slots.xSecondaryDataKey || !data?.length) return undefined;
const map: Record<number, string | number | undefined> = {};
data.forEach((row, index) => {
map[index] = getRowValue(row, slots.xSecondaryDataKey!) as string | number | undefined;

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.

🟠 [MAJOR] · code-quality-critique · confidence: 9/10

Problem: The yDomain prop from ChartYAxis is parsed into slots.yDomain but never used in the y-scale computation. The code always auto-computes yMin/yMax from data, completely ignoring any user-specified domain. On web, Recharts respects the domain prop. A numeric domain like [0, 100] is silently dropped — the DEV warning only fires for non-numeric domains. This breaks web/native parity for any consumer relying on a fixed y-axis domain.

Suggestion: Use slots.yDomain when provided: const yMin = slots.yDomain ? Number(slots.yDomain[0]) : (hasNegatives ? niceFloor(dataMin) : 0); and const yMax = slots.yDomain ? Number(slots.yDomain[1]) : resolveYMax(dataMax);. Also guard against yRange === 0 when domain min equals domain max.

if (max === -Infinity) max = 0;
return { dataMin: min, dataMax: max };
}, [data, visibleLines, allLines]);

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.

🟠 [MAJOR] · code-quality-critique · confidence: 9/10

Problem: The yTickCount prop from ChartYAxis is parsed into slots.yTickCount but the yTicks useMemo always uses the hardcoded constant Y_TICK_COUNT = 4 instead. Users who pass tickCount on native will not see the expected number of y-axis tick marks, breaking web/native parity. The prop is read but never referenced in any computation.

Suggestion: Use slots.yTickCount ?? Y_TICK_COUNT in the yTicks useMemo: const tickCount = slots.yTickCount ?? Y_TICK_COUNT; and loop for (let i = 0; i <= tickCount; i++). Add slots.yTickCount to the dependency array.

// and the active/inactive dimming (strokeOpacity).
const AnimatedPath = Animated.createAnimatedComponent(Path);
const AnimatedRect = Animated.createAnimatedComponent(Rect);

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.

🔵 [MINOR] · code-quality-critique · confidence: 8/10

Problem: The module-level let uniqueChartCounter = 0 is never reset between tests. Each test that renders a ChartLineWrapper increments the counter, so chart IDs embedded in clipPath IDs are order-dependent. Adding, removing, or reordering tests changes all subsequent IDs and breaks snapshot tests.

Suggestion: Export a resetChartIdCounter helper from the module and call it in beforeEach in the test file. Alternatively, use React.useId() with a fallback for the first render.

};

describe('<ChartLineWrapper /> (native)', () => {
it('should render a single line', () => {

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.

🔵 [MINOR] · code-quality-critique · confidence: 7/10

Problem: Multiple snapshot tests do not call fireLayout. Without a layout event, size remains {width: 0, height: 0} and the SVG content (lines, axes, grid, tooltip) is never rendered — the condition size.width > 0 && size.height > 0 is false. These snapshots only capture the empty component shell, providing no actual coverage of the chart rendering logic.

Suggestion: Call fireLayout(getByTestId('...-layout')) in all snapshot tests that expect SVG content. For tests without a testID prop, add one so the layout View can be found and the layout event fired.

y: value === null ? 0 : plotHeight - ((value - yMin) / yRange) * plotHeight,
value,
};
});

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.

🔵 [MINOR] · code-quality-critique · confidence: 7/10

Problem: dataSignature is computed as ${data.length}:${allDataKeys.join(',')}. When data values change but the array length and data keys remain the same, dataSignature does not change, so the LineSeries draw-in animation effect does not re-trigger. The line paths update but snap to the new shape without any animation. On web, Recharts animates data value changes smoothly.

Suggestion: Include a data content hash in dataSignature, e.g. JSON.stringify(data) or a shallow value hash, so value-only changes trigger the re-animation. Alternatively, accept this as an intentional native design choice and document it.

// Web: dashed/dotted lines begin later (LineChart.web.tsx:64-67).
const beginDelay = line.strokeStyle === 'dashed' ? baseDelay + duration : baseDelay;
const drawEasing = getIn(theme.motion, 'easing.standard');
const dimDuration = getIn(theme.motion, 'duration.gentle');

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.

🔵 [MINOR] · code-quality-critique · confidence: 6/10

Problem: The LineSeries draw animation useEffect sets draw.value = 0 then starts withDelay(withTiming(...)) but has no cleanup function. If the component unmounts mid-animation, the reanimated animation may continue running on the UI thread. The draw.value = 0 assignment on effect re-trigger can also cause a brief flash of the fully-clipped (invisible) state before the delayed animation begins.

Suggestion: Add a cleanup that cancels the animation: return () => { cancelAnimation(draw); }; (import cancelAnimation from react-native-reanimated). Apply the same cleanup to the dim animation effect.


const getSeriesNumber = (row: Record<string, unknown>, dataKey: string): number | null =>
toNullableNumber(getRowValue(row, dataKey));

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.

🙏🏻 [NEEDS CLARIFICATION] · api-decision-critique · confidence: 5/10

Is only numeric y support on native intentional, or should string y values also be coerced?

/>
{yTicks.map((tick, idx) => {
const y = plotHeight - ((tick - yMin) / yRange) * plotHeight;
return (

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.

🙏🏻 [NEEDS CLARIFICATION] · api-decision-critique · confidence: 4/10

Is the 'No data to display' empty state on native an intentional UX decision, or should it match web's behavior of rendering an empty chart?

…pshots

Slash auto-resolve widened colorToken to optional and broke native typegen;
mirror AreaChart's cast + typed resolveColor fallback, then refresh legend a11y snapshot.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

Wire yDomain/yTickCount into the native y-scale computation,
matching AreaChart.native behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@rohitr-raz
rohitr-raz merged commit 0150f07 into master Jul 15, 2026
21 checks passed
@rohitr-raz
rohitr-raz deleted the feat/blade-rn/LineChart branch July 15, 2026 14:59

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

UI Review

✅ 10 passed · ❌ 9 failed

Check Problem
Missing Cursor Line at Active Index No vertical cursor line is rendered at the active data point during scrub/tap. Users cannot see which column they are scrubbing without the cursor indicator.

Suggestion: Add a cursor line: {activeIndex !== undefined ? <Line x1={xForIndex(activeIndex)} x2={xForIndex(activeIndex)} y1={0} y2={plotHeight} stroke={getIn(theme.colors, 'surface.border.gray.normal')} strokeWidth={1} /> : null}
yRange=0 Division by Zero No guard against yRange=0. Flat data (all same values) produces NaN for all point y-coordinates.

Suggestion: Add yRange>0 guard: yRange > 0 ? plotHeight - ((value - yMin) / yRange) * plotHeight : plotHeight / 2
Reference Line Chip Height Inconsistency 10px height difference between chart types for the same ChartReferenceLine component.

Suggestion: Align chipHeight to 30 to match AreaChart.native.tsx.
Reference Line Label Missing fontWeight Reference line labels appear thinner on LineChart than on AreaChart.

Suggestion: Add fontWeight={theme.typography.fonts.weight.medium} to reference line label SvgText elements.
Reference Line Label Missing Truncation A very long reference line label will overflow the chip and plot area with no upper bound on chipWidth.

Suggestion: Add REF_LABEL_MAX_WIDTH=200 constant, cap chipWidth, and truncate with ellipsis — matching AreaChart.native.tsx.
Tooltip Styling Inconsistency with AreaChart Tooltip styling differs between chart types. 20px width difference may cause label wrapping on LineChart that AreaChart shows on one line.

Suggestion: Align tooltip constants to match AreaChart: TOOLTIP_WIDTH=180, spacing[3] padding, stronger shadow. Consider extracting tooltip into shared component.
Legend Visual Inconsistency with AreaChart Legend visual presentation differs between chart types for the same ChartLegend component.

Suggestion: Align to AreaChart: swatch 12px, text 'xsmall', opacity 0.4, add textDecorationLine strikethrough for deselected items.
Custom dot/activeDot Object Props Silently Ignored Custom dot/activeDot object configurations (radius, fill, stroke) are silently ignored on native. Web fully supports these via Recharts.

Suggestion: Extract dot/activeDot object props in readChildSlots and use them in Circle rendering. At minimum, log a DEV warning when object props with custom properties are used.
Story Coverage - Missing dotted strokeStyle dotted stroke style has no visual verification story on native.

Suggestion: Add a story variant with strokeStyle='dotted' alongside dashed and solid lines.
Passing checks (10)
Check
✅ Visual Parity - Colors and Theme Tokens
✅ Visual Parity - Stroke Width and Dash Patterns
✅ Visual Parity - Hover Dim Opacity and Animation
✅ SVG Path Construction - Monotone/Linear/Step
✅ SVG Path Construction - Null Segments
✅ Touch Interaction - Scrub and ScrollView Coexistence
✅ Touch Interaction - Per-Line Hover Dimming
✅ Tooltip Positioning - Edge Overflow
✅ Responsive Layout and Zero-Size Guard
✅ Story Coverage - Core Visual States

Usage

import { ChartLineWrapper, ChartLine } from '@razorpay/blade/components';
import {
  ChartXAxis,
  ChartYAxis,
  ChartCartesianGrid,
  ChartTooltip,
  ChartLegend,
  ChartReferenceLine,
} from '@razorpay/blade/components';

const data = [
  { month: 'Jan', sales: 4000, profit: 2000 },
  { month: 'Feb', sales: 3000, profit: 1500 },
  { month: 'Mar', sales: 5000, profit: 2500 },
];

<ChartLineWrapper data={data}>
  <ChartXAxis dataKey="month" />
  <ChartYAxis />
  <ChartCartesianGrid />
  <ChartTooltip />
  <ChartLegend />
  <ChartLine dataKey="sales" name="Sales" />
  <ChartLine dataKey="profit" name="Profit" strokeStyle="dashed" />
  <ChartReferenceLine y={4500} label="Target" />
</ChartLineWrapper>

Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

UI Review

✅ 15 passed · ❌ 16 failed · ⏭️ 2 skipped

Check Problem
Reference line chip height mismatch The reference line label pill is 20px tall on native LineChart vs 30px on web and AreaChart native. The label pill looks disproportionately small and cramped.

Suggestion: Change chipHeight from 20 to 30 to match web (RECT_HEIGHT=30) and AreaChart native (chipHeight=30).
Reference line label missing fontWeight Reference line label text on native LineChart defaults to regular weight, appearing thinner than intended compared to web and AreaChart native.

Suggestion: Add fontWeight={theme.typography.fonts.weight.medium} to the SvgText elements for reference line labels.
Reference line label no max-width cap or truncation A very long reference line label will produce a chip wider than the plot, overflowing the SVG canvas and overlapping other chart elements.

Suggestion: Add a max width cap (e.g., Math.min(200, Math.max(40, label.length * 6 + 16))) and truncate the label text with ellipsis.
Vertical reference line label not clamped to plot bounds When a vertical reference line is at or near the first or last data point, the label chip will extend beyond the plot edge.

Suggestion: Clamp the chip x position: x={Math.max(0, Math.min(x - chipWidth/2, plotWidth - chipWidth))}.
Legend deselected opacity mismatch Deselected legend items appear at 50% opacity instead of 40%, reducing visual distinction between selected and deselected series.

Suggestion: Change the deselected legend opacity from 0.5 to 0.4.
Legend missing line-through text decoration Deselected legend items lack the strikethrough text decoration, removing a secondary visual cue for the deselected state.

Suggestion: Add textDecorationLine={selected ? 'none' : 'line-through'} to the legend Text component.
Legend swatch size and text size inconsistency Legend swatch dots and text are different sizes between LineChart and AreaChart native, breaking design consistency when both appear on the same screen.

Suggestion: Align legend constants: use LEGEND_SWATCH_SIZE=12 and Text size='xsmall' to match AreaChart native.
Legend padding inconsistency with AreaChart Legend container padding differs between LineChart and AreaChart native, causing visible spacing differences.

Suggestion: Align legend container padding with AreaChart native.
Missing scrub cursor line During scrub interaction, there is no visual cursor line indicating the active x position. With multiple lines, the user has no clear indicator of which column is active.

Suggestion: Add a vertical cursor line at xForIndex(activeIndex) when activeIndex is defined, matching AreaChart native.
Tooltip shadow inconsistency with AreaChart native The LineChart tooltip has a noticeably lighter and smaller shadow compared to AreaChart native, breaking visual consistency.

Suggestion: Align tooltip shadow values with AreaChart native: shadowOpacity=0.24, shadowRadius=12, elevation=8.
Tooltip width inconsistency with AreaChart native The LineChart tooltip is 160px vs AreaChart's 180px, potentially wrapping labels more aggressively.

Suggestion: Align TOOLTIP_WIDTH to 180, or extract a shared constant.
Y-axis label rotation offset mismatch The rotated y-axis title is positioned 2px differently compared to AreaChart native, causing subtle misalignment.

Suggestion: Align the y-axis label x-offset to match AreaChart native.
Single data point with dot=false renders invisible A LineChart with a single data point and dot=false renders nothing visible. The user sees a blank chart area with axes but no data marker.

Suggestion: When pointCount === 1, automatically render a dot at the single point, or show a dev-mode warning.
yRange=0 division by zero When an explicit yDomain with equal min and max is provided, all line points compute y=NaN, rendering the line invisible without any error.

Suggestion: Add a guard: use yRange > 0 ? yRange : 1, or default to plotHeight when yRange===0.
X-tick label width estimation inconsistency Primary tick labels are estimated narrower than they should be, potentially causing the thinning algorithm to keep more labels than fit, leading to overlap.

Suggestion: Use estimateTickLabelWidth consistently for both primary and secondary labels.
Accessibility: chart container lacks accessibility props Screen reader users cannot understand what the chart represents. The chart is opaque to assistive technology.

Suggestion: Add accessibilityRole='image' and a default accessibilityLabel to the chart container.
Passing checks (15)
Check
✅ Visual parity: tooltip background and border
✅ Visual parity: tooltip text styles
✅ Visual parity: line stroke width and dash patterns
✅ Visual parity: dim opacity on hover
✅ Visual parity: animation begin delay for dashed lines
✅ Visual parity: reference line stroke color and dash pattern
✅ Visual parity: reference line chip fill and border colors
✅ Visual parity: empty data state
✅ Visual parity: negative values domain handling
✅ Visual parity: x-axis tick label wrapping and thinning
✅ Visual parity: tooltip edge clamping
✅ Touch interaction: tap-to-stay tooltip model
✅ Touch interaction: overflow visible for tooltip
✅ Theme color token usage
✅ Legend overflow with many series

Usage

import { ChartLineWrapper, ChartLine } from '@razorpay/blade/components';
import { ChartXAxis, ChartYAxis, ChartTooltip, ChartLegend, ChartCartesianGrid, ChartReferenceLine } from '@razorpay/blade/components';

const data = [
  { month: 'Jan', sales: 4000, profit: 2000 },
  { month: 'Feb', sales: 3000, profit: 1500 },
  { month: 'Mar', sales: 5000, profit: 2500 },
];

<ChartLineWrapper data={data} colorTheme="categorical">
  <ChartCartesianGrid />
  <ChartXAxis dataKey="month" />
  <ChartYAxis label="Revenue" />
  <ChartTooltip />
  <ChartLegend />
  <ChartLine dataKey="sales" name="Sales" />
  <ChartLine dataKey="profit" name="Profit" strokeStyle="dashed" />
  <ChartReferenceLine y={4000} label="Target" />
</ChartLineWrapper>

Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread .changeset/line-chart-react-native-support.md
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx
Comment thread packages/blade/src/components/Charts/LineChart/LineChart.native.tsx

@rzp-slash-public rzp-slash-public Bot left a comment

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.

✨ Agentic PR Review ✨

UI Review

✅ 9 passed

Passing checks (9)
Check
✅ Line rendering (monotone/linear/step)
✅ Tooltip positioning and edge clamping
✅ Touch interaction (tap-to-stay + scrub)
✅ Legend toggle
✅ X-axis label wrapping
✅ Reference lines
✅ Empty state
✅ Animation (draw-in + dimming)
✅ Responsive layout

Usage

import { ChartLineWrapper, ChartLine } from '@razorpay/blade';
import { ChartXAxis, ChartYAxis, ChartCartesianGrid, ChartTooltip, ChartLegend, ChartReferenceLine } from '@razorpay/blade';

<ChartLineWrapper data={data} colorTheme="categorical" testID="my-line-chart">
  <ChartCartesianGrid />
  <ChartXAxis dataKey="month" />
  <ChartYAxis label="Sales" />
  <ChartTooltip />
  <ChartLegend />
  <ChartLine dataKey="sales" name="Sales" color="data.background.categorical.blue.moderate" />
  <ChartLine dataKey="profit" name="Profit" strokeStyle="dashed" type="monotone" />
  <ChartReferenceLine y={4000} label="Target" />
</ChartLineWrapper>

}
return ticks;
}, [yMin, yRange, yTickCount]);

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.

🟠 [MAJOR] · code-quality-critique · confidence: 8/10

Problem: Number(slots.yDomain[1]) and Number(slots.yDomain[0]) will produce NaN when yDomain contains Recharts string sentinels like 'auto' or 'dataMin'. The DEV warning at line 710 only logs a console warning but execution continues with NaN values, causing all point Y coordinates, grid lines, and axis ticks to become NaN — the chart silently renders blank in production with no error.

Suggestion: Guard against NaN after Number() conversion: const yMax = slots.yDomain ? Number(slots.yDomain[1]) : resolveYMax(dataMax); if (!isFinite(yMax)) yMax = resolveYMax(dataMax); Apply the same pattern to yMin. Alternatively, fall back to computed domain when Number() yields NaN.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: Added isFinite() guard after Number() conversion for yDomain values. Non-finite results (from Recharts string sentinels like 'auto', 'dataMin') now fall back to the computed domain. [resolved by agent]

}, [yMin, yRange, yTickCount]);

const showAxes = slots.hasXAxis || slots.hasYAxis;
const hasSecondaryXLabels = Boolean(slots.xSecondaryDataKey);

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.

🟠 [MAJOR] · code-quality-critique · confidence: 7/10

Problem: yRange = yMax - yMin can be 0 when a user provides a degenerate yDomain (e.g. [5, 5] or [0, 0]). yRange is used as a divisor at lines 921, 1181, 1206, and 1348 for point Y mapping, grid lines, y-tick labels, and reference line Y — all produce Infinity/NaN, rendering the chart blank or crashing SVG. No guard exists for yRange === 0 at any of these division sites.

Suggestion: Add a guard after computing yRange: const safeYRange = yRange === 0 ? 1 : yRange; and use safeYRange in all division sites (lines 921, 1181, 1206, 1348). Or clamp yMax to yMin + 1 when they are equal.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: Added yToPixel helper that guards against division by zero when yRange === 0 (e.g. degenerate domain [5,5]). When yRange is 0, points are centered in the plot area instead of producing Infinity/NaN. [resolved by agent]

// every web hover side-effect (dim others + activeDot + tooltip + hoveredKey).
// Map a touch to the nearest index + line and apply it. Returns the index so the
// tap/scrub handlers can decide whether a release should toggle the selection off.
const indexAtTouchX = (locationX: number): number | undefined => {

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.

🔵 [MINOR] · code-quality-critique · confidence: 6/10

Problem: resolveColor is called inside the lineGeometries useMemo (line 927) and the tooltipRows useMemo (line 1058) but is not listed in either dependency array. While functionally correct (resolveColor's closure captures dataColorMapping and theme.colors which ARE in deps), this is an eslint react-hooks/exhaustive-deps violation that will produce warnings and could mask future bugs if resolveColor gains additional dependencies.

Suggestion: Either add resolveColor to the deps array (after wrapping it in useCallback) or inline the color resolution logic directly in both memos to avoid the lint violation.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: resolveColor is now wrapped in useCallback with proper deps, and added to the dependency arrays of lineGeometries and tooltipRows useMemos. [resolved by agent]

const slots = useMemo(() => readChildSlots(children), [children]);
const allLines = slots.lines;

const yAxisWarnedRef = useRef(false);

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.

🔵 [MINOR] · code-quality-critique · confidence: 7/10

Problem: onLayout handler closes over size and is recreated on every render. It's passed directly to the View's onLayout prop, causing unnecessary prop updates on every state change (e.g., every scrub move triggers a re-render which creates a new onLayout function).

Suggestion: Wrap onLayout in useCallback with [size.width, size.height] as deps, or use a sizeRef for comparison to avoid recreation entirely.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: onLayout is now wrapped in useCallback with functional setState (prev => ...) so it doesn't close over size and isn't recreated on every render. [resolved by agent]

touchStartLocationRef.current = {
x: e.nativeEvent.locationX,
y: e.nativeEvent.locationY,
};

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.

🔵 [MINOR] · code-quality-critique · confidence: 8/10

Problem: SCRUB_MOVE_THRESHOLD is a constant (value 8) defined inside the component body. It is recreated on every render even though it never changes. It should be hoisted to module level alongside other constants.

Suggestion: Move const SCRUB_MOVE_THRESHOLD = 8; to module-level constants section.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: SCRUB_MOVE_THRESHOLD has been hoisted to module-level constants section alongside other constants. [resolved by agent]

>
<View
style={{
width: 8,

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.

🔵 [MINOR] · ui-critique · confidence: 5/10

Problem: Tooltip is always positioned at top: padding.top regardless of where the user taps or scrubs. On web, the tooltip follows the cursor/data point. This fixed-top placement is a deliberate mobile pattern but diverges from web parity.

Suggestion: If web parity is desired, compute tooltip top from the nearest line's y-position with edge clamping. Otherwise, document this as an intentional mobile UX decision.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

The fixed-top tooltip placement is an intentional mobile UX decision. On mobile, a tooltip following the finger would be obscured by the finger itself. The fixed-top placement ensures the tooltip is always visible and readable during scrub interaction. This is documented as a deliberate mobile pattern divergence from web. [resolved by agent]

yTicks.map((tick, idx) => {
const y = plotHeight - ((tick - yMin) / yRange) * plotHeight;
return (
<Line

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.

🔵 [MINOR] · ui-critique · confidence: 8/10

Problem: The main interaction surface (View with onLayout and touch handlers) and the chart container (BaseBox) have no accessibilityRole, accessibilityLabel, or accessibilityHint. Screen reader users cannot perceive or interact with the chart content, and the SVG chart content is completely invisible to VoiceOver/TalkBack.

Suggestion: Add accessibilityRole='image' with an accessibilityLabel summarizing the chart, or use accessibilityRole='adjustable' for the scrub surface.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: Added accessibilityRole="image" and accessibilityLabel="Line chart" to the main interaction surface View so screen readers can perceive the chart content. [resolved by agent]

testID={`legend-${line.dataKey}`}
onPress={() => toggleLegend(line.dataKey)}
accessibilityRole="button"
accessibilityLabel={`${line.name ?? line.dataKey}, ${

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.

🔵 [MINOR] · ui-critique · confidence: 5/10

Problem: Tooltip value column has a fixed width of 44px (TOOLTIP_VALUE_WIDTH). Long formatted values (e.g., '$1,234,567') may overflow or truncate without ellipsis.

Suggestion: Consider using flexShrink on the label column and flexGrow on the value column, or add numberOfLines={1} with ellipsizeMode to the value Text.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: Added flexShrink: 1 on the label column and flexShrink: 0 on the value column, plus numberOfLines={1} with ellipsizeMode="tail" on the value Text to prevent overflow/truncation of long formatted values. [resolved by agent]

x={x}
y={chipHeight / 2 + TICK_FONT_SIZE / 3}
fontSize={TICK_FONT_SIZE}
fill={chipTextColor}

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.

🔵 [MINOR] · ui-critique · confidence: 8/10

Problem: Reference line chip width is estimated as Math.max(40, label.length * 6 + 16), assuming ~6px per character. Labels with wide characters (W, M) or narrow characters (i, l) will have inaccurate chip sizing.

Suggestion: For longer labels, consider measuring text or using a more conservative multiplier (e.g., 7px).

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: Changed the character width multiplier from 6px to 7px for a more conservative estimate that accommodates wider characters (W, M). Also added REF_LABEL_MAX_WIDTH cap with label truncation for very long labels. [resolved by agent]

setActiveIndex(index);

// Nearest visible line at this index by vertical distance to the touch.
let nearestKey: string | null = null;

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.

🔵 [MINOR] · ui-critique · confidence: 5/10

Problem: resolveColor falls back to tickColor (gray text) when a color token cannot be resolved. This could render an invisible or indistinguishable line if the token path is invalid.

Suggestion: Consider falling back to a more visible default (e.g., a categorical color token) or logging a warning in DEV when the fallback is hit.

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.

✨ Agentic Resolution ✨: Auto Comment Resolution Triggered (View Logs)

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.

Fixed: resolveColor now logs a DEV warning when a color token cannot be resolved and falls back to tickColor, making the fallback visible during development. [resolved by agent]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Human Help Needed 🧑🏻‍💻 Poor AI needs help from human for something rcore:eligible-for-auto-approval PR is approved by slash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants