From 734965bf5c66146adf2f519d183f022047435f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivica=20Batini=C4=87?= Date: Thu, 12 Feb 2026 22:13:17 +0100 Subject: [PATCH 1/5] refactor(context): improve type definitions --- packages/react/src/utils/create-context.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/react/src/utils/create-context.ts b/packages/react/src/utils/create-context.ts index 7d56cec5df..fea3c84152 100644 --- a/packages/react/src/utils/create-context.ts +++ b/packages/react/src/utils/create-context.ts @@ -1,6 +1,10 @@ import { hasProp, isFunction } from '@zag-js/utils' import { createContext as createReactContext, useContext as useReactContext } from 'react' +function getErrorMessage(hook: string, provider: string) { + return `${hook} returned \`undefined\`. Seems you forgot to wrap component within ${provider}` +} + interface CreateContextOptions { strict?: boolean | undefined hookName?: string | undefined @@ -10,11 +14,19 @@ interface CreateContextOptions { defaultValue?: T | undefined } -type CreateContextReturn = [React.Provider, () => T, React.Context] +type CreateContextReturn = [ + React.Provider, + HasValue extends true ? () => T : () => T | undefined, + HasValue extends true ? React.Context : React.Context, +] -function getErrorMessage(hook: string, provider: string) { - return `${hook} returned \`undefined\`. Seems you forgot to wrap component within ${provider}` -} +export function createContext(options?: CreateContextOptions & { strict?: true }): CreateContextReturn + +export function createContext( + options: CreateContextOptions & { strict: false; defaultValue: T }, +): CreateContextReturn + +export function createContext(options: CreateContextOptions & { strict: false }): CreateContextReturn export function createContext(options: CreateContextOptions = {}) { const { @@ -45,5 +57,5 @@ export function createContext(options: CreateContextOptions = {}) { return context } - return [Context.Provider, useContext, Context] as CreateContextReturn + return [Context.Provider, useContext, Context] as any } From 0f6310fa2ff474f2f3cb8b442b8692da7c3ebcab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivica=20Batini=C4=87?= Date: Mon, 16 Feb 2026 20:05:57 +0100 Subject: [PATCH 2/5] fix(context): ensure safe access to context properties across components --- .../src/components/checkbox/use-checkbox-group-context.tsx | 4 +--- .../react/src/components/field/examples/custom-control.tsx | 2 +- packages/react/src/components/field/field-context.tsx | 4 ++-- packages/react/src/components/field/field-error-text.tsx | 2 +- .../react/src/components/field/field-required-indicator.tsx | 4 ++-- packages/react/src/components/fieldset/fieldset-context.tsx | 4 ++-- .../react/src/components/fieldset/fieldset-error-text.tsx | 4 ++-- .../react/src/components/fieldset/fieldset-helper-text.tsx | 2 +- packages/react/src/components/fieldset/fieldset-legend.tsx | 2 +- packages/react/src/components/menu/menu-context.tsx | 4 ++-- packages/react/src/components/menu/menu-item.tsx | 5 +++-- packages/react/src/components/menu/use-menu-context.ts | 1 - .../use-navigation-menu-item-props-context.ts | 1 - 13 files changed, 18 insertions(+), 21 deletions(-) diff --git a/packages/react/src/components/checkbox/use-checkbox-group-context.tsx b/packages/react/src/components/checkbox/use-checkbox-group-context.tsx index ea2ab685b5..4435880ec1 100644 --- a/packages/react/src/components/checkbox/use-checkbox-group-context.tsx +++ b/packages/react/src/components/checkbox/use-checkbox-group-context.tsx @@ -3,9 +3,7 @@ import type { UseCheckboxGroupReturn } from './use-checkbox-group' export interface UseCheckboxGroupContext extends UseCheckboxGroupReturn {} -export const [CheckboxGroupContextProvider, useCheckboxGroupContext] = createContext< - UseCheckboxGroupContext | undefined ->({ +export const [CheckboxGroupContextProvider, useCheckboxGroupContext] = createContext({ name: 'CheckboxGroupContext', hookName: 'useCheckboxGroupContext', providerName: '', diff --git a/packages/react/src/components/field/examples/custom-control.tsx b/packages/react/src/components/field/examples/custom-control.tsx index 9fe68b9ecc..ec927234de 100644 --- a/packages/react/src/components/field/examples/custom-control.tsx +++ b/packages/react/src/components/field/examples/custom-control.tsx @@ -4,7 +4,7 @@ import styles from 'styles/field.module.css' export const CustomControl = () => ( Any Control - {(context) => } + {(context) => } Uses getInputProps() for maximum flexibility This field has an error diff --git a/packages/react/src/components/field/field-context.tsx b/packages/react/src/components/field/field-context.tsx index 180e5dbfe3..4e229b6e5c 100644 --- a/packages/react/src/components/field/field-context.tsx +++ b/packages/react/src/components/field/field-context.tsx @@ -1,8 +1,8 @@ import type { ReactNode } from 'react' -import { type UseFieldContext, useFieldContext } from './use-field-context' +import { useFieldContext } from './use-field-context' export interface FieldContextProps { - children: (context: UseFieldContext) => ReactNode + children: (context: ReturnType) => ReactNode } export const FieldContext = (props: FieldContextProps) => props.children(useFieldContext()) diff --git a/packages/react/src/components/field/field-error-text.tsx b/packages/react/src/components/field/field-error-text.tsx index 158f4bfc7e..b8c5eae38e 100644 --- a/packages/react/src/components/field/field-error-text.tsx +++ b/packages/react/src/components/field/field-error-text.tsx @@ -8,7 +8,7 @@ export interface FieldErrorTextProps extends HTMLProps<'span'>, FieldErrorTextBa export const FieldErrorText = forwardRef((props, ref) => { const field = useFieldContext() - const mergedProps = mergeProps(field.getErrorTextProps(), props) + const mergedProps = mergeProps(field?.getErrorTextProps(), props) if (field?.invalid) { return diff --git a/packages/react/src/components/field/field-required-indicator.tsx b/packages/react/src/components/field/field-required-indicator.tsx index 10e097fe54..7a74920198 100644 --- a/packages/react/src/components/field/field-required-indicator.tsx +++ b/packages/react/src/components/field/field-required-indicator.tsx @@ -12,11 +12,11 @@ export const FieldRequiredIndicator = forwardRef { const field = useFieldContext() - if (!field.required) { + if (!field?.required) { return fallback } - const mergedProps = mergeProps(field.getRequiredIndicatorProps(), props) + const mergedProps = mergeProps(field?.getRequiredIndicatorProps(), props) return ( {props.children ?? '*'} diff --git a/packages/react/src/components/fieldset/fieldset-context.tsx b/packages/react/src/components/fieldset/fieldset-context.tsx index acf60d6aa8..895f956e2a 100644 --- a/packages/react/src/components/fieldset/fieldset-context.tsx +++ b/packages/react/src/components/fieldset/fieldset-context.tsx @@ -1,8 +1,8 @@ import type { ReactNode } from 'react' -import { type UseFieldsetContext, useFieldsetContext } from './use-fieldset-context' +import { useFieldsetContext } from './use-fieldset-context' export interface FieldsetContextProps { - children: (context: UseFieldsetContext) => ReactNode + children: (context: ReturnType) => ReactNode } export const FieldsetContext = (props: FieldsetContextProps) => props.children(useFieldsetContext()) diff --git a/packages/react/src/components/fieldset/fieldset-error-text.tsx b/packages/react/src/components/fieldset/fieldset-error-text.tsx index ceb06abfae..abd24288e9 100644 --- a/packages/react/src/components/fieldset/fieldset-error-text.tsx +++ b/packages/react/src/components/fieldset/fieldset-error-text.tsx @@ -8,9 +8,9 @@ export interface FieldsetErrorTextProps extends HTMLProps<'span'>, FieldsetError export const FieldsetErrorText = forwardRef((props, ref) => { const fieldset = useFieldsetContext() - const mergedProps = mergeProps(fieldset.getErrorTextProps(), props) + const mergedProps = mergeProps(fieldset?.getErrorTextProps(), props) - return fieldset.invalid ? : null + return fieldset?.invalid ? : null }) FieldsetErrorText.displayName = 'FieldsetErrorText' diff --git a/packages/react/src/components/fieldset/fieldset-helper-text.tsx b/packages/react/src/components/fieldset/fieldset-helper-text.tsx index 322c48463e..5dd4f37bd3 100644 --- a/packages/react/src/components/fieldset/fieldset-helper-text.tsx +++ b/packages/react/src/components/fieldset/fieldset-helper-text.tsx @@ -8,7 +8,7 @@ export interface FieldsetHelperTextProps extends HTMLProps<'span'>, FieldsetHelp export const FieldsetHelperText = forwardRef((props, ref) => { const fieldset = useFieldsetContext() - const mergedProps = mergeProps(fieldset.getHelperTextProps(), props) + const mergedProps = mergeProps(fieldset?.getHelperTextProps(), props) return }) diff --git a/packages/react/src/components/fieldset/fieldset-legend.tsx b/packages/react/src/components/fieldset/fieldset-legend.tsx index 63a651bd8d..1aaa0f267b 100644 --- a/packages/react/src/components/fieldset/fieldset-legend.tsx +++ b/packages/react/src/components/fieldset/fieldset-legend.tsx @@ -8,7 +8,7 @@ export interface FieldsetLegendProps extends HTMLProps<'legend'>, FieldsetLegend export const FieldsetLegend = forwardRef((props, ref) => { const fieldset = useFieldsetContext() - const mergedProps = mergeProps(fieldset.getLegendProps(), props) + const mergedProps = mergeProps(fieldset?.getLegendProps(), props) return }) diff --git a/packages/react/src/components/menu/menu-context.tsx b/packages/react/src/components/menu/menu-context.tsx index 0ac85f16a6..05563adafc 100644 --- a/packages/react/src/components/menu/menu-context.tsx +++ b/packages/react/src/components/menu/menu-context.tsx @@ -1,8 +1,8 @@ import type { ReactNode } from 'react' -import { type UseMenuContext, useMenuContext } from './use-menu-context' +import { useMenuContext } from './use-menu-context' export interface MenuContextProps { - children: (context: UseMenuContext) => ReactNode + children: (context: ReturnType) => ReactNode } export const MenuContext = (props: MenuContextProps) => props.children(useMenuContext()) diff --git a/packages/react/src/components/menu/menu-item.tsx b/packages/react/src/components/menu/menu-item.tsx index c049000ada..f90ab2925d 100644 --- a/packages/react/src/components/menu/menu-item.tsx +++ b/packages/react/src/components/menu/menu-item.tsx @@ -36,8 +36,9 @@ export const MenuItem = forwardRef((props, ref) = // biome-ignore lint/correctness/useExhaustiveDependencies: intentional useEffect(() => { - return menu.addItemListener({ id: itemState.id, onSelect: itemProps.onSelect }) - }, [itemState.id, itemProps.onSelect]) + if (!itemState?.id) return + return menu.addItemListener({ id: itemState?.id, onSelect: itemProps.onSelect }) + }, [itemState?.id, itemProps.onSelect]) return ( diff --git a/packages/react/src/components/menu/use-menu-context.ts b/packages/react/src/components/menu/use-menu-context.ts index 01903f14d7..a386dac93b 100644 --- a/packages/react/src/components/menu/use-menu-context.ts +++ b/packages/react/src/components/menu/use-menu-context.ts @@ -7,5 +7,4 @@ export const [MenuProvider, useMenuContext] = createContext({ name: 'MenuContext', hookName: 'useMenuContext', providerName: '', - strict: false, }) diff --git a/packages/react/src/components/navigation-menu/use-navigation-menu-item-props-context.ts b/packages/react/src/components/navigation-menu/use-navigation-menu-item-props-context.ts index 2277d11982..3bf233d0a6 100644 --- a/packages/react/src/components/navigation-menu/use-navigation-menu-item-props-context.ts +++ b/packages/react/src/components/navigation-menu/use-navigation-menu-item-props-context.ts @@ -5,5 +5,4 @@ export const [NavigationMenuItemPropsProvider, useNavigationMenuItemPropsContext name: 'NavigationMenuItemPropsContext', hookName: 'useNavigationMenuItemPropsContext', providerName: '', - strict: false, }) From df1842c5d81c8309846bfc2230c4f1357d99f1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivica=20Batini=C4=87?= Date: Mon, 16 Feb 2026 20:08:26 +0100 Subject: [PATCH 3/5] fix(menu-item): simplify useEffect by removing unnecessary null check for itemState.id --- packages/react/src/components/menu/menu-item.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/react/src/components/menu/menu-item.tsx b/packages/react/src/components/menu/menu-item.tsx index f90ab2925d..c049000ada 100644 --- a/packages/react/src/components/menu/menu-item.tsx +++ b/packages/react/src/components/menu/menu-item.tsx @@ -36,9 +36,8 @@ export const MenuItem = forwardRef((props, ref) = // biome-ignore lint/correctness/useExhaustiveDependencies: intentional useEffect(() => { - if (!itemState?.id) return - return menu.addItemListener({ id: itemState?.id, onSelect: itemProps.onSelect }) - }, [itemState?.id, itemProps.onSelect]) + return menu.addItemListener({ id: itemState.id, onSelect: itemProps.onSelect }) + }, [itemState.id, itemProps.onSelect]) return ( From 264e72f110ebaf1421feed0ed1a9825a64e326d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivica=20Batini=C4=87?= Date: Mon, 16 Feb 2026 20:31:41 +0100 Subject: [PATCH 4/5] fix(menu): add optional chaining to context property access for safety --- packages/react/src/components/menu/menu-arrow-tip.tsx | 2 +- packages/react/src/components/menu/menu-arrow.tsx | 2 +- .../react/src/components/menu/menu-checkbox-item.tsx | 6 +++--- packages/react/src/components/menu/menu-content.tsx | 2 +- .../src/components/menu/menu-context-trigger.tsx | 2 +- packages/react/src/components/menu/menu-indicator.tsx | 2 +- .../src/components/menu/menu-item-group-label.tsx | 2 +- .../react/src/components/menu/menu-item-group.tsx | 2 +- .../react/src/components/menu/menu-item-indicator.tsx | 2 +- packages/react/src/components/menu/menu-item-text.tsx | 2 +- packages/react/src/components/menu/menu-item.tsx | 11 ++++++----- .../react/src/components/menu/menu-positioner.tsx | 2 +- .../src/components/menu/menu-radio-item-group.tsx | 2 +- .../react/src/components/menu/menu-radio-item.tsx | 6 +++--- packages/react/src/components/menu/menu-trigger.tsx | 4 ++-- .../react/src/components/menu/use-menu-context.ts | 1 + .../navigation-menu/navigation-menu-content.tsx | 2 +- .../navigation-menu-item-indicator.tsx | 2 +- .../navigation-menu/navigation-menu-link.tsx | 7 ++++++- .../use-navigation-menu-item-props-context.ts | 1 + 20 files changed, 35 insertions(+), 27 deletions(-) diff --git a/packages/react/src/components/menu/menu-arrow-tip.tsx b/packages/react/src/components/menu/menu-arrow-tip.tsx index e1388bd75b..2f7f148354 100644 --- a/packages/react/src/components/menu/menu-arrow-tip.tsx +++ b/packages/react/src/components/menu/menu-arrow-tip.tsx @@ -8,7 +8,7 @@ export interface MenuArrowTipProps extends HTMLProps<'div'>, MenuArrowTipBasePro export const MenuArrowTip = forwardRef((props, ref) => { const menu = useMenuContext() - const mergedProps = mergeProps(menu.getArrowTipProps(), props) + const mergedProps = mergeProps(menu?.getArrowTipProps(), props) return }) diff --git a/packages/react/src/components/menu/menu-arrow.tsx b/packages/react/src/components/menu/menu-arrow.tsx index 88a472ef7b..c4f6324d05 100644 --- a/packages/react/src/components/menu/menu-arrow.tsx +++ b/packages/react/src/components/menu/menu-arrow.tsx @@ -8,7 +8,7 @@ export interface MenuArrowProps extends HTMLProps<'div'>, MenuArrowBaseProps {} export const MenuArrow = forwardRef((props, ref) => { const menu = useMenuContext() - const mergedProps = mergeProps(menu.getArrowProps(), props) + const mergedProps = mergeProps(menu?.getArrowProps(), props) return }) diff --git a/packages/react/src/components/menu/menu-checkbox-item.tsx b/packages/react/src/components/menu/menu-checkbox-item.tsx index 3c9e4bd330..ebcec131c1 100644 --- a/packages/react/src/components/menu/menu-checkbox-item.tsx +++ b/packages/react/src/components/menu/menu-checkbox-item.tsx @@ -28,12 +28,12 @@ export const MenuCheckboxItem = forwardRef - + diff --git a/packages/react/src/components/menu/menu-content.tsx b/packages/react/src/components/menu/menu-content.tsx index 2039c82572..bae051786e 100644 --- a/packages/react/src/components/menu/menu-content.tsx +++ b/packages/react/src/components/menu/menu-content.tsx @@ -11,7 +11,7 @@ export interface MenuContentProps extends HTMLProps<'div'>, MenuContentBaseProps export const MenuContent = forwardRef((props, ref) => { const menu = useMenuContext() const presence = usePresenceContext() - const mergedProps = mergeProps(menu.getContentProps(), presence.getPresenceProps(), props) + const mergedProps = mergeProps(menu?.getContentProps(), presence.getPresenceProps(), props) if (presence.unmounted) { return null diff --git a/packages/react/src/components/menu/menu-context-trigger.tsx b/packages/react/src/components/menu/menu-context-trigger.tsx index 3647dec2ef..b863b7d05f 100644 --- a/packages/react/src/components/menu/menu-context-trigger.tsx +++ b/packages/react/src/components/menu/menu-context-trigger.tsx @@ -8,7 +8,7 @@ export interface MenuContextTriggerProps extends HTMLProps<'button'>, MenuContex export const MenuContextTrigger = forwardRef((props, ref) => { const menu = useMenuContext() - const mergedProps = mergeProps(menu.getContextTriggerProps(), props) + const mergedProps = mergeProps(menu?.getContextTriggerProps(), props) return }) diff --git a/packages/react/src/components/menu/menu-indicator.tsx b/packages/react/src/components/menu/menu-indicator.tsx index 21a4f33a44..b6dc65938e 100644 --- a/packages/react/src/components/menu/menu-indicator.tsx +++ b/packages/react/src/components/menu/menu-indicator.tsx @@ -8,7 +8,7 @@ export interface MenuIndicatorProps extends HTMLProps<'div'>, MenuIndicatorBaseP export const MenuIndicator = forwardRef((props, ref) => { const menu = useMenuContext() - const mergedProps = mergeProps(menu.getIndicatorProps(), props) + const mergedProps = mergeProps(menu?.getIndicatorProps(), props) return }) diff --git a/packages/react/src/components/menu/menu-item-group-label.tsx b/packages/react/src/components/menu/menu-item-group-label.tsx index 1c8c892472..14fa7b8933 100644 --- a/packages/react/src/components/menu/menu-item-group-label.tsx +++ b/packages/react/src/components/menu/menu-item-group-label.tsx @@ -10,7 +10,7 @@ export interface MenuItemGroupLabelProps extends HTMLProps<'div'>, MenuItemGroup export const MenuItemGroupLabel = forwardRef((props, ref) => { const menu = useMenuContext() const itemGroup = useMenuItemGroupContext() - const mergedProps = mergeProps(menu.getItemGroupLabelProps({ htmlFor: itemGroup.id }), props) + const mergedProps = mergeProps(menu?.getItemGroupLabelProps({ htmlFor: itemGroup.id }), props) return }) diff --git a/packages/react/src/components/menu/menu-item-group.tsx b/packages/react/src/components/menu/menu-item-group.tsx index 187fbd49a5..a45de816eb 100644 --- a/packages/react/src/components/menu/menu-item-group.tsx +++ b/packages/react/src/components/menu/menu-item-group.tsx @@ -19,7 +19,7 @@ export const MenuItemGroup = forwardRef((pro const menu = useMenuContext() const id = useId() const itemGroupProps = { id, ...optionalItemGroupProps } - const mergedProps = mergeProps(menu.getItemGroupProps(itemGroupProps), localProps) + const mergedProps = mergeProps(menu?.getItemGroupProps(itemGroupProps), localProps) return ( diff --git a/packages/react/src/components/menu/menu-item-indicator.tsx b/packages/react/src/components/menu/menu-item-indicator.tsx index f14044a874..89cf0a7b29 100644 --- a/packages/react/src/components/menu/menu-item-indicator.tsx +++ b/packages/react/src/components/menu/menu-item-indicator.tsx @@ -10,7 +10,7 @@ export interface MenuItemIndicatorProps extends HTMLProps<'div'>, MenuItemIndica export const MenuItemIndicator = forwardRef((props, ref) => { const menu = useMenuContext() const itemProps = useMenuItemPropsContext() - const mergedProps = mergeProps(menu.getItemIndicatorProps(itemProps), props) + const mergedProps = mergeProps(menu?.getItemIndicatorProps(itemProps), props) return }) diff --git a/packages/react/src/components/menu/menu-item-text.tsx b/packages/react/src/components/menu/menu-item-text.tsx index 28ac751a69..873f14fea3 100644 --- a/packages/react/src/components/menu/menu-item-text.tsx +++ b/packages/react/src/components/menu/menu-item-text.tsx @@ -10,7 +10,7 @@ export interface MenuItemTextProps extends HTMLProps<'div'>, MenuItemTextBasePro export const MenuItemText = forwardRef((props, ref) => { const menu = useMenuContext() const itemProps = useMenuItemPropsContext() - const mergedProps = mergeProps(menu.getItemTextProps(itemProps), props) + const mergedProps = mergeProps(menu?.getItemTextProps(itemProps), props) return }) diff --git a/packages/react/src/components/menu/menu-item.tsx b/packages/react/src/components/menu/menu-item.tsx index c049000ada..e388ddee15 100644 --- a/packages/react/src/components/menu/menu-item.tsx +++ b/packages/react/src/components/menu/menu-item.tsx @@ -31,17 +31,18 @@ export const MenuItem = forwardRef((props, ref) = ]) const menu = useMenuContext() - const mergedProps = mergeProps(menu.getItemProps(itemProps), localProps) - const itemState = menu.getItemState(itemProps) + const mergedProps = mergeProps(menu?.getItemProps(itemProps), localProps) + const itemState = menu?.getItemState(itemProps) // biome-ignore lint/correctness/useExhaustiveDependencies: intentional useEffect(() => { - return menu.addItemListener({ id: itemState.id, onSelect: itemProps.onSelect }) - }, [itemState.id, itemProps.onSelect]) + if (!itemState?.id) return + return menu?.addItemListener({ id: itemState.id, onSelect: itemProps.onSelect }) + }, [itemState?.id, itemProps.onSelect]) return ( - + diff --git a/packages/react/src/components/menu/menu-positioner.tsx b/packages/react/src/components/menu/menu-positioner.tsx index 4aa233326f..995ce0df41 100644 --- a/packages/react/src/components/menu/menu-positioner.tsx +++ b/packages/react/src/components/menu/menu-positioner.tsx @@ -9,7 +9,7 @@ export interface MenuPositionerProps extends HTMLProps<'div'>, MenuPositionerBas export const MenuPositioner = forwardRef((props, ref) => { const menu = useMenuContext() - const mergedProps = mergeProps(menu.getPositionerProps(), props) + const mergedProps = mergeProps(menu?.getPositionerProps(), props) const presence = usePresenceContext() if (presence.unmounted) { diff --git a/packages/react/src/components/menu/menu-radio-item-group.tsx b/packages/react/src/components/menu/menu-radio-item-group.tsx index 84ec342932..cae303b294 100644 --- a/packages/react/src/components/menu/menu-radio-item-group.tsx +++ b/packages/react/src/components/menu/menu-radio-item-group.tsx @@ -18,7 +18,7 @@ export const MenuRadioItemGroup = forwardRef diff --git a/packages/react/src/components/menu/menu-radio-item.tsx b/packages/react/src/components/menu/menu-radio-item.tsx index 6089c14e19..38f90ee39c 100644 --- a/packages/react/src/components/menu/menu-radio-item.tsx +++ b/packages/react/src/components/menu/menu-radio-item.tsx @@ -30,12 +30,12 @@ export const MenuRadioItem = forwardRef((pro type: 'radio', onCheckedChange: () => itemGroup.onValueChange?.({ value: partialItemProps.value }), } - const mergedProps = mergeProps(menu.getOptionItemProps(optionItemProps), localProps) - const optionItemState = menu.getOptionItemState(optionItemProps) + const mergedProps = mergeProps(menu?.getOptionItemProps(optionItemProps), localProps) + const optionItemState = menu?.getOptionItemState(optionItemProps) return ( - + diff --git a/packages/react/src/components/menu/menu-trigger.tsx b/packages/react/src/components/menu/menu-trigger.tsx index eba555994b..bb0ae23205 100644 --- a/packages/react/src/components/menu/menu-trigger.tsx +++ b/packages/react/src/components/menu/menu-trigger.tsx @@ -12,8 +12,8 @@ export const MenuTrigger = forwardRef((prop const presence = usePresenceContext() const mergedProps = mergeProps( { - ...menu.getTriggerProps(), - 'aria-controls': presence.unmounted ? undefined : menu.getTriggerProps()['aria-controls'], + ...menu?.getTriggerProps(), + 'aria-controls': presence.unmounted ? undefined : menu?.getTriggerProps()['aria-controls'], }, props, ) diff --git a/packages/react/src/components/menu/use-menu-context.ts b/packages/react/src/components/menu/use-menu-context.ts index a386dac93b..01903f14d7 100644 --- a/packages/react/src/components/menu/use-menu-context.ts +++ b/packages/react/src/components/menu/use-menu-context.ts @@ -7,4 +7,5 @@ export const [MenuProvider, useMenuContext] = createContext({ name: 'MenuContext', hookName: 'useMenuContext', providerName: '', + strict: false, }) diff --git a/packages/react/src/components/navigation-menu/navigation-menu-content.tsx b/packages/react/src/components/navigation-menu/navigation-menu-content.tsx index 15dac76b47..0a7cc7a3bc 100644 --- a/packages/react/src/components/navigation-menu/navigation-menu-content.tsx +++ b/packages/react/src/components/navigation-menu/navigation-menu-content.tsx @@ -21,7 +21,7 @@ export const NavigationMenuContent = forwardRef { const navigationMenu = useNavigationMenuContext() const itemProps = useNavigationMenuItemPropsContext() - const mergedProps = mergeProps(navigationMenu.getItemIndicatorProps(itemProps), props) + const mergedProps = mergeProps(navigationMenu.getItemIndicatorProps(itemProps!), props) return }, diff --git a/packages/react/src/components/navigation-menu/navigation-menu-link.tsx b/packages/react/src/components/navigation-menu/navigation-menu-link.tsx index 5308eeaaf7..33ee47c3ca 100644 --- a/packages/react/src/components/navigation-menu/navigation-menu-link.tsx +++ b/packages/react/src/components/navigation-menu/navigation-menu-link.tsx @@ -16,7 +16,12 @@ export const NavigationMenuLink = forwardRef', + strict: false, }) From 761310c6b494d8eab47e67cdd83379bd54951d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivica=20Batini=C4=87?= Date: Mon, 16 Feb 2026 20:37:27 +0100 Subject: [PATCH 5/5] fix(menu-separator): add optional chaining to safely access getSeparatorProps --- packages/react/src/components/menu/menu-separator.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/components/menu/menu-separator.tsx b/packages/react/src/components/menu/menu-separator.tsx index 17f8c71b00..ec7a192370 100644 --- a/packages/react/src/components/menu/menu-separator.tsx +++ b/packages/react/src/components/menu/menu-separator.tsx @@ -8,7 +8,7 @@ export interface MenuSeparatorProps extends HTMLProps<'hr'>, MenuSeparatorBasePr export const MenuSeparator = forwardRef((props, ref) => { const menu = useMenuContext() - const mergedProps = mergeProps(menu.getSeparatorProps(), props) + const mergedProps = mergeProps(menu?.getSeparatorProps(), props) return })