Skip to content

feat(TreeView): show a Popover preview when hovering a TreeViewItem - #4038

Open
saurav12 wants to merge 21 commits into
masterfrom
feat/treeview-item-tooltip-popover
Open

saurav12 wants to merge 21 commits into
masterfrom
feat/treeview-item-tooltip-popover

Conversation

@saurav12

@saurav12 saurav12 commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Description

Tree view items can now show a Popover preview on hover. The main use case is a rich preview next to a row, e.g. hovering "Payment Success" in a checkout-screens tree shows a thumbnail of that screen to the right. Moving the pointer from row to row switches previews in place, without fading out and in again.

<TreeViewItem
  title="Payment Success"
  value="payment-success"
  popover={{ title: 'Payment Success', content: <img src={preview} alt="" /> }}
/>

Builds on #4044 (merged), which made hover popovers switch in place with tooltips and each other.

Changes

New TreeViewItem prop

  • popover (title, titleLeading, content, footer, placement, maxWidth, onOpenChange): opens on mouse hover only.
  • Defaults to placement="right", so it doesn't cover the rows the pointer moves to next.
  • There is deliberately no tooltip prop: there's no use case for a plain-text tooltip on tree items yet. It can be added the same way later if one comes up.

Moving between rows

  • Switching uses Popover's built-in hover switching from feat(Popover): switch hover popovers and tooltips in place #4044: opening a popover replaces whichever one is showing, without a fade-out or fade-in. Only the first one of a hover streak fades in and only the last one fades out.
  • Leaving a row closes its popover after 160ms, so the pointer can cross the gap onto the popover (it stays open while the pointer is over it). Leaving for another row uses 80ms instead: the pointer isn't heading to the popover, but the old popover stays current long enough for the next row's popover to replace it in place.
  • Clicks, focus and mousedown inside the popover don't select or focus the row (the popover is portalled, but it is a React child of the row, so its events bubble into the row through the React tree).

Popover (internal only)

  • Adds a private _shouldManageFocus prop (default true, so no other Popover changes). TreeView turns focus management off; see below.

Other

  • Story: "With Hover Preview".
  • Docs: _decisions/decisions.md (B13 and switching), blade-mcp TreeView.md, changeset.

Additional Information

Why a prop, not <Popover><TreeViewItem /></Popover>: TreeView only accepts TreeViewItem / TreeViewLoadMore children and reads their props to build the tree, so a wrapper hides the item from it. No Blade parent that reads its children's props supports wrapping today (ActionList, Tabs, Breadcrumb, SegmentedControl). A wrapped Popover would also open on click by default and write aria-expanded on the row, so TreeView would have to silently override the consumer's Popover props. This follows the SideNavLink / AppBar precedent of overlays as props.

How the popover is attached: the treeitem row can't be Popover's trigger, because Popover writes aria-expanded / aria-haspopup onto its trigger. That would overwrite a branch's expanded state and make leaves announce as collapsed branches. A wrapper around the row also fails axe (aria-allowed-attr, and aria-required-children on role="tree"). So the Popover is controlled from the row's own pointer events and anchored on an aria-hidden, pointer-events: none box inside the row. Rows without popover render exactly as before, and existing snapshots are unchanged.

Why focus management is off for item popovers: since #4044, hover popovers are non-modal, so they no longer hide the page from screen readers. A non-modal popover with focus management, though, renders floating-ui's focus guards (role="button", tabindex="0") and an aria-owns span next to its trigger. Here the trigger is inside the treeitem, so that would add tab stops to the row and make its accessible name include the popover's content. A hover preview never takes focus, so _shouldManageFocus={false} turns it off.

Why the popover is mouse-only:

  • Touch: on a phone a tap would open the popover and select the row at once, the popover would flip below the row and cover the rows under it, and iOS Safari may treat the first tap as a hover. The row checks pointerType === 'mouse' on pointerenter. It uses pointer events rather than mouse events because browsers fire emulated mouse events after a tap.
  • Keyboard focus: arrowing through the tree would flash a large preview on every row, and the preview isn't linked to the row for assistive tech.

Because of both limits, popover content must never be the only place information lives. This is documented on the prop.

Testing

  • 8 popover tests in TreeView.web.test.tsx: hover, tree semantics untouched, reaching the popover and clicks inside it, first click while a popover is open, touch, axe audit with the popover closed and open, and three row-switching tests (popover to popover, in-place switch with a 0ms transition, early close when moving to a plain row). Plus one test in TreeViewDropdown.web.test.tsx: clicking inside an item popover in a Dropdown keeps the Dropdown open and selects nothing.
  • The switching tests run on fake timers: they advance a fixed 100ms (shorter than the 200ms exit animation) instead of waiting on real time, so they don't flake on a busy CI machine. The helpers are shared with the Popover tests in ~utils/testing/overlayTransitions.
  • All 133 TreeView, Popover and Tooltip tests pass. Web and native typechecks are clean.
  • Manual checks: an earlier version was checked in Storybook (Chrome), including phone width. The row switching was measured in the browser before it moved into Popover (0–2ms of overlap, down from a 200ms+ fade); the final version is covered by the tests above but hasn't been re-checked by hand. Touch is covered by a unit test only, not a real device.

Component Checklist

  • Update Component Status Page
  • Perform Manual Testing in Other Browsers
  • Add KitchenSink Story
  • Add Interaction Tests (if applicable)
  • Add changeset

🤖 Generated with Claude Code

TreeViewItem accepts `tooltip` and `popover` props, following the SideNav /
AppBar precedent of overlays as props (TreeView only accepts TreeViewItem
children, so wrapping an item in <Tooltip>/<Popover> is not possible).

- `tooltip` wraps the treeitem row: opens on hover and keyboard focus, and is
  linked through aria-describedby. The row keeps its title as its name.
- `popover` opens on mouse hover only, for rich previews. It is anchored on an
  aria-hidden box inside the row and controlled from the row's pointer events,
  because Popover writes aria-expanded on its trigger, which would overwrite
  the tree's own expanded state. It does not open on touch screens, where a
  tap only selects the row.

Both default to placement="right". Also updates the blade-mcp TreeView doc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8b91253

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

This PR includes changesets to release 2 packages
Name Type
@razorpay/blade Minor
@razorpay/blade-mcp Patch

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 github-actions Bot added blade Changes to packages/blade blade-mcp Changes to packages/blade-mcp labels Sep 25, 2026
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@saurav12 saurav12 self-assigned this Sep 25, 2026
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@rzpcibot

rzpcibot commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

🛡️ Coverage Report

Summary


