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

Problem with duration setting for animations in Vuejs #158

Open
patrickvuarnoz opened this issue Jan 29, 2025 · 6 comments
Open

Problem with duration setting for animations in Vuejs #158

patrickvuarnoz opened this issue Jan 29, 2025 · 6 comments
Labels
bug Something isn't working

Comments

@patrickvuarnoz
Copy link

Describe the bug

When setting the duration of an animation in Vuejs like in the following example it triggers an error:

<wa-animation name="slideInDown" easing="easeOut" duration="500" iterations="10" play>
  <wa-callout variant="danger">
    <wa-icon slot="icon" name="circle-exclamation" variant="regular"></wa-icon>
    <strong>Your account has been deleted</strong><br />
    We're very sorry to see you go!
  </wa-callout>
</wa-animation>

Image
Image

When using v-bind to set the duration then it works as expected:

<wa-animation name="slideInDown" easing="easeOut" v-bind:duration="500" iterations="10" play>
  ...
</wa-animation>

It seems that it is required for the duration to be an integer instead of a string. This may have something to do with Vuejs. BUT, the setting for iterations is not affected and can be set with v-bind or without. I could not pinpoint the problem as it seems that the component code of <wa-animation> does treat both properties the same.

I'm using 3.0.0-alpha.9.

@patrickvuarnoz patrickvuarnoz added the bug Something isn't working label Jan 29, 2025
@claviska
Copy link
Member

I'm having trouble reproducing this. I setup a new Vue 3 app:

npm create vue@latest

I added this to vite.config.ts:

    vue({
      template: {
        compilerOptions: {
          isCustomElement: tag => tag.startsWith('wa-')
        }
      }
    }),

Imported WA in index.html:

    <link rel="stylesheet" href="https://early.webawesome.com/[email protected]/dist/styles/themes/default.css" />
    <link rel="stylesheet" href="https://early.webawesome.com/[email protected]/dist/styles/native.css" />
    <script type="module" src="https://early.webawesome.com/[email protected]/dist/webawesome.loader.js"></script>

And added the following animation/button to App.vue:

    <div class="wrapper">
      <wa-animation name="bounce" duration="2000" iterations="3" play>
        <wa-button variant="brand">Click me</wa-button>
      </wa-animation>
    </div>

And it works:

Image

But I see nothing in the console. 🤔

Image

I do however see this exact error if I set duration or iterations to a negative number or a letter, and it remains in the console until I clear it or refresh even after setting it back to a correct value.

I'm wondering if that's also what you might be seeing.

@patrickvuarnoz
Copy link
Author

That's interesting. I cloned my project, ripped everything that's just noise to the issue and the issue still persisted. Just as I was wondering how I would share that code with you I tried copying your code from above and it just worked. That made me see the difference. You are importing WA via loader:

<script type="module" src="https://early.webawesome.com/[email protected]/dist/webawesome.loader.js"></script>

I am importing single WA components directly (because I had problems with WA components not being ready when Vuejs already wanted to access them – preloading the WA components solved this issue):

<script type="module" data-webawesome="https://early.webawesome.com/[email protected]/dist">
  import 'https://early.webawesome.com/[email protected]/dist/components/animation/animation.js';
  import 'https://early.webawesome.com/[email protected]/dist/components/callout/callout.js';
  import 'https://early.webawesome.com/[email protected]/dist/components/icon/icon.js';
</script>

Could it be that animation has dependencies that are not mentioned in the documentation? Or something else that is being loaded via loader.js that is missing when only animation.js is loaded?

@patrickvuarnoz
Copy link
Author

Interestingly it seems indeed to be related to Vuejs (or at least the way it is composing html). If I put the whole example into a plain html file it also just works fine:

<!DOCTYPE html>
<html lang="en" theme="default">
  <head>
    
    <!-- Web awesome -->
    <link rel="stylesheet" href="https://early.webawesome.com/[email protected]/dist/styles/themes/default.css" />
    <link rel="stylesheet" href="https://early.webawesome.com/[email protected]/dist/styles/native.css" />
    
    <script type="module" data-webawesome="https://early.webawesome.com/[email protected]/dist">
      import 'https://early.webawesome.com/[email protected]/dist/components/animation/animation.js';
      import 'https://early.webawesome.com/[email protected]/dist/components/callout/callout.js';
      import 'https://early.webawesome.com/[email protected]/dist/components/icon/icon.js';
    </script>
    
  </head>
  <body>
    
    <wa-animation name="slideInDown" easing="easeOut" duration="500" iterations="1" play>
      <wa-callout variant="danger">
        <wa-icon slot="icon" name="circle-exclamation" variant="regular"></wa-icon>
        <strong>Your account has been deleted</strong><br />
        We're very sorry to see you go!
      </wa-callout>
    </wa-animation>
    
  </body>
</html>

@claviska
Copy link
Member

I spent some time trying to get this to work with no luck. I think it has something to do with the timing of when Vue mounts and the component registers. The good news is, this problem will go away once Web Awesome is on npm.

Are you able to use the autoloader in the meantime? That seems to work consistently for me.

@patrickvuarnoz
Copy link
Author

Well, I just experienced the opposite with the autoloader. Not with this issue here, but with <wa-dropdown> for example. There I have some code like this:

      <wa-dropdown sync="width" stay-open-on-select>
        <wa-button
          variant="neutral"
          size="small"
          slot="trigger"
          caret
          class="ml-2">
          <span class="display-inline-block text-left" style="width:160px;">
            Topics
            <template v-if="topics.length">({{ topics.length }} of {{ store.topics.length }})</template>
          </span>
        </wa-button>
        <wa-menu v-on:wa-select="onTopicChange($event.detail.item.value)">
          <wa-menu-item value="all">All</wa-menu-item>
          <wa-menu-item value="none">None</wa-menu-item>
          <wa-divider></wa-divider>
          <wa-menu-item
            v-for="topic in store.topics"
            v-bind:key="topic.id"
            v-bind:value="topic.id"
            v-bind:checked="topics.includes(topic.id.toString()) ? true : false"
            type="checkbox">
            {{ topic.name }}
          </wa-menu-item>
        </wa-menu>
      </wa-dropdown>

When using the autoloader all checkboxes are toggled even though only one menu item should be checked:
Image

When preloading the components it behaves correctly:
Image

My assessment here was that the component is loaded too late via autoloader and Vue is not able to bind the values correctly as it does not know anything about the properties of the component. Or that initially it thinks this is plain HTML and when the component loads, it then all of a sudden has JS properties which might confuse Vue.

I am looking forward to the NPM solution but my expectation was that importing the components from there would do exactly the same as what I am currently doing with cherry picking. So I don't expect any difference in behaviour there.

I tried to check with the debugger in the browser how the values look like where the error occurs. It seems that both duration and iterations are strings at that time:
Image

Interestingly, if I bind duration with :duration="500" then the duration is passed as number, iterations still a string but no error occurs, even though to my understanding iterations should also be a number:
Image

From the documentation on MDN (https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#iterations) I saw that for iterations also a value of "Infinity" is allowed which is probably the reason no error is triggered as the option is allowed to be a (special) string as well.

An easy fix could simply be to cast duration to a number via Number.parseFloat() in createAnimation() (or earlier).

@patrickvuarnoz
Copy link
Author

PS: My current workaround is to just bind duration with :duration="500" instead of duration="500".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants