Closed didoo closed 8 months ago
@didoo That's a great question. Right now if you're using the default build (or a CDN) you're correct that there's not a way to detect directly whether the polyfill is used or not -- at least without something hacky like checking document.adoptedStyleSheets
or looking for class :popover-open
on an opened popover or something.
You can indirectly use the same logic that the polyfill uses to check for support, either by importing the isSupported
function, or replicating it in your own code. Either of these should work:
import { apply, isSupported } from '@oddbird/popover-polyfill/fn';
const usePolyfill = !isSupported();
if (usePolyfill) {
apply();
}
const isPolyfilled = !(typeof HTMLElement !== 'undefined' &&
typeof HTMLElement.prototype === 'object' &&
'popover' in HTMLElement.prototype);
I'm not opposed to adding a "flag" that indicates when the polyfill has been applied. Do you have a suggestion for how that could be communicated?
Ok, here's the reason why I need to know if the API has been polyfilled or not (which is not the same thing as being "supported", which is what the isSupported()
method does).
Let's imagine you have two instances (A1
and A2
) of the same component A
, in the same page
The component A
is implemented in a way that checks if isSupported()
is false
, in which case it invokes the apply()
method, polyfilling the API.
What happens is that when the instance A1
is rendered, isSupported()
is false
, so the apply()
method is invoked. But when comes to the instance of A2
to be rendered, now the API has been polyfilled, and now the isSupported()
call returns true
. Which is correct, because now it is supported.
The problem I have is that I may want to do something specific if the Popover API is not "native" but polyfilled. In my specific case, I want to use a fixed
position strategy with Floating UI, to avoid issues in Firefox with the position of the popover (it's mentioned in the caveats of the library, when a parent has CSS position relative
).
This means that only the first popover in the page will have a fixed
position (because I am checking via isSupported
), while the other ones have an incorrect position (they have an absolute
position).
Now, the question is: how do we register a "flag" that we can use to detect if the Popover API has been polyfilled or not? At the moment I don't have many ideas, the only thing that I can think of is to register an extra property like this, within the apply
method:
Object.defineProperties(HTMLElement.prototype, {
popoverIsPolyfilled: {
value: true,
writable: false,
enumerable: false,
configurable: true,
},
});
and expose a new public method like this:
export function isPolyfilled() {
return (
typeof HTMLElement !== 'undefined' &&
typeof HTMLElement.prototype === 'object' &&
'popoverIsPolyfilled' in HTMLElement.prototype
);
}
(in this file https://github.com/oddbird/popover-polyfill/blob/main/src/popover.ts)
I know it's not great, but I can't think of other alternatives (I don't think it's possible to add an extra property here https://github.com/oddbird/popover-polyfill/blob/main/src/popover.ts#L155-L156 and then read it, right?)
If you want I can open a PR to start the conversation in a more tangible way.
@keithamus or @mirisuzanne, I'm curious what you think about this API question. In brief, what's the best way to tell users when popover has been polyfilled?
I think a public method sounds like a good place to start. We could also consider adding a class/attribute to the root element. I imagine that could be useful for CSS in some cases, but maybe not as essential? Once we have a public method, adding your own attribute is simpler.
We've done this when we need to check:
const isNativePopover = /native code/.test(document.body.showPopover?.toString())
But I am also open to adding an API within the polyfill. I'd encourage us to make sure it doesn't return false positives when multiple versions of the polyfill are loaded, though (which is why we go with the above route).
Would @keithamus solution work/be acceptable for you @mirisuzanne @jgerigmeyer? If so, I can open a PR for the change.
@didoo Yes, I think that makes sense. Thanks!
I have opened #193.
Included in v0.4.1 release.
Quick question: is there a way to detect in code if the Popover API methods are polyfilled ot not? I looked into the
src
code but seems there's no way to differentiate or have a "flag" that can be used to detect this.