=============================== Coverage summary ===============================
Statements   : 84.1% ( 13026/15488 )
Branches     : 71.28% ( 8338/11697 )
Functions    : 83.67% ( 2943/3517 )
Lines        : 85.07% ( 12607/14818 )
================================================================================
Full Coverage Details
---------------------------------------|---------|----------|---------|---------|-------------------
File                                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------------------------------|---------|----------|---------|---------|-------------------
All files                              |    84.1 |    71.28 |   83.67 |   85.07 |                   
 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/scripts                         |   92.79 |    84.78 |      90 |   96.05 |                   
  tokenSerializer.js                   |   92.79 |    84.78 |      90 |   96.05 | ...64-265,356-357 
 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.67 |    53.47 |   69.35 |   70.83 |                   
  ActionList.tsx                       |     100 |      100 |     100 |     100 |                   
  ActionListBox.web.tsx                |   67.94 |    40.47 |   73.68 |   67.94 | ...00,243,317-325 
  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.web.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 |                   
 ...e/src/components/BaseAnimatedValue |    95.6 |    75.86 |   95.45 |   97.53 |                   
  BaseAnimatedValue.web.tsx            |   88.23 |    61.11 |   85.71 |   93.33 | 41,139            
  OdometerValue.web.tsx                |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  odometerUtils.ts                     |     100 |      100 |     100 |     100 |                   
 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 |    88.88 |     100 |     100 |                   
  BaseMenuItem.tsx                     |     100 |    89.47 |     100 |     100 | 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.web.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/BottomBar        |     100 |      100 |     100 |     100 |                   
  BottomBar.web.tsx                    |     100 |      100 |     100 |     100 |                   
 blade/src/components/BottomDock       |     100 |    66.66 |     100 |     100 |                   
  BottomDock.web.tsx                   |     100 |    66.66 |     100 |     100 | 39-58             
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/BottomNav        |   92.85 |    85.71 |     100 |   92.85 |                   
  BottomNav.web.tsx                    |   92.85 |    85.71 |     100 |   92.85 | 69                
  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 |   76.63 |    70.54 |   86.48 |   77.94 |                   
  AnimatedButtonContent.web.tsx        |     100 |      100 |     100 |     100 |                   
  BaseButton.tsx                       |   73.18 |    68.75 |   82.14 |   74.55 | ...02-608,797-802 
  StyledBaseButton.web.tsx             |     100 |    76.47 |     100 |     100 | 25,45-56,70       
  buttonTokens.ts                      |   91.66 |    83.33 |     100 |   91.66 | 426,436           
  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.web.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.66 |    71.13 |      90 |   95.76 |                   
  AreaChart.web.tsx                    |    91.6 |    71.13 |      90 |   95.72 | 219-223,317       
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
 blade/src/components/Charts/BarChart  |   91.78 |    79.83 |   89.06 |      95 |                   
  BarChart.web.tsx                     |      92 |    83.15 |      80 |   91.66 | ...73-377,484-488 
  BarChartContext.ts                   |      75 |      100 |      50 |   66.66 | 11                
  index.ts                             |       0 |        0 |       0 |       0 |                   
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
  useBarReferenceBand.tsx              |   91.47 |     77.7 |   95.12 |   97.33 | 172,290,395-400   
 ...nents/Charts/CommonChartComponents |   78.88 |    64.28 |   89.58 |   78.57 |                   
  CommonChartComponents.web.tsx        |   84.78 |    66.66 |   93.18 |   84.39 | ...62-878,907-908 
  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 |   90.45 |    76.92 |    84.5 |   94.27 |                   
  LineChart.web.tsx                    |   88.48 |    75.19 |   79.54 |   91.83 | ...20,500-504,545 
  LineChartContext.tsx                 |      75 |      100 |      50 |   66.66 | 10                
  componentIds.ts                      |     100 |      100 |     100 |     100 |                   
  index.ts                             |       0 |        0 |       0 |       0 |                   
  useReferenceBand.tsx                 |   94.56 |     80.3 |      96 |     100 | ...69,176,191-194 
 .../src/components/Charts/SankeyChart |   90.95 |    71.85 |   97.77 |   91.66 |                   
  SankeyChart.web.tsx                  |   91.83 |    72.09 |   97.72 |   92.81 | ...10-512,685,754 
  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     |   91.61 |    76.05 |     100 |   93.19 |                   
  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             
  nullBridgeUtils.ts                   |   95.65 |    76.19 |     100 |   98.75 | 75                
  referenceBandUtils.ts                |   96.96 |    83.33 |     100 |     100 | 14                
  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     |   91.26 |    77.77 |   96.55 |   95.69 |                   
  CounterInput.web.tsx                 |   89.53 |    77.77 |   95.65 |   94.73 | 179-184           
  CounterInputContext.tsx              |     100 |      100 |     100 |     100 |                   
  StyledCounterInput.tsx               |     100 |      100 |     100 |     100 |                   
  token.ts                             |     100 |      100 |     100 |     100 |                   
 blade/src/components/DatePicker       |   61.31 |    50.28 |    70.5 |   61.42 |                   
  BaseDatePicker.web.tsx               |   67.02 |    68.59 |      60 |   67.03 | ...66,504,591-625 
  Calendar.web.tsx                     |   62.71 |    85.71 |    37.5 |   63.63 | ...49-153,168-186 
  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 |     72.5 |     100 |     100 | 155-159,171-306   
  DateInput.web.tsx                    |   69.76 |     46.6 |   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                     |   78.75 |    81.17 |     100 |    78.2 | ...1-74,93-96,106 
  usePopup.ts                          |   94.73 |    58.33 |     100 |   94.73 | 46                
  utils.ts                             |    37.5 |    24.16 |   78.26 |   36.31 | ...81-421,484-710 
 ...ts/DatePicker/FilterChipDatePicker |   91.66 |    75.86 |     100 |   91.66 |                   
  DatePickerFilterChip.web.tsx         |    90.9 |       75 |     100 |    90.9 | 86,90             
  FilterChipDatePicker.web.tsx         |     100 |      100 |     100 |     100 |                   
  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/DotLoader        |     100 |      100 |     100 |     100 |                   
  DotLoader.web.tsx                    |     100 |      100 |     100 |     100 |                   
  dotLoaderTokens.ts                   |     100 |      100 |     100 |     100 |                   
  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         |   73.95 |    68.66 |   67.59 |   75.14 |                   
  Dropdown.tsx                         |   96.87 |    74.07 |     100 |   96.82 | 142,164           
  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              |     100 |    94.11 |     100 |     100 | 57                
  FilterChipGroupContext.web.tsx       |     100 |      100 |   66.66 |     100 |                   
  FilterChipSelectInput.web.tsx        |   67.39 |    68.91 |      60 |   69.87 | ...98,205-216,247 
  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                     |   60.16 |     62.4 |   53.33 |   60.52 | ...97-300,316-331 
  filterChipSelectInputUtils.ts        |   89.47 |    88.88 |     100 |   88.88 | 48,72             
  index.ts                             |       0 |        0 |       0 |       0 |                   
  types.ts                             |       0 |        0 |       0 |       0 |                   
  useDropdown.ts                       |   74.56 |    72.36 |      65 |   75.45 | ...12-531,556,567 
 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       |   54.75 |    65.02 |   37.25 |   58.04 |                   
  FileUpload.web.tsx                   |   46.66 |    66.44 |   28.57 |   50.83 | ...23-228,384-470 
  FileUploadItem.tsx                   |   69.23 |    68.75 |   42.85 |   69.23 | 110-124,153-159   
  FileUploadItemIcon.tsx               |   53.12 |    38.46 |     100 |   53.12 | 42-61             
  StyledFileUploadItemWrapper.web.tsx  |     100 |    83.33 |     100 |     100 | 18                
  StyledFileUploadWrapper.web.tsx      |     100 |      100 |     100 |     100 |                   
  fileUploadTokens.ts                  |    64.7 |        0 |      25 |   68.75 | 109-116           
  isFileAccepted.tsx                   |   78.57 |    58.33 |     100 |   78.57 | 19,24-27          
 blade/src/components/FilterChip       |   96.15 |       75 |   88.88 |   96.15 |                   
  BaseFilterChip.web.tsx               |      96 |       75 |   88.88 |      96 | 161               
  tokens.ts                            |     100 |      100 |     100 |     100 |                   
 ...rc/components/FloatingActionButton |     100 |      100 |     100 |     100 |                   
  FloatingActionButton.tsx             |     100 |      100 |     100 |     100 |                   
  ...tingActionButtonContainer.web.tsx |     100 |      100 |     100 |     100 |                   
 blade/src/components/Form             |   94.87 |    87.65 |     100 |    94.8 |                   
  AnimatedFormHint.web.tsx             |    92.3 |     87.5 |     100 |      92 | 71,89             
  FormHint.tsx                         |     100 |       92 |     100 |     100 | 30-35             
  FormHintWrapper.web.tsx              |     100 |      100 |     100 |     100 |                   
  FormLabel.tsx                        |   88.88 |       85 |     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.75 |    74.12 |   89.24 |   82.81 |                   
  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          |   89.04 |    85.71 |   84.61 |   90.14 | 18,231-238        
  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/compone...*[Comment body truncated]*

saurav12 and others added 2 commits September 26, 2026 00:50
The knowledgebase drift check fails on types a doc uses but never defines.
Inline the placement types and declare SpacingValueType locally, the same
way the Popover doc does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@rzp-slash rzp-slash 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 passed

Passing checks (1)
Check Screenshot
✅ TreeView With Tooltip and Popover

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeView>
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    tooltip={{ content: 'Shown after a payment goes through' }}
  />
  <TreeViewItem
    title="Checkout"
    value="checkout"
    popover={{
      title: 'Checkout',
      content: <img src="/previews/checkout.png" alt="" />,
    }}
  />
</TreeView>

Comment thread packages/blade/src/components/TreeView/TreeViewItem.web.tsx Outdated
Comment thread packages/blade/src/components/TreeView/TreeViewItem.web.tsx
Comment thread packages/blade/src/components/TreeView/types.ts Outdated
Comment thread packages/blade/src/components/TreeView/types.ts Outdated
Comment thread packages/blade/src/components/TreeView/TreeViewItem.web.tsx Outdated
- Close the hover popover after motion.delay.xquick instead of immediately,
  so the pointer can cross the gap from the row onto the popover. The popover
  is portalled but is a React child of the row, so React keeps the row's
  pointerenter/pointerleave firing while the pointer is over it.
- Ignore click / focus / mousedown / mouseup events on the row whose DOM
  target is outside the row. They bubble in from the popover through the
  React tree, so clicking popover content selected the row.
- Declare `placement` on `tooltip` / `popover` with `@default 'right'`
  instead of inheriting Tooltip's / Popover's `@default "top"` via Pick.
- Log the tooltip + popover dev warning once, from an effect.
- Tests: crossing the gap keeps the popover open, clicks inside it do not
  select the row, a row is selected on the first click while a popover is
  open, and the warning is logged once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@kamaleshs-bridge4 kamaleshs-bridge4 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

Passing checks (10)
Check Screenshot
✅ TreeView HoverPreview story loads
✅ Tooltip appears on hover (Payment Animation)
✅ Tooltip with title+content appears on hover (Payment Processing)
✅ Popover appears on hover (Payment Success)
✅ Popover appears on hover (Retry Payment)
✅ Disabled item tooltip appears (Cancel Payment)
✅ Tooltip appears on keyboard focus
✅ No tooltip/popover on item without props (Exit Payment)
✅ Default TreeView docs page - no regressions
✅ Story registered in Storybook sidebar

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeView>
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    tooltip={{ content: 'Shown after a payment goes through' }}
  />
  <TreeViewItem
    title="Checkout"
    value="checkout"
    popover={{
      title: 'Checkout',
      content: <img src="/previews/checkout.png" alt="" />,
    }}
  />
</TreeView>

Comment thread packages/blade/src/components/TreeView/TreeViewItem.web.tsx
Comment thread packages/blade/src/components/TreeView/TreeViewItem.web.tsx Outdated
Comment thread packages/blade/src/components/TreeView/types.ts Outdated
…popover is open

- Popover gains an internal `_isModal` prop (default true, so every existing
  Popover is unchanged). TreeViewItem passes `_isModal={false}`: a modal
  Popover sets aria-hidden on everything outside it, which hid the whole tree
  from screen readers while the pointer rested on a row.
- Test: the tree and its rows stay accessible while a popover is open.
- Document why the tooltip's `aria-label: undefined` works (Tooltip's
  cloneElement spread order) and which test guards it.
- Write the `tooltip` prop type as Pick<TooltipProps> & {...}, matching
  `popover`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 26, 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 added the Human Help Needed 🧑🏻‍💻 Poor AI needs help from human for something label Sep 26, 2026

@kamaleshs-bridge4 kamaleshs-bridge4 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

✅ 6 passed

Passing checks (6)
Check Screenshot
✅ TreeView with Tooltip and Popover - Initial render
✅ TreeView tooltip appears on hover
✅ TreeView tooltip appears on keyboard focus
✅ TreeView popover appears on hover
✅ TreeView popover does NOT appear on keyboard focus
✅ TreeView tooltip on disabled item

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeView selectionType="single">
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    leading={<CheckCircleIcon />}
    tooltip={{ content: 'Shown after a payment goes through' }}
  />
  <TreeViewItem
    title="Checkout"
    value="checkout"
    leading={<LayoutIcon />}
    popover={{
      title: 'Checkout',
      content: <img src="/previews/checkout.png" alt="" />,
      maxWidth: 'spacing.80',
      onOpenChange: ({ isOpen }) => console.log(isOpen),
    }}
  />
