|
| 1 | +# RFC: Extend `mountNode` prop in `Portal` |
| 2 | + |
| 3 | +[@layeshifter](https://github.com/layershifter) |
| 4 | + |
| 5 | +## Summary |
| 6 | + |
| 7 | +This RFC proposes extending the `mountNode` prop in the `Portal` component and its underlying components such as `Tooltip` and `Popup` to accept an object. |
| 8 | + |
| 9 | +## Background |
| 10 | + |
| 11 | +The `Portal` component has a `mountNode` prop that allows customizing the element to which the `Portal` will be attached. However, there is no way to customize classes applied to that element. Customization is needed to apply styles such as custom `z-index`es. We need to be able to customize the `mountNode` element to apply this type of custom styles ([microsoft/fluentui#26758](https://github.com/microsoft/fluentui/issues/26758)). |
| 12 | + |
| 13 | +## Problem statement |
| 14 | + |
| 15 | +Currently, there is no way to customize classes applied to that element. |
| 16 | + |
| 17 | +## Detailed Design or Proposal |
| 18 | + |
| 19 | +The proposal is to allow passing objects to the `mountNode` prop. This can be achieved by extending the `mountNode` prop to accept an object, which can be one of the following: |
| 20 | + |
| 21 | +```tsx |
| 22 | +function App() { |
| 23 | + return ( |
| 24 | + <> |
| 25 | + {/* Current usage, already exists */} |
| 26 | + <Portal mountNode={element} /> |
| 27 | + |
| 28 | + {/* Proposed usages */} |
| 29 | + <Portal mountNode={element} /> |
| 30 | + <Portal mountNode={{ element }} /> |
| 31 | + <Portal mountNode={{ className: 'foo' }} /> |
| 32 | + </> |
| 33 | + ); |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +### Pros and Cons |
| 38 | + |
| 39 | +- 👍 Similar to `positioning` prop. |
| 40 | +- 👍 Not a breaking change. |
| 41 | +- 👎 May create the impression that `mountNode` is a slot. |
| 42 | + |
| 43 | +## Discarded Solutions |
| 44 | + |
| 45 | +### Deprecate `mountNode`, add `portal` prop |
| 46 | + |
| 47 | +```tsx |
| 48 | +function App() { |
| 49 | + return ( |
| 50 | + <> |
| 51 | + <Portal portal={element} /> |
| 52 | + <Portal portal={{ element }} /> |
| 53 | + <Portal portal={{ className: 'foo' }} /> |
| 54 | + </> |
| 55 | + ); |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +### Pros and Cons |
| 60 | + |
| 61 | +- 👍 Similar to the `positioning` prop. |
| 62 | +- 👎 Can create an impression that `portal` is a slot. |
| 63 | +- 👎 Creates a breaking change in the future. |
| 64 | +- 👎 `<Portal portal={element} />` is not obvious as `<Portal mountNode={element} />`. |
| 65 | + |
| 66 | +### Add `mountNodeClassName` prop |
| 67 | + |
| 68 | +```tsx |
| 69 | +function App() { |
| 70 | + return ( |
| 71 | + <> |
| 72 | + {/* Current usage, already exists */} |
| 73 | + <Portal mountNode={element} /> |
| 74 | + |
| 75 | + {/* Proposed usages */} |
| 76 | + <Portal mountNode={element} mountNodeClassName="foo" /> |
| 77 | + </> |
| 78 | + ); |
| 79 | +} |
| 80 | +``` |
| 81 | + |
| 82 | +### Pros and Cons |
| 83 | + |
| 84 | +- 👎 Does not scale: what if we will need to add another property to manage? |
0 commit comments