Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a337d93
feat(react-headless-components-preview): add headless Popover built o…
mainframev Apr 20, 2026
9f3b6b9
docs(react-headless-components-preview): add Popover Storybook stories
mainframev Apr 20, 2026
9c9b1a8
docs(react-headless-components-preview): add Positioning concept Stor…
mainframev Apr 20, 2026
31da14c
refactor(react-headless-components-preview): rebuild usePositioning o…
mainframev Apr 21, 2026
a57bdf6
docs(headless): add Popover spec
mainframev Apr 22, 2026
583dd25
chore(react-dialog): remove accidentally committed duplicate file
mainframev Apr 22, 2026
b62dcc6
refactor(react-headless-components-preview): remove custom trapFocus …
mainframev Apr 27, 2026
cdbbfcf
docs(react-headless-components-preview): align Popover spec with iter…
mainframev Apr 27, 2026
1de9ff5
chore: adjust stories popover paths to use sub-paths
mainframev Apr 27, 2026
dde2f6a
test(react-headless-components-preview): switch usePositioning style …
mainframev Apr 27, 2026
c05836b
chore: format
mainframev Apr 27, 2026
be4f4ed
chore: change files
mainframev Apr 27, 2026
abb7b0b
feat(react-headless-components-preview): add PopoverAuto sub-component
mainframev Apr 27, 2026
90a044d
refactor(react-headless-components-preview): drop unused ref param fr…
mainframev Apr 27, 2026
6147a9e
fix(react-headless-components-preview): attach toggle listener whenev…
mainframev Apr 27, 2026
0e1d032
refactor(react-headless-components-preview): split usePopover and use…
mainframev Apr 27, 2026
68886c7
docs(react-headless-components-preview): shorten manual-vs-auto neste…
mainframev Apr 27, 2026
11dfb90
chore: update api md
mainframev Apr 28, 2026
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": "minor",
"comment": "feat: add headless Popover'",
"packageName": "@fluentui/react-headless-components-preview",
"email": "vgenaev@gmail.com",
"dependentChangeType": "patch"
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
## API Report File for "@fluentui/react-headless-components-preview"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import type { ContextSelector } from '@fluentui/react-context-selector';
import type { EventData } from '@fluentui/react-utilities';
import type { EventHandler } from '@fluentui/react-utilities';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import type { JSXElement } from '@fluentui/react-utilities';
import * as React_2 from 'react';
import type { Slot } from '@fluentui/react-utilities';

// @public
export type OnOpenChangeData = EventData<string, React_2.SyntheticEvent | Event> & {
open: boolean;
};

// @public
export type OpenPopoverEvents = MouseEvent | TouchEvent | React_2.FocusEvent<HTMLElement> | React_2.KeyboardEvent<HTMLElement> | React_2.MouseEvent<HTMLElement>;

// @public
export const Popover: {
(props: PopoverProps): JSXElement;
displayName: string;
};

// @public
export const PopoverAuto: {
(props: PopoverProps): JSXElement;
displayName: string;
};

// @public
export type PopoverContextValue = Pick<PopoverState, 'open' | 'setOpen' | 'toggleOpen' | 'triggerRef' | 'contentRef' | 'arrowRef' | 'openOnHover' | 'openOnContext' | 'disableAutoFocus' | 'withArrow' | 'inline' | 'mountNode' | 'popoverType'> & {
positioning: {
targetRef: React_2.RefCallback<HTMLElement>;
containerRef: React_2.RefCallback<HTMLElement>;
};
};

// @public
export type PopoverProps = {
children: [JSXElement, JSXElement] | JSXElement;
open?: boolean;
defaultOpen?: boolean;
onOpenChange?: EventHandler<OnOpenChangeData>;
openOnHover?: boolean;
openOnContext?: boolean;
mouseLeaveDelay?: number;
positioning?: PositioningShorthand;
withArrow?: boolean;
disableAutoFocus?: boolean;
closeOnScroll?: boolean;
closeOnIframeFocus?: boolean;
inline?: boolean;
mountNode?: HTMLElement | null;
};

// @public
export type PopoverState = Required<Pick<PopoverProps, 'open' | 'inline'>> & Pick<PopoverProps, 'onOpenChange' | 'openOnContext' | 'openOnHover' | 'withArrow' | 'disableAutoFocus' | 'mountNode'> & {
setOpen: (e: OpenPopoverEvents, open: boolean) => void;
toggleOpen: (e: OpenPopoverEvents) => void;
triggerRef: React_2.RefObject<HTMLElement | null>;
contentRef: React_2.RefObject<HTMLElement | null>;
arrowRef: React_2.RefObject<HTMLDivElement | null>;
popoverTrigger: React_2.ReactElement | undefined;
popoverSurface: React_2.ReactElement | undefined;
contextTarget: {
x: number;
y: number;
} | undefined;
setContextTarget: (target: {
x: number;
y: number;
} | undefined) => void;
positioning: PositioningReturn;
popoverType: PopoverType;
};

// @public
export const PopoverSurface: ForwardRefComponent<PopoverSurfaceProps>;

// @public (undocumented)
export type PopoverSurfaceProps = ComponentProps<PopoverSurfaceSlots>;

// @public
export type PopoverSurfaceSlots = {
root: Slot<'div'>;
};

// @public (undocumented)
export type PopoverSurfaceState = ComponentState<PopoverSurfaceSlots> & {
inline: boolean;
withArrow: boolean | undefined;
arrowRef: React_2.RefObject<HTMLDivElement | null>;
mountNode: HTMLElement | null | undefined;
'data-open': string;
};

// @public
export const PopoverTrigger: React_2.FC<PopoverTriggerProps>;

// @public
export type PopoverTriggerProps = {
children: React_2.ReactElement;
disableButtonEnhancement?: boolean;
};

// @public
export type PopoverTriggerState = {
children: React_2.ReactElement | null;
};

// @public
export type PopoverType = 'manual' | 'auto';

// @public
export const renderPopover: (state: PopoverState, contextValues: {
popover: PopoverContextValue;
}) => React_2.ReactElement;

// @public
export const renderPopoverSurface: (state: PopoverSurfaceState) => JSXElement;

// @public
export const renderPopoverTrigger: (state: PopoverTriggerState) => JSXElement | null;

// @public
export const usePopover: (props: PopoverProps) => PopoverState;

// @public (undocumented)
export const usePopoverAuto: (props: PopoverProps) => PopoverState;

// @public
export const usePopoverContext: <T>(selector: ContextSelector<PopoverContextValue, T>) => T;

// @public (undocumented)
export const usePopoverContextValues: (state: PopoverState) => {
popover: PopoverContextValue;
};

// @public
export const usePopoverSurface: (props: PopoverSurfaceProps, ref: React_2.Ref<HTMLDivElement>) => PopoverSurfaceState;

// @public
export const usePopoverTrigger: (props: PopoverTriggerProps) => PopoverTriggerState;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
## API Report File for "@fluentui/react-headless-components-preview"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import type * as React_2 from 'react';

// @public (undocumented)
export type Alignment = 'top' | 'bottom' | 'start' | 'end' | 'center';

// @public (undocumented)
export const ALIGNMENTS: {
readonly start: "start";
readonly center: "center";
readonly end: "end";
};

// @public
export function getPlacementString(position: Position, align: LogicalAlignment): string;

// @public (undocumented)
export type Position = 'above' | 'below' | 'before' | 'after';

// @public
export type PositioningImperativeRef = {
setTarget: (target: HTMLElement | null) => void;
updatePosition: () => void;
};

// @public (undocumented)
export type PositioningProps = {
position?: Position;
align?: Alignment;
offset?: number | {
mainAxis?: number;
crossAxis?: number;
};
fallbackPositions?: PositioningShorthandValue[];
coverTarget?: boolean;
target?: HTMLElement | React_2.RefObject<HTMLElement | null> | null;
strategy?: 'absolute' | 'fixed';
matchTargetSize?: 'width';
pinned?: boolean;
positioningRef?: React_2.Ref<PositioningImperativeRef>;
};

// @public (undocumented)
export type PositioningReturn = {
targetRef: React_2.RefCallback<HTMLElement>;
containerRef: React_2.RefCallback<HTMLElement>;
};

// @public (undocumented)
export type PositioningShorthand = PositioningProps | PositioningShorthandValue;

// @public (undocumented)
export type PositioningShorthandValue = 'above' | 'above-start' | 'above-end' | 'below' | 'below-start' | 'below-end' | 'before' | 'before-start' | 'before-end' | 'after' | 'after-start' | 'after-end';

// @public (undocumented)
export const POSITIONS: {
readonly above: "above";
readonly below: "below";
readonly before: "before";
readonly after: "after";
};

// @public
export function resolvePositioningShorthand(value: PositioningShorthand | undefined): PositioningProps;

// @public (undocumented)
export function usePositioning(options: PositioningProps): PositioningReturn;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"license": "MIT",
"dependencies": {
"@fluentui/react-accordion": "^9.11.0",
"@fluentui/react-aria": "^9.17.10",
"@fluentui/keyboard-keys": "^9.0.8",
"@fluentui/react-avatar": "^9.11.1",
"@fluentui/react-badge": "^9.5.2",
"@fluentui/react-button": "^9.9.1",
Expand All @@ -41,6 +43,7 @@
"@fluentui/react-search": "^9.4.2",
"@fluentui/react-select": "^9.5.1",
"@fluentui/react-shared-contexts": "^9.26.2",
"@fluentui/react-context-selector": "^9.2.15",
"@fluentui/react-skeleton": "^9.7.2",
"@fluentui/react-slider": "^9.6.2",
"@fluentui/react-spinbutton": "^9.6.2",
Expand Down Expand Up @@ -132,6 +135,18 @@
"import": "./lib/message-bar.js",
"require": "./lib-commonjs/message-bar.js"
},
"./popover": {
"types": "./dist/popover.d.ts",
"node": "./lib-commonjs/popover.js",
"import": "./lib/popover.js",
"require": "./lib-commonjs/popover.js"
},
"./positioning": {
"types": "./dist/positioning.d.ts",
"node": "./lib-commonjs/positioning.js",
"import": "./lib/positioning.js",
"require": "./lib-commonjs/positioning.js"
},
"./progress-bar": {
"types": "./dist/progress-bar.d.ts",
"node": "./lib-commonjs/progress-bar.js",
Expand Down
Loading
Loading