{"action":"created","issue":{"url":"https://api.github.com/repos/css-modules/css-modules-loader-core/issues/28","repository_url":"https://api.github.com/repos/css-modules/css-modules-loader-core","labels_url":"https://api.github.com/repos/css-modules/css-modules-loader-core/issues/28/labels{/name}","comments_url":"https://api.github.com/repos/css-modules/css-modules-loader-core/issues/28/comments","events_url":"https://api.github.com/repos/css-modules/css-modules-loader-core/issues/28/events","html_url":"https://github.com/css-modules/css-modules-loader-core/pull/28","id":106220600,"number":28,"title":"Values!","user":{"login":"geelen","id":23264,"avatar_url":"https://avatars.githubusercontent.com/u/23264?v=3","gravatar_id":"","url":"https://api.github.com/users/geelen","html_url":"https://github.com/geelen","followers_url":"https://api.github.com/users/geelen/followers","following_url":"https://api.github.com/users/geelen/following{/other_user}","gists_url":"https://api.github.com/users/geelen/gists{/gist_id}","starred_url":"https://api.github.com/users/geelen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/geelen/subscriptions","organizations_url":"https://api.github.com/users/geelen/orgs","repos_url":"https://api.github.com/users/geelen/repos","events_url":"https://api.github.com/users/geelen/events{/privacy}","received_events_url":"https://api.github.com/users/geelen/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":39,"created_at":"2015-09-13T14:40:56Z","updated_at":"2016-04-20T11:43:42Z","closed_at":"2015-10-21T10:05:30Z","pull_request":{"url":"https://api.github.com/repos/css-modules/css-modules-loader-core/pulls/28","html_url":"https://github.com/css-modules/css-modules-loader-core/pull/28","diff_url":"https://github.com/css-modules/css-modules-loader-core/pull/28.diff","patch_url":"https://github.com/css-modules/css-modules-loader-core/pull/28.patch"},"body":"**EDIT: the final version replaces `@let` and `@import` with, simply, `@value`. See the [postcss-modules-values](https://github.com/css-modules/postcss-modules-values) for more info**\r\n\r\nHey friends, I've got an implementation of a legit extension to CSS Modules that I think we should adopt, fully, in core, and tell people to use it. I.e. this would become the **third of three features** (local scoping & composition are the first two), so this is a **reasonably big change** to our public API.\r\n\r\nBut I think it's the final piece of the puzzle to make CSS Modules _really_ capable of changing the way people structure their CSS.\r\n\r\nI thought I'd start with the syntax I'm proposing. We're totally going to bikeshed these names, but let's do that in a chat room, **not in this issue**. This issue is for discussing whether this deserves to be part of CSS Modules core.\r\n\r\nAnd with that, my proposal:\r\n\r\n---\r\n\r\n## ~~Constants~~ Values\r\n\r\n```css\r\n/* colors.css */\r\n@let primary: #BF4040;\r\n@let secondary: #1F4F7F;\r\n\r\n.text-primary {\r\n  color: primary;\r\n}\r\n\r\n.text-secondary {\r\n  color: secondary;\r\n}\r\n```\r\n\r\n```css\r\n/* breakpoints.css */\r\n@let small: (max-width: 599px);\r\n@let medium: (min-width: 600px) and (max-width: 959px);\r\n@let large: (min-width: 960px);\r\n```\r\n\r\n```css\r\n/* my-component.css */\r\n@let colors: \"./colors.css\";\r\n@import primary, secondary from colors;\r\n@import small as bp-small, large as bp-large from \"./breakpoints.css\";\r\n\r\n.header {\r\n  composes: text-primary from colors;\r\n  box-shadow: 0 0 10px secondary;\r\n}\r\n\r\n@media bp-small {\r\n  .header {\r\n    box-shadow: 0 0 4px secondary;\r\n  }\r\n}\r\n@media bp-large {\r\n  .header {\r\n    box-shadow: 0 0 20px secondary;\r\n  }\r\n}\r\n```\r\n\r\nSo, it breaks down to two things:\r\n\r\n`@let` to declare a constant. It can be one of the following:\r\n- a complex expression in quotes e.g. `\"/path/to/file.css\"`. The quotes are kept, so when this is used, it has to be somewhere that quotes would make sense (i.e. an `@import` or `composes` statement)\r\n- a valid CSS value e.g. `#BF4040` or `inset 0 0 2px 2px black`\r\n- a media expression e.g. `screen and (max-width: 599px)`\r\n\r\n`@import` to import a constant.\r\n- You can give it a local alias `@import theirName as myName`\r\n- You can import multiple on one line `@import a, b from \"./c.css\"`.\r\n- You can use a constant in place of the stringed-path `@let foo: \"./foo.css\"; @import bar from foo;`\r\n\r\nOnce you have your constant defined, it'll be substituted in in one of two places:\r\n- A CSS declaration value: e.g. `box-shadow: 0 0 20px secondary` where `secondary` is a Constant\r\n- A media expression e.g. `@media small` where `small` is a Constant\r\n\r\nOne more thing, for Sass compiler compatibility, both at-rules can be prefixed with a single `-`, so `@-import` and `@-let` will work (`@import` will make Sass try to load a file and your computer will set on fire). And the `@let x: y;` statement doesn't _need_ the `:` in the middle since Sass crashes on that too. I prefer using the `:` (I think it reads better) but Sass folks won't be able to insert it.\r\n\r\n---\r\n\r\n### Rationale\r\n\r\nFirst up, this solves some problems people are having: #25 #33 #36\r\n\r\nIt also completely removes the need for my custom-media PR: #18 \r\n\r\nIt gives the whole system a flexibility we just don't have right now. I mean, none of what we're doing can't be done with other things, like a PostCSS plugin or Sass. But consider the following when you mix & match Sass & CSS Modules:\r\n\r\n```scss\r\n/* vars.scss */\r\n$primary: #BF4040;\r\n$secondary: #1F4F7F;\r\n```\r\n\r\n```scss\r\n/* colors.css */\r\n@import \"./vars\";\r\n\r\n.text-primary {\r\n  color: $primary;\r\n}\r\n\r\n.text-secondary {\r\n  color: $secondary;\r\n}\r\n```\r\n\r\n```scss\r\n/* my-component.scss */\r\n@import \"./vars\";\r\n\r\n.header {\r\n  composes: text-primary from \"./colors.scss\";\r\n  box-shadow: 0 0 10px $secondary;\r\n}\r\n```\r\n\r\nIt works, and I think I'd like to put out a blog post about why you, if you have a big Sass app and want to start using CSS Modules, you should aim to get to here as a stepping-stone, but I think if that's the _only_ way to do anything advanced with CSS Modules it's confusing at best and misleading at worst.\r\n\r\nMy key complaint is that **you're mixing and matching two different ways of including other files**. When you use Sass `@import \"./vars\"`, you're effectively concatenating that file into yours. So if you have any actual CSS markup there (i.e. not just variable definitions) that'll get duplicated through your app. That's because Sass is designed to be a single-global compilation and CSS Modules is a multi-file system. CSS Modules won't inject the same content twice, but if you use Sass `@import` it will. I think we can do better.\r\n\r\nMy other argument is that we have an opportunity here. **If CSS Modules can handle symbol-passing between files, we can totally break our dependency on global preprocessors**. Let's look at the above situation with my Constants proposal:\r\n\r\n\r\n```scss\r\n/* colors.scss */\r\n$primary: #BF4040;\r\n$secondary: #1F4F7F;\r\n\r\n/* We can use Sass to fill these @let declarations */\r\n@let primary $primary; \r\n@let secondary $secondary;\r\n\r\n/* We can get kinda clever with what we export too */\r\n@let secondary-dark darken($secondary, 20%);\r\n\r\n/* And then the rest of the file can be normal Sass */\r\n.text-primary {\r\n  color: $primary;\r\n}\r\n\r\n.text-secondary {\r\n  color: $secondary;\r\n}\r\n```\r\n\r\n```scss\r\n/* my-component.scss */\r\n@-import primary, secondary-dark as secondary from \"./colors.scss\";\r\n\r\n.header {\r\n  composes: text-primary from \"./colors.scss\";\r\n  box-shadow: 0 0 10px secondary;\r\n}\r\n```\r\n\r\nNow, we're still using Sass (as a lot of people will want to do), but **we've made it a single-file preprocessor**. We now use CSS Modules to export information (using `@let`), but we've broken the global shackles of Sass. And, in fact, our component file isn't Sass at all! We're starting to actually use modularity to change the level of abstraction that component authors are working against.\r\n\r\nI believe that by promoting Sass as being the go-to for all the variables, mixins & functions that are missing from CSS Modules is missing a *huge* opportunity to better inform people about the way they can structure the app. By offering Constants, we can say \"sure, use all the Sass you want, but make it compile constants & classes that you can import and compose throughout your application.\" By breaking the old-school idea of files being concatenated together, we get to _truly_ modularise our code.\r\n\r\nThis all applies to PostCSS as well, since they almost all assume they're working on a single global css object. I just think that the unit of \"single global css object\" is now a single file, not the concatenation of many files.\r\n\r\nOh and *one more thing*, this would allow CSS Modules to `@import` constants from, say, a JSON file that's shared between some inline styles and your whole CSS codebase. Some folks have been asking for that, and this would let us offer it.\r\n\r\n---\r\n\r\nAnd just to be clear, I'm proposing adding this and *basically no more*. Beyond this, everything people want to use can live in userland (probably as PostCSS plugins). But at the moment we have no human-accessible way to pass information between files, and I think we need it.\r\n\r\nThoughts?"},"comment":{"url":"https://api.github.com/repos/css-modules/css-modules-loader-core/issues/comments/212392495","html_url":"https://github.com/css-modules/css-modules-loader-core/pull/28#issuecomment-212392495","issue_url":"https://api.github.com/repos/css-modules/css-modules-loader-core/issues/28","id":212392495,"user":{"login":"dimaip","id":837032,"avatar_url":"https://avatars.githubusercontent.com/u/837032?v=3","gravatar_id":"","url":"https://api.github.com/users/dimaip","html_url":"https://github.com/dimaip","followers_url":"https://api.github.com/users/dimaip/followers","following_url":"https://api.github.com/users/dimaip/following{/other_user}","gists_url":"https://api.github.com/users/dimaip/gists{/gist_id}","starred_url":"https://api.github.com/users/dimaip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimaip/subscriptions","organizations_url":"https://api.github.com/users/dimaip/orgs","repos_url":"https://api.github.com/users/dimaip/repos","events_url":"https://api.github.com/users/dimaip/events{/privacy}","received_events_url":"https://api.github.com/users/dimaip/received_events","type":"User","site_admin":false},"created_at":"2016-04-20T11:43:42Z","updated_at":"2016-04-20T11:43:42Z","body":"@HugoGiraudel currently it gets overwritten. To me that's messy and annoying, so I would prefer to have `$red` instead, but that's too late I guess for such discussions."}}