diff --git a/text/0000-targeted-slots.md b/text/0000-targeted-slots.md new file mode 100644 index 0000000..7f84dcd --- /dev/null +++ b/text/0000-targeted-slots.md @@ -0,0 +1,775 @@ +- Start Date: 2022-08-07 +- RFC PR: (leave this empty) +- Svelte Issue: (leave this empty) + +# Targeted Slots + +## Summary + +This allows you to pass and combine CSS styles added in parent and child component, read `bind:this={target}` inside child component, and pass other attributes. + +It's easiest to think of Targeted Slots as regular SvelteJS slots, but adding attributes and special attributes to the slots also from inside the child component. + +It combines attributes given to slot in the parent component, with attributes added in the child component. +The original SvelteJS slots can only do in parent component. + +Instead of a fallback for an element that is in simple slots, there will be a fallback for content and some attributes. + +Generally - gives superpowers of combining to... ``, and improves the performance of slots. + +## Motivation + +In short - the same as in these RFCs: + +- Declarative Actions - https://github.com/sveltejs/rfcs/pull/41 +- Implement forward directive - https://github.com/sveltejs/rfcs/pull/60 +- Targeted style inheritance - https://github.com/sveltejs/rfcs/pull/66 +(I hope the links are enough, because otherwise I would have to copy the Motivation section with this RFC) +- And, in general, all the problems with `:global` and passing styles between parent and child components that everyone knows about. + +I wrote the first glimpses of this idea here: + +- that Declarative Actions are a bit like `` + slots - https://github.com/sveltejs/rfcs/pull/41#issuecomment-934364393 +- the first idea to implement `` + slots - https://github.com/sveltejs/rfcs/pull/41#issuecomment-1126434719 +- the idea of grouping attributes in Forward Directive - https://github.com/sveltejs/rfcs/pull/60#issuecomment-1073263370 +- discovery that an idea useful in Declarative Actions, can be useful in Forward Directive - https://github.com/sveltejs/rfcs/pull/60#issuecomment-1204651747 +- discovery that the same idea can also work in Targeted Style - https://github.com/sveltejs/rfcs/pull/66#issuecomment-1207270679 + (funnily enough, the name is similar, although mine was taken from the `` tag in Declarative Actions) + +## Detailed design + +Basic example + +```svelte + + +``` + +```svelte + + +``` + +It gives the effect of + +```svelte +
+``` + +So, combining attributes placed in `Parent` and in `Child`. The same way of combining SvelteJS special attributes. + +In case of attribute name collisions, the value of the attribute in `Parent` overwrites the value of the attribute in `Child`. + +Here you can see a big difference from simple slots, but despite appearances, there are great similarities. +Below is an explanation of the differences in syntax, etc. + +### Implementation + +#### **Similarities to slots** + +Using the `slot="name"` attribute. + +```svelte + + +``` + +--- + +Using one or multiple slots. + +```svelte + + +``` + +```svelte + + + + + +``` + +--- + +Using multiple slots with the same name in `Child`. +(example in "Differences from slots", because the syntax itself differs) + +--- + +Using `let:val`. + +```svelte + +{val} +``` + +--- + +Reading the value of `$$slots.name` in `Child`. + +--- + +The tag `` will not find any benefit in Targeted Slots, but it too can be used in the same way as before. +(there is a variant of `` that you will use to pass styles for element-child slot, in a special case, but about it in "Differences from slots") + + +#### **Differences from slots** + +In `Child` using the `` tag, instead of the `` tag, with the necessary `targeted:name` attribute instead of `name="name"`. + +```svelte + + +``` + +This is because the `name` attribute can be useful in ``, because it is a simple HTML attribute, it is not just for slots. +You will be able to use the `name` attribute in this sense - https://www.w3schools.com/tags/att_name.asp + +The name `targeted` came from the name of the `` tag, from the **Declarative Directive** proposal. + +--- + +Targeted Slots can only work with `svelte:element`, e.g. ``. Therefore, to emphasize that there is something dynamic going on here. +(although in "Rejected at this time" I wonder about that) + +--- + +Using in `Child` multiple slots with the same name, but with a new syntax. This is possible in simple slots, but I show how to do it with the new syntax. + +```svelte + + + +``` + +(With that case, there are some "Unresolved questions" about bindings} + +--- + +The ability to not add `this="tagName"` for `` - because `this="tagName"` can be added in `Parent`, or in `Child`. + +```svelte + + +``` + +```svelte + + +``` + +...or... + +```svelte + + +``` + +```svelte + + +``` + +When it is not added either in `Parent` or in `Child`, it is like adding `this={null}`. + +--- + +To be able to use in `` other special attributes and simple HTML attributes, you need to implement `` differently - through an object. + +```svelte + +{val} +``` + +```svelte + + +``` + +It's less pretty, but it's a compromise worth making. + +This will make it possible to write something like this. + +```svelte + + +``` + +...where the attributes `name="some-name"` and `val="simple"`, are simple HTML attributes, not things passed to `let:val`, nor the slot name. + +--- + +No ``(fallback of the whole element). It's important to be able to do a fallback of the content itself. + +```svelte + + +``` + +```svelte + +Content that will not disappear. +``` + +If there is no content in `Parent` in ``, the content from `Child` is visible. That is, as if the fallback is for the content, not for the whole element. + +If one needs, the fallback of the whole element can be done with `$$slots.name` and `{#if}`. + +--- + + +Using the special attribute `bind:this={target}` in the slot. This was not present in simple slots at all. + +```svelte + + +``` + +```svelte + + +``` + +It's **very important** because it's essential for solving the problems described in **Declarative Actions**. + +Allows to hide complex logic in `Child`, hidden under a simple element visible in `Parent`. + +Declarative Actions is the idea that for `use:Component` you can use a `Component`, with `` in the `Component`, to be able to use the advantages of SvelteJS syntax, and at the same time use the advantages of actions. + +My proposal also does this, but in a different (more universal and without using the action attribute) way. +But I found that Targeted Slots does not have the equivalent of using multiple `use:action1 use:action2` in a single element. This is one of the Unresolved questions. + +--- + +Passing the slot on to `SubChild`. + +```svelte + + +``` + +```svelte + + +``` + +```svelte + + +``` + +Here you are not creating a slot target in `Child`, but passing a slot from `Parent` to `SubChild`. +All attributes set in `Parent`, will be assigned to `` in `SubChild`. + +As you can see, neither in `Parent` nor in `Child` you don't need `this="name"` in ``, just in one place, this time in `SubChild`. + +Simplified syntax when same name in `slot:name="name"` simplified to `slot:name`. + +Such a need is written in the **Forward Directive** proposal, but also in **Targeted styles** proposal, for styles (more on that later). + +--- + +Passing CSS classes from `Parent` to `Child`. + +```svelte + + +
+ +
+ + +``` + +```svelte + + + +Foo + + + +``` + +The rule is simple - if any class or tagName is declared in `Parent`, then the styles written in `Parent` apply to the slot element. + +--- + +Passing classes from `Parent` to `SubChild`. + +```svelte + + + +``` + +```svelte + + +``` + +```svelte + + + +``` + +The button in `SubChild` will have red text. + +--- + +The class name of targeted element can be the same in `Parent` and `Child`, because SvelteJS adds its hash (one in `Parent`, one in `Child`), so it won't interfere. + +```svelte + + +
+ +
+ + +``` + +```svelte + + + +Foo + + +``` + +--- + +The last few descriptions, exhaust the subject of **Targeted style inheritance** proposal. +Only one more challenging case remains. + +Pass styles for the element-child slot. + +To get this, you need a specific selector. + +Attribute `svelte:selector` for ``. + +It is done like this: + +```svelte + + +
+ +
+ + +``` + +```svelte + + + + + Foo + +``` + +Then any style from `Parent` that is matched in some `svelte:selector` will be remembered. +When `Child` is called, it will be searched with the selector from `svelte:selector` and the found elements will get the corresponding hashes. + +You can list multiple selectors in `svelte:selector`, after a comma. As for example in standard `document.querySelectorAll("selector1, selector2")`. + +Or more nicely: + +```svelte + +``` + +Using `:scope`, e.g. `` - when you want a direct child selector targeted slot. +This is standard syntax - https://developer.mozilla.org/en-US/docs/Web/CSS/:scope + +--- + +The `svelte:selector` attribute can also be useful in ``. + +```svelte + + +
+ +
+ + +``` + +```svelte + + + + + +``` + +This will bypass the compulsion to use an element-container in `Parent` when you just want to pass the style to elements in `Child`. + +Note that it is not ``, but ``. +The first works in the standard way, the second allows you to keep content from `Child`, and pass styles for that content. + +--- + +In **Forward Directive** they propose a complex system of attribute exceptions. +With Targeted Slots, you can freely place attributes in separate named slots. +This will completely replace this complicated exceptions system. + + +```svelte + + + + + + +``` + +```svelte + + +Foo + +Foo +``` + +This is an example of simple exception, by using a separate name. +In one place there is both `click` and `mouseover`, and in another place there is only `click`. + + +--- + +Ability to mix simple slots, with Targeted Slots. + +```svelte + + +``` + +```svelte + + + +``` + +...or... + +```svelte + + + +
+
+``` + +```svelte + + + +``` + +...or... + +```svelte + + + + + +``` + +```svelte + + + +``` + +Also you will be able to use the unnamed slot, and at the same time inside the Targeted Slot. + +```svelte + + + {val} + +``` + +```svelte + + + +``` + +And many other forms of mixing. +Simply no knowledge of the reason not to allow it. These are sometimes two separate purposes of use, and simplified syntax. + + +## How we teach this + +Therefore, because it is similar to slots, but nevertheless a little different, you need to take advantage of the fact that slots everyone knows. +But also make a clear distinction between what is different from slots, so that one is not confused with the other. + +## Drawbacks + +Possible confusion of this with ordinary slots. Therefore, it is rather necessary to give other names. +On the other hand, if we say that these are slots + extras, it is easier to understand. +This is the dilemma. + + +## Alternatives + +- Declarative Actions - https://github.com/sveltejs/rfcs/pull/41 +- Implement forward directive - https://github.com/sveltejs/rfcs/pull/60 +- Targeted style inheritance - https://github.com/sveltejs/rfcs/pull/66 + +And everything written in the "Alternatives" section of these RFCs. + +## Unresolved questions + +Someone sees `` and thinks it's a simple slot. And it is a Targeted Slot. +Therefore, perhaps the name of the `slot` attribute should be changed into another one. But I don't know into which one? + +--- + +What part of attributes and special attributes can be easily handled with this API. This is known to the maintainers who directly work on SvelteJS. + +--- + +The issue of the order in which CSS classes are overridden isn't certain either, as it depends on which component is initialized first, or something like that.... It's also for the SvelteJS engine specialis. +This can be solved, it seems to me, by double using .hashParent.hashParent from Parent to override .hashChild from Child. I think such a method is used somewhere in Svelte. + +--- + +For the reason that in this proposal there is no fallback for the element, only for the content of the element, you can do it. + +```svelte + + + + + +``` + +```svelte + +content +``` + +But perhaps it's too complicated? + +--- + +`Component` as Targeted Slot? +I don't know how this could be handled. + +```svelte + + + + +``` + +```svelte + + +``` + +...? + +I don't know if this is good. +But it could be useful (example needed) + +--- + +What about this? What does `el` refer to, in `Parent`? + +```svelte + + + +``` + +```svelte + + + + + +``` + +It seems that in `Parent`, `el` should be an array. + +Perhaps a new syntax `bind:these={els]` is needed? + +```svelte + + + +``` + +--- + +Targeted Slots does not have the equivalent of using multiple `use:action1 use:action2` in a single element. +This was pointed out by user mimbrown. + +So far I have no idea how to solve this. + +### Rejected at this time + +The attribute value written in `Parent`, should overwrite the attribute value written in `Child`. +Maybe it should be possible to decide the order of overwriting? + +--- + +Perhaps allowing the use of simple `
` etc., instead of `` - Both in `Parent` (with `slot="name"`) and in `Child`(with `targeted:name`) - this will give a slightly nicer look, but maybe it is technically impossible? +Then you have to rely on the `targeted:name` `slot`, `slot:subname` attributes themselves - they would be the ones that would cause the dynamic behavior of the slots. + +--- + +Using `` or simple ``, instead of ``. +The first introduces an unnecessary new basic tag. The second can be confusing. +There is an option with ``. I don't know if it's worth it. + +The `` better reflects a situation where attributes from two elements are combined. + +--- + +Passing more than one `targeted:name` to one target and to `slot:subname`. + +```svelte + + +``` + +```svelte + + +``` + +I don't know if it would be useful for anything, and if it wouldn't cause too much complication. + +--- + +For the reason that in this proposal there is no fallback for the element, only for the content of the element, you can do it. + +```svelte + + + + +``` + +```svelte + +content +``` + +This opens up the chance to use the `let:val` syntax in the other direction. + +```svelte + + + + +``` + +```svelte + +content {val} {val2} +``` + +New special attribute `pass:val="val"`. + +But it is not necessary, because it is possible to pass data through `Child` parameters. + +--- + +If we adopt the syntax `pass:val="val"`, it could also be used instead of the object in `targeted:name={ {val} }`. + +```svelte + + + content {val} {val2} + +``` + +```svelte + + +``` + +--- + +Leaving the fallback element, and passing the content in this complicated and stupid way: + +```svelte + +only content fallback whole element fallback +``` + +I'm writing this just so you know that I have different thoughts. + +--- + +In the comments on the Forward Directive proposal, there is a desire to cross-mix attributes (between `Component` and `element`), but that would be strange. Although sometimes, in special cases, it would look more graceful. + +This is another oddity that I wrote just for the record.