Skip to content

chore: Audit style props in AI package#10218

Merged
LFDanLu merged 5 commits into
mainfrom
audit-props-for-ai-package
Jun 17, 2026
Merged

chore: Audit style props in AI package#10218
LFDanLu merged 5 commits into
mainfrom
audit-props-for-ai-package

Conversation

@snowystinger

Copy link
Copy Markdown
Member

Closes

Mostly matched everything to PromptField, it seemed the most correct.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@rspbot

rspbot commented Jun 17, 2026

Copy link
Copy Markdown

@devongovett

devongovett commented Jun 17, 2026

Copy link
Copy Markdown
Member

Sorry I wasn't clear. We should:

  • Not include UNSAFE for now (except for wrappers around existing S2 components).
  • Exclude className/style.
  • The styles prop should be StyleString for AI-specific components. For simple wrappers around S2 components, just accept whatever the S2 component accepted.

Going for easiest path here, not going out of our way to restrict and also not going out of our way to allow.

also updated chat to be more consistent and other audit todos
@rspbot

rspbot commented Jun 17, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jun 17, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jun 17, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jun 17, 2026

Copy link
Copy Markdown
## API Changes

@react-spectrum/ai

/@react-spectrum/ai:Attachment

 Attachment {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children: ReactNode | (AttachmentRenderProps) => ReactNode
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   download?: boolean | string
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onAction?: () => void
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, TagRenderProps>
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StyleString
   target?: HTMLAttributeAnchorTarget
   uploadProgress?: number
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/ai:MessageFeedback

 MessageFeedback {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   defaultValue?: MessageFeedbackValue
   id?: string
   isDisabled?: boolean
   onChange?: (MessageFeedbackValue) => void
   slot?: string | null
-  styles?: StyleString
+  styles?: StylesPropWithHeight
   thumbDownLabel?: string
   thumbUpLabel?: string
   value?: MessageFeedbackValue
 }

/@react-spectrum/ai:MessageSource

 MessageSource {
   children: ReactNode
   defaultExpanded?: boolean
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   id?: Key
   isDisabled?: boolean
   isExpanded?: boolean
   label: string
   onExpandedChange?: (boolean) => void
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
-  styles?: StyleString
+  styles?: StylesProp
 }

/@react-spectrum/ai:SourceList

 SourceList {
+  UNSAFE_className?: UnsafeClassName
+  UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children: React.ReactNode
   id?: string
   label?: ReactNode
   labelElementType?: ElementType = 'label'
   role?: 'group' | 'region' = 'group'
-  styles?: StyleString
 }

/@react-spectrum/ai:SourceListItem

 SourceListItem {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   children: React.ReactNode
   download?: boolean | string
   href?: Href
   hrefLang?: string
   id?: string
   isDisabled?: boolean
   onBlur?: (FocusEvent<Target>) => void
   onClick?: (MouseEvent<FocusableElement>) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onHoverChange?: (boolean) => void
   onHoverEnd?: (HoverEvent) => void
   onHoverStart?: (HoverEvent) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
-  render?: (DetailedHTMLProps<LinkWithRequiredHref, HTMLAnchorElement> | React.JSX.IntrinsicElements[keyof React.JSX.IntrinsicElements], LinkRenderProps) => ReactElement
   routerOptions?: RouterOptions
   slot?: string | null
   styles?: StyleString
   target?: HTMLAttributeAnchorTarget

/@react-spectrum/ai:MessageSuggestion

 MessageSuggestion {
   aria-controls?: string
   aria-current?: boolean | 'true' | 'false' | 'page' | 'step' | 'location' | 'date' | 'time'
   aria-describedby?: string
   aria-details?: string
   aria-disabled?: boolean | 'true' | 'false'
   aria-expanded?: boolean | 'true' | 'false'
   aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
   aria-label?: string
   aria-labelledby?: string
   aria-pressed?: boolean | 'true' | 'false' | 'mixed'
   autoFocus?: boolean
   children: ReactNode
   excludeFromTabOrder?: boolean
   form?: string
   formAction?: ButtonHTMLAttributes<HTMLButtonElement>['formAction']
   formEncType?: string
   formMethod?: string
   formNoValidate?: boolean
   formTarget?: string
   id?: string
   name?: string
   onBlur?: (FocusEvent<Target>) => void
   onClick?: (MouseEvent<FocusableElement>) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onHoverChange?: (boolean) => void
   onHoverEnd?: (HoverEvent) => void
   onHoverStart?: (HoverEvent) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   preventFocusOnPress?: boolean
-  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, ButtonRenderProps>
-  size?: 'S' | 'M' | 'L' | 'XL'
+  size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   styles?: StyleString
   type?: 'button' | 'submit' | 'reset' = 'button'
   value?: string

/@react-spectrum/ai:PromptField

 PromptField {
-  UNSAFE_className?: UnsafeClassName
-  UNSAFE_style?: CSSProperties
   acceptedAttachmentTypes?: Array<string>
   children: React.ReactNode
   isGenerating?: boolean
   onAddAttachments?: (Array<PromptFieldAttachment>) => void
   onStop?: () => void
   onSubmit?: (TokenSegmentList, Array<PromptFieldAttachment>) => void
   styles?: StyleString
 }

/@react-spectrum/ai:PromptToken

 PromptToken {
   children: React.ReactNode
   className?: ClassNameOrFunction<TokenRenderProps>
-  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, TokenRenderProps>
   style?: StyleOrFunction<TokenRenderProps>
 }

/@react-spectrum/ai:Chat

 Chat {
   children?: ReactNode
-  className?: string
-  style?: CSSProperties
+  styles?: StyleString
 }

/@react-spectrum/ai:Thread

 Thread <T extends {}> {
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (T) => ReactNode
-  className?: ClassNameOrFunction<GridListRenderProps> = 'react-aria-GridList'
   items?: Iterable<T>
+  styles?: StyleString
 }

/@react-spectrum/ai:ThreadItem

 ThreadItem {
   children?: ChildrenOrFunction<GridListItemRenderProps>
-  className?: ClassNameOrFunction<GridListItemRenderProps> = 'react-aria-GridListItem'
   isStreaming?: boolean
   shouldAnnounceOnMount?: boolean
+  styles?: StyleString
   textValue?: string
 }

/@react-spectrum/ai:AttachmentProps

 AttachmentProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children: ReactNode | (AttachmentRenderProps) => ReactNode
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   download?: boolean | string
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onAction?: () => void
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, TagRenderProps>
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StyleString
   target?: HTMLAttributeAnchorTarget
   uploadProgress?: number
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/ai:PromptFieldProps

 PromptFieldProps {
-  UNSAFE_className?: UnsafeClassName
-  UNSAFE_style?: CSSProperties
   acceptedAttachmentTypes?: Array<string>
   children: React.ReactNode
   isGenerating?: boolean
   onAddAttachments?: (Array<PromptFieldAttachment>) => void
   onStop?: () => void
   onSubmit?: (TokenSegmentList, Array<PromptFieldAttachment>) => void
   styles?: StyleString
 }

/@react-spectrum/ai:PromptTokenProps

 PromptTokenProps {
   children: React.ReactNode
   className?: ClassNameOrFunction<TokenRenderProps>
-  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, TokenRenderProps>
   style?: StyleOrFunction<TokenRenderProps>
 }

/@react-spectrum/ai:MessageFeedbackProps

 MessageFeedbackProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   defaultValue?: MessageFeedbackValue
   id?: string
   isDisabled?: boolean
   onChange?: (MessageFeedbackValue) => void
   slot?: string | null
-  styles?: StyleString
+  styles?: StylesPropWithHeight
   thumbDownLabel?: string
   thumbUpLabel?: string
   value?: MessageFeedbackValue
 }

/@react-spectrum/ai:MessageSourceProps

 MessageSourceProps {
   children: ReactNode
   defaultExpanded?: boolean
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   id?: Key
   isDisabled?: boolean
   isExpanded?: boolean
   label: string
   onExpandedChange?: (boolean) => void
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
-  styles?: StyleString
+  styles?: StylesProp
 }

/@react-spectrum/ai:SourceListProps

 SourceListProps {
+  UNSAFE_className?: UnsafeClassName
+  UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children: React.ReactNode
   id?: string
   label?: ReactNode
   labelElementType?: ElementType = 'label'
   role?: 'group' | 'region' = 'group'
-  styles?: StyleString
 }

/@react-spectrum/ai:SourceListItemProps

 SourceListItemProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   children: React.ReactNode
   download?: boolean | string
   href?: Href
   hrefLang?: string
   id?: string
   isDisabled?: boolean
   onBlur?: (FocusEvent<Target>) => void
   onClick?: (MouseEvent<FocusableElement>) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onHoverChange?: (boolean) => void
   onHoverEnd?: (HoverEvent) => void
   onHoverStart?: (HoverEvent) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
-  render?: (DetailedHTMLProps<LinkWithRequiredHref, HTMLAnchorElement> | React.JSX.IntrinsicElements[keyof React.JSX.IntrinsicElements], LinkRenderProps) => ReactElement
   routerOptions?: RouterOptions
   slot?: string | null
   styles?: StyleString
   target?: HTMLAttributeAnchorTarget

/@react-spectrum/ai:MessageSuggestionProps

 MessageSuggestionProps {
   aria-controls?: string
   aria-current?: boolean | 'true' | 'false' | 'page' | 'step' | 'location' | 'date' | 'time'
   aria-describedby?: string
   aria-details?: string
   aria-disabled?: boolean | 'true' | 'false'
   aria-expanded?: boolean | 'true' | 'false'
   aria-haspopup?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
   aria-label?: string
   aria-labelledby?: string
   aria-pressed?: boolean | 'true' | 'false' | 'mixed'
   autoFocus?: boolean
   children: ReactNode
   excludeFromTabOrder?: boolean
   form?: string
   formAction?: ButtonHTMLAttributes<HTMLButtonElement>['formAction']
   formEncType?: string
   formMethod?: string
   formNoValidate?: boolean
   formTarget?: string
   id?: string
   name?: string
   onBlur?: (FocusEvent<Target>) => void
   onClick?: (MouseEvent<FocusableElement>) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onHoverChange?: (boolean) => void
   onHoverEnd?: (HoverEvent) => void
   onHoverStart?: (HoverEvent) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   preventFocusOnPress?: boolean
-  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, ButtonRenderProps>
-  size?: 'S' | 'M' | 'L' | 'XL'
+  size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   styles?: StyleString
   type?: 'button' | 'submit' | 'reset' = 'button'
   value?: string

/@react-spectrum/ai:ChatProps

 ChatProps {
   children?: ReactNode
-  className?: string
-  style?: CSSProperties
+  styles?: StyleString
 }

/@react-spectrum/ai:ThreadProps

 ThreadProps <T extends {}> {
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (T) => ReactNode
-  className?: ClassNameOrFunction<GridListRenderProps> = 'react-aria-GridList'
   items?: Iterable<T>
+  styles?: StyleString
 }

/@react-spectrum/ai:ThreadItemProps

 ThreadItemProps {
   children?: ChildrenOrFunction<GridListItemRenderProps>
-  className?: ClassNameOrFunction<GridListItemRenderProps> = 'react-aria-GridListItem'
   isStreaming?: boolean
   shouldAnnounceOnMount?: boolean
+  styles?: StyleString
   textValue?: string
 }

/@react-spectrum/ai:BasicHorizontalCard

+BasicHorizontalCard {
+  children: ReactNode | (HorizontalCardRenderProps) => ReactNode
+  density?: 'compact' | 'regular' | 'spacious' = 'regular'
+  download?: boolean | string
+  href?: Href
+  hrefLang?: string
+  id?: Key
+  isDisabled?: boolean
+  onAction?: () => void
+  onPress?: (PressEvent) => void
+  onPressChange?: (boolean) => void
+  onPressEnd?: (PressEvent) => void
+  onPressStart?: (PressEvent) => void
+  onPressUp?: (PressEvent) => void
+  ping?: string
+  referrerPolicy?: HTMLAttributeReferrerPolicy
+  rel?: string
+  routerOptions?: RouterOptions
+  size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
+  styles?: StyleString
+  target?: HTMLAttributeAnchorTarget
+  textValue?: string
+  value?: T
+  variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
+}

/@react-spectrum/ai:CardPreview

+CardPreview {
+  children: ReactNode
+  id?: string
+  styles?: StyleString
+}

/@react-spectrum/ai:HorizontalCard

+HorizontalCard {
+  children: ReactNode | (HorizontalCardRenderProps) => ReactNode
+  density?: 'compact' | 'regular' | 'spacious' = 'regular'
+  download?: boolean | string
+  href?: Href
+  hrefLang?: string
+  id?: Key
+  isDisabled?: boolean
+  onAction?: () => void
+  onPress?: (PressEvent) => void
+  onPressChange?: (boolean) => void
+  onPressEnd?: (PressEvent) => void
+  onPressStart?: (PressEvent) => void
+  onPressUp?: (PressEvent) => void
+  ping?: string
+  referrerPolicy?: HTMLAttributeReferrerPolicy
+  rel?: string
+  routerOptions?: RouterOptions
+  size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
+  styles?: StyleString
+  target?: HTMLAttributeAnchorTarget
+  textValue?: string
+  value?: T
+  variant?: 'primary' | 'secondary' | 'tertiary' = 'primary'
+}

/@react-spectrum/ai:HorizontalCardProps

+HorizontalCardProps {
+  children: ReactNode | (HorizontalCardRenderProps) => ReactNode
+  density?: 'compact' | 'regular' | 'spacious' = 'regular'
+  download?: boolean | string
+  href?: Href
+  hrefLang?: string
+  id?: Key
+  isDisabled?: boolean
+  onAction?: () => void
+  onPress?: (PressEvent) => void
+  onPressChange?: (boolean) => void
+  onPressEnd?: (PressEvent) => void
+  onPressStart?: (PressEvent) => void
+  onPressUp?: (PressEvent) => void
+  ping?: string
+  referrerPolicy?: HTMLAttributeReferrerPolicy
+  rel?: string
+  routerOptions?: RouterOptions
+  size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
+  styles?: StyleString
+  target?: HTMLAttributeAnchorTarget
+  textValue?: string
+  value?: T
+  variant?: 'primary' | 'secondary' | 'tertiary' = 'primary'
+}

/@react-spectrum/ai:BasicCardProps

+BasicCardProps {
+  children: ReactNode | (HorizontalCardRenderProps) => ReactNode
+  density?: 'compact' | 'regular' | 'spacious' = 'regular'
+  download?: boolean | string
+  href?: Href
+  hrefLang?: string
+  id?: Key
+  isDisabled?: boolean
+  onAction?: () => void
+  onPress?: (PressEvent) => void
+  onPressChange?: (boolean) => void
+  onPressEnd?: (PressEvent) => void
+  onPressStart?: (PressEvent) => void
+  onPressUp?: (PressEvent) => void
+  ping?: string
+  referrerPolicy?: HTMLAttributeReferrerPolicy
+  rel?: string
+  routerOptions?: RouterOptions
+  size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
+  styles?: StyleString
+  target?: HTMLAttributeAnchorTarget
+  textValue?: string
+  value?: T
+  variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
+}

@LFDanLu LFDanLu added this pull request to the merge queue Jun 17, 2026
Merged via the queue into main with commit b8b0688 Jun 17, 2026
30 checks passed
@LFDanLu LFDanLu deleted the audit-props-for-ai-package branch June 17, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants