Skip to content

fix: update expand hover behaviors#9906

Open
snowystinger wants to merge 4 commits intomainfrom
new-expand-behaviors
Open

fix: update expand hover behaviors#9906
snowystinger wants to merge 4 commits intomainfrom
new-expand-behaviors

Conversation

@snowystinger
Copy link
Copy Markdown
Member

@snowystinger snowystinger commented Apr 10, 2026

Closes

Discussed in slack, this gets rid of the full row hover behavior when disabledBehavior is selection and there is no onAction. Instead it adds a hover style to the expand button directly

✅ 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
Copy link
Copy Markdown

rspbot commented Apr 10, 2026

gridArea: 'expand-button',
color: {
default: 'inherit',
isHovered: baseColor('neutral-subdued').isHovered,
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.

the change in color when hovered feels almost indistinguishable to me in light mode haha. Definitely much more noticeable in dark mode. Same with Tree

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmmm what else would we use? the text is neutral-subdued, so using the hover state for it is the logical choice

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 10, 2026

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 11, 2026

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 11, 2026

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 11, 2026

## API Changes

@react-spectrum/s2

/@react-spectrum/s2:DatePicker

 DatePicker <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoComplete?: string
   autoFocus?: boolean
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: DateValue | null
   description?: ReactNode
-  errorMessage?: ReactNode | (ValidationResult) => ReactNode
+  errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   isRequired?: boolean
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   minValue?: DateValue | null
   name?: string
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (MappedDateValue<DateValue> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   styles?: StylesProp
   validate?: (MappedDateValue<DateValue>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: DateValue | null
 }

/@react-spectrum/s2:DateRangePicker

 DateRangePicker <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   endName?: string
-  errorMessage?: ReactNode | (ValidationResult) => ReactNode
+  errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   id?: string
   interactOutsideBehavior?: 'clear' | 'reset' | 'select' = 'select'
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   isRequired?: boolean
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   minValue?: DateValue | null
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   startName?: string
   styles?: StylesProp
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: RangeValue<DateValue> | null
 }

/@react-spectrum/s2:DatePickerProps

 DatePickerProps <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoComplete?: string
   autoFocus?: boolean
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: DateValue | null
   description?: ReactNode
-  errorMessage?: ReactNode | (ValidationResult) => ReactNode
+  errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   id?: string
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   isRequired?: boolean
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   minValue?: DateValue | null
   name?: string
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (MappedDateValue<DateValue> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   styles?: StylesProp
   validate?: (MappedDateValue<DateValue>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: DateValue | null
 }

/@react-spectrum/s2:DateRangePickerProps

 DateRangePickerProps <T extends DateValue> {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   allowsNonContiguousRanges?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean
   contextualHelp?: ReactNode
   createCalendar?: (CalendarIdentifier) => Calendar
   defaultOpen?: boolean
   defaultValue?: RangeValue<DateValue> | null
   description?: ReactNode
   endName?: string
-  errorMessage?: ReactNode | (ValidationResult) => ReactNode
+  errorMessage?: ReactNode
   firstDayOfWeek?: 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
   form?: string
   granularity?: Granularity
   hideTimeZone?: boolean = false
   id?: string
   interactOutsideBehavior?: 'clear' | 'reset' | 'select' = 'select'
   isDateUnavailable?: (DateValue) => boolean
   isDisabled?: boolean
   isInvalid?: boolean
   isOpen?: boolean
   isReadOnly?: boolean
   isRequired?: boolean
   label?: ReactNode
   labelAlign?: Alignment = 'start'
   labelPosition?: LabelPosition = 'top'
   maxValue?: DateValue | null
   maxVisibleMonths?: number = 1
   minValue?: DateValue | null
   necessityIndicator?: NecessityIndicator = 'icon'
   onBlur?: (FocusEvent<Target>) => void
   onChange?: (RangeValue<MappedDateValue<DateValue>> | null) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onKeyDown?: (KeyboardEvent) => void
   onKeyUp?: (KeyboardEvent) => void
   onOpenChange?: (boolean) => void
   pageBehavior?: PageBehavior = visible
   placeholderValue?: DateValue | null
   shouldCloseOnSelect?: boolean | () => boolean = true
   shouldFlip?: boolean = true
   shouldForceLeadingZeros?: boolean
   size?: 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   startName?: string
   styles?: StylesProp
   validate?: (RangeValue<MappedDateValue<DateValue>>) => ValidationError | boolean | null | undefined
   validationBehavior?: 'native' | 'aria' = 'native'
   value?: RangeValue<DateValue> | null
 }

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants