Comments (7)
Importing CSS from URLs is not yet supported directly by the static styles
property. There are ways you could convert a URL to a style sheet object, but none of the ways are particularly ergonomic. Import assertions may in the future help with statically importing CSS files, but I agree that there's going to have to be some stop-gap solution while we wait for the aforementioned feature to stabilize.
That being said, the code style I originally wanted to encourage was a pattern where you write components that come with styles and import them where they're being used. That way, styles are not decoupled from the structure of the component, and the component is always accompanied by the intended styles. So, for example, if you wanted to have a special button that's styled in a particular way, you'd create a StyledButton
and import where it's being used:
export class StyledButton extends Component {
static captureProps = true;
forwardProps = new Ref;
static styles = css`
button {
background: green;
}
`;
template = html`
<button destiny:ref=${this.forwardProps}>
<slot/>
</button>
`
}
and then use it like this:
import { StyledButton } from "./StyledButton.js";
html`
<!-- Other content -->
<${StyledButton}>Click me</${StyledButton}>
`;
However, there are a couple of problems with this:
- This isn't very ergonomic to do. I could work on making it more ergonomic if this is the pattern we want to ultimately encourage. Perhaps something similar to styled-components?
- This doesn't work well for form elements because form-associated custom elements are not yet supported by browsers (planned with P3 in Firefox, implemented in Chromium, planned with P2 in Webkit). Until the feature is supported in all major browsers, there needs to be some other workaround for this use-case.
from destiny.
While this would technically be somewhat trivial to implement, after some deliberation, I'm not convinced it's necessarily a good idea. Encouraging globally declared rules is a little orthogonal to the design of the rest of the library, and kind of defeats the whole point of styles being scoped by the components.
Since this issue was first raised, support for static styles has been added, which allow you to reuse styles:
class Foo extends Component {
static styles = [
myReusedStyles,
css`
/* styles specific to the component */
`,
];
}
It may be less convenient to have to explicitly opt into using the styles you intend to be global in every component, but explicitness tends to make debugging things easier and tends to be less bug prone.
from destiny.
Whilst I didn't know we could do something like [reusableStyles, css...]
Here's my initial thoughts:
Why would people want to use global styles?
-
They have a
global.css
stylesheet, that may give a common style to allinput
element, buttons etc. This isn't really achievable with scoped css because you'd have to rewrite the same CSS (stay with me here) -
Pulling in libraries, eg
<link rel="/public/css/boostrap.min.css">
or pulling it through a CDN
I personally think these are very valid usecases. As of now, they cannot be done. (stay with me...). Which leads me on to...
How can we address those?
- We can address the first point by using the example @0kku has shown in the description of this issue. this could be along the lines of:
// ./public/components/styles.ts
// Instead of your view linking to the css file, that css file is instead converted to a JS exported variabled
import { html } from ...
export const globalStyles = css`
input { color: red }
`
// ./public/components/Chat.ts
import { globalStyles } from ...
class Chat extends Component {
static styles = [
globalStyles,
css`
.some-scoped-elem { ... }
`
]
}
Now I guess this bring a slight problem: every component will have to add this same line. Now is that a bad thing? Maybe it's subjective. So maybe it's down to @0kku as to whether they implement some logic to apply 'global styles' to components, which from what I understand, is considered bad practice: the whole idea of the shadow dom is only scoped css applies.
- I don't believe we can address this already. I believe the only way this would be supported is extra work done by @0kku. I would not know what that work would be,, but the idea would be that global available styles would apply to components. Maybe this can be strict: global available styles imported from a url are only supported? eg bootstrap
from destiny.
I'm guessing there must some some projects (company software, pet projects etc) that use a shadow dom and have a common UI/styling, where styles are shared across components. I'm just curious how they handle it?
from destiny.
I'm guessing there must some some projects (company software, pet projects etc) that use a shadow dom and have a common UI/styling, where styles are shared across components. I'm just curious how they handle it?
I have to admit that I'm not sure what the generally agreed-on way to do this is, but I would guess that the most common pattern is to include a <link rel="stylesheet" href="global-styles.css" />
tag in the component's template. This approach will work with Destiny as well, should you want to use it.
from destiny.
@0kku Wow that is something i've done in other porjects, but completely overlooked regarding this topic for Destiny...
I retract my original opinions and would 100% agree with you, on the fact that buttons, lists etc (any common element) should be a component and used as a 'sub component'.
To be honest, i'd argue it can be ergonomic - after all be it react or destiny, we use components right? You have a 'custom slider component'? or a button? or a form? Thats a component that can accept props (if needed).
Example:
GET /user/new
will display a UsersNew
component. That component will use FormComponent
as a 'child'. You pass in a click ahndler for the submit button. That form component will consist of using input components too
I have to admit that I'm not sure what the generally agreed-on way to do this is, but I would guess that the most common pattern is to include a tag in the component's template. This approach will work with Destiny as well, should you want to use it.
I guess that is a way, but it doesn't feel right, you know? Seems like it does go against the premise of scoped components?
Regarding general styles eg on the body
, or helper classes eg .flex
or .text-align-c
, they could be a reusableStyles
variable
The only thing i'm left thinking about is 'external' styles, again going back to bootstrap (just an example, could be tailwind, literally anything), whether it's in a lib
dir, or you're using a cdn to serve it. And from what you've said, that seems near impossible or not a very ergonomic approach
Maybe this is just a matter discussing how an application would go about using external/third party stylesheets?
from destiny.
After a long convesation with @0kku, re've discovered that using global stylesheets is possible:
abstract class BaseComponent extends Component {
protected html (input: TemplateResult) {
return xml`
<link rel="stylesheet" href="styles.css" />
${input}
`
}
}
class CustomButton extends BaseComponent {
override template = this.html(xml`<button>hello:)</button><p>hi as well</p>`)
}
class AppRoot extends BaseComponent {
override template = this.html(xml`<p>hello</p><${CustomButton} />`)
}
register(AppRoot)
I suggest the above and the notes from #15 (comment) (eg styles = [css'${globalStyles}, css'${thisComponentStyles}']
)
@0kku I'm happy to write work on a write up for this and you could add it to the wiki? afaik outsider contributors can't edit the wiki
from destiny.
Related Issues (20)
- Add withSorted to ReadonlyReactiveArray
- Add withReversed to ReadonlyReactiveArray
- Implement ci
- Reach acceptable test coverage
- Review eslint config
- Investigate use of a formatter
- Review codebase for refactoring opportunities
- Investigate splitting project into DOM and reactivity parts
- Publish preminified/prebundled versions
- Publish on NPM
- Type checking for templates
- Performance regression in slice
- Support reactive arguments in slice
- Investigate perf improvements to flatMap
- Lingering rendering nodes
- ReactiveValues should probably flatten
- ReactiveValue<boolean>::toggle()?
- Implement ReadonlyReactiveArray::groupBy()
- Investigate functional components HOT 5
- Investigate safer "protected" fields
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from destiny.