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

Reusable components for different projects #3000

Closed
elite174 opened this issue Jun 10, 2019 · 23 comments
Closed

Reusable components for different projects #3000

elite174 opened this issue Jun 10, 2019 · 23 comments

Comments

@elite174
Copy link

elite174 commented Jun 10, 2019

I have interesting question about components reusability.

For instance, I have several projects and I also have Button component. Button can be yellow, green, white etc. In one project I need to have green Button, but in another project I need to have yellow Button. Now I can set different styles in Button component (i.e. I can write different styles in <style> tag and then choose the theme of the Button using props

<script>
    export let theme;
</script>

<style>
    .Button_theme_green{
        color: green;
    }

    .Button_theme_red{
        color: red;
    }
</style>

<button class=`Button_theme_${theme}`>Button</button>

, however in this case the Button component becomes heavier than I need (On the page there will be unusable styles). How can I organize the component so that I can have only necessary code (Like modifiers in BEM methodology https://github.com/bem/bem-react/tree/master/packages/core )?

@Conduitry
Copy link
Member

Have you seen #1550 and the discussion there?

@elite174
Copy link
Author

Yes, it's not about theming, it's about reusable and light components

@s0kil
Copy link

s0kil commented Jun 11, 2019

@elite174 I have faced a similar issue and I solved it like this:

Button.svelte

<script>
    export let theme;
</script>

<style>
  button[theme="primary"] {
    background: tomato;
  }

  button[theme="text"] {
    background: blue;
  }
</style>

<button theme={theme}>Button</button>

App.svelte

<script>
    import Button from "./Button.svelte";
</script>

<Button theme="primary" />
<Button theme="text" />

@elite174
Copy link
Author

elite174 commented Jun 11, 2019

@s0kil
You didn't solve the problem, because all the styles are on the page! You only need styles for primary button, if you use only primary theme. Your page shouldn't contain styles for theme=text if you don't use theme=text

@s0kil
Copy link

s0kil commented Jun 11, 2019

@s0kil
You didn't solve the problem, because all the styles are on the page! You only need styles for primary button, if you use only primary theme. Your page shouldn't contain styles for theme=text if you don't use theme=text

Svelte will automatically remove unused styles.

Let's say in one component I use primary theme, and in another text.
Svelte will only include the styles required for each component.

@elite174
Copy link
Author

elite174 commented Jun 11, 2019

@s0kil

Omg
Does it work for classes too?

@s0kil
Copy link

s0kil commented Jun 11, 2019

@elite174 I was wrong, when the attribute is set dynamically, all the styles get included.

Only on static attributes, unused CSS is removed.

<style>
  .primary {
    background: tomato;
  }

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

<!-- `.primary` won't be included in bundle -->
<button class="text">Button</button>

@elite174
Copy link
Author

@elite174 I was wrong, when the attribute is set dynamically, all the styles get included.

Only on static attributes, unused CSS is removed.

<style>
  .primary {
    background: tomato;
  }

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

<!-- `.primary` won't be included in bundle -->
<button class="text">Button</button>

Aha! So my point is that it would be great if there is a mechanism to use only necessary things, because without this features you won't be able to use svelte in a big company that has many projects and one repo with components for all the projects, because the components will be too heavy.

@elite174
Copy link
Author

elite174 commented Jun 11, 2019

So, look at the BEM. I can easily turn my components into "building blocks" and use only necessary things. Svelte doesn't allow to do that.

@s0kil
Copy link

s0kil commented Jun 11, 2019

Here is another option, you could use css-in-js, Here is a blog post by Rich, and using babel-plugin-emotion will remove dead code.

@elite174
Copy link
Author

image

Meh. It doesn't really convenient and doesn't suit for big companies.

@s0kil
Copy link

s0kil commented Jun 11, 2019

I agree, I don't like JS runtime for CSS.
reshadow would be a great solution for this once it supports static style extraction

@elite174
Copy link
Author

Ok, we are talking about css, but there is also functionality issue. For instance, I have basic component and I want to enhance it. I also want several modifications that can be used in composition. Is it possible in svelte?

@s0kil
Copy link

s0kil commented Jun 11, 2019

Ok, we are talking about css, but there is also functionality issue. For instance, I have basic component and I want to enhance it. I also want several modifications that can be used in composition. Is it possible in svelte?

@Conduitry @Rich-Harris

@sahajre
Copy link

sahajre commented Jun 11, 2019

I think in simplistic way what you can use is:

// App.svelte

<svelte:head>
	<link rel="stylesheet" href="theme.green.css">
</svelte:head>

<button class="button_theme">Button</button>
// theme.green.css

.button_theme {
    background-color: green;
}
// theme.red.css

.button_theme {
    background-color: red;
}

Choose the theme you want by including the CSS theme file.

@s0kil
Copy link

s0kil commented Jun 11, 2019

@sahajre That is a decent solution, unless you have a large application, and you actually care about performance.

@slominskir
Copy link

slominskir commented Jun 26, 2019

@sahajre That is a decent solution, unless you have a large application, and you actually care about performance.

What do you mean? Just curious. Are browsers dumb and try to download (and parse) same file multiple times? I thought I read that Chrome attempts to avoid redundant parsing at least (WICG/webcomponents#282 (comment)).

@elite174 Yes, it's not about theming, it's about reusable and light components

Care to elaborate? There is a lot of overlap between theming, styling, and reusable components.

@mjgartendev
Copy link

I've found using functional/atomic classes work better than BEM with the dynamic nature of svelte. E.g., classes like .bg-primary .radius-sm .shadow-md can be defined globally and then dynamically set with something like .bg-{variant} anywhere you need it without even including a style block per component.

You can also set overriding styles on svelte:head or spread an object of conditional classnames pretty easily when needed.

@slominskir
Copy link

Styling custom components is surprisingly complicated, especially if trying to avoid global styles with naming conventions and instead leverage the shadow DOM. Maybe it’s not worth it? First I've got default and core style inside component style block (some of which should not be overridden). Next component is theme-able so needs to respond to a theme stylesheet, which I guess is going to do so via CSS vars since ::part and ::theme aren’t browser ready yet. Finally my components are for a highly configurable user dashboard so a user might override a particular component’s style (say set a specific component background red to call it out). These overrides are probably stored in a database and fed into component as a JSON object and transformed to inline styles on html element style attribute (maybe Constructable Stylesheet can be used instead of JSON / string input once support improves).

@analytically
Copy link

Check out https://tailwindcss.com/

@stalkerg
Copy link
Contributor

stalkerg commented Dec 9, 2019

It's why I am trying to avoid making components for "buttons" and use global styles for common things.
Component styles it mostly for some component-specific things and not about the global theme.
Color of a button it's part of your app theme.

@antony
Copy link
Member

antony commented Feb 18, 2020

There is an RFC for a solution to this here: sveltejs/rfcs#13

In the interim, you can use a global stylesheet as you would with any other project. It has been the conclusion of various discussions that there are no plans to provide unscoped styling from within a component.

I suggest we take discussion of component styling there so that we can draw it to some sort of a conclusion.

@antony antony closed this as completed Feb 18, 2020
@verdulife
Copy link

<script>
    export let theme = { bg: red, txt: white, };
</script>

<button style='background-color: {theme.bg}; color: {theme.txt}'>Button</button>

Good enough?

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

No branches or pull requests

10 participants