Skip to content

feat: support list of agent actions in ResponseStatus - #10359

Open
catherine wants to merge 8 commits into
mainfrom
f/response_status_list
Open

feat: support list of agent actions in ResponseStatus#10359
catherine wants to merge 8 commits into
mainfrom
f/response_status_list

Conversation

@catherine

@catherine catherine commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

This PR introduces <ExecutionTrace> and <ExecutionTraceItem> - components that render inside a <ResponseStatus> in order to highlight the steps an agent took while crafting its response.

Screenshot 2026-07-24 at 4 15 42 PM

@rspbot

rspbot commented Jul 23, 2026

Copy link
Copy Markdown

@catherine
catherine force-pushed the f/response_status_list branch from 238eccc to 19e3229 Compare July 24, 2026 23:16
@rspbot

rspbot commented Jul 24, 2026

Copy link
Copy Markdown

@catherine
catherine marked this pull request as ready for review July 24, 2026 23:24
@catherine
catherine force-pushed the f/response_status_list branch from 19e3229 to 23ca611 Compare July 24, 2026 23:49
@catherine
catherine force-pushed the f/response_status_list branch from 23ca611 to ee22f43 Compare July 24, 2026 23:52
@rspbot

rspbot commented Jul 24, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 24, 2026

Copy link
Copy Markdown

devongovett
devongovett previously approved these changes Jul 25, 2026

@devongovett devongovett left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great!

* Additional detail revealed when the step is expanded, such as tool call input or output.
* If omitted, the row is static and cannot be expanded.
*/
detail?: ReactNode;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to move this into children with title/panel wrappers like the RSP Disclosure API at some point


export interface ExecutionTraceItemProps extends DOMProps, AriaLabelingProps {
/** Allows detail content to render but prevents the row from being collapsible. */
isDetailNotCollapsible?: boolean;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can debate this name 😄 allowsExpanding could work if the default is false. disallowCollapsing? 😂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image Support Left/Right arrow to expand/collapse ??

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a list of disclosures at the moment
https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/
No left/right for now

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isAlwaysOpen

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to isAlwaysOpen, allowsExpanding makes it sound like there is a state where it could still be "closed" and just not expandable IMO

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was struggling to name this one 😅 -- I'm also a fan of isAlwaysOpen and have updated to that

@devongovett

devongovett commented Jul 25, 2026

Copy link
Copy Markdown
Member

might want a lil padding around this for the focus ring

image

also when it's expanded there's some extra space on the right

image

textAlign: 'start'
});

const detailTriggerChevronStyles = style({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heads up there may be a merge conflict with #10349 depending the merge order

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks for putting that on my radar

const detailTriggerStyles = style({
display: 'block',
paddingY: 4,
marginTop: -2,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this for? could it be paddingTop:2 and no marginTop instead?

return (
<Button
className={renderProps =>
// TODO: remove size conditional once size is also removed from ResponseStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we resolve by removing size?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ removed

font: 'body',
display: 'flex',
gap: 8,
marginTop: {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a lot of margin/paddingTop: +/-2 what's driving all of these?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initially it was solving some alignment issues between the step's icon/label when there was a hover state -- I'll do a pass to review/remove any that are no longer applicable now since we decided to remove the hover state

'--divider-display': {
type: 'display',
value: {
default: 'flex',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intention here is display: block, there's no children inside of the line?

const executionTraceItemContentStyles = style({
display: 'flex',
flexDirection: 'column',
paddingBottom: 12,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last one shouldn't have padding bottom, it's doubled up with the padding from the wrapper of the ol

</RACDisclosure>
) : (
<div
className={mergeStyles(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can do this at build time, if you put the shared properties into a const, you can spread it into both styles, then we can get rid of the mergeStyles and it'll be a little more declarative

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ cleaned up 🧹

<Provider values={[[IconContext, {styles: iconStyle({size: 'M'})}]]}>
<CenterBaseline>{icon}</CenterBaseline>
</Provider>
<div className={executionTraceItemDividerStyles} />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<div className={executionTraceItemDividerStyles} />
<div role="presentation" className={executionTraceItemDividerStyles} />

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 added

docs
</ExecutionTraceItem>
</ExecutionTrace>
{/* <div>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? dead code?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover from a demo - good catch, removed ✅


export interface ExecutionTraceItemProps extends DOMProps, AriaLabelingProps {
/** Allows detail content to render but prevents the row from being collapsible. */
isDetailNotCollapsible?: boolean;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isAlwaysOpen


export interface ExecutionTraceItemProps extends DOMProps, AriaLabelingProps {
/** Allows detail content to render but prevents the row from being collapsible. */
isDetailNotCollapsible?: boolean;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to isAlwaysOpen, allowsExpanding makes it sound like there is a state where it could still be "closed" and just not expandable IMO

);
}

export interface ExecutionTraceItemProps extends DOMProps, AriaLabelingProps {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the ExecutionTraceItems also include the ability to set expanded by default/controlled? I don't think I've see that in other chat experiences so no need to add right now until requested by other teams, but maybe something to keep in mind

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the future, would be nice to to also have the ExecutionTrace added to the "Chat" stories so we can see how it looks in a chat as a whole

- Set `role="presentation”` on vertical item divider
- Remove dead code in Storybook example
- Clean up styles around row content alignment with leading icon
@rspbot

rspbot commented Jul 27, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 27, 2026

Copy link
Copy Markdown
## API Changes

react-aria-components

/react-aria-components:GridListHeaderProps

-GridListHeaderProps {
-  children?: ReactNode
-  className?: string
-  id?: string
-  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
-  style?: CSSProperties
-}

@react-spectrum/ai

/@react-spectrum/ai:ResponseStatus

 ResponseStatus {
   children: ReactNode
   defaultExpanded?: boolean
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   id?: Key
   isDisabled?: boolean
   isExpanded?: boolean
   onExpandedChange?: (boolean) => void
-  size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   status?: 'loading' | 'failed' | 'success' = 'loading'
   styles?: StyleString
 }

/@react-spectrum/ai:ResponseStatusProps

 ResponseStatusProps {
   children: ReactNode
   defaultExpanded?: boolean
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   id?: Key
   isDisabled?: boolean
   isExpanded?: boolean
   onExpandedChange?: (boolean) => void
-  size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   status?: 'loading' | 'failed' | 'success' = 'loading'
   styles?: StyleString
 }

/@react-spectrum/ai:ExecutionTrace

+ExecutionTrace {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: ReactNode
+  id?: string
+  styles?: StyleString
+}

/@react-spectrum/ai:ExecutionTraceItem

+ExecutionTraceItem {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: ReactNode
+  detail?: ReactNode
+  icon?: ReactNode
+  id?: string
+  isAlwaysOpen?: boolean
+  styles?: StyleString
+}

/@react-spectrum/ai:ExecutionTraceProps

+ExecutionTraceProps {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: ReactNode
+  id?: string
+  styles?: StyleString
+}

/@react-spectrum/ai:ExecutionTraceItemProps

+ExecutionTraceItemProps {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: ReactNode
+  detail?: ReactNode
+  icon?: ReactNode
+  id?: string
+  isAlwaysOpen?: boolean
+  styles?: StyleString
+}

@react-spectrum/s2

/@react-spectrum/s2:SideNav

-SideNav <T> {
-  UNSAFE_className?: UnsafeClassName
-  UNSAFE_style?: CSSProperties
-  aria-describedby?: string
-  aria-details?: string
-  aria-label?: string
-  aria-labelledby?: string
-  autoFocus?: boolean | FocusStrategy
-  children?: ReactNode | (T) => ReactNode
-  defaultExpandedKeys?: Iterable<Key>
-  dependencies?: ReadonlyArray<any>
-  disabledKeys?: Iterable<Key>
-  expandedKeys?: Iterable<Key>
-  id?: string
-  items?: Iterable<T>
-  onExpandedChange?: (Set<Key>) => any
-  selectedRoute: string
-  slot?: string | null
-  styles?: StylesPropWithHeight
-}

/@react-spectrum/s2:SideNavItem

-SideNavItem {
-  aria-label?: string
-  children: ReactNode
-  download?: boolean | string
-  hasChildItems?: boolean
-  href?: Href
-  hrefLang?: string
-  id?: Key
-  isDisabled?: boolean
-  onHoverChange?: (boolean) => void
-  onHoverEnd?: (HoverEvent) => void
-  onHoverStart?: (HoverEvent) => void
-  onPress?: (PressEvent) => void
-  onPressChange?: (boolean) => void
-  onPressEnd?: (PressEvent) => void
-  onPressStart?: (PressEvent) => void
-  onPressUp?: (PressEvent) => void
-  ping?: string
-  referrerPolicy?: HTMLAttributeReferrerPolicy
-  rel?: string
-  routerOptions?: RouterOptions
-  target?: HTMLAttributeAnchorTarget
-  textValue: string
-}

/@react-spectrum/s2:SideNavItemContent

-SideNavItemContent {
-  children: ReactNode
-}

/@react-spectrum/s2:SideNavItemLink

-SideNavItemLink {
-  children?: ReactNode
-}

/@react-spectrum/s2:SideNavSection

-SideNavSection <T extends {}> {
-  aria-label?: string
-  children?: ReactNode | (T) => ReactElement
-  dependencies?: ReadonlyArray<any>
-  id?: Key
-  items?: Iterable<T>
-}

/@react-spectrum/s2:SideNavHeader

-SideNavHeader {
-  children?: ReactNode
-  id?: string
-}

/@react-spectrum/s2:SideNavProps

-SideNavProps <T> {
-  UNSAFE_className?: UnsafeClassName
-  UNSAFE_style?: CSSProperties
-  aria-describedby?: string
-  aria-details?: string
-  aria-label?: string
-  aria-labelledby?: string
-  autoFocus?: boolean | FocusStrategy
-  children?: ReactNode | (T) => ReactNode
-  defaultExpandedKeys?: Iterable<Key>
-  dependencies?: ReadonlyArray<any>
-  disabledKeys?: Iterable<Key>
-  expandedKeys?: Iterable<Key>
-  id?: string
-  items?: Iterable<T>
-  onExpandedChange?: (Set<Key>) => any
-  selectedRoute: string
-  slot?: string | null
-  styles?: StylesPropWithHeight
-}

/@react-spectrum/s2:SideNavItemProps

-SideNavItemProps {
-  aria-label?: string
-  children: ReactNode
-  download?: boolean | string
-  hasChildItems?: boolean
-  href?: Href
-  hrefLang?: string
-  id?: Key
-  isDisabled?: boolean
-  onHoverChange?: (boolean) => void
-  onHoverEnd?: (HoverEvent) => void
-  onHoverStart?: (HoverEvent) => void
-  onPress?: (PressEvent) => void
-  onPressChange?: (boolean) => void
-  onPressEnd?: (PressEvent) => void
-  onPressStart?: (PressEvent) => void
-  onPressUp?: (PressEvent) => void
-  ping?: string
-  referrerPolicy?: HTMLAttributeReferrerPolicy
-  rel?: string
-  routerOptions?: RouterOptions
-  target?: HTMLAttributeAnchorTarget
-  textValue: string
-}

/@react-spectrum/s2:SideNavItemContentProps

-SideNavItemContentProps {
-  children: ReactNode
-}

/@react-spectrum/s2:SideNavItemLinkProps

-SideNavItemLinkProps {
-  children?: ReactNode
-}

/@react-spectrum/s2:SideNavSectionProps

-SideNavSectionProps <T> {
-  aria-label?: string
-  children?: ReactNode | (T) => ReactElement
-  dependencies?: ReadonlyArray<any>
-  id?: Key
-  items?: Iterable<T>
-}

/@react-spectrum/s2:SideNavHeaderProps

-SideNavHeaderProps {
-  children?: ReactNode
-  id?: string
-}

@rspbot

rspbot commented Jul 27, 2026

Copy link
Copy Markdown

Agent Skills Changes

Removed (1)
  • s2/skills/react-spectrum-s2/references/components/SideNav.md
Modified (7)
Install

React Spectrum S2:

npx skills add https://d1pzu54gtk2aed.cloudfront.net/pr/dd77302922507be5bfdf01bd4747e49fe4ec01c7/

React Aria:

npx skills add https://d5iwopk28bdhl.cloudfront.net/pr/dd77302922507be5bfdf01bd4747e49fe4ec01c7/

@yihuiliao yihuiliao added SideNav and removed SideNav labels Jul 27, 2026
@yihuiliao

Copy link
Copy Markdown
Member

ah sorry ignore me adding labels to this PR...i didn't mean to do that


return (
<Button
className={renderProps => mergeStyles(buttonStyles({...renderProps}), detailTriggerStyles)}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @devongovett

might want a lil padding around this for the focus ring

I've nudged the space around the focus ring:

Screenshot 2026-07-27 at 11 11 43 AM

Separately, I will follow up looking into the space that is added when the disclosure is expanded. It's happening both to the top level ResponseStatus disclosure and these new children

Screenshot 2026-07-27 at 11 11 34 AM

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants