Skip to content

Commit

Permalink
apply disabled fix when inside a disabled fieldset
Browse files Browse the repository at this point in the history
And if we are in a disabled fieldset, double check that we are not in
the first legend. Because in that case we are visually outside of the
fieldset and according to the spec those elements should **not** be
considered disabled.

Fixes: #194
  • Loading branch information
RobinMalfait committed Jan 22, 2021
1 parent de16c1b commit b39759a
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 1 deletion.
4 changes: 3 additions & 1 deletion packages/@headlessui-react/src/components/menu/menu.tsx
Expand Up @@ -12,6 +12,7 @@ import { useId } from '../../hooks/use-id'
import { Keys } from '../keyboard'
import { Focus, calculateActiveIndex } from '../../utils/calculate-active-index'
import { resolvePropValue } from '../../utils/resolve-prop-value'
import { isDisabledReactIssue7711 } from '../../utils/bugs'

enum MenuStates {
Open,
Expand Down Expand Up @@ -413,7 +414,8 @@ function Item<TTag extends React.ElementType = typeof DEFAULT_ITEM_TAG>(
}, [bag, id])

const handleClick = React.useCallback(
(event: { preventDefault: Function }) => {
(event: React.MouseEvent) => {
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
if (disabled) return event.preventDefault()
dispatch({ type: ActionTypes.CloseMenu })
disposables().nextFrame(() => state.buttonRef.current?.focus({ preventScroll: true }))
Expand Down
2 changes: 2 additions & 0 deletions packages/@headlessui-react/src/components/switch/switch.tsx
Expand Up @@ -5,6 +5,7 @@ import { render } from '../../utils/render'
import { useId } from '../../hooks/use-id'
import { Keys } from '../keyboard'
import { resolvePropValue } from '../../utils/resolve-prop-value'
import { isDisabledReactIssue7711 } from '../../utils/bugs'

type StateDefinition = {
switch: HTMLButtonElement | null
Expand Down Expand Up @@ -84,6 +85,7 @@ export function Switch<TTag extends React.ElementType = typeof DEFAULT_SWITCH_TA
const toggle = React.useCallback(() => onChange(!checked), [onChange, checked])
const handleClick = React.useCallback(
(event: React.MouseEvent) => {
if (isDisabledReactIssue7711(event.currentTarget)) return
event.preventDefault()
toggle()
},
Expand Down
30 changes: 30 additions & 0 deletions packages/@headlessui-react/src/utils/bugs.ts
@@ -0,0 +1,30 @@
// See: https://github.com/facebook/react/issues/7711
// See: https://github.com/facebook/react/pull/20612
// See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-disabled (2.)
export function isDisabledReactIssue7711(element: Element): boolean {
let parent = element.parentElement
let legend = null

while (parent && !(parent instanceof HTMLFieldSetElement)) {
if (parent instanceof HTMLLegendElement) legend = parent
parent = parent.parentElement
}

let isParentDisabled = parent?.getAttribute('disabled') === '' ?? false
if (isParentDisabled && isFirstLegend(legend)) return false

return isParentDisabled
}

function isFirstLegend(element: HTMLLegendElement | null): boolean {
if (!element) return false

let previous = element.previousElementSibling

while (previous !== null) {
if (previous instanceof HTMLLegendElement) return false
previous = previous.previousElementSibling
}

return true
}

0 comments on commit b39759a

Please sign in to comment.