-
-
Notifications
You must be signed in to change notification settings - Fork 33
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
[RFC] Pluggable styling API #57
Comments
Following from #122 I can think of 2 places where support needs to be added to allow the developer a possibility to configure things: how styles and class names are generated (a), and to configure which library is rendering the components (b). #122 contains examples of a. Just to generate some conversation, I will provide this example showcasing both: diff --git a/src/components/Composition.tsx b/src/components/Composition.tsx
index c9905d3..dd9c7bf 100644
--- a/src/components/Composition.tsx
+++ b/src/components/Composition.tsx
-const CompositionWrapper = styled.div<CompositionProps>`
- ${applyStyles};
- display: ${({ inline }) => (inline ? 'inline-grid' : 'grid')};
-`
-
-const Composition: React.FunctionComponent<CompositionProps> = ({
- children,
- ...restProps
-}) => {
+const Composition: React.FunctionComponent<CompositionProps> = (props) => {
+ const {
+ children,
+ className,
+ inline,
+ ...restProps
+ } = props
const areaComponents = parseTemplates(restProps)
const hasAreaComponents = Object.keys(areaComponents).length > 0
const childrenType = typeof children
@@ -40,11 +39,18 @@ const Composition: React.FunctionComponent<CompositionProps> = ({
)
return (
- <CompositionWrapper {...restProps}>
+ <Layout.produceComponent.div
+ className={[
+ className,
+ Layout.produceStyles(applyStyles(props)),
+ Layout.produceStyles`display: ${() => (inline ? 'inline-grid' : 'grid')};`
+ ].join(' ')}
+ {...restProps}
+ >
{hasAreaComponents && hasChildrenFunction
? (children as ChildrenFunction)(areaComponents)
: children}
- </CompositionWrapper>
+ </Layout.produceComponent.div>
)
} The component is moved inside render method, which is not good for performance. This was done so that the user can configure the library after imports, as it's confusing for the end dev has to run If it's possible to keep the component back outside the render method whilst ensuring a good dev ex then that would be the approach. |
@bitttttten Hi. I will try to put up an specification of the pluggable styling solution in the description above. Please, I would be thankful for any kind of input from your side! The first question I wonder about is what is the signature of the |
Yeah, I was thinking about styled-components and how their css api does not handle committing styles to the dom like emotion does. Here you can see my test of exactly this. More work needs to be done for styled-components. And I was wondering about your original idea of having pre-defined plugins, especially for the use case of using a different library. I think it's pretty simple. For example, you could do: import { Composition } from 'atomic-layout/emotion' Which looks like: import Layout from './Layout'
import css from 'emotion'
Layout.configure({
produceStyles: (styles, ...rest) => css([styles], ...rest)
})
export default Layout
export { default as Box } from './components/Box'
export { default as Composition } from './components/Composition'
export { default as Only } from './components/Only' Although this does not address any of other benefits, like decoupling atomic layout from a view library, having atomic layout emit CSS for dev's to handle at build time, and so on. It feels like inspiration should be taken from astroturf for that (not api design, but more the philosophy?). (I am in the middle of a long weekend, so hopefully this comment is clear.. also I will probably come back with more feedback later on! 😛 ) |
Hello, @bitttttten. I've established some changes to adopt pluggable styling solution under #145. May I please ask you to checkout that branch and see if it works with |
I've updated the Pluggable styling API request with the specification of the feature. It describes the feature behavior and changes introduces by the pull request. |
Hey @kettanaito, I just wanted to notice that "SSR with no config" benefit that @bitttttten has mentioned in #122 is only present in BTW I just watched "Creating layouts that last". It's a great talk.
Not every CSS-in-JS framework lets you operate on classNames. I wanted to ask, since I experienced that migrations from styled-components to
turns into
|
Hi, @hasparus. Thanks! Indeed, emotion and styled-components share a similar API, that's why emotion support is one of the first on the table to be adopted. Take a look at my comment in the related issue. It describes where styled-components are used. It may be also useful to read through initial emotion support thred. TL;DR I think such support should happen, but it needs to be done properly. My main concern is how to build/distribute such variation of a library. For example, if you would like to use it with emotion, which package should be listed in peer dependencies? Both? It looks like it should be distributed as a separate |
wow! Thanks for quick response and for the link to your previous comment. I think doing similar thing as
I guess people would be fine without @emotion/core in peerDependencies. My reasoning behind it is: If someone is looking for a way to use atomic-layout with Emotion, they probably have Emotion already installed. Swapping import name is a pretty brute way to go, and although it may be a quick win which allows allows introducing atomic-layout to 1.6m weekly downloads of |
Supporting styled-components-like styling solutions by injection of I can imagine that other styling solutions (well, mby except styledjsx or linaria) could be supported with "support/plugin packages". Do you have in mind a list of styling solutions you'd like to support with atomic-layout? |
That's a good reference from rebass, thanks! I reckon import replacement can be done via Rollup directly, but since Atomic Layout already uses Babel, it should be fine as well. The only question I have: where should this replacement happen? The end consumer cannot affect the bundled code, so I suppose it must be done during the library's build. Do you have an idea how the build pipeline would look like in this case?
My dreamland API of such dynamic styling solution would look similar to this: import Layout from 'atomic-layout'
// import styled from 'styled-components'
import styled from '@emotion/styled'
Layout.configure({
produceStyles: styled,
})
I would rather define which styling API Atomic Layout expects, than which libraries it supports. Since now we operate on styled-components-like API, I would stick with it for time being. Which makes styling support narrow down to the following solutions, initially:
When such API expectations are established, we provide a developer with a contract, not a boundaries of a specific dependency. As long as the contract is fulfilled, Atomic Layout (its styling part) works. (Making styled function parametrized also solves the peer dependency issue, as now Atomic Layout won't require any styling peer dependency, but would require the |
The more I think about the monorepo pattern the more it makes sense to be as a library's developer. When each variation of the library is a separate scoped package it can target variantion-specific implementation, dependencies, and test suites without creating a mess. As mentioned previously, the core of the library can be separated into As the library's consumer, however, I feel struggle, as each library's vairant is a separate package. There has to be some naming convetion, like:
Such imports are lengthy, and combined with the library's usage rate in a code base can become irritating quite fast. One can solve that with import resolve alias (in case of webpack), but that's not beginner-friendly in general. |
FYI emotion follows this pattern: import styled, { css } from '@emotion/native'
const Container = styled.View`
display: flex;
justify-content: center;
align-items: center;
margin: 50px;
` https://emotion.sh/docs/@emotion/native I have never used it myself, but the library also exposes a |
@bitttttten thanks for the feedback. The first step to support emotion is coming to an end, I'm yet to verify a few nuances and about to merge. The second step would be to create and publish the actual |
Official Emotion supportAtomic Layout now distributes a dedicated package that supports Emotion, called $ npm install @atomic-layout/emotion @emotion/core @emotion/styled |
Ahh you pulled it off! Congrats ✨ |
What
I propose to establishing a support for different CSS-in-JS libraries to help developers take benefits of Atomic Layout using their favorite styling solution.
Why
Implementation
To enable such support it has been decided to convert the library to a monorepo that consist of the following parts:
@atomic-layout/core
, responsible for media queries calculation, areas parsing, parametric components generation without attachment to any specific styling/rendering solution)@atomic-layout/emotion
)All rendering libraries would list
@atomic-layout/core
as a dependency and utilize functions and types the core library exports.Usage
To use Atomic Layout with another styling solution (implying that such solution is supported) import the respective
@atomic-layout/X
package and use it with the same API described in the documentation:The text was updated successfully, but these errors were encountered: