Back to Fluentui

Popup Migration

apps/public-docsite-v9/src/Concepts/Migration/FromV0/Components/Popup.mdx

4.40.2-hotfix26.1 KB
Original Source

import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Concepts/Migration/from v0/Components/Popup Migration" />

Popup Migration

Overview:

Before:

tsx
import { Popup, Button } from '@fluentui/react-northstar';
const Component = () => <Popup trigger={<Button>trigger</Button>} content="content" />;

After:

tsx
import { Popover, PopoverTrigger, PopoverSurface, Button } from '@fluentui/react-components';
const Component = () => (
  // v0 Popup has default position/align above/start, while v9 has default above/center. Therefore adding `positioning` prop here
  // v0 Popup no arrow by default, while v9 has. Therefore adding `noArrow` prop here
  <Popover positioning={'above-start'} noArrow>
    <PopoverTrigger>
      <Button>trigger</Button>
    </PopoverTrigger>
    <PopoverSurface>content</PopoverSurface>
  </Popover>
);

How to migrate props:

Popup propsmigrate guide
defaultOpen, closeOnScroll, inline, open, onOpenChange, mountNode, mouseLeaveDelay, trapFocuskeep it as is
content, contentRefsee Migrate content and contentRef in this document
triggerMove `trigger` to JSX children of `PopoverTrigger` component
pointingReplace with `withArrow={true}`
onReplace `on='hover'` with `openOnHover`; `on='content'` with `openOnContext`

Postioning props:

align, autoSize, flipBoundary, offset,overflowBoundary,popperRef,position,positionFixed,target, unstable_disableTether, unstable_pinned are now attributes of the positioning prop.

v9 positioning shorthand is recommended when only positon or/and align is used: <Popup position="below" align="end" /> can be migrated to a string like <Popover positioning="below-end" />.

See Migrate positioning props for more.

Removed props:

accessibility - so far there is no usage of custom accessibility on Popup in TMP. Please consult with fluent team on how to migrate custom accessibility if you're using any.

renderContent - please use JSX children as content. updatePosition can be replaced with popperRef.current.updatePosition() (codesandbox example RenderContentExample.jsx)

tabbableTrigger - by default v0 has tabbableTrigger=true. When tabbableTrigger=false is specified, popup trigger will not have aria-haspopup="dialog". If this is desired, it can be achieved by adding aria-haspopup=undefined on popup trigger (codesandbox example)

autoFocus - can be achieved by setting focus manually on popover content (codesandbox example AutoFocusExample.jsx)

Here's a codesandbox comparing v0 Popup and v9 Popover.

Migrate content and contentRef

contentRef can be replaced by React ref on PopoverSurface.

When content value is JSX, move it to children of PopoverSurface component. When content value is shorthand object, for example

js
content = { content: 'hi', variables: { someVariable: true } };

Migrate variables to use makeStyles API. Before:

tsx
// in COMPONENT_NAME.tsx
import { Popup } from '@fluentui/react-northstar';

export const Component = props => (
  <Popup
    content={{
      content: props.content,
      variables: { isCustomPopup: true },
    }}
    trigger={props.trigger}
  />
);

// in popup-content-styles.ts
export const popupContentStyles = {
  root: ({ variables: { isCustomPopup } }) => ({
    ...(isCustomPopup && {
      backgroundColor: colorSchemeBrand.background,
    }),
  }),
};

After:

tsx
// in COMPONENT_NAME.tsx
import { Popover, PopoverTrigger, PopoverSurface } from '@fluentui/react-components';
import { useStyles } from './COMPONENT_NAME.styles.ts';

export const Component = () => {
  const classes = useStyles();
  return (
    <Popover positioning={'above-start'} noArrow>
      <PopoverTrigger>{props.trigger}</PopoverTrigger>
      <PopoverSurface className={classes.customPopup}>{props.content}</PopoverSurface>
    </Popover>
  );
};

// in COMPONENT_NAME.styles.ts
import { makeStyles, tokens } from '@fluentui/react-components';

export const useStyles = makeStyles({
  customPopup: {
    backgroundColor: tokens.colorBrandBackground,
  },
});

⚠️ If this is your first time migrating style overrides, please read the general guide on how to migrate styles.

Nested popups

If you have nested popups, and migrate to v9 inner popup first, you might have a problem with handling of Escape key.

To prevent this problem you can use onKeyDown prop on PopoverSurface to prevent Escape key from bubbling up to the outer popup.

tsx
<PopoverSurface
  onKeyDown={e => {
    if (e.key === 'Escape') {
      e.stopPropagation();
    }
  }}
/>

You can check out this codesandbox for an example.

Note: this workaround is not needed if you migrate outer popup first or if you migrate both popups at the same time.