Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

applying the polyfill to dynamic elements #91

Open
dreyks opened this issue Mar 10, 2023 · 12 comments · May be fixed by #123
Open

applying the polyfill to dynamic elements #91

dreyks opened this issue Mar 10, 2023 · 12 comments · May be fixed by #123
Labels
Milestone

Comments

@dreyks
Copy link

dreyks commented Mar 10, 2023

Hey! thx for the polyfill!

I'm trying to bolt it onto a dropdown and I'm applying the polyfil after the dropdown is open. This works. But when I close the dropdown and open it again - the css-vars on the element aren't being set.

As far as I understood from the code since the CSS was already transformed and there are no anchor() functions anymore no elements are targeted

is it somehow possible to achieve what i'm trying to achieve? :)

UPD: ahh, I see now that "dynamically added/removed anchors or targets" is not yet supported 😢

fwiw, I'm ready to help if any help is needed

@jgerigmeyer
Copy link
Member

@dreyks Thanks for your offer! We're always happy for contributions. 😄

I am planning to take a look at this issue in the next few days, starting by providing an API for users to re-run the polyfill on demand. It's a bit tricky because the polyfill makes changes directly to the original source CSS, so re-running it isn't as simple as just doing the same thing again. But I have some ideas of how to address this. (Then later hopefully we can also add an observer or something so that the polyfill itself can re-run intelligently.)

In this case it would be helpful if you could share the HTML/JS code you're trying to run -- that way as I work on it I can test directly against your use-case (and add it to the demo page).

@jgerigmeyer jgerigmeyer self-assigned this Mar 10, 2023
@dreyks
Copy link
Author

dreyks commented Mar 10, 2023

thx for the response!

i'm doing this on a closed-source ui library, i'll try to craft a simplified example

@dreyks
Copy link
Author

dreyks commented Mar 10, 2023

meanwhile, I've moved the definition of anchorFunctions outside of parseCSS here so that it is maintained between polyfill invocations and now everything seems to be working, but i'm not sure it's the most performant solution 😂

@dreyks
Copy link
Author

dreyks commented Mar 14, 2023

here's an example (i realized I forgot how to write DOM-oriented JS without React 😂 )

https://codesandbox.io/s/wonderful-darkness-tmslme?file=/index.html

it shows text hints depending on if it's polyfilled or native

@jgerigmeyer
Copy link
Member

@dreyks Apologies for the delay here, I've needed to focus on other projects for the past month or so. I still hope to get to this feature before too long, but in the meantime contributions are welcome if you (or anyone) is motivated to submit a PR! 😄

@lucsoft
Copy link

lucsoft commented Apr 9, 2024

Any updates on this? Seeing how Chrome will land CSS Anchor Positioning, in May, would be great to have this issue solved :)

@jgerigmeyer
Copy link
Member

@lucsoft I agree! 😅

I'm hoping to spend some time on this in April, but honestly we could also use help from the community. Code contributions are welcome, as well as financial support (especially from companies that plan to use this in production).

@goodwinchris
Copy link

Any movement here? Can't really use the polyfill in my angular application without it

@jamesnw
Copy link
Contributor

jamesnw commented Jan 10, 2025

@goodwinchris We'd love to make this happen! Financial support (especially from companies that plan to use this in production) will be key to getting this done.

In the meantime, you may be able to use it, depending on your use case. If you are able to detect when the anchor and positioned element are both in the dom, you can call the polyfill manually, and it should detect them. Here's an example in React- #283 (comment). If you're able to get it working in Angular, please post the code to help others! Thanks!

@goodwinchris
Copy link

@jamesnw thanks for the reply, I'll look into if my company would be able and willing to contribute.

I can get the polyfill working on any one of our pages but my issue is that we have multiple pages within the application which need the polyfill to be run once they are rendered and there is now way to run it on a page that needs it and then again on a different page without the polyfill breaking (unless I'm doing something incorrectly there).

@goodwinchris
Copy link

goodwinchris commented Jan 13, 2025

Hey, I've found a workaround that works pretty well for my usecase. I was a bit confused by the docs around the elements option so I'm just going to add detail here even if it may seem obvious.

First, if you want to specify an element to be targeted by the polyfill instead of ALL elements, you can do that by passing an HTMLElement. The easiest way to target these is with document.getElementById('foo'). The easiest way to ensure you have all elements (trigger and popover) is to wrap them. both in a parent element with the id you'd like to target.

Then, it appears there is a way to pass the styles you'd like to work with into the polyfill but I had trouble figuring out how to pass them in, especially with Angular. This lead me to inline all relevant styles with those elements and then just pass in the element.

Since I'm using the polyfill to make my tooltips component work correctly, I added the polyfill just to my tooltips component. Every instance of my component in my application will run the polyfill on its own, this will ensure that each polyfill runs when the elements it needs to run on have been added to the page. I've also gone a step further here and added the polyfill to run in the ngAfterViewInit method and added a setTimeout() as well to push any code to the end of the js stack. All this results in:

import applyPolyfill from '@oddbird/css-anchor-positioning/fn';
...
export class TooltipComponent implements AfterViewInit {
  ngAfterViewInit(): void {
      setTimeout(() => {
        const tooltipWrapper = document.getElementById(`uniqueTooltipKey`);
        if (tooltipWrapper) {
          void applyPolyfill({
            elements: [tooltipWrapper],
            excludeInlineStyles: false,
            useAnimationFrame: false,
          });
        }
      }, 0);
    }
  }
<!-- keep in mind this will need to be dynamic -->
<div id="{{this.tooltipKey}}">
  <button
    type="button"
    attr.style="anchor-name: {{ '--' + this.tooltipKey + '-anchor' }};"
    attr.popovertarget="{{ this.tooltipKey }}"
  >
    {{ tooltipsList[tooltipKey].buttonValue }}
  </button>
  <div
    attr.style="
      position-anchor: {{ '--' + this.tooltipKey + '-anchor' }};
      bottom: anchor(top); 
      left: anchor(50%);
    "
    popover
  >
...
    </div>
</div>

Notes: Because the polyfill is scoped to just the elements I chose (in this case, the #foo element [this id will be dynamically created by each tooltip]) and excludeInlineStyles is set to false, all I needed was my HTML to look like this:

@jamesnw
Copy link
Contributor

jamesnw commented Jan 15, 2025

Thanks for this writeup, and I'm glad you found a way to get this working. I would like to rework the elements and excludeInlineStyles portion of the documentation to make this clearer- let me know if you have thoughts on that.

One thing to note- if excludeInlineStyles is false, the polyfill will be applied to every element in the DOM that has any inline anchor styles. Alternatively, you could do something like {excludeInlineStyles: true, elements: [trigger, popover]}, so that only the inline styles on those elements are impacted. I have opened #289 which proposes making {elements: [wrapper]} polyfill wrapper's children as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants