Skip to content

Conversation

jacwright
Copy link
Contributor

Makes transitions only run when the closest non-component block containing them has changed state.

Implements #1480.

Details

Without the containedTransitions compiler option, all transitions are run whenever their element is added/remove from the dom. With containedTransitions the transitions are only run when the closest non-component block (e.g. an if-block or each-block) changes state. This means the transitions on the items of an each-block will not run when the each-block first appears on screen, or when it is removed, but they will run when items are added/removed from the each block. In addition, if a whole page fades in with a transition at the page level, the there will not be other transitions occuring inside the page.

The transition containers do not include components, since a component is a reusable container and not a state-driven block. Thus, a transition at the root of a component will run when that component is added to the DOM inside an if-block or each-block the same way an element with a transition inside either of those blocks is run.

Makes transitions only run when the closest non-component block containing them has changed state.

Implements #1480.

### Details

Without the `containedTransitions` compiler option, all transitions are run whenever their element is added/remove from the dom. With `containedTransitions` the transitions are only run when the closest non-component block (e.g. an if-block or each-block) changes state. This means the transitions on the items of an each-block will not run when the each-block first appears on screen, or when it is removed, but they will run when items are added/removed from the each block. In addition, if a whole page fades in with a transition at the page level, the there will not be other transitions occuring inside the page.

The transition containers do not include components, since a component is a reusable container and not a state-driven block. Thus, a transition at the root of a component will run when that component is added to the DOM inside an if-block or each-block the same way an element with a transition inside either of those blocks is run.
@jacwright jacwright requested a review from Rich-Harris August 25, 2018 16:43
@Rich-Harris
Copy link
Member

I'm still of the view that this is probably best expressed within the markup, with a directive of some kind. I'm worried that a component-level compiler option (which for all practical purposes is an app-level option) is too blunt.

What if we had something like this instead?

{#if showList}
  <ul transition:fade childtransition:false>
    {#each items as item (item.id)}
      <li transition:slide>{item.label}</li>
    {/each}
  </ul>
{/if}

childtransition is maybe a bit cumbersome but you get the idea. Thoughts?

@jacwright
Copy link
Contributor Author

I went with a carte blanche approach because I believe this is the way transitions should work and wanted to allow trying/testing it out. However, though this won't be the default, I agree you should be able to choose how it works in a certain situation, whatever the default. I will work on it some more.

@jacwright
Copy link
Contributor Author

jacwright commented Aug 27, 2018

I've been trying to figure out how to do this. In this model of transitions for SPAs, it is the if/each block that should stop nested transitions, not an HTML element with a directive that stops nested transitions from running. And I don't believe extending the block syntax with additional language is appropriate for this case.

Something like childtransition:false assumes you have control over the context of your component too. If I have a file system tree component that opens and closes a folder when you toggle the arrow next to it, I would want those transitions (open/close) to run when you click, but not when the tree appears or is removed from the page. That component should determine its own behavior (or at least, its own defaults).

What about adding a couple properties to the transition object? Alongside duration and delay you could have updateOnly: true, or intro: false and outro: false. In this situation, the transition system would be given to know if the transition was from an intro (the block was just added to the DOM), an update (the value the block depends on was changed), or an outro (the block was removed from the DOM), and the transition could determine when it ran. I would appreciate if defaults could be set at the app/compiler level, but those defaults could be adjusted on a case-by-case basis. What are your thoughts about this approach @Rich-Harris?

Of course, names could be create: false and destroy: false instead if intro/outro. Whatever works best.

jacwright added a commit that referenced this pull request Aug 29, 2018
Allows transitions to skip running when they are added to the DOM or removed from it. Similar to the compiler option `skipIntroByDefault` this allows the intro/outro to be skipped.

Example:

```html
{#if visible}
  {#each things as thing}
    <div transition:fade></div>
  {/each}
{/if}

<script>
export default {
  transitions: {
    fade(node, params) {
      return {
        intro: false,
        outro: false,
        duration: 400,
        css: t => {
          return `opacity: ${t}`;
        }
      };
    }
  }
};
</script>
```

In this example items in the each-block will fade in and fade out when they are added to or removed from `things` but the list will appear suddenly and disappear suddenly (no fade) when `visible` is toggled to `true` or `false`.

This is another try at #1480 from the compiler option in #1692.

Intro and outro transitions will run unless `intro` or `outro` on the transition object (e.g. next to duration/delay) are set to false. Transition defaults can be set in the root options, including intro and outro.
@jacwright jacwright closed this Sep 10, 2018
@jacwright jacwright deleted the gh-1480 branch September 12, 2018 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants