Skip to content

Commit

Permalink
fixup! fixup! Add controlled popover
Browse files Browse the repository at this point in the history
  • Loading branch information
atmelmicro committed Dec 10, 2024
1 parent 785822d commit af6f18a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 11 deletions.
21 changes: 16 additions & 5 deletions src/components/Popover/Popover.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,31 @@ export const Popover = React.forwardRef((props, ref) => {
const {
placement,
children,
popoverHelperId,
popoverTargetId,
portalId,
...restProps
} = props;

const PopoverEl = (
<>
{!!popoverHelperId && <div className={styles.helper} id={popoverHelperId} popover="auto" />}
{/**
* This hack is needed because the default behavior of the Popover API is to place the popover into a
* top-layer. It is currently not possible to position an element in the top-layer relative to a normal element.
* This will create a hidden browser popover, then with CSS it will open and close the RUI popover.
*/}
{!!popoverTargetId && (
<div
className={styles.helper}
id={popoverTargetId}
popover="auto"
/>
)}
<div
{...transferProps(restProps)}
className={classNames(
styles.root,
ref && styles.isRootControlled,
popoverHelperId && styles.controlledPopover,
popoverTargetId && styles.controlledPopover,
getRootSideClassName(placement, styles),
getRootAlignmentClassName(placement, styles),
)}
Expand All @@ -46,7 +57,7 @@ export const Popover = React.forwardRef((props, ref) => {

Popover.defaultProps = {
placement: 'bottom',
popoverHelperId: null,
popoverTargetId: null,
portalId: null,
};

Expand Down Expand Up @@ -78,7 +89,7 @@ Popover.propTypes = {
* This sets the ID of the internal helper element for the popover.
* Assign the same ID to `popovertarget` of a trigger to make it open and close.
*/
popoverHelperId: PropTypes.string,
popoverTargetId: PropTypes.string,
/**
* If set, popover is rendered in the React Portal with that ID.
*/
Expand Down
10 changes: 9 additions & 1 deletion src/components/Popover/Popover.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,18 @@
}
}

// Controlled popover
/**
* Controlled popover
* Hide the popover by default. This is needed because the popover is
* controlled via CSS with the help of the helper popover. The popover can't
* be displayed directly, because relative positioning doesn't work with
* elements on the top-layer, so this CSS hack is needed.
*/
.controlledPopover {
display: none;
}

// Hide the popover helper element
.helper {
position: fixed;
inset: unset;
Expand All @@ -67,6 +74,7 @@
pointer-events: none;
}

// If the popover helper is open, show the actual popover
.helper:popover-open ~ .controlledPopover {
display: block;
}
Expand Down
10 changes: 5 additions & 5 deletions src/components/Popover/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,10 @@ React.createElement(() => {

## Controlled Popover

To make it easier to implement the popover in your app, you can set the
`popoverHelperId` prop to the same ID as the `popovertarget` of a trigger.
This uses the browser Popover API and will control the popover by closing it
when the trigger or backdrop is pressed.
Popover API can be used to control visibility of Popover component. You need to
set `id` on the trigger element and matching `popoverTargetId` attribute on the
Popover component. This leverages the browser's Popover API to control the
popover, automatically closing it when the trigger or the backdrop is pressed.

```docoff-react-preview
React.createElement(() => {
Expand All @@ -308,7 +308,7 @@ React.createElement(() => {
label="Want to see a popover? Click me!"
popovertarget="my-popover-helper"
/>
<Popover id="my-popover" popoverHelperId="my-popover-helper">
<Popover id="my-popover" popoverTargetId="my-popover-helper">
Hello there!
</Popover>
</PopoverWrapper>
Expand Down

0 comments on commit af6f18a

Please sign in to comment.