Checkout extension popover can't be closed from an internal button

:waving_hand: Hello! We have a popover that displays additional help text. We want to have a button within the popover that dismisses the popover. However, calling ui.overlay.close("my-overlay") does not close the popover.

Based off of the documentation on ui.overlay.close(), I would expect this to work.

Supported overlay components are Modal, Sheet and Popover.

Here’s a repro example:

<BlockStack>
      <Link
        overlay={
          <Popover id="my-overlay">
            <View padding="base">
              <BlockStack spacing="base">
                Here's important information!
                <Button onPress={() => ui.overlay.close("my-overlay")}>
                  Got it. Clicking me won't close the overlay.
                </Button>
              </BlockStack>
            </View>
          </Popover>
        }
      >
        Need more help from a popover?
      </Link>

      <Link
        overlay={
          <Modal id="my-modal-overlay">
            <View padding="base">
              <BlockStack spacing="base">
                Here's important information!
                <Button onPress={() => ui.overlay.close("my-modal-overlay")}>
                  Got it. Clicking me will close the modal.
                </Button>
              </BlockStack>
            </View>
          </Modal>
        }
      >
        Need more help from a modal?
      </Link>
    </BlockStack>


Anyone run into something similar? Or have a workaround? Thank you!

Hey @szafan - looking into this for you, I’ll loop back with you once I have an answer or next steps, appreciate you flagging this!

Hey again @szafan, we’re looking into this as a potential bug and I’ve spoken with the product team for you on this. I can’t guarantee a turnaround time for a fix, but I’ll keep my eyes on this and update you as soon as I have more info.

Thanks again for raising this here.

1 Like

Hey @szafan - just reaching back out here with some good news! A fix for this is deployed and should be live. Can you let us know if you’re still seeing the issue pop up? If so, I can definitely look into this further.

1 Like

Woohoo! I’m also seeing that it’s fixed. Thanks for your help :slight_smile:

1 Like

Hey @Alan_G I’m still facing the issue with latest version “2025.7.1”

Hi @Himanshu_Soni :waving_hand: , thanks for flagging this! Are you seeing this happen with a similar example to the one szafan shared earlier? If you’re open to share a repro example and a link to the affected shop, I’m more than happy to take a look and get back in touch with our product team to look into this with you.

Hope to hear from you soon!

@Alan_G Thanks for replying, here is the example.

<Modal id={id} onClose={()=>{handleClose()}} size="max" >
	<Button kind="primary" onPress={() => handleSelectQuote(selectedQuote)} >
		Protect my purchase
	</Button>
	<Button kind="secondary" onPress={()=> {
		console.log("no thanks");
		ui.overlay.close(id)
	}}>
		No, Thanks
	</Button>
</Modal>

No worries, thanks @Himanshu_Soni, I’ll try to replicate things on my end and loop back with you here once I have more info to share

Hey @Himanshu_Soni :waving_hand: , I was able to work with our product team a bit more closely on this, and we weren’t able to replicate the issue. Would you be open to sharing a minimal reproduction of your extension where the error persists? If you’re open to sharing that, I can set up a DM and we can take a look at your code to see if we can replicate that way.

Hope to hear from you soon - let me know if you have a preferred way to share that and we can look into things further :slight_smile:

Hey @Himanshu_Soni - just wanted to touch base with you here to see if you’re still seeing this issue pop up?

Going to close this thread out just for tracking, but let me know if I can help out further :slight_smile:

Hey @Alan_G, thanks for following up.

I did a clean install, and it worked fine this time.
Looks like the issue was with some packages on my side. Appreciate your support!

Hey @Himanshu_Soni - glad things are working for you now, let me know if I can help out further!

@Alan_G I know this thread has been closed for a while, but I’m seeing the same thing for a modal:

This is for a Preact extension using @shopify/ui-extensions 2025.10.8. The demo above was made using this code:

import { render } from 'preact';

const modalId = 'test-modal';

const TestApp = () => <>
  <s-button commandFor={modalId}>Open modal</s-button>

  <s-modal id={modalId}>
    <s-button onClick={() => { shopify.ui.overlay.close(modalId); }}>
      Close modal
    </s-button>
  </s-modal>
</>;

export default () => {
  render(<TestApp />, document.body);
};

The Shopify dev assistant also agreed that the code I’ve shared here is the way this should be being done, so this very much looks like a bug rather than anything wrong with my code. Not being able to programatically close a modal after the user triggers an action from it severely limits the UX we’re able to provide, so if we could get a fix soon that’d be great :folded_hands:

Editing to add: I’ve tried updating to the current latest @shopify/ui-extensions package (2026.1.1) and the issue still persists there too.

Hi @AndyPye,

In 2025-10 and up, Modal and a few other components offers instance methods. Its listed under the Methods heading in a component’s page.

On Modal:

There’s an example on how to use them in the more general “Use Polaris web component” pages. I believe the example there is exactly what you need.

Thanks,

JF

1 Like

Hi JF. Thanks for sharing this – I was used to the “close via JS API” approach and honestly hadn’t seen the documentation for the instance methods. FWIW it seems like the AI assistant on the docs site isn’t familiar with the instance methods either, because when I asked it how I could programatically close a modal, it only told me about the shopify.ui.overlay.close() method.

One small issue I ran into with the instance methods approach was what type to use for the ref. I ended up using

const modalRef = useRef<HTMLElementTagNameMap['s-modal'] | null>(null);

which seemed to keep the TS engine happy, but I’m not sure if there’s a preferred/better way than digging directly into the element tag name map :thinking:

Either way, I’m now able to programatically close the modal – thanks for your help! :person_bowing: