sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
80.26k stars 4.27k forks source link

Multiple components in one file #2940

Closed clitetailor closed 5 years ago

clitetailor commented 5 years ago

What is this: This is a feature request

Description: Sometimes, putting one component per one file is overkill and hard to maintain, especially when you have a lot of components. Use cases:

Allow multiple-component declarations in one file would help a lot.

Proposal Example:

design.svelte

{#def Input}
  <input class="input" {...$$props} />

  <style>
    .input {
      background: blue;
    }
  </style>
{/def}

{#def Button}
  <button class="button" {...$$props}>
    <slot></slot>
  </button>

  <style>
    .button {
      background: blue;
    }
  </style>
{/def}

app.svelte

<Button>Hi</Button>

<script>
  import { Button, Input } from './design.svelte'
</script>
qmzik commented 5 years ago

I like the idea about private components

kylecordes commented 5 years ago

While this would reduce file count on some projects, it would make the syntax of a svelte component/file a bit further from appearing to be just ordinary HTML CSS and JavaScript. It would add another layer of learning complexity, another speed bump to new users.

At the same time, "one file per component" is already substantially more dense and concise than is generally seen in some other SPA frameworks out there (at least if you follow their style guides). Perhaps one file per component is dense enough after all?

bketelsen commented 5 years ago

as a newbie to JS & Svelte, I'd like to add a voice here discouraging extra syntax and confusion for component definition. the reason Svelte is working so well for me is that it's really easy to understand what's happening, and where it's defined. Anything that adds complexity will increase the barriers to adoption. Thanks for listening :)

Conduitry commented 5 years ago

This isn't something we're interested in natively providing in the Svelte compiler. This sounds like something that could be implemented in, for example, a Rollup plugin without a tremendous amount of effort.

PierBover commented 5 years ago

Personally I think Svelte should support multiple components per file. It's very common to need micro components (buttons, etc) for a single use in a view.

Svelte and Vue both have this single file component concept and personally I've found it quite impractical. What happens in practice is that instead of creating new files for these micro components these become part of the template and then the logic becomes a mess.

The fact there is no official solution for this problem is one of the reasons we won't be adopting Svelte. If this was solved in any way, it should be either included in the official compiler or some sort of official plugin/loader/etc. A third party solution to such a central problem would only introduce fragility.

benwinding commented 5 years ago

All these comments are great, but it would be really great if Svelte could support some kind of sub-components or templates.

For example in Angular (bear with me) they have a tag called <ng-template>, which is used to recreate things within the same component, kind of like a private subcomponent...

Would the native html <template> tag be an alternative? Or would that break browser compatibility or something?

antony commented 5 years ago

I have to disagree with @PierBover and @benwinding - it's trivial to create another small file for sub-components - I do this myself, using a parent folder for the main component, and keeping my smaller (sub) compoents folder local to it.

I view the concept of multi-components in a file, and having some sort of extra magic tag as increasing complexity for no real reason.

PierBover commented 5 years ago

I view the concept of multi-components in a file, and having some sort of extra magic tag as increasing complexity for no real reason.

It's not about magic and certainly not "for no real reason". Being able to create multiple components in the same file answers to very pragmatic reasons. It's not even a matter of opinion, in some situations it is objectively faster to work with multiple components in the same file.

Following your workflow of creating a folder. What if you created a component and later on you needed to add another component in it? Now you have to create a folder, move the component there, change your imports in other files, etc. Compare that to just adding another component to the same file which takes seconds.

Not only that but every time you want to work on that view you have to open all those little files in your editor instead of opening a single file. That again takes more time than just opening a single file.

stavalfi commented 5 years ago

we have over 2000 components in our react app. it's not possible to maintain 1500 different files. reducing the amount of files is a requirement for moving from react to selve.

@yinonc

benwinding commented 5 years ago

Ok, after working with svelte for a while I'm officially reversing my opinion on this (I commented above). Components are better off in a SINGLE file

I come from the Angular 2+ world where every component must be added to a module before being used in the parent component. This makes components very heavy weight as you need to change at least 2 places in order to use a component.

Svelte components on the other hand are extremely light-weight and only need to be imported by the component that's using it! So there's no real gain in having it in the same file! except for the fact that it's a private component... which is not the best reason in my opinion

Single file components advantages:

I'm sticking with single file components! :fist_raised:

swyxio commented 5 years ago

kudos for publicly changing your mind :)

PierBover commented 5 years ago

Easier to maintain

I guess it's very subjective but IMO less files and less folders makes projects much easier to navigate and reason about.

Encourage simpler components

I've experienced quite the opposite in Vue. I tended to created fat components since it's quite tedious to create a new component. OTOH it's also true that Vue 2 components have a lot more boilerplate than Svelte 3 components.

Another benefit of having multiple components in the same file is when you have a collection of related components together. It makes it super easy to implement changes in all of those and see how these are related together.

I was very pro Vue single file components and anti JSX a couple of years ago, but after using different libraries and frameworks with JSX on a couple of projects I changed my mind.

Anyway, I won't continue to beat a dead horse...

Cheers!

PaulMaly commented 5 years ago

@clitetailor I know, this is not what you looking for, but maybe it would help a little bit:

./components/design/index.js


export { default as Button } from './components/Button.svelte';
export { default as Input } from './components/Input.svelte';

./components/design/components/Button.svelte

<button class="button" {...$$props}>
  <slot></slot>
</button>

<style>
  .button {
    background: blue;
}
</style>

Usage:

<Button>Hi</Button>

<script>
  import { Button, Input } from './components/design';
</script>
saintech commented 4 years ago

@PaulMaly, does this work OK with SSR in Sapper?

PaulMaly commented 4 years ago

@saintech I believe it should.

droidMakk commented 4 years ago

I have to disagree with @PierBover and @benwinding - it's trivial to create another small file for sub-components - I do this myself, using a parent folder for the main component, and keeping my smaller (sub) compoents folder local to it.

I view the concept of multi-components in a file, and having some sort of extra magic tag as increasing complexity for no real reason.

awkwardly acceptable while trying to maintain a clean code structure.

milahu commented 4 years ago

edit: i have to admit, a top level switch is a bad solution for sub-components

the solution is [``](https://svelte.dev/tutorial/svelte-self) [here](https://svelte.dev/repl/60767c8ddcf54514a582931ff630487a?version=3.24.1) is the repl ```svelte
{#if type == 'main_component'}
main_component
lets include sub_component ....
{:else if type == 'sub_component'}
sub_component on level {level}
{#if level < 4} {/if} {/if}
``` edit: why the downvote? : P i expect a compiler to optimize such dead code .... assuming the dead code is harming performance to optimize such code, we would need "set once" props, like ```js export init set_me_only_once; ``` proposing the new pseudo type `init` behaving similar to the C preprocessor macros `#define` and `#if` edit: we could require a list of constant values, like in a switch statement ```js export init set_me_only_once = ['preset_1', 'preset_2']; ``` currently, this is not optimized by svelte, but by rollup (problem is, rollup is not aware of components?) ```svelte

Hello {name}!

{#if false}
dead code html
{/if} ``` for my [svelte-layout](https://svelte.dev/repl/dea43257dc9c4236b99d4f51dbe222cd?version=3.24.1) i need two large components that differ only in details so im using a `type` prop to switch the component variant to avoid maintaining two components with 90% same code (no, i dont want to use a `shared.js` file) svelte could optimize this with a space-time-tradeoff ("function unswitching") by cloning the component for every init value and optimize each subtype for its init value yay component ~~inheritance~~ unswitching maybe this can be implemented as a preprocessor if svelte allows a preprocessor to create new components (*.svelte files) and transform component calls like `` to `` edit: this probably only makes sense for deep recursion like [`{#if level < 2500}`](https://svelte.dev/repl/fb5ce01040a34e01a3170baf9b24f240?version=3.24.1) ([unswitched](https://svelte.dev/repl/aa0778aecd0f4435acab4726386c4b8f?version=3.24.1)) or calling `` like [50 000 times](https://svelte.dev/repl/37123f27b0bd4a6f9a24609fb30b4b0a?version=3.24.1) ([unswitched](https://svelte.dev/repl/91a1f9e9d9a04f799e2155eefda44fed?version=3.24.1)) cos hot code (like a mousemove handler) can be optimized already and cold code optimization is an unnecessary/premature optimization
judehunter commented 3 years ago

Having worked with Vue on a medium sized project (hundreds of components), I can definitely say I have done exactly what @PierBover described - instead of tediously creating multiple components (so multiple files), I left them as part of the template of the main component, which ultimately led to extremely unmaintainable code.

Now I can't imagine using Vue or Svelte for a bigger project and having thousands of files for every little component. This is where React most certainly has the upper hand.

Now I know Svelte's components are more lightweight than Vue's, but it's still the same problem which leads to such anti-patterns as described above.

milahu commented 3 years ago

assuming we want something like

<!-- App.svelte -->
<script>
  import Widget from './WidgetCollection.svelte';
  let name;
</script>
<div>
  <Widget.Input bind:value={name} />
  <Widget.Output>{name}</Widget.Output>
  <Widget.InputAndOutput />
</div>

and

<!-- WidgetCollection.svelte -->
<!-- proposal of a {#component} block -->
{#component Input}
  <script>
    export let value;
  </script>
  <input bind:value={value} />
{/component}
{#component Output}
  <div class="output"><slot /></div>
{/component}
{#component InputAndOutput}
  <script>
    export let value;
  </script>
  <Input bind:value={value} />
  <Output>{value}</Output>
{/component}

so the WidgetCollection component acts as a namespace that contains multiple sub-components, and inside that namespace, components can call sibling components. (also if they are defined later.) does that make sense?

the sub-components can be defined as static properties like

// WidgetCollection.svelte.js
class WidgetCollection extends SvelteComponent { ... }
WidgetCollection.Input = class Input extends SvelteComponent { ... };
WidgetCollection.Output = class Output extends SvelteComponent { ... };
export default WidgetCollection;

then subcomponent instances can be created like

let input1 = new WidgetCollection.Input();
let input2 = new this.constructor.Input(); // inside a `WidgetCollection` instance

this could be implemented as a bundler plugin

milahu commented 3 years ago

this could be implemented as a bundler plugin

... five hours later, here (diff) is my working prototype. sample input:

<!-- App.svelte -->

{#component SubComponent}
  <script>
    export let value;
  </script>
  <div>
    subcomponent.value = <input bind:value={value} />
  </div>
{/component}

<script>
  let message = 'Hello World';
</script>

<main>
  <div>
    app.message = {message}
  </div>
  <SubComponent bind:value={message} />
</main>

in some cases the svelte runtime says SubComponent is not defined or App is not defined ... just hit reload until it works ; )

KevsRepos commented 3 years ago

@milahu This looks like a good attempt, gotta try that out! like!

JuanDouek commented 3 years ago

What about implementing something like this:

<script>
  import { Button, Input } from './*';
</script>

<Button/>
<Input/>

Because Svelte is a compiler it can be transform into:

<script>
  import Button from './Button.svelte';
  import Input from './Input.svelte';
</script>

Also:

<script>
  import Widgets from './*';
</script>

<Widgets.Button/>
<Widgets.Input/>
alfosua commented 3 years ago

There could be some way to define sub-components and use them in the same file (into the parent component) only. Such sub-component would share the same scope of styling and scripting. They could be called internal templates or just templates. With that, we could reduce code further by pre-configuring.

Example

<!--Form.svelte-->
<script>
export let onAnyInput;

import PublicCustomLabel from './PublicCustomLabel.svelte'
import PublicCustomInput from './PublicCustomInput .svelte';

import { capitalize} from '../logic/strings.js'
import { generateRandomName } from '../logic/random.js'
import { logChangeFor } from '../logic/logging.js';
import { v4 as uuid } from 'uuid';

const secondPrivateFieldProps = {
  id: "field-2",
  name: "second field",
  type: "number",
};

const thirdPrivateFieldProps = createPropsForThirdPrivateField();

function handleSubmit() {
  /* Perform request */
}

function createPropsForThirdPrivateField() {
  return {
     id: `field-3-${uuid4()}`,
     name: generateRandomName (),
     type: 'datetime-local',
     labelClass: 'special-label',
  };
}
</script>

<form on:submit|preventDefault={handleSubmit} />
  <PrivateField id="field-1" name="first field" type="text" inputClass="special-input">Some Text</PrivateField>
  <PrivateField {...secondPrivateFieldProps}>Some Number</PrivateField>
  <PrivateField {...thirdPrivateFieldProps}>capitalize(thirdPrivateFieldProps.name)</PrivateField>
  <button type="submit">Ahoy!</button>
</form>

{#template PrivateField with props={id, labelClass: "common-label", inputClass: "common-input"}}
  <PublicCustomLabel class={props.labelClass} for={props.id}>
    <slot />
  </PublicCustomLabel
  <PrivateCustomeInput {{ ...props, class: props.inputClass }}>
{/template}

{#template PrivateCustomInput with props={id, name, type, class: "common-input"}}
  <PublicCustomInput
    {...props}
    on:input={onAnyInput}
    on:change={() => logChangeFor(props.id, props.name, props.type)}
    >
{/template}

<style>
  .common-input {
    /* Some CSS */
  }
  .special-input {
    /* Some CSS */
  }
  .common-label {
    /* Some CSS */
  }
  .special-label {
    /* Some CSS */
  }
</style>

Then, when I use it:

<!--App.svelte-->
<script>
import Form from './components/Form.svelte';

function handleAnyInput() {
  /* Code to handle any input... */
  /* This event would be triggered by every PrivateCustomInput element into the Form */
}
</script>

<main>
  <Form onAnyInput={handleAnyInput} />
</main>

The Private and Public prefixes are just for making it clear they are as accessible as they say. I don't think it could be very useful to make sub-components public, but if done correctly and in the right circumstances, it could work. If making sub-components public is needed, maybe it should be explicitly specified:

<!--SomeComponent.js-->
{#template SomeSubComponent exported with props}
  <!--Some markup here-->
{/template}

And then:

import { SomeSubComponent } from './components/SomeComponent.svelte';
import SomeComponent from './components/SomeComponent.svelte'; // but still, default export points to parent component

And it would share the same script, style and props that the parent component would do.

Although honestly, if I ever need a file to have several exported components, I think a JavaScript file with some export from statements will do.

/* ComponenCollection.js */
export {default as SomeComponent} from './components/SomeComponent.svelte';
export {default as OtherComponent} from './components/OtherComponent.svelte';
export {default as OneMoreComponent} from './components/OneMoreComponent.svelte';
yahao87 commented 3 years ago

I also suffered a lot in Vue with this problem. As the size of the project grew, more and more files made maintenance difficult. I am sorry that this discussion ended like this. I tried to do Svelte, but gave up because of this problem. I look forward to seeing this discussion resume someday. I will return to React. T.T

milahu commented 3 years ago

I will return to React

solidjs could help

example (playground)

import { render, For } from "solid-js/web";
import { createSignal, children } from "solid-js";
import { createStore } from "solid-js/store";

function Button(props) {
  const getChildren = children(() => props.children);
  const getOnClick = () => props.onClick;
  return (
    <button type="button" onClick={getOnClick()}>
      {getChildren()}
    </button>
  );
}

function App() {
  const [store, setStore] = createStore({ count: 0 });
  const increment = () => {
    setStore('count', store.count + 1);
    console.log(`store.count=${store.count}`);
  };
  return (
    <Button onClick={increment}>
      {store.count}
    </Button>
  );
}

render(() => <App />, document.getElementById("app")!);
ogofe commented 2 years ago

I have to agree with @clitetailor that this feature should be added to Svelte. If you want to stick with single-filed components, I don't see how this would stop you from doing so, but for some of us, it would be really useful to be able to create subcomponents in one file thereby reducing the need for redundant files.

For example, let's I want to create two loading button variations in LoadingButton.svelte one with a circular loader and another with a progress bar beneath, that would mean two files having just a few lines of varying code.

danspinola commented 2 years ago

I agree that multiple components per file are beneficial.

Jojoshua commented 2 years ago

I was also hoping for finding a way to bundle multiple components within a single file @Conduitry . I agree that the typical case 1-1 is sufficient but my reasoning for this feature is so that you can easily read and understand a section of large html in the template.

Splitting it up into modular components would improve readability. Again, this would be for sections that are not large/meaningful enough to live in a new file but when encapsulated provide value for the reader.

KevsRepos commented 2 years ago

Actually, in between, I actually think having multiple components per file is unnecessary. Back then, when I tried to find a solution for that and stumbled across this issue, I was just switching from react to svelte. So I was just used to have multiple components per file, especially react taught me to keep components as small as possible. That is even one recommendation on the react documentation.

So I had the misconception, that a component should really only do one very single thing. A component should be reusable, yes, but that doesnt mean that we must split it up until its so tiny, that it actually becomes unreadable, as you cant see any correlations anymore.

So I got used to single file components and they work perfectly.

subhasishdas159 commented 2 years ago

Really need this feature. It'll allow for more freedom.

vqt123 commented 2 years ago

Bump, would like to be able to define multiple components in one file

nicksulkers commented 2 years ago

I occasionally find myself looking for a feature like this.

Creating many small files for basically just repeated html/css (that are only used in a single component anyway) and having to open them when reading through is kind of a hassle.

If used well, subcomponents could definitely boost productivity and readability.

intensr commented 2 years ago

@clitetailor I know, this is not what you looking for, but maybe it would help a little bit:

./components/design/index.js

export { default as Button } from './components/Button.svelte';
export { default as Input } from './components/Input.svelte';

./components/design/components/Button.svelte

<button class="button" {...$$props}>
  <slot></slot>
</button>

<style>
  .button {
    background: blue;
}
</style>

Usage:

<Button>Hi</Button>

<script>
  import { Button, Input } from './components/design';
</script>

hey this is all i need but it doesnt really work with typescript (index.ts instead of index.js) any clue to get this working with typescript?

gutbk201 commented 2 years ago

I agree support of multiple components in one file, as well as private component. let's replace component by function and think about it.

You need to write a function to do three things, B,C and D. Each thing takes about 20 lines of code.You have three choices of implementation.

  1. write B,C and D into one function.
  2. write functions for each things, ends up three functions in one file.
  3. write one file for one function.

For separate of concerns, the best choice is 2, but you can't pick it. Only 1. and 3. are left. For lazy and convenient, you would pick 1. Drawback is, the function is cumbersome, hard to maintain. Other programmers would have difficulty reading the 60lines of code as well. Since you can't pick option 2., it encourages programmers to do this anyway, as somebody did above.

Let's replace back the term component to function, write one file for one component. Picking option 3, great thing is better code readability.Bad thing is namespace pollution. To write new feature, selecting a right place from nested folders is viable if number of components is below 100. But more than that, the difficulty increases fast. You are likely to search by a key word you known to find the right path. When it's more than 200, you end up searching the right key, it still shows up lots of similar names of file. Imagine what would happen if it's more than 500. Also, number of components increase faster if you follow the rules one component one file and one component do one thing at the same time.

Benefit of private component is, some components are intended to be private, so they don't pollute the namespace, and telling other programmers it only serves locally. In some cases it can be reused as well. Private component has the benefits of option 1 and option 3, a good balance between both.

GermanJablo commented 1 year ago

If you want to stick with single-filed components, I don't see how this would stop you from doing so

+1. I think this should be the focus of the discussion, instead of discussing personal opinions about why you like it or why you don't. Why not allow everyone to do what they want?

lafkpages commented 1 year ago

@stavalfi

moving from react to selve

Bro really said "selve" 💀

sken130 commented 1 year ago

Saying private components is not needed is like saying Java should not have inner classes and C# should not have nested classes. I really hope we can take existing wisdoms, rather than re-experiencing all the frustrations of the lack of inner class/private components and the incomplete alternatives which don't solve all the problems before we finally realize again the feature is needed.

Even only 5% of people have encountered valid use cases for inline components, it's already enough to make it a valid feature.

Also, when persuading other developers and management to adopt a new framework like Svelte instead of React, sometimes, a single downside (apart from ecosystem being small) is enough for them to turn you down, despite having so many other advantages. And the lack of inline components is one of such downsides. This features may look small, but if you need it, then it is a critical feature. I want to use Svelte, but I don't know what argument I could make up for the lack for this feature.

Asking people to go back to React is a lazy argument which makes the competitor happy. Don't you want to win, Svelte?

GermanJablo commented 1 year ago

Proof of concept

I've done a proof of concept of what Svelte might look like if the components were functions instead of files, just like most other frameworks do.

You can see the result here, selecting the "Svelte 2" option above (credit to component-party, this is a fork). I've gotten as far as converting the examples up to the "Slot Fallback" section.

As you can see, in most cases "Svelte 2" has even fewer characters than the official "Svelte" version, without sacrificing its elegant syntax.

The reason why I did this is because I see that the initial proposal of this thread is based on using a wrapper tag for the whole component, and I see that it is something similar to the RFC that the Svelte team has been discussing here. Using a wrapper instead of using functions results in code that is less aesthetic, more verbose, and more detached from most frameworks.

Also, I think it's easier to reason about component properties in terms of function parameters, rather than imports and exports. That's not to mention that in the world of JS, you can export constants or variables. An abstraction that does not translate well to functions.

As an additional note, in the component-party fork I linked to above, I used .jsx for "Svelte 2" solely because the highlighting of the code improves readability. But as you can see, it's not a valid .jsx, it's still using the characteristic Svelte syntax.

Summary of arguments in favor of multiple components per file

This thread already has 38 comments, and the similar RFC I already mentioned has 85 comments. Therefore, I would like to recap the arguments that I consider most relevant to the discussion, and perhaps add a new one.

1. In some situations it is objectively faster to work with multiple components in the same file.

@PierBover 's comment is incredibly well worded. I don't think I can improve on what he said, so I'll quote him:

It's not about magic and certainly not "for no real reason". Being able to create multiple components in the same file answers to very pragmatic reasons. It's not even a matter of opinion, in some situations it is objectively faster to work with multiple components in the same file.

Following your workflow of creating a folder. What if you created a component and later on you needed to add another component in it? Now you have to create a folder, move the component there, change your imports in other files, etc. Compare that to just adding another component to the same file which takes seconds.

Not only that but every time you want to work on that view you have to open all those little files in your editor instead of opening a single file. That again takes more time than just opening a single file.

2. This will not prevent you from continuing to use one component per file

As I and others mentioned above. Even if the previous point was false and having multiple components in the same file was only a matter of opinion and personal taste... that would not prevent you from using one component per file!

I think the personal opinions in this thread about why some people don't like this practice just add noise to the discussion. "Why not allow everyone to do what they want?".

EDIT: Just to be clear. I am not proposing that Svelte leave SFC. The two forms can coexist as it happens with Vuejs

3. Reduction to the absurd.

The following argument I am almost sure I have heard from Dan Abramov and in my words, it goes something like this:

For those who argue that 1 component per file is a good practice, why not use the same logic to do 1 function per file?

If you think about it, a component is actually nothing more than a function. If it was "bad practice to put components in the same file, it would also be bad practice to have JS functions in the same file. Of course, I don't think anyone thinks that.

4. Facilitates migration from other frameworks and enriches the ecosystem.

For many, migrating a project to Svelte is an impediment due to SFCs. Allowing multiple components per file would allow many users to adopt Svelte and others to be happier using it. And even those who do not care about this feature, it would benefit them by increasing the users and therefore the ecosystem.

arkmech commented 1 year ago

Example simplified React example to illustrate concept (These markups have lots of classes or can have multiple elements). This pattern keeps the markup at the end very clean where you only concerned with layout. Components aren't complicated enough for their own file, but complicated enough to be stored in its own variable.

So ya'll telling me that I need to create a separate component for titleMarkup, descriptionMarkup, and actionMarkup?

const Component = (props) => {
  const iconMarkup = iconType === 'default' && props.icon && (
    <Icon size='sm' icon={props.icon} />
  );

  const titleMarkup = title && (
    <TitleTag>
      {title}
    </TitleTag>
  );

  const descriptionMarkup = description && (
    <p>
      {description}
    </p>
  );

  const actionMarkup = primaryActionContent && (
    <Button>
      {primaryActionContent}
    </Button>
  );

  return (
    <div  id={id}>
      {iconMarkup}
      <div>
        <div>
          {titleMarkup}
          {descriptionMarkup}
        </div>
        {actionMarkup}
      </div>
    </div>
  );
arkmech commented 1 year ago

Multiple components per file in some way needs to be implemented. For those that say, we want to keep Svelte simple. Ok, then just don't use the feature when its implemented. For those that want to use the feature, its there when you need it...

Both parties are satisfied if multiple components per file is implemented.

chientrm commented 1 year ago

The best component is no component.

zachlankton commented 1 year ago

This post has inspired me to work on a project. I really love svelte, but I missed JSX and function components, including the ability to have multiple components in a single file.

This project is a work in progress, but thought I would share for anyone who might be interested.

https://github.com/Rezact/Rezact

subhasish-smiles commented 1 year ago

Will be possible with new upcoming svelte 5?

danielo515 commented 1 year ago

People complains about svelte having a lot of syntax already, but that is due to the design decisions made. Svelte thought that custom syntax for things the language can already solve was a great idea, and hence it ended with a lot of syntax that really looks like a niche metalanguage. The reason this why this is trivial in other libraries, not even needing anything from the library itself, just JS syntax, and as oppose in Svelte it will require new syntax is because this decisions, but there is now way back unless they decide to greatly simplify in a future release.

My point is that, Svelte should accept that they require a lot of syntax for things that are trivial in other frameworks, and fulfill the needs of their community. This is a necessity, and many people already explained many reasons. Something as simple as having the same UI section of a component appear in several places already requires this. And no, I don't want to create a separate component and have to come up with a nice name that makes clear it is a internal component and not a general component to use, my IDE does not differentiate, and I don't want to see 5k components when fuzzy jumping to a part of my application.

wporoslo commented 11 months ago

Will be possible with new upcoming svelte 5?

Snippets enable this to some extent https://svelte-5-preview.vercel.app/docs/snippets

At least the "private" component part

Jojoshua commented 9 months ago

Another valid use case for multiple components in single file would be for something like shadcn ui. More specifically shadcn-svelte, where something that should be an easy copy paste now necessitates multiple copy paste files and probably another folder for grouping https://www.shadcn-svelte.com/docs/installation

subhasish-smiles commented 9 months ago

While working with react, I get this freedom. Having multiple components in the same file is definitely a feature I miss working with svelte now. Sometimes I need to define a small component that doesn't need to be put into a separate file of its own. It would be awesome if svelte allows this feature to exist in svelte, Thanks in advance!

nicksulkers commented 9 months ago

While I still appreciate something like function components, I find that Svelte 5 Snippets sufficiently meet my needs. Any component that requires more than a Snippet usually deserves a file of it's own.

WhyFenceCode commented 7 months ago

New Idea: Compile time variant flags/item flagging:

Pros / Cons

Reasons

Downsides

Example Usage Idea:

App.svelte

<script>
    import { Buttons(v1, a2, a3, a4) }  from './Buttons.svelte';
</script>

<Buttons:v1 answer={"Button 1"}></Buttons:v1>
<Buttons:a2:a3 answer={"Button 2"}>Button2</Buttons:a2:a3>
<Buttons:a2:a4 answer={"Button 2"}>Button2</Buttons:a2:a4>

Buttons.svelte

<script>
    export let answer;
</script>

{def:v1}
    <button class="button">{answer}</button>

   <style>
      .button {
           background: blue;
      }
   </style>
{/def}

{def:a2}
    <button class="button">{answer}</button>
    <button class="button">{answer}</button>

{def:a3}
   <style>
      .button {
           background: blue;
      }
   </style>
{/def}
{def:a4}
   <style>
      .button {
           background: blue;
      }
   </style>
{/def}
{/def}

Proposal

Add the def:[id] flag that gets evaluated to multiple versions at compile, with the <[Element]:[id]> getting used in the html to point towards these and resolving to those versions on compile as well. This would allow for complex structures with a complex structure. While there is more syntax in my mind that is trivial.

Final Thing

Should I make this a new issue? It's only partially related, as it has other uses.

Antonio-Bennett commented 7 months ago

@WhyFenceCode make it a new issue for sure