</TreeView>

@kamaleshs-bridge4 kamaleshs-bridge4 added the rcore:eligible-for-auto-approval PR is approved by slash label Sep 26, 2026
…verlap

Moving the pointer down the tree showed the previous tooltip / popover fading
out under the next one (popovers also waited their 160ms hover-bridge delay).

- Tooltip: skip the transition during the delay group's instant phase, as
  floating-ui recommends. A tooltip replaced by the next one in the group
  disappears at once; the first still fades in and the last still fades out.
  Applies to every grouped Tooltip, not only TreeView.
- TreeViewItem popovers join BladeProvider's FloatingDelayGroup (the Tooltip
  group), so opening a popover or tooltip closes whichever one is open. A
  replaced popover is unmounted instead of fading out. Only items with a
  `popover` subscribe to the group.
- Leaving a row for another row closes its popover at once instead of after
  the hover-bridge delay (the pointer is not heading to the popover).
- Popover: replace the internal `_isModal` with `_shouldManageFocus`
  (default true). TreeView turns focus management off entirely: non-modal
  mode rendered floating-ui's focus guards (role=button, tabindex=0) and an
  aria-owns span inside the row, adding tab stops and renaming the row after
  the popover content while it was open.
- Tests: popover/tooltip/mixed switches leave one overlay within 100ms
  (shorter than the 200ms exit animation), row-to-row closes without delay,
  and the axe audit also runs with a popover open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@kamaleshs-bridge4 kamaleshs-bridge4 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

✅ 2 passed

Passing checks (2)
Check Screenshot
✅ TreeView HoverPreview story
✅ TreeView Sizes story (regression check)

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeViewItem
  title="Payment Success"
  value="payment-success"
  tooltip={{ content: 'Shown after a payment goes through' }}
/>

<TreeViewItem
  title="Payment Processing"
  value="payment-processing"
  popover={{ title: 'Payment Processing', content: <img src={preview} alt="" /> }}
/>

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash PR Healer has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@kamaleshs-bridge4 kamaleshs-bridge4 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

✅ 2 passed

Passing checks (2)
Check Screenshot
✅ TreeView With Tooltip and Popover
✅ Popover Switching Between Hover Popovers

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeViewItem
  title="Payment Success"
  value="payment-success"
  leading={<CheckCircleIcon />}
  tooltip={{ content: 'Shown after a payment goes through' }}
/>
<TreeViewItem
  title="Payment Success"
  value="payment-success"
  popover={{ title: 'Payment Success', content: <img src={preview} alt="" /> }}
/>

Comment thread .changeset/popover-hover-delay-group.md
saurav12 and others added 3 commits September 28, 2026 18:01
… explain the minor bump

- The in-place switch test checked, inside one 100ms window, both that the
  replaced popover was gone and that the new one had a 0ms transition.
  Popover applies its transition styles on the next animation frame, which
  can land after 100ms on a slow CI machine. The removal check keeps the
  100ms window (shorter than the 200ms fade it guards against); the
  transition value check uses the default timeout.
- Changeset: state that hover popovers being modal was unintended (the
  modal setting was hard-coded for every popover), which is why this ships
  as a minor release, and describe the one keyboard difference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…frame timing

Same fix as in the Popover branch: the check that the replaced popover is
gone keeps its 100ms window (shorter than the 200ms fade it guards
against), while the check that the new popover opened with a 0ms
transition waits the default timeout. Popover applies transition styles on
the next animation frame, which landed after 100ms on CI (Run Tests (4)).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash PR Healer has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

saurav12 and others added 3 commits September 28, 2026 18:14
The switching tests checked that a replaced overlay is gone within a real
100ms window, which failed on a busy CI machine ("popover back to tooltip"
chains a 1ms tooltip open delay and a 0ms close). They now advance fake
time by a fixed 100ms (shorter than the 200ms exit animation), in 10ms
steps so timers scheduled by React updates in one step fire in the next.
Each still fails with Popover's hover group or the Tooltip tweak disabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two switching tests checked that a replaced overlay is gone within a
real 100ms window, which can fail on a busy CI machine (the same test
shape failed on #4038). They now advance fake time by a
fixed 100ms (shorter than the 200ms exit animation), in 10ms steps so
timers scheduled by React updates in one step fire in the next. Each
still fails with the hover group, the close delay or the Tooltip tweak
disabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@rzp-slash rzp-slash 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 Screenshot
✅ TreeView With Tooltip and Popover - tree items render
✅ TreeView - tooltip shows on hover
✅ TreeView - popover shows on hover
✅ TreeView - selection and expand/collapse still work
✅ Popover Switching Between Hover Popovers - buttons render
✅ Popover - hover popover opens and switches in place
✅ Popover - tooltip and popover switching in the same group
✅ TreeView Sizes - no regression in existing story
✅ Popover OpenInteraction - no regression in existing story

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeView>
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    tooltip={{ content: 'Shown after a payment goes through' }}
  />
  <TreeViewItem
    title="Retry Payment"
    value="retry-payment"
    popover={{
      title: 'Retry Payment',
      content: <img src="/previews/retry.png" alt="" />,
    }}
  />
</TreeView>

@rzp-slash rzp-slash 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

✅ 2 passed

Passing checks (2)
Check Screenshot
✅ TreeView With Tooltip and Popover
✅ Popover Switching Between Hover Popovers

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeView>
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    tooltip={{ content: 'Shown after payment goes through' }}
  />
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    popover={{ title: 'Payment Success', content: <img src={preview} alt="" /> }}
  />
</TreeView>

saurav12 added a commit that referenced this pull request Sep 29, 2026
* feat(Popover): switch hover popovers and tooltips in place

Hover popovers join BladeProvider's FloatingDelayGroup, the group every
Tooltip is in, so moving the pointer between hover overlays switches them
in place instead of fading out and in again.

- Popover (openInteraction="hover" only): joins the delay group with its
  own floating context. Opening one closes whichever overlay is showing;
  the replaced one closes with a 0ms transition and the new one opens with
  a 0ms transition during the group's instant phase. Controlled popovers
  are asked to close through onOpenChange. A close request that arrives
  before the popover has claimed the group (mounted open, or opened in the
  same update) is ignored.
- Hover popovers are no longer modal: they do not trap focus or mark the
  rest of the page aria-hidden.
- Hover popovers close 80ms after the pointer leaves the trigger (instead
  of immediately), so the next overlay can replace them in place; moving
  onto the popover cancels the close.
- Tooltip skips its transition during the instant phase, as floating-ui
  recommends.
- Click popovers are unchanged and stay out of the group.
- Story, tests (real timers), changeset and blade-mcp Popover doc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(Popover): make the hover switch test independent of frame timing; explain the minor bump

- The in-place switch test checked, inside one 100ms window, both that the
  replaced popover was gone and that the new one had a 0ms transition.
  Popover applies its transition styles on the next animation frame, which
  can land after 100ms on a slow CI machine. The removal check keeps the
  100ms window (shorter than the 200ms fade it guards against); the
  transition value check uses the default timeout.
- Changeset: state that hover popovers being modal was unintended (the
  modal setting was hard-coded for every popover), which is why this ships
  as a minor release, and describe the one keyboard difference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(Popover): run the hover switching tests on fake timers

The two switching tests checked that a replaced overlay is gone within a
real 100ms window, which can fail on a busy CI machine (the same test
shape failed on #4038). They now advance fake time by a
fixed 100ms (shorter than the 200ms exit animation), in 10ms steps so
timers scheduled by React updates in one step fire in the next. Each
still fails with the hover group, the close delay or the Tooltip tweak
disabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#4044 (hover popovers join the tooltip delay group) is
squash-merged into master, so this branch now takes it from master. The
only Popover change left in this PR is the internal `_shouldManageFocus`
prop TreeView needs (its popover trigger sits inside a treeitem).

- Conflict in Popover.web.tsx: keep `disabled={!_shouldManageFocus}`
  on FloatingFocusManager; everything else is master's.
- TreeView changeset: reference #4044 instead of "the
  Popover changeset", which ships separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

TreeView.web.test.tsx and PopoverHoverGroup.web.test.tsx (from
#4044) each defined the same helpers. Move them to
~utils/testing/overlayTransitions and import them in both:

- REPLACED_OVERLAY_TIME: 100ms, shorter than the 200ms exit animation
- advanceTime: advances jest fake timers in 10ms steps, so timers
  scheduled by React updates in one step fire in the next
- getOpenTransitionDuration: reads a popover's computed
  transition-duration

No test behaviour changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 29, 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 Sep 29, 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

✅ 7 passed

Passing checks (7)
Check Screenshot
✅ TreeView With Tooltip and Popover — popover opens on hover
✅ TreeView With Tooltip and Popover — tooltip opens on hover
✅ TreeView With Tooltip and Popover — row-to-row overlay switching
✅ TreeView With Tooltip and Popover — hovering a plain row closes the overlay
✅ TreeView With Tooltip and Popover — popover stays open when hovering the popover itself
✅ TreeView With Tooltip and Popover — click inside popover does not select the row
✅ TreeView Single Select — regression: tree renders and selection works

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeView selectionType="single">
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    popover={{ title: 'Payment Success', content: <img src={preview} alt="" /> }}
  />
  <TreeViewItem
    title="Payment Processing"
    value="payment-processing"
    tooltip={{ content: 'Shown while the bank confirms' }}
  />
</TreeView>

Comment thread packages/blade/src/components/TreeView/TreeViewItem.web.tsx Outdated
Review question: an item popover is portalled outside DropdownOverlay, so
would a press inside it (e.g. a footer button) be an outside press for
the Dropdown's useDismiss and close it?

It is not: floating-ui's useDismiss also checks the React tree, and the
popover is a React child of the row inside the overlay. The new test
opens a TreeView in a SelectInput Dropdown, clicks a footer button in an
item popover, and checks the button handler runs, the Dropdown and
popover stay open, and nothing is selected (it fails without the row's
event-target guard).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

(Review Cancelled - Superseded by a new run)

@saurav12 saurav12 added Approved by Blade Designers 💅🏼 Usecase and UI is approved by a designer from blade team and removed Approved by Blade Designers 💅🏼 Usecase and UI is approved by a designer from blade team labels Sep 29, 2026
saurav12 and others added 2 commits September 30, 2026 15:50
There is no use case for a plain-text tooltip on tree items yet, so
TreeViewItem only offers `popover` (the hover preview). This also removes
the "both tooltip and popover passed" case raised in review.

- Remove the `tooltip` prop, TreeViewItemTooltip, the Tooltip aria-label
  workaround and the both-props dev warning.
- Story "With Hover Preview": every previewable row uses `popover`.
- Tests: drop the tooltip-only and tooltip switching tests; the popover
  tests (incl. popover-to-popover switching and the Dropdown click test)
  stay.
- decisions.md B13 records why TreeView uses a prop instead of wrapping in
  <Popover> and why there is no tooltip prop; blade-mcp doc and changeset
  updated (changeset renamed to treeview-item-popover.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Slash AI Review has been triggered. View execution logs

@saurav12 saurav12 changed the title feat(TreeView): show a Tooltip or Popover when hovering a TreeViewItem feat(TreeView): show a Popover preview when hovering a TreeViewItem Sep 30, 2026

@kamaleshs-bridge4 kamaleshs-bridge4 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 Screenshot
✅ TreeView hover preview opens to the right of a row
✅ Popover stays open while pointer moves onto it
✅ Preview switches in place between rows
✅ No popover on disabled row or rows without popover prop
✅ Tree expansion still works (Checkout branch)
✅ Hover does not select; row click selects; popover click does not select
✅ Popover does not open on keyboard focus
✅ Existing Single Select story regression check
✅ Existing In Dropdown story regression check

Usage

import { TreeView, TreeViewItem } from '@razorpay/blade/components';

<TreeView>
  <TreeViewItem
    title="Payment Success"
    value="payment-success"
    popover={{ title: 'Payment Success', content: <img src={preview} alt="" /> }}
  />
</TreeView>

This branch has not been deployed

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

Labels

blade Changes to packages/blade blade-mcp Changes to packages/blade-mcp 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