Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) Add subdialog support to Menu and Autocomplete #7561

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft

Conversation

LFDanLu
Copy link
Member

@LFDanLu LFDanLu commented Jan 3, 2025

Closes

✅ 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

rspbot commented Jan 3, 2025

@rspbot
Copy link

rspbot commented Jan 3, 2025

Base automatically changed from autocomplete_audit_for_release to main January 6, 2025 18:58
…ually focused

typically submenus dont have focus restore turned on since it would move focus manually back to the trigger when keyboard closing the menu. However, we cant move focus to virtually focused triggers so enable focus restore on the submenu in these cases
@rspbot
Copy link

rspbot commented Jan 14, 2025

…tch events to the temporarily cleared focus item

the second part of this message refers to the following flow: over submenu via hover in autocomplete, use arrowLeft to close it and then try to reopen it via arrowRight
@rspbot
Copy link

rspbot commented Jan 16, 2025

@rspbot
Copy link

rspbot commented Jan 16, 2025

@rspbot
Copy link

rspbot commented Jan 16, 2025

## API Changes

react-aria-components

/react-aria-components:Dialog

 Dialog {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   className?: string
   id?: string
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   role?: 'dialog' | 'alertdialog' = 'dialog'
   slot?: string | null
   style?: CSSProperties
 }

/react-aria-components:DialogProps

 DialogProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   className?: string
   id?: string
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   role?: 'dialog' | 'alertdialog' = 'dialog'
   slot?: string | null
   style?: CSSProperties
 }

@react-aria/dialog

/@react-aria/dialog:AriaDialogProps

 AriaDialogProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   id?: string
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   role?: 'dialog' | 'alertdialog' = 'dialog'
 }

@react-aria/menu

/@react-aria/menu:AriaSubmenuTriggerProps

 AriaSubmenuTriggerProps {
   delay?: number = 200
   isDisabled?: boolean
+  isVirtualFocus?: boolean
   parentMenuRef: RefObject<HTMLElement | null>
   submenuRef: RefObject<HTMLElement | null>
   type?: 'dialog' | 'menu'
 }

@react-spectrum/dialog

/@react-spectrum/dialog:Dialog

 Dialog {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   bottom?: Responsive<DimensionValue>
   children: ReactNode
   end?: Responsive<DimensionValue>
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isDismissable?: boolean
   isHidden?: Responsive<boolean>
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
   onDismiss?: () => void
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   order?: Responsive<number>
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   role?: 'dialog' | 'alertdialog' = 'dialog'
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/dialog:SpectrumDialogProps

 SpectrumDialogProps {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   bottom?: Responsive<DimensionValue>
   children: ReactNode
   end?: Responsive<DimensionValue>
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isDismissable?: boolean
   isHidden?: Responsive<boolean>
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
   onDismiss?: () => void
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   order?: Responsive<number>
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   role?: 'dialog' | 'alertdialog' = 'dialog'
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

@react-spectrum/s2

/@react-spectrum/s2:Dialog

 Dialog {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   id?: string
   isDismissible?: boolean
   isKeyboardDismissDisabled?: boolean
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   role?: 'dialog' | 'alertdialog' = 'dialog'
   size?: 'S' | 'M' | 'L' = 'M'
   slot?: string | null
   styles?: StylesProp

/@react-spectrum/s2:CustomDialog

 CustomDialog {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   id?: string
   isDismissible?: boolean
   isKeyboardDismissDisabled?: boolean
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   padding?: 'default' | 'none' = 'default'
   role?: 'dialog' | 'alertdialog' = 'dialog'
   size?: 'S' | 'M' | 'L' | 'fullscreen' | 'fullscreenTakeover'
   slot?: string | null
 }

/@react-spectrum/s2:FullscreenDialog

 FullscreenDialog {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   id?: string
   isKeyboardDismissDisabled?: boolean
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   role?: 'dialog' | 'alertdialog' = 'dialog'
   slot?: string | null
   styles?: StylesProp
   variant?: 'fullscreen' | 'fullscreenTakeover' = "fullscreen"

/@react-spectrum/s2:Popover

 Popover {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   containerPadding?: number = 12
   crossOffset?: number = 0
   hideArrow?: boolean = false
   id?: string
   offset?: number = 8
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   placement?: Placement = 'bottom'
   role?: 'dialog' | 'alertdialog' = 'dialog'
   shouldFlip?: boolean = true
   size?: 'S' | 'M' | 'L'
   styles?: StylesProp
 }

/@react-spectrum/s2:DialogProps

 DialogProps {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   id?: string
   isDismissible?: boolean
   isKeyboardDismissDisabled?: boolean
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   role?: 'dialog' | 'alertdialog' = 'dialog'
   size?: 'S' | 'M' | 'L' = 'M'
   slot?: string | null
   styles?: StylesProp

/@react-spectrum/s2:CustomDialogProps

 CustomDialogProps {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   id?: string
   isDismissible?: boolean
   isKeyboardDismissDisabled?: boolean
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   padding?: 'default' | 'none' = 'default'
   role?: 'dialog' | 'alertdialog' = 'dialog'
   size?: 'S' | 'M' | 'L' | 'fullscreen' | 'fullscreenTakeover'
   slot?: string | null
 }

/@react-spectrum/s2:FullscreenDialogProps

 FullscreenDialogProps {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode | (DialogRenderProps) => ReactNode
   id?: string
   isKeyboardDismissDisabled?: boolean
+  onKeyDown?: (KeyboardEvent) => void
+  onKeyUp?: (KeyboardEvent) => void
   role?: 'dialog' | 'alertdialog' = 'dialog'
   slot?: string | null
   styles?: StylesProp
   variant?: 'fullscreen' | 'fullscreenTakeover' = "fullscreen"

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.

2 participants