# Popover

A popover is a small surface that appears when someone interacts with a component to give nonessential, contextual information without blocking them.

## Best practices

### Do

- Use popovers for brief, nonessential contextual information.
- Limit dimensions so the popover does not obscure important UI.
- Position it so its relationship to the trigger or context is clear.

### Don't

- Nest popovers.
- Put task-essential or repeated information in a popover.
- Use a popover for a complex layout or blocking interaction; use a dialog.

## Behavior and states

- Popovers grow to accommodate their content by default.
- Set overflow to scroll when content exceeds the available dimensions.
- Position popovers so people can tell what the information relates to.
- Don’t nest popovers.
- Popovers can have structured content and interactive components.
- If you need to show a more complex layout or block the page behind, try a dialog.
- For unstructured plain text, try a tooltip.

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-popover--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { PopoverProps } from "@coreai-ds/react-components";
import * as React from 'react';
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";

export const Default = (props: Omit<PopoverProps, 'children'>) => {
    const ExampleContent = (): React.JSX.Element => (<div className="popover-default-example__content">
        <h3 className="popover-default-example__content-header">Popover content</h3>

        <div>This is some popover content</div>
      </div>);
    const styles = /* css */ `
      .popover-default-example__content-header {
        margin-top: 0;
      }
    `;
    return (<>
        <style>{styles}</style>
        <Popover {...props}>
          <PopoverTrigger disableButtonEnhancement>
            <Button>Popover trigger</Button>
          </PopoverTrigger>

          <PopoverSurface className="popover-default-example" tabIndex={-1}>
            <ExampleContent />
          </PopoverSurface>
        </Popover>
      </>);
};

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### Popover API

Wrapper component that manages state for a PopoverTrigger and a PopoverSurface components.

```ts
interface PopoverProps {
  /**
   * A popover can appear styled with brand or inverted.
   * When not specified, the default style is used.
   */
  appearance?: "brand" | "inverted";

  /**
   * Can contain two children including `PopoverTrigger` and `PopoverSurface`.
   * Alternatively can only contain `PopoverSurface` if using a custom `target`.
   */
  children: JSXElement | [JSXElement, JSXElement];

  /**
   * Flag to close the Popover when an iframe outside a PopoverSurface is focused
   * @default true
   */
  closeOnIframeFocus?: boolean;

  /**
   * Close when scroll outside of it
   * @default false
   */
  closeOnScroll?: boolean;

  /**
   * Used to set the initial open state of the Popover in uncontrolled mode
   * @default false
   */
  defaultOpen?: boolean;

  /**
   * Enables standard behavior according to the [HTML dialog spec](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal)
   * where the focus trap involves setting outside elements inert,
   * making navigation leak from the trapped area back to the browser toolbar and vice-versa.
   * @default false
   */
  inertTrapFocus?: boolean;

  /**
   * Popovers are rendered out of DOM order on `document.body` by default, use this to render the popover in DOM order
   * @default false
   */
  inline?: boolean;

  /**
   * Must be used with the `trapFocus` prop
   * Enables older Fluent UI focus trap behavior where the user
   * cannot tab into the window outside of the document. This is now
   * non-standard behavior according to the [HTML dialog spec](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal)
   * where the focus trap involves setting outside elements inert.
   * @deprecated this behavior is default provided now, to opt-out of it in favor of standard behavior use the `inertTrapFocus` property
   */
  legacyTrapFocus?: boolean;

  /**
   * Where the portal children are mounted on DOM
   * @default a new element on document.body without any styling
   */
  mountNode?: HTMLElement | { element?: HTMLElement | null; className?: string; } | null | undefined;

  /**
   * Sets the delay for closing popover on mouse leave
   */
  mouseLeaveDelay?: number;

  /**
   * Call back when the component requests to change value
   * The `open` value is used as a hint when directly controlling the component
   */
  onOpenChange?: ((e: OpenPopoverEvents, data: OnOpenChangeData) => void);

  /**
   * Controls the opening of the Popover
   * @default false
   */
  open?: boolean;

  /**
   * Flag to open the Popover as a context menu. Disables all other interactions
   * @default false
   */
  openOnContext?: boolean;

  /**
   * Flag to open the Popover by hovering the trigger
   * @default false
   */
  openOnHover?: boolean;

  /**
   * Configures the position of the Popover.
   * Explore [Positioning docs](https://react.fluentui.dev/?path=/docs/concepts-developer-positioning-components--docs) for more options.
   */
  positioning?: PositioningShorthand;

  /**
   * Determines popover padding and arrow size
   * @default medium
   */
  size?: "small" | "medium" | "large";

  /**
   * Slot for the surface motion animation.
   * For more information refer to the [Motion docs page](https://react.fluentui.dev/?path=/docs/motion-motion-slot--docs).
   */
  surfaceMotion?: PresenceMotionSlotProps | null;

  /**
   * Should trap focus
   * @default false
   */
  trapFocus?: boolean;

  /**
   * By default Popover focuses the first focusable element in PopoverSurface on open.
   * Specify `disableAutoFocus` to prevent this behavior.
   * @default false
   */
  unstable_disableAutoFocus?: boolean;

  /**
   * Display an arrow pointing to the target.
   * @default false
   */
  withArrow?: boolean;
}
```

