179 Matching Annotations
  1. Last 7 days
    1. It looks like the issue stems from having "svelte" as a dependency instead of a devDependencies in package.json within the sapper project. This causes import 'svelte' to load the rollup excluded npm package's set_current_component instead of from within the sapper generated server.js.
    1. Most simple example: <script> import ChildComponent from './Child.svelte'; </script> <style> .class-to-add { background-color: tomato; } </style> <ChildComponent class="class-to-add" /> ...compiles to CSS without the class-to-add declaration, as svelte currently does not recognize the class name as being used. I'd expect class-to-add is bundled with all nested style declarations class-to-add is passed to ChildComponent as class-to-add svelte-HASH This looks like a bug / missing feature to me.
    1. I worry about that being a bit of a Pandora's box — it throws encapsulation completely out the window. The nature of CSS custom properties is that they're inert unless the child chooses to do something with them, which wouldn't be the case for other things.
    2. Allow creating custom components with the same abilities as native dom. By all means keep the same level of encapsulation, don't push class on components, but allow a component to mark the class property or another as a CSS Class property, in which case you could pass it through the same transformation that native elements go through
    3. The problem with working around the current limitations of Svelte style (:global, svelte:head, external styles or various wild card selectors) is that the API is uglier, bigger, harder to explain AND it loses one of the best features of Svelte IMO - contextual style encapsulation. I can understand that CSS classes are a bit uncontrollable, but this type of blocking will just push developers to work around it and create worse solutions.
    1. There is a good amount of properties that should mostly be applied from a parent's point of view. We're talking stuff like grid-area in grid layouts, margin and flex in flex layouts. Even properties like position and and the top/right/left/bottom following it in some cases.
    2. Svelte will not offer a generic way to support style customizing via contextual class overrides (as we'd do it in plain HTML). Instead we'll invent something new that is entirely different. If a child component is provided and does not anticipate some contextual usage scenario (style wise) you'd need to copy it or hack around that via :global hacks.
    3. The main reason using classes isn't a great solution is that it completely breaks encapsulation in a confusing way, the paren't shouldn't be dictating anything, the component itself should. The parent can pass things and the child can choose to use them or not but that is different: control is still in the hands of the component itself, not an arbitrary parent.
    4. The RFC is more appropriate because it does not allow a parent to abritrarily control anything below it, that responsibility still relies on the component itself. Just because people have been passing classes round and overriding child styles for years doesn't mean it is a good choice and isn't something we wnat to encourage.
    5. For my point of view, and I've been annoyingly consistent in this for as long as people have been asking for this feature or something like it, style encapsulation is one of the core principles of Svelte's component model and this feature fundamentally breaks that. It would be too easy for people to use this feature and it would definitely get abused removing the style safety that Svelte previously provided.
    6. This allows passing classes to child components with svelte-{hash} through the class prop and prevents removing such classes from css.
    1. The point of the feature is to not rely on the third-party author of the child component to add a prop for every action under the sun. Rather, they could just mark a recipient for actions on the component (assuming there is a viable target element), and then consumers of the library could extend the component using whatever actions they desire.
    2. They don't need to add a prop for every action. The action itself can be passed in as a prop. <script> export let action; </script> <div use:action>whatever</div> The argument for the action can be another prop or can be part of the same prop.
    1. Your tooltip component will have to wrap your image with a span tag or something, it can’t just add events to its children. And if you are adding multiple actions to it you will have to wrap it multiple times.
      <Concern1> <Concern2> </Concern2> </Concern1>

      vs.

      <img use:concern1 use:concern2>

    1. And of course, if you don't use them you don't pay for them
    2. I have created an action for form validation and its really working well
    3. the notion that any given component should be in charge of its own thing, and not do something outside of itself. I.e., loosely coupled components in a sandbox, not tightly coupled to something outside of its own scope.
    4. <slot ref:img data-visible="{{visible}}" /> In the above everything on <slot> is lost since slot is a space in the HTML, not an actual element. How could we translate this to zero or ten elements inside the slot?

      But I think this is a solved problem with current Svelte: just pass the lets to the slot content, and the slot content can decide how to pass those let props on to any or all of its child elements as it sees fit...

    5. the ability to pass around element names as strings in place of components
    1. Since one of Svelte's main principles is reacting only to data changes (as opposed to re-render the whole app with the full state all the time)
    2. I mean, it's not that bad and it's certainly not much of a runtime cost (especially since it'd only affect components which actually use it -- thanks disappearing framework!).

      "disappearing framework"

    3. Re Object.keys(undefined), I think I'm ok with that failing. AFAIK it would also fail in React
    4. The more I think about this, the more I think that maybe React already has the right solution to this particular issue, and we're tying ourselves in knots trying to avoid unnecessary re-rendering. Basically, this JSX... <Foo {...a} b={1} {...c} d={2}/> ...translates to this JS: React.createElement(Foo, _extends({}, a, { b: 1 }, c, { d: 2 })); If we did the same thing (i.e. bail out of the optimisation allowed by knowing the attribute names ahead of time), our lives would get a lot simpler, and the performance characteristics would be pretty similar in all but somewhat contrived scenarios, I think. (It'll still be faster than React, anyway!)
    1. Proving to myself that isValid does correctly change to true even when a key in $errors is an array.

    1. Child can't update things by reassignment if you do:

      <Child bind:things={things} />
      

      but can if you do;

      <Child bind:things={$object.things} />
      
    1. Demonstrates that even though object.value kind of works, it will be out of date. You need to subscribe to it to get current value: $object.value

    1. Forwarding events from the native element through the wrapper element comes with a cost, so to avoid adding extra event handlers only a few are forwarded. For all elements except <br> and <hr>, on:focus, on:blur, on:keypress, and on:click are forwarded. For audio and video, on:pause and on:play are also forwarded.
  2. Sep 2020
    1. I'm personally surprised about that, given the degree to which web component advocates prioritise encapsulation — it seems like a footgun, honestly
    2. Personally, I think class is too blunt an instrument — it breaks encapsulation, allowing component consumers to change styles that they probably shouldn't, while also denying them a predictable interface for targeting individual styles, or setting theme properties globally
    3. ...but ultimately the component itself has control over what is exposed, and can specify its own fallback values using normal CSS custom property syntax:
    1. Proposes a syntax similar to JSX.

      My question would instead be, why not just use JSX for Svelte templates?

    2. The static analysis considerations make things like hero.enemies.map(...) a non-starter — the reason Svelte is able to beat most frameworks in benchmarks is that the compiler has a deep understanding of a component's structure, which becomes impossible when you allow constructs like that.
    1. color: red; //doesn't apply this rule, because scoping doesn't extend to children
    2. Say I want to style this javascript routing anchor tag on various pages (some may be buttons, plain links, images) it makes it incredibly difficult. Eg:
    3. Having to wrap everything in a selector :global(child) { } is hacky
    1. A component should be in complete control of itself. Not only should a component's styles not leak out but other component's style should never leak in. Consider this 'Encapsulation part 2' if you will. When writing a component, you have certain guarantees that not only will the styles you write be contained within the component, but nothing from the outside should affect you either. You have a certain confidence that if it works in isolation, then it will continue to work when embedded within a complex application.
    2. CSS encapsulation is a critical feature of single file components in Svelte; it allows you to think only about the styles that live together in a given component. Managing CSS has long been one of the more challenging aspects of building for the web; we have no desire to bring those problems back via official APIs that encourage the de-scoping of CSS. We do not wish to revisit the age of namespaced CSS selectors and required preprocessors.
    3. Often, allowing the parents to compose elements to be passed into components can offer the flexibility needed to solve this problem. If a component wants to have direct control over every aspect of a component, then it should probably own the markup as well, not just the styles. Svelte's slot API makes this possible. You can still get the benefits of abstracting certain logic, markup, and styles into a component, but, the parent can take responsibility for some of that markup, including the styling, and pass it through. This is possible today.
    4. Svelte is an opinionated tool; it has opinions about how things should be done and what should be allowed. By adding constraints, we have managed to create a simple API and a performant output. These are often conscious decisions: we don't necessarily agree with historic approaches or how other tools are doing things, and we are happy to push back where we think there may be a better way. This is one of those cases, and I feel that context is important here.
    5. The problem with the export { className as class } approach is that the classes defined in the parent/calling component still have to be marked as being global otherwise they get removed.
    1. In my mind, the primary argument for this is that it's a very common thing to need and cleaner than the current alternative of string manipulation or wrapping the child component in a <div class:active><Child /></div>.
    1. Syntax-wise, I would like to be able to pass id, style and class DOM attributes as well as (ideally) svelte props to whatever the slot was replaced with, so prefixing everything with attr in the slot that should be passed sounds like a good idea. Examples: <slot attr:class=“test” attr:class:active={true} /> or <slot attr:style=“color: red” attr:id=“henlo” />
    1. So to experience another change-detector I made a little “sister” of Svelte is Malina.js, which instead of checking if a variable was changed, it checks if a binding was changed (bind-checking). Below are a few examples how it’s better.
    2. Svelte offers an immutable way — but it’s just a mask to hide “assignment”, because assignment triggers an update, but not immutability. So it’s enough to write todos=todos, after that Svelte triggers an update.
    1. Like with React, you can pass in callback props like onSave and onDelete, which is the main way you send data out of a component to a parent.
    2. But if you’ve spent time building front ends with components, it’s hard to go back. Svelte lets us do that with a minimum of fuss or code bloat.
    3. $: declares a relationship, where remaining should always be 10 - count. This might seem weird, but it’s conceptually the same as declaring a variable that you know will be re-calculated in every React render loop — except that remaining will get recalculated only when count changes.
    4. Since you often want to do calculations based on state, Svelte also has the “reactive declaration” symbol, $:. It’s like a let declaration, but whenever any variable referenced in the expression — count in this case — is updated, the expression is re-run, the new variable’s value is updated, and the component is re-rendered.
    5. The heart of Svelte’s magic is “reactivity”. Every let declaration sets up a listener, where any time the variable is assigned to, the change triggers a render of the component. So when the increment function calls count++, the component will re-render, which will update the value shown to the user by Count: {count}.
    1. To change component state and trigger a re-render, just assign to a locally declared variable.
    2. Reactive statements run immediately before the component updates, whenever the values that they depend on have changed.
    3. For interoperability with RxJS Observables, the .subscribe method is also allowed to return an object with an .unsubscribe method, rather than return the unsubscription function directly.
    1. Svelte, on the other hand, is a compiler. In a way, Svelte is more like a programming language than a library.
    2. In most component frameworks, you need to write some code to define your component. With React, the simplest component is an empty function. In other frameworks, you need to import a library and call a special function to define and create your component. With Svelte, you just create a new .svelte file.

      If you compare these two:

      • With React, the simplest component is an empty function.
      • With Svelte, you just create a new .svelte file.

      Creating a new empty function is actually easier/faster than creating and importing a new file. Because you don't have to create a new file just to create a new one-line component. You can create simple helper components within the same file as the main component they help with, and sometimes it is nice to have the flexibility and freedom to compose your files however you want, including the freedom to group multiple closely related components together in the same file.

      In fact one thing I've sometimes found very useful and handy is to be able to define very simple helper components (functions) within the definition of my main component.

      So I would actually put this comparison in the "win" category for React, not Svelte.

    3. With Svelte, components and files have a one-to-one relationship. Every file is a component, and files can't have more than one component. This is generally a "best practice" when using most component frameworks.
    4. Being able to use an empty file as a Svelte component was useful during refactoring, because I could just create a placeholder file for the new component, import it and start using it
    1. You're not limited to using $count inside the markup, either — you can use it anywhere in the <script> as well, such as in event handlers or reactive declarations.

      Don't forget to make the statement reactive. Referencing $count is not enough to get it to be re-run on update!!

      Example:

      $: console.log(`the count is ${$count}`);
      
    1. Stores are global state. While context is local state.
    2. Notice it's not related to components. Another crucial difference is that it's accessible from outside of components. And good way to determine where goes where is to ask yourself, can this particular state and functionality still makes sense outside of the displayed component?
    1. This package exposes an hyperscript compatible function: h(tag, properties, ...children) which returns a svelte component.
    1. In this app, we have a <Hoverable> component that tracks whether the mouse is currently over it. It needs to pass that data back to the parent component, so that we can update the slotted contents. For this, we use slot props.
    1. The previous example contained a default slot, which renders the direct children of a component. Sometimes you will need more control over placement, such as with this <ContactCard>. In those cases, we can use named slots.

      This is a nicer solution than react children props, which is only clean if you pass in a single child.

      The React children prop is an unregulated wild west where people are free to use the prop almost any way they want (including passing in a function).

      I kind of like how Svelte provides a standard, consistent API, which doesn't have the limitations of React childern.