use HTMLElement for generic DOM node types (#3169)

We keep specific types for elements with special meaning, such as
`HTMLButtonElement`, `HTMLLabelElement` or `HTMLInputElement` because
they receive certain attributes that generic DOM nodes (such as
HTMLDivElement) don't

For the components where we use simple `div` elements (and where people
use `as={...}`) that renders a different element, it doesn't make sense
to use `HTMLDivElement`. Using a more generic `HTMLElement` is simpler
and more correct (we still had `HTMLUListElement` and `HTMLLIElement`
for "div" DOM nodes which is incorrect).

This shouldn't be a breaking change because an `HTMLDivElement` is still
a valid `HTMLElement`. The other way around wouldn't be the case.
This commit is contained in:
Robin Malfait
2024-05-03 15:32:55 +02:00
committed by GitHub
parent f0e3e5b4a6
commit 0bd8c47c28
9 changed files with 27 additions and 27 deletions
@@ -550,7 +550,7 @@ let ComboboxDataContext = createContext<
inputRef: MutableRefObject<HTMLInputElement | null>
buttonRef: MutableRefObject<HTMLButtonElement | null>
optionsRef: MutableRefObject<HTMLUListElement | null>
optionsRef: MutableRefObject<HTMLElement | null>
} & Omit<StateDefinition<unknown>, 'dataRef'>)
| null
>(null)
@@ -1425,7 +1425,7 @@ function ButtonFn<TTag extends ElementType = typeof DEFAULT_BUTTON_TAG>(
let refocusInput = useRefocusableInput(data.inputRef)
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLUListElement>) => {
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLElement>) => {
switch (event.key) {
// Ref: https://www.w3.org/WAI/ARIA/apg/patterns/menu/#keyboard-interaction-12
@@ -1574,7 +1574,7 @@ export type ComboboxOptionsProps<TTag extends ElementType = typeof DEFAULT_OPTIO
function OptionsFn<TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG>(
props: ComboboxOptionsProps<TTag>,
ref: Ref<HTMLUListElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let {
@@ -1750,7 +1750,7 @@ function OptionFn<
// TODO: One day we will be able to infer this type from the generic in Combobox itself.
// But today is not that day..
TType = Parameters<typeof ComboboxRoot>[0]['value'],
>(props: ComboboxOptionProps<TTag, TType>, ref: Ref<HTMLLIElement>) {
>(props: ComboboxOptionProps<TTag, TType>, ref: Ref<HTMLElement>) {
let data = useData('Combobox.Option')
let actions = useActions('Combobox.Option')
@@ -1772,7 +1772,7 @@ function OptionFn<
: data.options[data.activeOptionIndex]?.id === id
let selected = data.isSelected(value)
let internalOptionRef = useRef<HTMLLIElement | null>(null)
let internalOptionRef = useRef<HTMLElement | null>(null)
let bag = useLatestValue<ComboboxOptionDataRef<TType>['current']>({
disabled,
@@ -107,7 +107,7 @@ export type DescriptionProps<TTag extends ElementType = typeof DEFAULT_DESCRIPTI
function DescriptionFn<TTag extends ElementType = typeof DEFAULT_DESCRIPTION_TAG>(
props: DescriptionProps<TTag>,
ref: Ref<HTMLParagraphElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let providedDisabled = useDisabled()
@@ -61,7 +61,7 @@ enum DialogStates {
interface StateDefinition {
titleId: string | null
panelRef: MutableRefObject<HTMLDivElement | null>
panelRef: MutableRefObject<HTMLElement | null>
}
enum ActionTypes {
@@ -135,7 +135,7 @@ export type DialogProps<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> =
function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
props: DialogProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let {
@@ -173,7 +173,7 @@ function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
open = (usesOpenClosedState & State.Open) === State.Open
}
let internalDialogRef = useRef<HTMLDivElement | null>(null)
let internalDialogRef = useRef<HTMLElement | null>(null)
let dialogRef = useSyncRefs(internalDialogRef, ref)
let ownerDocument = useOwnerDocument(internalDialogRef)
@@ -440,7 +440,7 @@ export type DialogOverlayProps<TTag extends ElementType = typeof DEFAULT_OVERLAY
function OverlayFn<TTag extends ElementType = typeof DEFAULT_OVERLAY_TAG>(
props: DialogOverlayProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let { id = `headlessui-dialog-overlay-${internalId}`, ...theirProps } = props
@@ -492,7 +492,7 @@ export type DialogBackdropProps<TTag extends ElementType = typeof DEFAULT_BACKDR
function BackdropFn<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG>(
props: DialogBackdropProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let { id = `headlessui-dialog-backdrop-${internalId}`, ...theirProps } = props
@@ -547,7 +547,7 @@ export type DialogPanelProps<TTag extends ElementType = typeof DEFAULT_PANEL_TAG
function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
props: DialogPanelProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let { id = `headlessui-dialog-panel-${internalId}`, ...theirProps } = props
@@ -594,7 +594,7 @@ export type DialogTitleProps<TTag extends ElementType = typeof DEFAULT_TITLE_TAG
function TitleFn<TTag extends ElementType = typeof DEFAULT_TITLE_TAG>(
props: DialogTitleProps<TTag>,
ref: Ref<HTMLHeadingElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let { id = `headlessui-dialog-title-${internalId}`, ...theirProps } = props
@@ -54,7 +54,7 @@ interface StateDefinition {
linkedPanel: boolean
buttonRef: MutableRefObject<HTMLButtonElement | null>
panelRef: MutableRefObject<HTMLDivElement | null>
panelRef: MutableRefObject<HTMLElement | null>
buttonId: string | null
panelId: string | null
@@ -433,7 +433,7 @@ export type DisclosurePanelProps<TTag extends ElementType = typeof DEFAULT_PANEL
function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
props: DisclosurePanelProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let { id = `headlessui-disclosure-panel-${internalId}`, ...theirProps } = props
@@ -90,9 +90,9 @@ export type FocusTrapProps<TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_
function FocusTrapFn<TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_TAG>(
props: FocusTrapProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let container = useRef<HTMLDivElement | null>(null)
let container = useRef<HTMLElement | null>(null)
let focusTrapRef = useSyncRefs(container, ref)
let {
initialFocus,
@@ -418,7 +418,7 @@ let ListboxDataContext = createContext<
listRef: MutableRefObject<Map<string, HTMLElement | null>>
buttonRef: MutableRefObject<HTMLButtonElement | null>
optionsRef: MutableRefObject<HTMLUListElement | null>
optionsRef: MutableRefObject<HTMLElement | null>
} & Omit<StateDefinition<unknown>, 'dataRef'>)
| null
>(null)
@@ -1003,7 +1003,7 @@ function OptionsFn<TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG>(
container?.focus({ preventScroll: true })
}, [data.listboxState, data.optionsRef, data.optionsRef.current])
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLUListElement>) => {
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLElement>) => {
searchDisposables.dispose()
switch (event.key) {
@@ -1176,7 +1176,7 @@ function OptionFn<
data.activeOptionIndex !== null ? data.options[data.activeOptionIndex].id === id : false
let selected = data.isSelected(value)
let internalOptionRef = useRef<HTMLLIElement | null>(null)
let internalOptionRef = useRef<HTMLElement | null>(null)
let getTextValue = useTextValue(internalOptionRef)
let bag = useLatestValue<ListboxOptionDataRef<TType>['current']>({
disabled,
@@ -93,7 +93,7 @@ interface StateDefinition {
__demoMode: boolean
menuState: MenuStates
buttonRef: MutableRefObject<HTMLButtonElement | null>
itemsRef: MutableRefObject<HTMLDivElement | null>
itemsRef: MutableRefObject<HTMLElement | null>
items: { id: string; dataRef: MenuItemDataRef }[]
searchQuery: string
activeItemIndex: number | null
@@ -590,7 +590,7 @@ export type MenuItemsProps<TTag extends ElementType = typeof DEFAULT_ITEMS_TAG>
function ItemsFn<TTag extends ElementType = typeof DEFAULT_ITEMS_TAG>(
props: MenuItemsProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let {
@@ -675,7 +675,7 @@ function ItemsFn<TTag extends ElementType = typeof DEFAULT_ITEMS_TAG>(
},
})
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLDivElement>) => {
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLElement>) => {
searchDisposables.dispose()
switch (event.key) {
@@ -730,7 +730,7 @@ export type PopoverOverlayProps<TTag extends ElementType = typeof DEFAULT_OVERLA
function OverlayFn<TTag extends ElementType = typeof DEFAULT_OVERLAY_TAG>(
props: PopoverOverlayProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let { id = `headlessui-popover-overlay-${internalId}`, ...theirProps } = props
@@ -804,7 +804,7 @@ export type PopoverPanelProps<TTag extends ElementType = typeof DEFAULT_PANEL_TA
function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
props: PopoverPanelProps<TTag>,
ref: Ref<HTMLDivElement>
ref: Ref<HTMLElement>
) {
let internalId = useId()
let {
@@ -822,7 +822,7 @@ function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
let beforePanelSentinelId = `headlessui-focus-sentinel-before-${internalId}`
let afterPanelSentinelId = `headlessui-focus-sentinel-after-${internalId}`
let internalPanelRef = useRef<HTMLDivElement | null>(null)
let internalPanelRef = useRef<HTMLElement | null>(null)
let anchor = useResolvedAnchor(rawAnchor)
let [floatingRef, style] = useFloatingPanel(anchor)
let getFloatingPanelProps = useFloatingPanelProps()
@@ -303,7 +303,7 @@ function useNesting(done?: () => void, parent?: NestingContextValues) {
// ---
let DEFAULT_TRANSITION_CHILD_TAG = Fragment
type TransitionChildRenderPropArg = MutableRefObject<HTMLDivElement>
type TransitionChildRenderPropArg = MutableRefObject<HTMLElement>
let TransitionChildRenderFeatures = RenderFeatures.RenderStrategy
function TransitionChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_CHILD_TAG>(