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

Declarative Actions #41

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open

Declarative Actions #41

wants to merge 22 commits into from

Conversation

Zizico2
Copy link

@Zizico2 Zizico2 commented Nov 25, 2020

@aewing
Copy link

aewing commented Nov 27, 2020

It seems like this is already possible by wrapping the element with a component and slot props -- maybe use:Component is just syntactical sugar for wrapping an element with a component?

@Zizico2
Copy link
Author

Zizico2 commented Nov 27, 2020

It seems like this is already possible by wrapping the element with a component and slot props -- maybe use:Component is just syntactical sugar for wrapping an element with a component?

How would slot props solve the problem? And a component can't really assume its slot only has one child.

@aewing
Copy link

aewing commented Nov 27, 2020

It seems like this is already possible by wrapping the element with a component and slot props -- maybe use:Component is just syntactical sugar for wrapping an element with a component?

How would slot props solve the problem? And a component can't really assume its slot only has one child.

How would they not? What would this make possible that would not otherwise be possible by wrapping an element with a component? I mention slot props because use:Component might assist in facilitating the flow of data there.

To your point about a slot containing multiple child nodes, perhaps in the context of use:Component we could expect one or more nodes, or throw an error for multiple child nodes. Taking an array might not be a bad thing... what if I wanted the action to apply to all child nodes?

@Zizico2
Copy link
Author

Zizico2 commented Nov 27, 2020

It seems like this is already possible by wrapping the element with a component and slot props -- maybe use:Component is just syntactical sugar for wrapping an element with a component?

How would slot props solve the problem? And a component can't really assume its slot only has one child.

How would they not? What would this make possible that would not otherwise be possible by wrapping an element with a component? I mention slot props because use:Component might assist in facilitating the flow of data there.

To your point about a slot containing multiple child nodes, perhaps in the context of use:Component we could expect one or more nodes, or throw an error for multiple child nodes. Taking an array might not be a bad thing... what if I wanted the action to apply to all child nodes?

Check out the "More on styling" section of the RFC. How would you do that with a wrapper component and slot props? I have an example with a wrapper Component. Applying styles to the parent is not the same as applying styles to the Element itself. How would you solve the problem I propose there? Could you spin up an example on the REPL?

Regarding this:

what if I wanted the action to apply to all child nodes?

Then it wouldn't be an action anymore. That is in no way possible with current actions either. If you truly wanted that you could apply the action individually to all the elements you wanted I guess.

@aewing
Copy link

aewing commented Nov 27, 2020

Check out the "More on styling" section of the RFC. How would you do that with a wrapper component and slot props? I have an example with a wrapper Component. Applying styles to the parent is not the same as applying styles to the Element itself. How would you solve the problem I propose there? Could you spin up an example on the REPL?

The use of :global isn't exactly awesome, but there are ways:
https://svelte.dev/repl/7b0c6c778aa04b2da0e862a71721c187?version=3.30.0

Then it wouldn't be an action anymore.

True.

@Zizico2
Copy link
Author

Zizico2 commented Nov 27, 2020

The use of :global isn't exactly awesome, but there are ways:
https://svelte.dev/repl/7b0c6c778aa04b2da0e862a71721c187?version=3.30.0

Ah, I see. One of my intentions with this RFC was to avoid :global as with global css there are, indeed, ways.
That solution is in fact better looking than the ones I proposed as possible alternatives. I'll add the PassiveModifier (even though it assumes a single child) approach to the the "More on Styling" section when I have some time, probably later today.
(there might be a way to style parent Elements in the future, :has)

But apart from styling I still do think Declarative Actions are a generally better way to write Actions.

@aewing
Copy link

aewing commented Nov 27, 2020

I can certainly see the appeal, I was just thinking it might be possible to deliver the reactivity you seek without introducing the <target /> element and a special paradigm for reactive actions by leveraging components instead.
It's too bad you can't bind:this to a component's let: declaration, or this reactivity would be a lot easier with a component wrapper. But what if you could? What if a component could assert that it only takes a single child? What if onMount (or some other mechanism) provided the refs of child elements? Might there be a less complicated path to this reactivity within components?

@Zizico2
Copy link
Author

Zizico2 commented Nov 27, 2020

There might be other ways. Introducing a new Element (or using <slot />) will always be necessary for styling though, since Svelte will delete non used styles. Without relying on global styling that is.

EDIT:
As I said in the RFC, an alternative could be to introduce <target /> for use in Components. This could cannibalize actions though.

@dummdidumm
Copy link
Member

One thing that is not clear to me is how well the proposed type of actions will be composable. A big strength of the current actions (and a reason to keep the "old" way in, even if this RFC would be implemented) is that they are just functions and can easily be mixed and matched with other functions or even actions.

@isaacHagoel
Copy link

Hi,
Sorry for being late to the party. I am the author of the most popular (afaik) drag and drop library, svelte-dnd-action, which uses an action (that is actually aggregating two other actions).
The team that I am leading at work also uses svelte for some of our production apps and we write custom actions very frequently.
imo, actions are one of the most powerful and unique features svelte offers (and in many ways svelte's answer to React hooks) and replacing it would be a huge step backwards. The define a very clean interface for how javascript code can interact and be integrated seamlessly with svelte applications. The author of the action gets (almost) unlimited control and the consumers of the action get a tiny, elegant API.
Here is when we reach out for actions in their current form (outside of the obvious usecases):

  1. actions in their current form are not limited to reasoning about a single component. they can be used to tie components together (ex: holding a map with references to each component that uses the action and triggering events on any of them whenever it sees fit). It can address infinitely complex usecases yet, from the perspective of the consumer of the action, there is a nice, compact, declarative API that completely encapsulates all of the implementation details.
  2. When we want to implement functionality that can be easily ported to be used with any library/ framework/ vanilla js. Because actions don't need svelte as a dependency they can easily be wrapped with a React hook or be used directly (calling update when needed) in any codebase. I experimented with it here and we do it for one of the internal libraries we've created at work.

If you go with this please do it in addition and not instead the existing API.

@Prinzhorn
Copy link

Prinzhorn commented Sep 28, 2021

A declarative action would be usable with use or as regular ol' function?

Yes. If you currently import Foo from Foo.svelte you get a constructor and can do either <Foo> or manually new Foo(). If you import a declarative action (a component that has a context="action" block) doing import foo from foo.svelte you will get a function (not a constructor) that is indistinguishable from any regular action you wrote imperatively by hand. The module just happens to import from svelte/internal if needed. (So I'm pretty sure you could compile a declarative action to vanilla JS and use it in React if you really wanted to just like you can with a Svelte component. I don't.)

For me one open question is if this should have a different extension (e.g. .action). But these are so similar to regular components that it would be weird and tooling like the prettier plugin could already format this right now. The question would be how we teach this if the only difference between declarative action and regular component is the existence of context="action"? For the compiler it's not an issue, if there is context="action" it will allow <svelte:target> and fail if it sees a regular <script> without context (like I said above context="module" would work for actions identical to component right now by scoping it outside the function).

Edit: The big issue with DX/teaching is that from the import statement you cannot distinguish between action and component, but both are used very differently. However, now that I think about it, that's true for literally every .js file you import. It's your responsibility to actually import a function that corresponds to the action spec, the compiler doesn't know.

Edt2: We can also attach a Symbol to the current constructor function and to the new action functions to get useful errors during dev. So if you use: a component or <Foo> an action, we can detect that.

@Zizico2
Copy link
Author

Zizico2 commented Sep 28, 2021

For the compiler it's not an issue, if there is context="action" it will allow svelte:target and fail if it sees a regular <script> without context

What about actions without a script at all? Declarative actions would allow for actions that only apply styling or that only wrap the <svelte:target /> element in more elements (should we allow the latter? It's a question I brought to light in the rfc). Should we just force every action to have a script? Even if it is empty?

@Zizico2
Copy link
Author

Zizico2 commented Sep 28, 2021

Edit: The big issue with DX/teaching is that from the import statement you cannot distinguish between action and component, but both are used very differently. However, now that I think about it, that's true for literally every .js file you import. It's your responsibility to actually import a function that corresponds to the action spec, the compiler doesn't know.

This could just come down to a naming convention. UpperCamelCase.svelte for components and lowerCamelCase.svelte for actions.

@Prinzhorn
Copy link

What about actions without a script at all?

Good point, maybe the existence of <svelte:target> triggers it, because that's what an action requires. It's the point of an action.

I realized that declarative actions would change my mental model for actions.;

  • Currently: actions are my escape hatch into the DOM world and I can do with the node whatever I want
  • New: actions allow horizontal extension of elements. In contrast to the component system (with composition/context etc.) which are all vertical.

Once I had this new mental model three things came to my mind:

  1. "Should we allow more Elements than the Element in an action?" gets a very clear no from me. That's not what actions are for (that would be a vertical change) and once you allow that it becomes even harder to distinguish components from actions. And it would bring a lot of new problems when a component plus multiple actions want to change the tree (who would win?). With attributes it's just a matter of having a well defined order (e.g. setting an attribute in an action overrides the one in the component).

  2. Declarative actions would solve another problem I currently have: utility first CSS frameworks. I'm using Tailwind for the first time and it doesn't pair well with Svelte. I don't want to extract things into components just for the styling, for me components need to do something. But even if I extract them things get worse. E.g. I cannot use animate because now the element (styled component) is not an immediate child of the keyed each. With declarative actions I could just style my element using actions (with the current actions that would just result in tons of ugli toggleClass calls). It would also keep things DRY, because currently my styled <Button> has a path for <a> and one for <button> with basically identical styles.

  3. Maybe we can teach it using the vertical/horizontal terminology?

Regarding the parameters: I think we stick with the current approach, because declarative actions have the current action spec as compile target (they need to be compiled to something anyway). So the parameters become export const parameters in the declarative component. Doesn't matter what you put in it (a primitive value, function or object) it is reactive in the same way props are right now. If you pass an object and use parameters.foo somewhere Svelte will do it's surgical updates so that you don't need to do it (that's my main motivation for declarative actions, I want consistency and not diff parameters and newParameters in update manually).

If the maintainers could signal if this is something they can see happening I'll go ahead an review the whole rfc. I still haven't read it in it's entirety.

@Zizico2
Copy link
Author

Zizico2 commented Sep 30, 2021

We shall wait.

And I don't think I understood this:

Regarding the parameters: I think we stick with the current approach, because declarative actions have the current action spec as compile target (they need to be compiled to something anyway). So the parameters become export const parameters in the declarative component. Doesn't matter what you put in it (a primitive value, function or object) it is reactive in the same way props are right now. If you pass an object and use parameters.foo somewhere Svelte will do it's surgical updates so that you don't need to do it (that's my main motivation for declarative actions, I want consistency and not diff parameters and newParameters in update manually).

What's stopping us from allowing multiple props, like in a Component, and then compiling them into a single function parameter? This could be less intuitive then just forcing actions to have a single prop and letting the user handle that themselves I guess, but it would sure be more ergonomic.

@Prinzhorn
Copy link

Prinzhorn commented Oct 5, 2021

What's stopping us from allowing multiple props, like in a Component, and then compiling them into a single function parameter? This could be less intuitive then just forcing actions to have a single prop and letting the user handle that themselves I guess, but it would sure be more ergonomic.

So what you're suggesting is that actions compiled from declarative action always require the argument to be an object? Because right now I have actions that get a single function as argument.

You could always do this if you want to:

<script>
export let parameters;

$: {foo, bar} = parameters;
</script>

This would be 100% backwards compatible. If you you want this:

<script>
export let foo;
export let bar;
</script>

Then you need to change actions that currently don't use an object if you want to migrate to declarative actions.

But there could also be a magic $$params / $$restParams or something that would hold my function and in this case I wouldn't declare any exports?

@lukaszpolowczyk
Copy link

lukaszpolowczyk commented Oct 5, 2021

Such a loose thought:

Isn't Declarative Actions more of a component + svelte:element + additional goodies?

  1. declarative action:
<!-- action.svelte -->
<script>
</script>
<target on:click={_=>{}} />
<!-- App.svelte -->
<script>
   import { action } from './action.svelte';
</script>
<div use:action {...individualPropsdiv>

vs

  1. svelte:element:
<!-- action.svelte -->
<script>
   export tag;
</script>
<svelte:element tag={tag} on:click={_=>{}} {...$$restProps}><slot/></svelte:element>
<!-- App.svelte -->
<script>
   import { action } from './action.svelte';
</script>
<action tag="div" {...individualProps}></action>

What difference?
In the First, you can use on:click etc. in both action and App.
In Second, you can use on:click etc, only in action (or get a bit more tiring with createEventDispatcher, for example).

So actually, you need to set on:click, bind:val, class:name etc. dynamically?
Maybe some $$specialProps and support for it in svelte:element? Then it would work:

  1. svelte:element +$$specialProps:
<!-- action.svelte -->
<script>
   export tag;
</script>
<svelte:element tag={tag} on:click={_=>{}} {...$$restProps} special-props={$$specialProps}><slot/></svelte:element>
<!-- App.svelte -->
<script>
   import { action } from './action.svelte';
</script>
<action tag="div" {...individualProps} on:click={_=>} class:name bind:val></action>

Attributes on:click={_=>} class:name bind:val would be hidden in $$specialProps? It would not be an ordinary object, but a special object that retains svelte attributes.
The component itself would have to allow on:click class:name etc. - or you would have to enable support via e.g. <Component mode="action"/>?

Summary:
declarative action == svelte:element +$$specialProps
I don't know if that would solve anything, maybe it would be more universal?
Let this comment be treated, perhaps, as an inspiration for reflection.

@Zizico2
Copy link
Author

Zizico2 commented Oct 5, 2021

So what you're suggesting is that actions compiled from declarative action always require the argument to be an object? Because right now I have actions that get a single function as argument.

Ah... I was completely disregarding actions with a single parameter. I guess we could force having an object as a parameter. Maybe leaving it as it is, is better though. I would personally prefer the "forcing object as parameter" option. This may not be a popular opinion though.

@iacore
Copy link

iacore commented Jan 5, 2022

It seems like this syntax implicates dynamic injection of any directive at runtime. I feel like this will be both confusing and abused.

@lukaszpolowczyk
Copy link

lukaszpolowczyk commented May 13, 2022

UPDATE 2

A separate RFCS for this - #68
"Targeted Slots - passing and mixing attributes and styles to component, access the slotted element from inside the component"


An alternative syntax that gives more possibilities, using slots, but also less graceful:

<!-- App.svelte -->
<script>
import Com from "./Com.svelte";
</script>
<Com>
  <svelte:element slot="button" class="class1"></svelte:element>
</Com>
<style>
  .class1 {}
</style>
<!-- Com.svelte -->
<script>
let target;
</script>
<slot name="button" targeted this="button" bind:this={target} class="class2" on:click={_=>{}}/>
<style>
  .class2 {}
</style>

Description:

  • the targeted attribute in the <slot> tag causes the slot to accept html attributes, svelte special attributes, and can use bind:this={target}.
  • using <svelte:element shows that it is possible to set tagName inside a component
  • by using named slots, multiple targets can be used, not just one as in the original Declarative Actions proposal
  • unfortunately, by using slots, the syntax is less graceful

I would very much appreciate your feedback, do you like it?

UPDATE 1

I noticed one mistake.
Slots pass parameters by name, which causes two problems:

  • <slot targeted> is treated as passing a boolean, which would be read in <svelte:element let:targeted>. We don't want that, because it would break the old syntax.
  • Other attributes in <slot> are also passed, and read by let:val. This conflicts with the proposed treatment of these attributes, as attributes of an element.

Solution

  • We need to replace the targeted attribute with, for example, targeted:name. Then there is no collision problem. From then on, attributes should be treated as attributes of the element. It also frees up the name attribute, which also someone may want to use in a different way than naming a slot....
  • Passing the value to let:val would be done via this targeted:name={ {val: "string"} } and read <svelte:element let:val> - This may be a less pretty way, but I think it's worth it, given the benefits.

The same example in a new way:

<!-- App.svelte -->
<script>
import Com from "./Com.svelte";
</script>
<Com>
  <svelte:element slot="button" class="class1"></svelte:element>
</Com>
<style>
  .class1 {}
</style>
<!-- Com.svelte -->
<script>
let target;
</script>
<slot targeted:button  this="button" bind:this={target} class="class2" on:click={_=>{}}/>
<style>
  .class2 {}
</style>

Where button in target:button is the name of the slot.

And you can something like this:

  <svelte:element slot="button" class="class1" let:val>{val}</svelte:element>
  ...
  <slot targeted:button={{ val: "string" }} 
    this="button" bind:this={target} class="class2" on:click={_=>{}} name="name1"
  />

Where the name attribute is in this sense - https://www.w3schools.com/tags/att_name.asp, not in the sense of a slot name.
And in the value of targeted:button you pass val to let:val in <svelte:element let:val>.

This is a compromise to release the attributes of the slot, and be able to use them as attributes of a dynamic element.

DISCLAIMER: If one believes that "slots should be left alone", one could call it different. But it would literally work as upgraded slots.

@lukaszpolowczyk
Copy link

A minor note - Using Declarative Actions is a bit like using the is attribute on a Custom element declared in Web Components:
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is

This <p use:wordCount></p>, is equivalent to <p is="word-count"></a>. :D

I don't know, maybe this will encourage someone to pursue Declarative Actions. :)

obraz

@madeleineostoja
Copy link

I don’t know what the is syntax has to do with this proposal, the is=“el” was also abandoned from the web components spec because safari wouldn’t implement it

@lukaszpolowczyk
Copy link

@madeleineostoja Topic appears to be unfinished - https://bugs.webkit.org/show_bug.cgi?id=182671#c18

As for the lack of similarity - maybe I have more imagination.... I don't want the topic to be closed by a drawn out side discussion.

In a nutshell:
You have a database of attributes and parameters from an element + you add your own.
This is such an extension of the element behavior, INstead of wrapping the element.

Both the Declarative Action and the is attribute from Custom Element:

  • increases code clarity
  • allows you to extend the element in a simple way (Declarative Action uses the advantages of Svelte syntax, you do many things more simply than with use:action function)
  • doesn't hide the properties and attributes of the component (and wrapping hides the properties of the component, and you have to extract them additionally to the component properties)

A regular use:action, where action is a simple function, also works like this, but the analogy is less because it doesn't use the advantages of the Svelte Component syntax, which means that extending the function is more difficult. (Element extended by-> action function)

Extension, use:DeclarativeAction vs the is attribute:
Element extended by-> Svelte Component
vs
Element extended by-> Custom Element

Wrapper, putting Element in Svelte Component slot(or inside Component) vs putting Element in slot(or inside Custom Element):
Element wrapped by Svelte Component
vs
Element wrapped by Custom Element

Summary:
Declarative Action, is to use Svelte Component, without wrapping.
Attribute is, is to use Custom Element, without wrapping.

@madeleineostoja
Copy link

madeleineostoja commented Jun 8, 2022

Not going to get wrapped up in this, just wanted to mention that I was quite involved in spec discussions during the early days of web components, and I can assure you that customised built ins (is="") will never see the light of day in Safari, which is why it was dropped from the final spec.

I don't understand what you're trying to get across, and there's no need for comments like "maybe I have more imagination"

@lukaszpolowczyk
Copy link

I don't understand what you're trying to get across, and there's no need for comments like "maybe I have more imagination"

I meant that maybe I associate things that don't fit together as I think they do.
It wasn't that you had too little imagination, I just had maybe "too much".

All in all, I feel bad that almost anything I write is received negatively.
I thought the analogy to something existing (in Firefox and Chrome), would help get people interested in Declarative Actions. I would love to see Declarative Actions implemented.

@Zizico2
Copy link
Author

Zizico2 commented Jul 1, 2022

An alternative syntax that gives more possibilities, using slots, but also less graceful:

<!-- App.svelte -->
<script>
import Com from "./Com.svelte";
</script>
<Com>
  <svelte:element slot="button" class="class1"></svelte:element>
</Com>
<style>
  .class1 {}
</style>
<!-- Com.svelte -->
<script>
let target;
</script>
<slot name="button" targeted this="button" bind:this={target} class="class2" on:click={_=>{}}/>
<style>
  .class2 {}
</style>

Description:

  • the targeted attribute in the <slot> tag causes the slot to accept html attributes, svelte special attributes, and can use bind:this={target}.
  • using <svelte:element shows that it is possible to set tagName inside a component
  • by using named slots, multiple targets can be used, not just one as in the original Declarative Actions proposal
  • unfortunately, by using slots, the syntax is less graceful

I would very much appreciate your feedback, do you like it?

This is great. If I'm not forgetting anything this would be fantastic. I think I've alluded to a solution like this in a comment to an issue that I'm not finding right now xd. This might even be easier to teach since you could drop the notion of "Declarative Actions" completely. It's just a targetted slot in a "normal" Component.

@Zizico2
Copy link
Author

Zizico2 commented Jul 1, 2022

I've been really busy lately. If you want to you'd be welcome to open a pull request for my RFC, introducing this as an alternative. I'd happily review it. @lukaszpolowczyk

@lukaszpolowczyk
Copy link

@Zizico2 Check out my RFCS:
#68 - Targeted Slots - passing and mixing attributes and styles to component, access the slotted element from inside the component

The syntax may not be as nice as <div use:Component>, but that makes it more comprehensive and standards-compliant (I hope).

@mimbrown
Copy link

@Prinzhorn redirected me here after I posted a similar issue. A couple thoughts, as I'm getting caught up and have been pondering this more:

  • Just going to toss in <svelte:composable> as another alternative name.
  • While @lukaszpolowczyk's RFC is quite interesting and powerful, it's not nearly as ergonomic as I would hope for this feature.
  • While I think there should NOT be any other elements outside of the composable in its definition, I can actually see the ability to define children in a composable as both feasible and useful. Use case: material-style ripple (on click, add an element, animate the element, then remove).
  • Actions, as they currently stand, may not be the right fit for compiled composability. The main reason is that they are not considered in SSR (see this issue). So if I defined a composable whose only job was to add a class (trivial example), then that class would not show up until hydration (not ideal). So maybe this is a completely new thing, not attached via use:. Possible alternatives (brainstorming):
<!-- Given a composable named `dropZone` -->

<div with:dropZone />
<div compose:dropZone />
<div also:dropZone />

@Zizico2
Copy link
Author

Zizico2 commented Sep 15, 2022

@Prinzhorn redirected me here after I posted a similar issue. A couple thoughts, as I'm getting caught up and have been pondering this more:

* Just going to toss in `<svelte:composable>` as another alternative name.

* While @lukaszpolowczyk's RFC is quite interesting and powerful, it's not nearly as ergonomic as I would hope for this feature.

* While I think there should NOT be any other elements outside of the composable in its definition, I can actually see the ability to define children in a composable as both feasible and useful. Use case: material-style ripple (on click, add an element, animate the element, then remove).

* Actions, as they currently stand, may not be the right fit for compiled composability. The main reason is that they are not considered in SSR (see [this issue](https://github.com/sveltejs/svelte/issues/4375)). So if I defined a composable whose only job was to add a class (trivial example), then that class would not show up until hydration (not ideal). So maybe this is a completely new thing, not attached via `use:`. Possible alternatives (brainstorming):
<!-- Given a composable named `dropZone` -->

<div with:dropZone />
<div compose:dropZone />
<div also:dropZone />

It's funny you mention the material ripple. That was the first time I felt the need for something like Declarative Actions adn then I generalized from there. And I don't think you would need to add an element to implement the material ripple. I think adding elements would make this RFC more convoluted than it needs to be and we would lose the differentiation between vertical and horizontal that @Prinzhorn conjectured in an earlier comment. You're right that using the current action infrastructure maybe wouldn't play nice with SSR. But I don't see why that couldn't be changed. Idk if handling SSR would make it different enough from Imperative Actions to warrant a different notation like with:dropZone as you mention.

There's a new RFC where your input would be greatly appreciated, you seem to have some nice thoughts on the matter. I honestly think it almost supersedes this one, but there's some discussion about it on that RFC.

The biggest drawback I see is:
You lose the ability to apply multiple actions (targeted slots in that RFC) to the same element.

With declarative actions you can do:

<div use:action1 use:action1 use:action2 use:action3>Hi!</div>

With targeted slots this doesn't really work. I do have some thoughts that could make this work with targeted slots but I'll brew them for some more time xD. I'll post them over there when I can formalize my thoughts.

#68

EDIT: Ok... I completely overlooked that you (@mimbrown) had already read @lukaszpolowczyk's RFC. I won't change the comment though, just keep in mind I hadn't noticed xD

@lukaszpolowczyk
Copy link

With targeted slots this doesn't really work. I do have some thoughts that could make this work with targeted slots but I'll brew them for some more time xD. I'll post them over there when I can formalize my thoughts.

@Zizico2 I'm waiting for your solution to this problem, as I myself don't have any good idea about it yet.

@mimbrown
Copy link

It's funny you mention the material ripple. That was the first time I felt the need for something like Declarative Actions adn then I generalized from there. And I don't think you would need to add an element to implement the material ripple. I think adding elements would make this RFC more convoluted than it needs to be and we would lose the differentiation between vertical and horizontal that @Prinzhorn conjectured in an earlier comment.

It is interesting we had the same use case in mind! I think there are inevitably going to be use cases where adding child elements through a declarative action will be helpful/necessary, but I agree that it complicates the proposal. I would be in favor of a V1 where children are disallowed and continuing this discussion for future versions.

You're right that using the current action infrastructure maybe wouldn't play nice with SSR. But I don't see why that couldn't be changed. Idk if handling SSR would make it different enough from Imperative Actions to warrant a different notation like with:dropZone as you mention.

About SSR, I don't think there's a scenario where the current use:action syntax will support SSR in the future. You can't really tell users, "An action is a function that takes a DOM element and performs custom logic on it, except you have to support the scenario where we are in an SSR context and your function is actually getting passed a pseudo non-DOM element." That was the main gist I got from #4375, and I agree. Since actions already exist as a non-compiled feature, I think something different might be required. That's my 2 cents.

EDIT: Ok... I completely overlooked that you (@mimbrown) had already read @lukaszpolowczyk's RFC. I won't change the comment though, just keep in mind I hadn't noticed xD

Haha np. It goes without saying that I agree with my comments over there :)

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.

None yet

10 participants