### PopoverProvider API

```ts
interface PopoverProviderProps {
  children?: ReactNode;

  value: PopoverContextValue;
}
```

### PopoverSurface API

PopoverSurface component renders react children in a positioned box

```ts
interface PopoverSurfaceProps {
  as?: "div";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### PopoverTrigger API

Wraps a trigger element as an only child and adds the necessary event handling to open a popover.

```ts
interface PopoverTriggerProps {
  children?: ReactElement<any, string | JSXElementConstructor<any>> | ((props: PopoverTriggerChildProps<ARIAButtonType, {}>) => ReactElement<any, string | JSXElementConstructor<any>> | null) | null;

  /**
   * Disables internal trigger mechanism that ensures a child provided will be a compliant ARIA button.
   * @default false
   */
  disableButtonEnhancement?: boolean;
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Anchor To Custom Target

Source: Fluent, adapted for CoreAI.

A Popover can be used without a trigger and anchored to any DOM element. This can be useful if
a Popover instance needs to be reused in different places.

_Not using a PopoverTrigger will require more work to make sure your scenario is accessible,_
_such as, implementing accessible markup and keyboard interactions for your trigger._

[Download source](/coreai-design-system/source/examples/components-popover--anchor-to-custom-target.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { PositioningImperativeRef } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    container: {
        display: 'flex',
        gap: '10px',
    },
    contentHeader: {
        marginTop: '0',
    },
});

const ExampleContent = () => {
    const styles = useStyles();
    return (<div>
      <h3 className={styles.contentHeader}>Popover content</h3>

      <div>This is some popover content</div>
      <Button>Action</Button>
    </div>);
};

export const AnchorToCustomTarget = (): JSXElement => {
    const positioningRef = React.useRef<PositioningImperativeRef>(null);
    const buttonRef = React.useCallback((el: HTMLButtonElement | null) => {
        positioningRef.current?.setTarget(el);
    }, [positioningRef]);
    const styles = useStyles();
    return (<div className={styles.container}>
      <Popover positioning={{ positioningRef }}>
        <PopoverTrigger disableButtonEnhancement>
          <Button>Popover trigger</Button>
        </PopoverTrigger>

        <PopoverSurface>
          <ExampleContent />
        </PopoverSurface>
      </Popover>

      <Button ref={buttonRef}>Custom target</Button>
    </div>);
};

export default AnchorToCustomTarget;
```

## Appearance

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-popover--appearance.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import * as React from 'react';

const useLayoutStyles = makeStyles({
    root: {
        display: 'flex',
        flexDirection: 'column',
        rowGap: tokens.spacingVerticalMNudge,
    },
});

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
});

const ExampleContent = () => {
    const styles = useStyles();
    return (<div>
      <h3 className={styles.contentHeader}>Popover content</h3>

      <div>This is some popover content</div>
      <Button>Action</Button>
    </div>);
};

export const Appearance = (): JSXElement => {
    const layoutStyles = useLayoutStyles();
    return (<div className={layoutStyles.root}>
      <Popover>
        <PopoverTrigger disableButtonEnhancement>
          <Button>Default appearance Popover trigger</Button>
        </PopoverTrigger>

        <PopoverSurface>
          <ExampleContent />
        </PopoverSurface>
      </Popover>

      <Popover appearance="brand">
        <PopoverTrigger disableButtonEnhancement>
          <Button>Brand appearance Popover trigger</Button>
        </PopoverTrigger>

        <PopoverSurface>
          <ExampleContent />
        </PopoverSurface>
      </Popover>

      <Popover appearance="inverted">
        <PopoverTrigger disableButtonEnhancement>
          <Button>Inverted appearance Popover trigger</Button>
        </PopoverTrigger>

        <PopoverSurface>
          <ExampleContent />
        </PopoverSurface>
      </Popover>
    </div>);
};

export default Appearance;
```

## Controlling Open And Close

Source: Fluent, adapted for CoreAI.

The opening and close of the `Popover` can be controlled with your own state.
The `onOpenChange` callback will provide the hints for the state and triggers based on the appropriate
event.

_When controlling the open state of the `Popover`, extra effort is required to ensure that interactions are_
_still appropriate and that keyboard accessibility does not degrade._

[Download source](/coreai-design-system/source/examples/components-popover--controlling-open-and-close.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import type { PopoverProps } from "@coreai-ds/react-components";
import type { CheckboxProps } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import { Checkbox } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
    container: {
        display: 'flex',
        flexDirection: 'column',
    },
});

const ExampleContent = () => {
    const styles = useStyles();
    return (<div>
      <h3 className={styles.contentHeader}>Popover content</h3>

      <div>This is some popover content</div>
      <Button>Action</Button>
    </div>);
};

export const ControllingOpenAndClose = (): JSXElement => {
    const styles = useStyles();
    const [open, setOpen] = React.useState(false);
    const handleOpenChange: PopoverProps['onOpenChange'] = (e, data) => setOpen(data.open || false);
    const onChange: CheckboxProps['onChange'] = (e, { checked }) => {
        setOpen(checked as boolean);
    };
    return (<div className={styles.container}>
      <Popover open={open} onOpenChange={handleOpenChange}>
        <PopoverTrigger disableButtonEnhancement>
          <Button>Controlled trigger</Button>
        </PopoverTrigger>
        <PopoverSurface>
          <ExampleContent />
        </PopoverSurface>
      </Popover>
      <Checkbox value="open" name="state" label="open" checked={open} onChange={onChange}/>
    </div>);
};

export default ControllingOpenAndClose;
```

## Custom Trigger

Source: Fluent, adapted for CoreAI.

Native elements and Fluent components have first class support as children of `PopoverTrigger`
so they will be injected automatically with the correct props for interactions and accessibility attributes.

It is possible to use your own custom React component as a child of `PopoverTrigger`. These components should
use ref forwarding with [React.forwardRef](https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-to-dom-components)

[Download source](/coreai-design-system/source/examples/components-popover--custom-trigger.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import * as React from 'react';
import type { PopoverTriggerChildProps } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";

const CustomPopoverTrigger = React.forwardRef<HTMLButtonElement, Partial<PopoverTriggerChildProps>>((props, ref) => {
    return (<Button {...props} ref={ref}>
      Custom Trigger
    </Button>);
});

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
});

const ExampleContent = () => {
    const styles = useStyles();
    return (<div>
      <h3 className={styles.contentHeader}>Popover content</h3>

      <div>This is some popover content</div>
      <Button>Action</Button>
    </div>);
};

export const CustomTrigger = (): JSXElement => {
    return (<Popover>
      <PopoverTrigger>
        <CustomPopoverTrigger />
      </PopoverTrigger>
      <PopoverSurface>
        <ExampleContent />
      </PopoverSurface>
    </Popover>);
};

export default CustomTrigger;
```

## Internal Update Content

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-popover--internal-update-content.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { PopoverProps } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
});

const ExampleContent = () => {
    const styles = useStyles();
    return (<div>
      <h3 className={styles.contentHeader}>Popover content</h3>

      <div>This is some popover content</div>
    </div>);
};

export const InternalUpdateContent = (): JSXElement => {
    const [visible, setVisible] = React.useState(false);
    const focusRef = React.useRef<HTMLAnchorElement>(null);
    const changeContent = () => setVisible(true);
    const onOpenChange: PopoverProps['onOpenChange'] = (e, data) => {
        if (data.open === false) {
            setVisible(false);
        }
    };
    React.useEffect(() => {
        if (visible) {
            focusRef.current?.focus();
        }
    }, [visible]);
    return (<Popover onOpenChange={onOpenChange}>
      <PopoverTrigger disableButtonEnhancement>
        <Button>Popover trigger</Button>
      </PopoverTrigger>

      <PopoverSurface>
        <ExampleContent />

        {visible ? (<div>
            The second panel content{' '}
            <Link href="#" ref={focusRef}>
              and a link
            </Link>
          </div>) : (<div>
            <Button onClick={changeContent}>Action</Button>
          </div>)}
      </PopoverSurface>
    </Popover>);
};

export default InternalUpdateContent;
```

## Motion Custom

Source: Fluent, adapted for CoreAI.

Popover animations can be customized using the [Motion APIs](https://react.fluentui.dev/?path=/docs/motion-apis-createpresencecomponent--docs), together with the `surfaceMotion` slot.

[Download source](/coreai-design-system/source/examples/components-popover--motion-custom.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { createPresenceComponent } from "@coreai-ds/react-components";
import { fadeAtom } from "@fluentui/react-motion-components-preview";
import { blurAtom } from "@fluentui/react-motion-components-preview";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import * as React from 'react';

const FadeInBlurOut = createPresenceComponent({
    enter: fadeAtom({ duration: 500, direction: 'enter' }),
    exit: [fadeAtom({ duration: 500, direction: 'exit' }), blurAtom({ duration: 500, direction: 'exit' })],
});

export const MotionCustom = (): JSXElement => (<Popover surfaceMotion={{
        children: (_, motionProps) => <FadeInBlurOut {...motionProps}/>,
    }}>
    <PopoverTrigger disableButtonEnhancement>
      <Button>Open popover</Button>
    </PopoverTrigger>

    <PopoverSurface>
      <h3 style={{ marginTop: 0 }}>Popover content</h3>
      <p>This popover fades in and blurs out.</p>
      <Button>Action</Button>
    </PopoverSurface>
  </Popover>);

export default MotionCustom;
```

## Motion Disabled

Source: Fluent, adapted for CoreAI.

To disable the Popover transition animation, set the `surfaceMotion` prop to `null`.

[Download source](/coreai-design-system/source/examples/components-popover--motion-disabled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import * as React from 'react';

export const MotionDisabled = (): JSXElement => (<Popover surfaceMotion={null}>
    <PopoverTrigger disableButtonEnhancement>
      <Button>Open popover</Button>
    </PopoverTrigger>

    <PopoverSurface>
      <h3 style={{ marginTop: 0 }}>Popover content</h3>
      <p>This popover has motion disabled</p>
      <Button>Action</Button>
    </PopoverSurface>
  </Popover>);

export default MotionDisabled;
```

## Nested Popovers

Source: Fluent, adapted for CoreAI.

Popovers can be nested within each other. Too much nesting can result in
extra accessibility considerations and are generally not a great user experience,

Since nested popovers will generally have an interactive `PopoverTrigger` to control
the nested popover, make sure to combine their usage with the `trapFocus` prop for correct
screen reader and keyboard accessibility.

- Try and limit nesting to 2 levels.
- Make sure to use `trapFocus` when nesting.
- Creating nested popovers as separate components will result in more maintainable code.

[Download source](/coreai-design-system/source/examples/components-popover--nested-popovers.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
});

const SecondNestedPopover = () => {
    const styles = useStyles();
    const id = useId();
    return (<Popover trapFocus>
      <PopoverTrigger disableButtonEnhancement>
        <Button>Second nested trigger</Button>
      </PopoverTrigger>

      <PopoverSurface aria-labelledby={id}>
        <div>
          <h3 id={id} className={styles.contentHeader}>
            Popover content
          </h3>

          <div>This is some popover content</div>
        </div>
        <Button>Second nested button</Button>
      </PopoverSurface>
    </Popover>);
};

const FirstNestedPopover = () => {
    const styles = useStyles();
    const id = useId();
    return (<Popover trapFocus>
      <PopoverTrigger disableButtonEnhancement>
        <Button>First nested trigger</Button>
      </PopoverTrigger>

      <PopoverSurface aria-labelledby={id}>
        <div>
          <h3 id={id} className={styles.contentHeader}>
            Popover content
          </h3>

          <div>This is some popover content</div>
        </div>
        <Button>First nested button</Button>
        <SecondNestedPopover />
        <SecondNestedPopover />
      </PopoverSurface>
    </Popover>);
};

export const NestedPopovers = (): JSXElement => {
    const styles = useStyles();
    const id = useId();
    return (<Popover trapFocus>
      <PopoverTrigger disableButtonEnhancement>
        <Button>Root trigger</Button>
      </PopoverTrigger>

      <PopoverSurface>
        <div>
          <h3 id={id} className={styles.contentHeader}>
            Popover content
          </h3>

          <div>This is some popover content</div>
        </div>
        <Button>Root button</Button>
        <FirstNestedPopover />
      </PopoverSurface>
    </Popover>);
};

export default NestedPopovers;
```

## Non Interactive Content

Source: Fluent, adapted for CoreAI.

A `Popover` without interactive content is an edge case. Use a `Tooltip` for simple non-interactive content. If richer content requires a `Popover`, set `tabIndex={-1}` on `PopoverSurface` and give the surface an accessible name so its content is announced when it receives focus.

[Download source](/coreai-design-system/source/examples/components-popover--non-interactive-content.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
});

export const NonInteractiveContent = (): JSXElement => {
    const styles = useStyles();
    const headingId = useId('popover-heading');
    return (<Popover>
      <PopoverTrigger disableButtonEnhancement>
        <Button>Popover trigger</Button>
      </PopoverTrigger>

      <PopoverSurface tabIndex={-1} aria-labelledby={headingId}>
        <h3 id={headingId} className={styles.contentHeader}>
          Popover content
        </h3>
        <p>This is some non-interactive popover content.</p>
      </PopoverSurface>
    </Popover>);
};

export default NonInteractiveContent;
```

## Trapping Focus

Source: Fluent, adapted for CoreAI.

When a `Popover` contains focusable elements, the modal dialog pattern will apply. By using the `trapFocus`
prop, the component sets `aria-hidden`appropriately to parent elements in the document so that elements
not contained in the focus trap are hidden to screen reader users. This focus trap is automatically removed
when the `Popover` is closed.

[Download source](/coreai-design-system/source/examples/components-popover--trapping-focus.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
});

export const TrappingFocus = (): JSXElement => {
    const styles = useStyles();
    const id = useId();
    return (<Popover trapFocus>
      <PopoverTrigger disableButtonEnhancement>
        <Button>Popover trigger</Button>
      </PopoverTrigger>

      <PopoverSurface aria-labelledby={id}>
        <div>
          <h3 id={id} className={styles.contentHeader}>
            Popover content
          </h3>

          <div>This is some popover content</div>
        </div>

        <div>
          <Button>Action</Button>
          <Button>Action</Button>
        </div>
      </PopoverSurface>
    </Popover>);
};

export default TrappingFocus;
```

## With Arrow

Source: Fluent, adapted for CoreAI.

The `withArrow` prop can be used to display an arrow pointing to the target.

[Download source](/coreai-design-system/source/examples/components-popover--with-arrow.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    contentHeader: {
        marginTop: '0',
    },
});

const ExampleContent = () => {
    const styles = useStyles();
    return (<div>
      <h3 className={styles.contentHeader}>Popover content</h3>

      <div>This popover has an arrow pointing to its target</div>
      <Button>Action</Button>
    </div>);
};

export const WithArrow = (): JSXElement => (<Popover withArrow>
    <PopoverTrigger disableButtonEnhancement>
      <Button>Popover trigger</Button>
    </PopoverTrigger>

    <PopoverSurface>
      <ExampleContent />
    </PopoverSurface>
  </Popover>);

export default WithArrow;
```

## With Arrow Autosize

Source: Fluent, adapted for CoreAI.

When using the arrow with the `autoSize` positioning feature, make sure to move the `overflow` from the popover to an inner element to avoid clipping the arrow.

[Download source](/coreai-design-system/source/examples/components-popover--with-arrow-autosize.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';

const useContentStyles = makeStyles({
    root: {
        boxSizing: 'border-box',
        padding: '16px',
        overflowY: 'auto',
        height: '100%',
    },
    header: {
        marginTop: '0',
    },
});

const ExampleContent = () => {
    const styles = useContentStyles();
    return (<div className={styles.root}>
      <h3 className={styles.header}>Popover content</h3>

      <Button>Action</Button>

      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum semper, nulla at pretium pulvinar, erat nibh
        ultricies risus, eget tincidunt neque nisl non nunc. Integer tempus augue nec facilisis suscipit. Aenean finibus
        orci id turpis euismod, sit amet varius neque porta. Curabitur et urna vel orci luctus dictum. Mauris sed eros
        euismod, cursus justo non, facilisis nibh. Aliquam blandit leo ut nisl tincidunt, sit amet ultrices lacus
        molestie. Phasellus aliquet massa non vestibulum condimentum. Vivamus posuere, ligula eu pharetra fringilla,
        lorem leo elementum risus, vitae tempor odio purus sed libero. Vestibulum porta nisl a metus ultricies, vel
        dignissim lectus facilisis. Etiam interdum mi a suscipit aliquet. Nullam rhoncus molestie purus, id porta neque
        consequat vitae. Sed id aliquam elit. Praesent nunc libero, vulputate vitae porta nec, venenatis sed augue.
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum semper, nulla at pretium pulvinar, erat nibh
        ultricies risus, eget tincidunt neque nisl non nunc. Integer tempus augue nec facilisis suscipit. Aenean finibus
        orci id turpis euismod, sit amet varius neque porta. Curabitur et urna vel orci luctus dictum. Mauris sed eros
        euismod, cursus justo non, facilisis nibh. Aliquam blandit leo ut nisl tincidunt, sit amet ultrices lacus
        molestie. Phasellus aliquet massa non vestibulum condimentum. Vivamus posuere, ligula eu pharetra fringilla,
        lorem leo elementum risus, vitae tempor odio purus sed libero. Vestibulum porta nisl a metus ultricies, vel
        dignissim lectus facilisis. Etiam interdum mi a suscipit aliquet. Nullam rhoncus molestie purus, id porta neque
        consequat vitae. Sed id aliquam elit. Praesent nunc libero, vulputate vitae porta nec, venenatis sed augue.
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum semper, nulla at pretium pulvinar, erat nibh
        ultricies risus, eget tincidunt neque nisl non nunc. Integer tempus augue nec facilisis suscipit. Aenean finibus
        orci id turpis euismod, sit amet varius neque porta. Curabitur et urna vel orci luctus dictum. Mauris sed eros
        euismod, cursus justo non, facilisis nibh. Aliquam blandit leo ut nisl tincidunt, sit amet ultrices lacus
        molestie. Phasellus aliquet massa non vestibulum condimentum. Vivamus posuere, ligula eu pharetra fringilla,
        lorem leo elementum risus, vitae tempor odio purus sed libero. Vestibulum porta nisl a metus ultricies, vel
        dignissim lectus facilisis. Etiam interdum mi a suscipit aliquet. Nullam rhoncus molestie purus, id porta neque
        consequat vitae. Sed id aliquam elit. Praesent nunc libero, vulputate vitae porta nec, venenatis sed augue.
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum semper, nulla at pretium pulvinar, erat nibh
        ultricies risus, eget tincidunt neque nisl non nunc. Integer tempus augue nec facilisis suscipit. Aenean finibus
        orci id turpis euismod, sit amet varius neque porta. Curabitur et urna vel orci luctus dictum. Mauris sed eros
        euismod, cursus justo non, facilisis nibh. Aliquam blandit leo ut nisl tincidunt, sit amet ultrices lacus
        molestie. Phasellus aliquet massa non vestibulum condimentum. Vivamus posuere, ligula eu pharetra fringilla,
        lorem leo elementum risus, vitae tempor odio purus sed libero. Vestibulum porta nisl a metus ultricies, vel
        dignissim lectus facilisis. Etiam interdum mi a suscipit aliquet. Nullam rhoncus molestie purus, id porta neque
        consequat vitae. Sed id aliquam elit. Praesent nunc libero, vulputate vitae porta nec, venenatis sed augue.
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum semper, nulla at pretium pulvinar, erat nibh
        ultricies risus, eget tincidunt neque nisl non nunc. Integer tempus augue nec facilisis suscipit. Aenean finibus
        orci id turpis euismod, sit amet varius neque porta. Curabitur et urna vel orci luctus dictum. Mauris sed eros
        euismod, cursus justo non, facilisis nibh. Aliquam blandit leo ut nisl tincidunt, sit amet ultrices lacus
        molestie. Phasellus aliquet massa non vestibulum condimentum. Vivamus posuere, ligula eu pharetra fringilla,
        lorem leo elementum risus, vitae tempor odio purus sed libero. Vestibulum porta nisl a metus ultricies, vel
        dignissim lectus facilisis. Etiam interdum mi a suscipit aliquet. Nullam rhoncus molestie purus, id porta neque
        consequat vitae. Sed id aliquam elit. Praesent nunc libero, vulputate vitae porta nec, venenatis sed augue.
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum semper, nulla at pretium pulvinar, erat nibh
        ultricies risus, eget tincidunt neque nisl non nunc. Integer tempus augue nec facilisis suscipit. Aenean finibus
        orci id turpis euismod, sit amet varius neque porta. Curabitur et urna vel orci luctus dictum. Mauris sed eros
        euismod, cursus justo non, facilisis nibh. Aliquam blandit leo ut nisl tincidunt, sit amet ultrices lacus
        molestie. Phasellus aliquet massa non vestibulum condimentum. Vivamus posuere, ligula eu pharetra fringilla,
        lorem leo elementum risus, vitae tempor odio purus sed libero. Vestibulum porta nisl a metus ultricies, vel
        dignissim lectus facilisis. Etiam interdum mi a suscipit aliquet. Nullam rhoncus molestie purus, id porta neque
        consequat vitae. Sed id aliquam elit. Praesent nunc libero, vulputate vitae porta nec, venenatis sed augue.
      </div>
    </div>);
};

export const WithArrowAutosize = (): JSXElement => (<Popover withArrow positioning={{ autoSize: true }}>
    <PopoverTrigger disableButtonEnhancement>
      <Button>Popover trigger</Button>
    </PopoverTrigger>

    {/* 1. Reset the overflow behavior on `PopoverSurface` to avoid clipping of arrow */}
    <PopoverSurface style={{ overflow: 'visible', padding: 0 }}>
      {/* 2. Set the height of the popover content to 100% to fill the available space and allow scrolling */}
      <ExampleContent />
    </PopoverSurface>
  </Popover>);

export default WithArrowAutosize;
```

## Without Trigger

Source: Fluent, adapted for CoreAI.

When using a `Popover` without a `PopoverTrigger`, it is up to the user to make sure that the focus is restored correctly
when the popover is closed. This can be done quite easily by using the `useRestoreFocusTarget` hook. The `Popover` already
uses the `useRestoreFocusSource` hook directly, which will restore focus to the most recently focused target on close.

[Download source](/coreai-design-system/source/examples/components-popover--without-trigger.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { useId } from "@coreai-ds/react-components";
import type { PositioningImperativeRef } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { useRestoreFocusTarget } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Popover } from "@coreai-ds/react-components";
import { PopoverSurface } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    container: {
        display: 'flex',
        gap: '10px',
    },
    contentHeader: {
        marginTop: '0',
    },
});

export const WithoutTrigger = (): JSXElement => {
    const [open, setOpen] = React.useState(false);
    const headerId = useId();
    const buttonRef = React.useRef<HTMLButtonElement>(null);
    const positioningRef = React.useRef<PositioningImperativeRef>(null);
    const styles = useStyles();
    const restoreFocusTargetAttribute = useRestoreFocusTarget();
    React.useEffect(() => {
        if (buttonRef.current) {
            positioningRef.current?.setTarget(buttonRef.current);
        }
    }, [buttonRef, positioningRef]);
    return (<div className={styles.container}>
      <Button {...restoreFocusTargetAttribute} ref={buttonRef} onClick={() => setOpen(s => !s)}>
        Toggle popover
      </Button>
      <Popover onOpenChange={(e, data) => {
            if (e.target === buttonRef.current) {
                // Ignore events that are triggered by the button to avoid re-opening the popover
                return;
            }
            setOpen(data.open);
        }} trapFocus open={open} positioning={{ positioningRef }}>
        <PopoverSurface aria-labelledby={headerId}>
          <div>
            <h3 id={headerId} className={styles.contentHeader}>
              Popover content
            </h3>

            <div>This is some popover content</div>
          </div>

          <div>
            <Button>Action</Button>
            <Button>Action</Button>
          </div>
        </PopoverSurface>
      </Popover>
    </div>);
};

export default WithoutTrigger;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=167560-4316)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/popover/usage)