Skip to content

Commit 5fb6052

Browse files
authored
apply disabled fix when inside a disabled fieldset (#202)
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
1 parent de16c1b commit 5fb6052

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

packages/@headlessui-react/src/components/menu/menu.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { useId } from '../../hooks/use-id'
1212
import { Keys } from '../keyboard'
1313
import { Focus, calculateActiveIndex } from '../../utils/calculate-active-index'
1414
import { resolvePropValue } from '../../utils/resolve-prop-value'
15+
import { isDisabledReactIssue7711 } from '../../utils/bugs'
1516

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

415416
const handleClick = React.useCallback(
416-
(event: { preventDefault: Function }) => {
417+
(event: React.MouseEvent) => {
418+
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
417419
if (disabled) return event.preventDefault()
418420
dispatch({ type: ActionTypes.CloseMenu })
419421
disposables().nextFrame(() => state.buttonRef.current?.focus({ preventScroll: true }))

packages/@headlessui-react/src/components/switch/switch.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { render } from '../../utils/render'
55
import { useId } from '../../hooks/use-id'
66
import { Keys } from '../keyboard'
77
import { resolvePropValue } from '../../utils/resolve-prop-value'
8+
import { isDisabledReactIssue7711 } from '../../utils/bugs'
89

910
type StateDefinition = {
1011
switch: HTMLButtonElement | null
@@ -84,6 +85,7 @@ export function Switch<TTag extends React.ElementType = typeof DEFAULT_SWITCH_TA
8485
const toggle = React.useCallback(() => onChange(!checked), [onChange, checked])
8586
const handleClick = React.useCallback(
8687
(event: React.MouseEvent) => {
88+
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
8789
event.preventDefault()
8890
toggle()
8991
},
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// See: https://github.com/facebook/react/issues/7711
2+
// See: https://github.com/facebook/react/pull/20612
3+
// See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-disabled (2.)
4+
export function isDisabledReactIssue7711(element: Element): boolean {
5+
let parent = element.parentElement
6+
let legend = null
7+
8+
while (parent && !(parent instanceof HTMLFieldSetElement)) {
9+
if (parent instanceof HTMLLegendElement) legend = parent
10+
parent = parent.parentElement
11+
}
12+
13+
let isParentDisabled = parent?.getAttribute('disabled') === '' ?? false
14+
if (isParentDisabled && isFirstLegend(legend)) return false
15+
16+
return isParentDisabled
17+
}
18+
19+
function isFirstLegend(element: HTMLLegendElement | null): boolean {
20+
if (!element) return false
21+
22+
let previous = element.previousElementSibling
23+
24+
while (previous !== null) {
25+
if (previous instanceof HTMLLegendElement) return false
26+
previous = previous.previousElementSibling
27+
}
28+
29+
return true
30+
}

0 commit comments

Comments
 (0)