Replies: 2 comments 1 reply
-
@thien-do - What I did is the following: I have a shared The way I solved this was to:
Sorry don't have a great code example that is easily sharable: import { Popover as HeadlessPopover } from '@headlessui/react';
// since I am using typescript, this is the interface I have to model the imperative code
export interface PopoverRef {
toggle: () => void;
open: () => void;
close: () => void;
isOpen: () => void;
}
// shared Popover Component
export const Popover = forwardRef<PopoverRef, PopoverProps>(
(
{
// ... whatever props you have
onChange,
}: PopoverNewProps,
ref
) => {
const isOpen = useRef<boolean>(false);
const [referenceElement, setReferenceElement] = useState<HTMLElement>(null);
const [popperElement, setPopperElement] = useState<HTMLElement>(null);
const [arrowElement, setArrowElement] = useState<HTMLElement>(null);
const [closeElement, setCloseElement] = useState<HTMLElement>(null);
useImperativeHandle<unknown, PopoverRef>(
ref,
() => {
return {
toggle: () => referenceElement && referenceElement.click(),
open: () => !popperElement && referenceElement && referenceElement.click(),
close: () => closeElement && closeElement.click(),
isOpen: () => !!popperElement,
};
},
[referenceElement, popperElement, closeElement]
);
/// This is unrelated to your question, but I also use this to tell a parent component that the open state changed
// Sometimes I need to reset something in the parent when the popover closes
const checkIfStateChanged = useCallback(
(open: boolean) => {
if (open !== isOpen.current) {
// use ref to avoid re-render every time open state changes
isOpen.current = open;
if (onChange) {
nextTick(() => onChange(open));
}
}
},
[onChange]
);
return (
<HeadlessPopover className="slds-is-relative" as="span">
{({ open }) => {
checkIfStateChanged(open);
return (
... Then in the parent component, you can set a ref and call the exposed imperative functions export const SomeComponent = () => {
const popoverRef = useRef<PopoverRef>(null);
// You could call this from a useEffect or wherever you need to
function closePopover() {
popoverRef.current.close();
// Could also open
// popoverRef.current.open();
}
return (
<PopoverNew
ref={popoverRef} |
Beta Was this translation helpful? Give feedback.
1 reply
-
Any updates on this? |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
My situation is kind of the opposite of #427 : I want to programmatically open a Popover from outside (or even inside) of the component.
Currently what I do is to have a ref to the button, then trigger its "click" method. Does anyone know a better way?
Beta Was this translation helpful? Give feedback.
All reactions