Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "feat: expose missing resolved state through additive data attributes",
"packageName": "@fluentui/react-headless-components-preview",
"email": "vgenaev@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@
> [!WARNING] > **This package is in preview and not production-ready.** APIs may change without notice before final release. **Do not use in production.**
>
> This package exposes unstyled, headless Fluent UI v9 primitives for teams building custom design systems. For most teams, [`@fluentui/react-components`](https://www.npmjs.com/package/@fluentui/react-components) remains the recommended default.

## State selector contract

Headless components expose resolved interaction and structural state through `data-*` attributes. Consumers that wrap these components, including visual-system packages, must preserve the attributes on the slot where headless emits them.

Existing attributes retain their current names and value semantics. Visual axes such as appearance, size, and shape are intentionally not part of the headless contract.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

```ts

import type { AvatarGroupBaseState } from '@fluentui/react-avatar';
import { AvatarGroupContextValue } from '@fluentui/react-avatar';
import { AvatarGroupContextValues } from '@fluentui/react-avatar';
import type { AvatarGroupItemBaseProps } from '@fluentui/react-avatar';
Expand All @@ -12,7 +13,6 @@ import { AvatarGroupItemBaseState as AvatarGroupItemState } from '@fluentui/reac
import { AvatarGroupBaseProps as AvatarGroupProps } from '@fluentui/react-avatar';
import type { AvatarGroupProps as AvatarGroupProps_2 } from '@fluentui/react-avatar';
import { AvatarGroupSlots } from '@fluentui/react-avatar';
import { AvatarGroupBaseState as AvatarGroupState } from '@fluentui/react-avatar';
import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import type { EventData } from '@fluentui/react-utilities';
Expand Down Expand Up @@ -81,7 +81,12 @@ export { AvatarGroupProps }

export { AvatarGroupSlots }

export { AvatarGroupState }
// @public (undocumented)
export type AvatarGroupState = AvatarGroupBaseState & {
root: {
'data-layout'?: AvatarGroupBaseState['layout'];
};
};

export { PartitionAvatarGroupItems }

Expand All @@ -97,7 +102,7 @@ export { renderAvatarGroupItem }
export const renderAvatarGroupPopover: (state: AvatarGroupPopoverState, contextValues: AvatarGroupContextValues) => JSXElement;

// @public
export const useAvatarGroup: (props: AvatarGroupProps, ref: React_2.Ref<HTMLElement>) => AvatarGroupState;
export const useAvatarGroup: (props: AvatarGroupProps, ref: React_2.Ref<HTMLDivElement>) => AvatarGroupState;

// @public
export const useAvatarGroupContextValues: (state: AvatarGroupState) => AvatarGroupContextValues;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type ButtonState = ButtonBaseState & {
'data-disabled'?: string;
'data-disabled-focusable'?: string;
'data-icon-only'?: string;
'data-icon-position'?: ButtonBaseState['iconPosition'];
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export type CardSlots = CardSlots_2;
export type CardState = CardBaseState & {
root: {
'data-selected'?: string;
'data-disabled'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type CheckboxState = CheckboxBaseState & {
root: {
'data-disabled'?: string;
'data-checked'?: string;
'data-label-position'?: CheckboxBaseState['labelPosition'];
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export type OptionState = OptionState_2 & {
root: {
'data-disabled'?: string;
'data-selected'?: string;
'data-multiselect'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export type OptionState = OptionState_2 & {
root: {
'data-disabled'?: string;
'data-selected'?: string;
'data-multiselect'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ export type InfoButtonSlots = {
};

// @public
export type InfoButtonState = ComponentState<InfoButtonSlots>;
export type InfoButtonState = ComponentState<InfoButtonSlots> & {
root: {
'data-open'?: string;
};
};

// @public
export const InfoLabel: ForwardRefComponent<InfoLabelProps>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type InputSlots = InputSlots_2;
export type InputState = InputBaseState & {
root: {
'data-disabled'?: string;
'data-invalid'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type LabelSlots = LabelSlots_2;
export type LabelState = LabelBaseState & {
root: {
'data-disabled'?: string;
'data-required'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type MenuButtonState = MenuButtonBaseState & {
'data-disabled'?: string;
'data-disabled-focusable'?: string;
'data-icon-only'?: string;
'data-open'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import { MenuItemLinkProps } from '@fluentui/react-menu';
import { MenuItemLinkSlots } from '@fluentui/react-menu';
import { MenuItemLinkState } from '@fluentui/react-menu';
import type { MenuItemProps as MenuItemProps_2 } from '@fluentui/react-menu';
import { MenuItemRadioBaseProps as MenuItemRadioProps } from '@fluentui/react-menu';
import { MenuItemRadioBaseState as MenuItemRadioState } from '@fluentui/react-menu';
import type { MenuItemRadioBaseProps } from '@fluentui/react-menu';
import type { MenuItemRadioBaseState } from '@fluentui/react-menu';
import { MenuItemSlots } from '@fluentui/react-menu';
import type { MenuItemState as MenuItemState_2 } from '@fluentui/react-menu';
import { MenuItemSwitchProps } from '@fluentui/react-menu';
Expand Down Expand Up @@ -64,10 +64,6 @@ import { useMenuDivider_unstable as useMenuDivider } from '@fluentui/react-menu'
import { useMenuGroup_unstable as useMenuGroup } from '@fluentui/react-menu';
import { useMenuGroupContextValues_unstable as useMenuGroupContextValues } from '@fluentui/react-menu';
import { useMenuGroupHeader_unstable as useMenuGroupHeader } from '@fluentui/react-menu';
import { useMenuItemCheckboxBase_unstable as useMenuItemCheckbox } from '@fluentui/react-menu';
import { useMenuItemLinkBase_unstable as useMenuItemLink } from '@fluentui/react-menu';
import { useMenuItemRadioBase_unstable as useMenuItemRadio } from '@fluentui/react-menu';
import { useMenuItemSwitchBase_unstable as useMenuItemSwitch } from '@fluentui/react-menu';
import { useMenuListContextValues_unstable as useMenuListContextValues } from '@fluentui/react-menu';

// @public
Expand Down Expand Up @@ -113,14 +109,14 @@ export { MenuGroupState }
export const MenuItem: ForwardRefComponent<MenuItemProps>;

// @public
export const MenuItemCheckbox: ForwardRefComponent<MenuItemCheckboxProps>;
export const MenuItemCheckbox: ForwardRefComponent<MenuItemCheckboxProps_2>;

export { MenuItemCheckboxProps }

export { MenuItemCheckboxState }

// @public
export const MenuItemLink: ForwardRefComponent<MenuItemLinkProps>;
export const MenuItemLink: ForwardRefComponent<MenuItemLinkProps_2>;

export { MenuItemLinkProps }

Expand All @@ -134,21 +130,33 @@ export type MenuItemProps = MenuItemProps_2;
// @public
export const MenuItemRadio: ForwardRefComponent<MenuItemRadioProps>;

export { MenuItemRadioProps }
// @public (undocumented)
export type MenuItemRadioProps = MenuItemRadioBaseProps;

export { MenuItemRadioState }
// @public (undocumented)
export type MenuItemRadioState = MenuItemRadioBaseState & {
root: {
'data-disabled'?: string;
'data-has-submenu'?: string;
'data-submenu-open'?: string;
'data-checked'?: string;
};
};

export { MenuItemSlots }

// @public (undocumented)
export type MenuItemState = MenuItemState_2 & {
root: {
focusgroupstart?: string;
'data-disabled'?: string;
'data-has-submenu'?: string;
'data-submenu-open'?: string;
};
};

// @public
export const MenuItemSwitch: ForwardRefComponent<MenuItemSwitchProps>;
export const MenuItemSwitch: ForwardRefComponent<MenuItemSwitchProps_2>;

export { MenuItemSwitchProps }

Expand Down Expand Up @@ -254,13 +262,17 @@ export { useMenuGroupHeader }
// @public
export const useMenuItem: (props: MenuItemProps, ref: React_2.Ref<ARIAButtonElement<"div">>) => MenuItemState;

export { useMenuItemCheckbox }
// @public (undocumented)
export const useMenuItemCheckbox: (props: MenuItemCheckboxProps_2, ref: React_2.Ref<ARIAButtonElement<"div">>) => MenuItemCheckboxState_2;

export { useMenuItemLink }
// @public (undocumented)
export const useMenuItemLink: (props: MenuItemLinkProps_2, ref: React_2.Ref<HTMLAnchorElement>) => MenuItemLinkState_2;

export { useMenuItemRadio }
// @public (undocumented)
export const useMenuItemRadio: (props: MenuItemRadioProps, ref: React_2.Ref<ARIAButtonElement<"div">>) => MenuItemRadioState;

export { useMenuItemSwitch }
// @public (undocumented)
export const useMenuItemSwitch: (props: MenuItemSwitchProps_2, ref: React_2.Ref<HTMLDivElement>) => MenuItemSwitchState_2;

// @public
export const useMenuList: (props: MenuListProps, ref: React_2.Ref<HTMLElement>) => MenuListState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ import { DrawerFooterProps as NavDrawerFooterProps } from '@fluentui/react-drawe
import { DrawerFooterSlots as NavDrawerFooterSlots } from '@fluentui/react-drawer';
import { DrawerHeaderProps as NavDrawerHeaderProps } from '@fluentui/react-drawer';
import { DrawerHeaderSlots as NavDrawerHeaderSlots } from '@fluentui/react-drawer';
import { NavItemBaseProps as NavItemProps } from '@fluentui/react-nav';
import type { NavItemBaseProps } from '@fluentui/react-nav';
import type { NavItemBaseState } from '@fluentui/react-nav';
import { NavItemRegisterData } from '@fluentui/react-nav';
import { NavItemSlots } from '@fluentui/react-nav';
import { NavItemBaseState as NavItemState } from '@fluentui/react-nav';
import { NavItemValue } from '@fluentui/react-nav';
import { NavBaseProps as NavProps } from '@fluentui/react-nav';
import { NavProvider } from '@fluentui/react-nav';
import { NavSlots } from '@fluentui/react-nav';
import type { NavSubItemBaseState } from '@fluentui/react-nav';
import { NavSubItemBaseProps as NavSubItemProps } from '@fluentui/react-nav';
import { NavSubItemSlots } from '@fluentui/react-nav';
import { NavSubItemBaseState as NavSubItemState } from '@fluentui/react-nav';
import { OnNavItemSelectData } from '@fluentui/react-nav';
import type { OverlayDrawerProps as OverlayDrawerProps_2 } from '@fluentui/react-drawer';
import * as React_2 from 'react';
Expand All @@ -53,8 +53,6 @@ import { useNavCategoryContext_unstable as useNavCategoryContext } from '@fluent
import { useNavCategoryContextValues_unstable as useNavCategoryContextValues } from '@fluentui/react-nav';
import { useNavCategoryItemContext_unstable as useNavCategoryItemContext } from '@fluentui/react-nav';
import { useNavContext_unstable as useNavContext } from '@fluentui/react-nav';
import { useNavItemBase_unstable as useNavItem } from '@fluentui/react-nav';
import { useNavSubItemBase_unstable as useNavSubItem } from '@fluentui/react-nav';

// @public
export const Nav: ForwardRefComponent<NavProps>;
Expand Down Expand Up @@ -99,6 +97,10 @@ export type NavCategoryItemSlots = {
// @public
export type NavCategoryItemState = ComponentState<NavCategoryItemSlots> & NavCategoryItemContextValue & {
selected: boolean;
root: {
'data-open'?: string;
'data-selected'?: string;
};
};

export { NavCategoryProps }
Expand Down Expand Up @@ -177,13 +179,19 @@ export type NavDrawerState = ComponentState<NavDrawerSlots> & Omit<NavContextVal
// @public
export const NavItem: ForwardRefComponent<NavItemProps>;

export { NavItemProps }
// @public (undocumented)
export type NavItemProps = NavItemBaseProps;

export { NavItemRegisterData }

export { NavItemSlots }

export { NavItemState }
// @public (undocumented)
export type NavItemState = NavItemBaseState & {
root: {
'data-selected'?: string;
};
};

export { NavItemValue }

Expand Down Expand Up @@ -237,7 +245,12 @@ export { NavSubItemProps }

export { NavSubItemSlots }

export { NavSubItemState }
// @public (undocumented)
export type NavSubItemState = NavSubItemBaseState & {
root: {
'data-selected'?: string;
};
};

export { OnNavItemSelectData }

Expand Down Expand Up @@ -315,12 +328,14 @@ export const useNavDrawerFooter: (props: NavDrawerFooterProps, ref: React_2.Ref<
// @public
export const useNavDrawerHeader: (props: NavDrawerHeaderProps, ref: React_2.Ref<HTMLElement>) => NavDrawerHeaderState;

export { useNavItem }
// @public (undocumented)
export const useNavItem: (props: NavItemProps, ref: React_2.Ref<HTMLButtonElement | HTMLAnchorElement>) => NavItemState;

// @public
export const useNavSectionHeader: (props: NavSectionHeaderProps, ref: React_2.Ref<HTMLDivElement>) => NavSectionHeaderState;

export { useNavSubItem }
// @public (undocumented)
export const useNavSubItem: (props: NavSubItemProps, ref: React_2.Ref<HTMLButtonElement | HTMLAnchorElement>) => NavSubItemState;

// @public
export const useNavSubItemGroup: (props: NavSubItemGroupProps, ref: React_2.Ref<HTMLDivElement>) => NavSubItemGroupState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ export type PersonaSlots = Omit<PersonaSlots_2, 'avatar' | 'presence'> & {
};

// @public
export type PersonaState = ComponentState<PersonaSlots> & Pick<PersonaState_2, 'textPosition' | 'numTextLines'>;
export type PersonaState = ComponentState<PersonaSlots> & Pick<PersonaState_2, 'textPosition' | 'numTextLines'> & {
root: {
'data-text-position'?: PersonaState_2['textPosition'];
};
};

// @public (undocumented)
export const renderPersona: (state: PersonaState) => JSXElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ export type ProgressBarProps = ProgressBarBaseProps;
export type ProgressBarSlots = ProgressBarSlots_2;

// @public
export type ProgressBarState = ProgressBarBaseState;
export type ProgressBarState = ProgressBarBaseState & {
root: {
'data-indeterminate'?: string;
};
};

// @public
export const renderProgressBar: (state: ProgressBarState) => JSXElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export type RadioSlots = RadioSlots_2;
export type RadioState = RadioBaseState & {
root: {
'data-disabled'?: string;
'data-label-position'?: RadioBaseState['labelPosition'];
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type SelectSlots = SelectSlots_2;
export type SelectState = SelectBaseState & {
root: {
'data-disabled'?: string;
'data-invalid'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type SpinButtonState = SpinButtonBaseState & {
'data-disabled'?: string;
'data-spin-state'?: string;
'data-at-bound'?: string;
'data-invalid'?: string;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type SwitchState = SwitchBaseState & {
'data-disabled'?: string;
'data-disabled-focusable'?: string;
'data-checked'?: string;
'data-label-position'?: SwitchBaseState['labelPosition'];
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type TabState = TabBaseState & {
focusgroupstart?: string;
'data-icon-only'?: string;
'data-selected'?: string;
'data-disabled'?: string;
};
};

Expand Down
Loading
Loading