astroturfcss / astroturf Goto Github PK
View Code? Open in Web Editor NEWBetter Styling through Compiling: CSS-in-JS for those that want it all.
Home Page: https://astroturfcss.github.io/astroturf/
License: MIT License
Better Styling through Compiling: CSS-in-JS for those that want it all.
Home Page: https://astroturfcss.github.io/astroturf/
License: MIT License
New major version of css-loader
has been released 2 days ago. Upon trying it out with astroturf I was getting the following error:
Looks like the option importLoader
that astroturf is passing to css-loader has been renamed.
astroturf is passing:
But the expected options schema has importModules
:
Fixing css-loader to 1.0.1 fixes the problem.
The following code
// styles.js
const Title = styled('div')`
font-size: 20px;
`
const Item = styled('div')`
${Title} {
margin-right: 32px;
}
`
produces css
.styles-Title\.module__cls1___3mrVE {
font-size: 20px;
}
.styles-Item\.module__cls1___29Xnj .styles-Title.module__cls1___3mrVE {
margin-right: 32px;
}
As you can see .styles-Item\.module__cls1___29Xnj .styles-Title.module__cls1___3mrVE
selector only escapes .
in its first part while the interpolated part has it unescaped (while it's still escaped when directly referenced on the first line)
Hi!
Thanks for the best css-in-js library! We're using Component API in our application, and I noticed odd behaviour in a new version: all props matching css classes are passed to DOM elements. As far as I remember astroturf filtered props earlier.
Example:
let Base = styled.div`
position: relative;
…
&.isBig {
size: 32px;
}
`
…
return React.createElement(Base, { isBig }, …)
And now I'm getting:
Warning: React does not recognize the `isBig` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `isbig` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
Is it correct behaviour and we have to filter props manually?
Thanks!
Is it possible to access the template literal expression value?
In this case, I was trying to log plain css to the console, so that the following code:
const margin = 10;
const height = 50;
const styles = css.box { height: ${height}px; margin-bottom: ${margin}px; }
;
console.log(cssOutput)
would output
.box {
height: 50px;
margin-bottom: 10px;
}
Where cssOutput is the expression I'm looking for.
styled-components 4 got cool feature:
const Icon = styled.div`
fill: red;
`
<Icon as={href ? Link : Button} />
Let’s backport it to css-literal-loader’s styled
components
I was under impression that css
api simply produces a bunch of class names that can be used with any (or none) js framework. But looks like there is a hard dependency on React. Why is that? Is there a tool similar to astroturf that is not exclusive to react?
Thanks!
Thank you for such a wonderful tool. There was a need to use it together with the storybook, but I can not understand what the problem is. I use custom settings for webpack
Module not found: Error: Cannot find module '…/node_modules/astroturf/loader.js!/…/node_modules/babel-loader/lib/index.js!/…/node_modules/astroturf/loader.js!/…/node_modules/core-js/modules/web.timers.js'
Function styled from file styled.js takes 3 parameters but type declaration for interface CreateStyled from index.d.ts takes 2 parameters.
Since we've got a lot of new-ish api surface area i thought it would be helpful to maybe talk through a more unified vision and approach. Below are a few API options I think are feasible technically but obviously have some tradeoffs
with the following constraints
Pros
Cons
css
propconst Button = styled.button`
display: inline-block;
&.busy {
background-image: url(...);
}
&.variant-primary {
color: white;
background-color: blue;
}
&.variant-secondary {
color: black;
background-color: palegray;
}
`;
function Button({ variant, ...props }) {
return (
<button
variant={variant}
css={css`
display: inline-block;
&.variant-primary {
color: white;
background-color: blue;
}
&.variant-secondary {
color: black;
background-color: palegray;
}
`}
{...props}
/>
);
}
Pros
Cons
const Button = styled.button`
display: ${p => p.display || 'inline-block'};
&.busy {
background-image: url(...);
}
&.variant-primary {
color: white;
background-color: blue;
}
&.variant-secondary {
color: black;
background-color: palegray;
}
`;
same as above
Pros
Cons
const Button = styled.button`
display: inline-block;
/* this would use css props, but doesn't technically need to. hard to optimize tho*/
background-image: ${p => p.busy && 'url(...)'};
${p =>
p.primary &&
css`
color: white;
background-color: blue;
`}
${p =>
p.secondary &&
css`
color: black;
background-color: palegray;
`}
`;
function Button({ variant, ...props }) {
return (
<button
css={css`
display: inline-block;
${variant === 'primary' &&
css`
color: white;
background-color: blue;
`}
${variant === 'secondary' &&
css`
color: black;
background-color: palegray;
`}
`}
{...props}
/>
);
}
amazing work!
i want use this loader in a side project, but just can't make it work right.
would the doc be more specifically?
install && usage? theme? best practice ...
Hi, it would be nice to have comparison with other zero-runtime css-in-js libs.
Maybe even in README.md.
For example, I have tried linaria — on trivial cases it feels the same. More or less.
But I think there will be differences in big projects, in complex cases;
Why use astroturf? Better performance, better support, some core differences that are invisible from the start? This information may help alot.
Regards.
This is the covention most frameworks seem to be adapting for differentiating css module files nowadays. Using this as the default extension would mean there is no additional css-loader setup for uses in Gatsby, CRA, etc
The first paragraph is critical for open source tool promotion. We spend few days in rewriting main thee first sentence in PostCSS docs.
The current first paragraph is good, but we can do it better:
My first draft (it definitely should be changes, at least English should be fixed):
astroturf is zero-runtime CSS-in-JS. In contrast to styled-components it doesn’t compile CSS in brower. astroturf use Babel to compile styled to static CSS once on deploy for better perfomance. It’s just works with CSS, PostCSS, Less, Sass, or any other css preprocessor, and plays nicely with existing style tooling like mini-css-extract-plugin.
[code example]
astroturf allows you to write CSS in JS files, so have the whole component in the single file. Like CSS Modules it has built-in CSS isolation for better code maintainability.
Preact is a great React alternative for many use cases. It will be nice to have out-of-box support for styled
API.
What do you think about decss project? (syntax sugar over CSS Modules with styled-component’s like React components).
How can I combine decss and css-literar-loader?
I am trying to move my project to your awesome tool. And I miss two methods from styled-components
API:
keyframes
should return @keyframes
with unique name. injectGlobal
should allow to pass CSS without added unique classes.
On a previous project I used https://github.com/TrySound/postcss-inline-svg to inline SVGs.
It would make sense (IMO) for the following to work:
import dropdownIcon from 'url-loader!./assets/icons/dropdown.svg';
css`
.dropdown {
background-image: url(${dropdownIcon});
}
`
Is there any way to make it work? Or have I gotten the definition of "statically analyzable" completely wrong?
I think that we can support Adapting based on props by compiling it to style
prop.
// input
const Color = styled('span')`
color: ${(props) => props.color};
`;
// output
const Color = (props) => {
return (
<span className={...} style={{ color: props.color }}>
{props.children}
</span>
);
}
Hi! Astroturf can work with react-app-rewired and without eject create-react-app?
Hi there 👋
I've been looking through the code (because I want to make something similar to this). Good work here! I'm wondering whether you're handling sourcemaps. Just unsure whether I missed it somewhere or if it isn't supported yet. If it's not, then I may be able to contribute back sometime :)
Project created with CRA, config-overrides
setup:
config.module.rules.push({
test: /\.(js|mjs|jsx|ts|tsx)$/,
use: [
{
loader: 'astroturf/loader',
options: { extension: '.module.css' },
},
],
})
Components code:
export const OptionElement = styled('li')`
padding: 8px 10px;
list-style-type: none;
&:hover {
background-color: red;
}
`
Result CSS:
.OptionElement_option-element__3KySt {
padding: 8px 10px;
list-style-type: none;
(!) &: hover {;
(!) background-color: red;
(!)}: ;
}
I'm looking for css-in-js library for my project, linaria
and astroturf
are in my preference.
astroturf
looks better for me because we already use css modules using .less
.
The problem is when I use { legacy: true }
for @babel/plugin-proposal-decorators
build will crash with error message: AstroTurfLoaderError: Cannot use the decorators and decorators-legacy plugin together
.
My babel config is:
{
presets: [
['@babel/preset-env', {
loose: true,
}],
'@babel/preset-react',
],
plugins: [
'@babel/plugin-syntax-dynamic-import',
[
'@babel/plugin-proposal-decorators',
{ legacy: true },
],
'@babel/plugin-proposal-object-rest-spread',
['@babel/plugin-proposal-class-properties', { loose: true }],
[
'@babel/plugin-transform-runtime',
{
corejs: false,
helpers: true,
regenerator: true,
useESModules: false,
},
],
],
}
What i do wrong?
The code:
import { css } from 'css-literal-loader/styled';
const styles = css`
.demo {
color: hotpink;
}
`;
Error:
Uncaught (in promise) Error: `css` template literal evaluated at runtime!
Are the docs correct? The only thing that's being exported is the following:
First off I'd like to say great work on this library.
Has anyone got the library working with an SSR setup? I'm particularly interested in extracting the CSS for a component into <style> tags in the HTML document.
Additionally does anyone know of an example of code splitting with this library?
Hi! I like you library and have one question:
How I can make css specificity for elements?
For example, I have semantic-ui component with .ui.menu {color: red}
in library css.
If I do something like this, it's don't replace color:
const styles = css`
.replaceColor {
color: green;
}`
.headerMenu-styles_replaceColor__lrgNe
specificity less that .ui.menu
I use little hack for that, add pseudo-class .replaceColor::nth-child(n)
or use repeated class .replaceColor.replaceColor
Maybe you know more elegant solution? Thanks! :)
It would be great to see rollup plugin/loader or example in the docs if it's already possible.
I think React is picking up even on the ref: undefined
.
This has grow past a simple webpack loader! We should pick a proper name any suggestions?
I found good feature in linaria. Source map support should not be so hard if Babel gives you a position for a literal node.
We need:
source-map
(0.7 use async API, if it is a problem, using 0.6 is OK. I still use 0.6 in PostCSS, because we can’t use async API in few places)generator.addMapping
.data:uri
and add to CSS file.I updated astroturf
and got this error during test:
TypeError: Cannot read property 'node' of null
at importNodes.forEach.path (node_modules/astroturf/plugin.js:180:18)
at Array.forEach (<anonymous>)
at PluginPass.post (node_modules/astroturf/plugin.js:175:19)
at transformFile (node_modules/@babel/core/lib/transformation/index.js:94:27)
at runSync (node_modules/@babel/core/lib/transformation/index.js:45:3)
at transformSync (node_modules/@babel/core/lib/transform.js:43:38)
at transform (node_modules/@babel/core/lib/transform.js:22:38)
My Babel config:
{
"presets": [
[
"@babel/preset-env",
{
"loose": true
}
]
],
"plugins": [
"./builder/auto-import",
"babel-plugin-transform-typograf",
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread"
],
"env": {
"test": {
"plugins": [
"babel-plugin-dynamic-import-node",
[
"astroturf/plugin",
{
"allowGlobal": true,
"writeFiles": false
}
],
[
"babel-plugin-transform-rename-import",
{
"replacements": [
{
"original": "^.*\\.(css|less|sss)$",
"replacement": "identity-obj-proxy"
}
]
}
]
]
}
}
}
There is very popular API in Emotion and Styled Components styled.div
instead of styled('div')
.
I pretty sure, that most of Styled Components user will make the mistake and write styled.div
.
Maybe we should improve error message for them? Like:
if (process.env.NODE_ENV !== 'production') {
styled.div = () => {
throw new Error('Use styled("div") instead')
}
}
With process.env.NODE_ENV !== 'production'
we will not increase runtime size in production.
Hi,
I discovered astrotruf via twitter some hours ago and Im very impressed! Great work! 👍
I wonder what would be the best way to add TypeScript definitions. Its somehow different compared to styled-components
.
I guess for the component API something like this would be fine:
const Button = styled<{primary?: boolean; color: 'green'}>('button')`
color: black;
border: 1px solid black;
background-color: white;
&.primary {
color: blue;
border: 1px solid blue;
}
&.color-green {
color: green;
}
` // JSX.IntrinsicElements.button & {primary?: boolean; color: 'green'};
But the css
API gives me a headache:
const styles = css<{box: string; footer: string}>`
.box {
height: ${height}px;
margin-bottom: ${margin}px;
}
.footer {
position: absolute;
top: ${bottom}px;
}
`;
Both way are somehow error prone (what is if I forgot to rename the class inside the tagged string literal?)....
Would be great to start some discussion here :)
Any ideas?
Hi! Can I use reference to other components like in styled-components?
For example:
const Button = styled.button`
color: black;
`;
const Icon = styled.span`
color: yellow;
${Button}:hover & {
color: green;
}
`;
Parcel is a builder with great DX and performance. And it has built-in CSS Modules support too.
Hi! When I run test I recive this error:
FAIL src/Button/tests/Button.test.tsx
● Test suite failed to run
`css` template literal evaluated at runtime!
6 | };
7 |
> 8 | const styles = css`
| ^
9 | .button{
10 | color: red;
11 |
at css (node_modules/astroturf/runtime/styled.js:98:9)
at Object.<anonymous> (src/Button/Button.tsx:8:13)
at Object.<anonymous> (src/Button/tests/Button.test.tsx:3:1)
I think I need to configure transform prop in jest config or modify babel config with test env, but I don't know exactly how. Any ideas?
One of the biggest reason to use styled-components is RN support.
It definitely, should be some CSS→RN loader for webpack. We need only show some example in the docs.
import { css } from 'css-literal-loader/styled'
let styles = css`
.bold {
font-weight: bold;
}
.list {
padding: 8px 0;
}
.item {
padding: 2px 0;
margin-left: 15px;
color: var(--dangerous);
list-style: disc;
}
`
console.log(Object.keys(styles))
Prints []
.
It could be environment or config problem. But I have no idea where I shouls look at.
How to toggle visible ? Like sass example
.parent {
color: red;
.child {
display: none
}
&:hover {
.child {
display: block
}
}
}
Thank you for this!
Any plans to make it support webpack 4? Currently it throws:
ERROR in ./src/components/app.jsx
Module not found: Error: Can't resolve './app__css_literal_loader_0.css'
See 'as' prop example & code example below there seem to be syntax errors & missing code
const mixins = css`
.show {
display: block;
}
`;
const Block = <BlockStyled active={false} />
const BlockStyled = styled.div`
&.active {
composes: ${mixins.show};
}
`;
Styles from mixins apply regardless of active property.
New step in tool promotion is to write an article.
CSS Tricks is a good platform for the first article.
How I see the content:
Unfortunately, I can’t help with writing because I am not native.
Need example with next.js
It really feels like this should work.
At least, I keep typing it on accident.
If you have styled component that accepts bool modifiers, it will strip any boolean prop, not just the relevant ones.
const Foo =({ grow }) => <div>{String(grow)</div>
const StyledFoo = styled(Foo)`
&.bar {
color: red;
}
`
I am using the postcss-loader with the stylelint plugin. When I'm using css-literal-loader I get the following error:
ERROR in ./~/css-loader?modules&camelcase&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./~/postcss-loader!./src/App__css_literal_loader_0.css
Module build failed: Error: ENOENT: no such file or directory, stat '/css-experiments/src/App__css_literal_loader_0.css'
at Error (native)
@ ./src/App__css_literal_loader_0.css 4:14-221 13:2-17:4 13:2-17:4 14:20-227
This could be due to how stylelint works. But it would be a killer feature. This could be considered a feature request. Maybe this can be used as inspiration: https://github.com/styled-components/stylelint-processor-styled-components
Hi.
I want to get classes like Card
and Card--large
.
In the documentation I found an example like this:
const Card = styled('form')`
width: 150px;
height: 120px;
&.large {
width: 300px;
height: 240px;
}
`;
// …
return (<Card large />);
It will generate somethins like this:
<form class="UserCard-Card--3mYhX UserCard-Card--2O_am"></form>
with webpack config
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{
loader: "astroturf/css-loader",
options: {
modules: true,
localIdentName: '[name]--[hash:base64:5]',
},
}
],
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: ['babel-loader', 'astroturf/loader'],
}
]
},
But is there any way to get canonical BEM .Card
and .Card--large
classes?
<form class="Card__3mYhX Card--large__3mYhX"></form>
Regards. Anton.
A major sticking point for people with zero-runtime CSS-in-JS solutions (e.g. css-modules) has been around code-sharing. The import styles from './styles.css';
is problematic since its not a standard node module.
Currently, I see a few (unideal) options:
The benefit of #1
is that your consumers don't have to use css-loader. The downside is they have to manually import your pre-build css file.
@ai and I discussed and a good solution might be a babel version of style-loader. More context: https://twitter.com/lunde_andrews/status/1034116264774516737.
How can I import variables from other files?
I would have something like theme.js:
export default {
primary: '#fff'
}
Then I would import it using import theme from './theme'
and use it with ${theme.primary}
inside my css-literal.
But I always get CssLiteralLoaderError: Could not evaluate css. inline css must be statically analyzable, if I import the css from another file.
Within the same file it works but I would like to share a theme across many css-literal definitions.
Every help is gladly appreciated.
There is a complains that Astroturf uses too many HOCs which create big React tree.
https://twitter.com/oleg008/status/1111215885275017218
Hooks could improve the case
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.