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

RFC: @inherits for easier composition of multiple styles #633

Closed
tivac opened this issue Jul 3, 2019 · 6 comments · Fixed by #635
Closed

RFC: @inherits for easier composition of multiple styles #633

tivac opened this issue Jul 3, 2019 · 6 comments · Fixed by #635

Comments

@tivac
Copy link
Owner

tivac commented Jul 3, 2019

Feature Use Case

modular-css already supports wildcard values like @value * from "./file.css"; that basically sucks in all values from the specified file and makes them available in the local scope.

Something like that for classes/IDs would be pretty convenient as well.

Feature Proposal

@inherits: "./file-to-inherit-from.css";

/* file-to-inherit-from.css */
.rulea {
    color: red;
}

.ruleb {
    color: blue;
}

/* inheritor.css */
@inherits: "./file-to-inherit-from.css";

.rulec {
    /* no file specifier needed, because of @inherits above .rulea is considered local */
    composes: rulea;
    
    background-color: red;
}

would export

const css = require("./inheritor.css");

// css is
/*
{
    rulea : "abcd123_rulea",
    ruleb : "abcd123_ruleb",
    rulec : "abcd123_rulea dcba_321_rulec"
}
*/
@tivac tivac changed the title Wildcard composes RFC: @inherits for easier composition of multiple styles Jul 3, 2019
@stffrd
Copy link
Contributor

stffrd commented Jul 3, 2019

Is this really any different than:

/* file-to-inherit-from.css */
.rulea {
    color: red;
}

.ruleb {
    color: blue;
}

/* inheritor.css */
.rulec {
    composes: rulea from "./file-to-inherit-from.css";
    
    background-color: red;
}

I guess I'm more curious as to what problem this is trying to solve?

Is it having too many @value statements?
There's a level of explicitness that I really like about mcss, especially knowing if I see a composes key in the wild I can reasonably know almost immediately where it's coming from because it's either composes: thing from "./file.css" or composes: thing from base where base is an @value.

@tivac
Copy link
Owner Author

tivac commented Jul 3, 2019

@stffrd in your example this is the output from the CSS file.

const css = require("./inheritor.css");

//css is
/*
{
    rulec : "abcd123_rulea dcba_321_rulec"
}
*/

if you wanted to also get .rulea and .ruleb in there you would need to do this.

/* inheritor.css */
@value parent: "./file-to-inherit-from.css";

.rulea {
    composes: rulea from parent;
}

.ruleb {
    composes: ruleb from parent;
}

.rulec {
    composes: rulea from parent;
    
    background-color: red;
}

which is already annoying me with 3 rules, and if I imagine 10+ it seems nightmarish.

@stffrd
Copy link
Contributor

stffrd commented Jul 3, 2019

Oh I see. Yeah I can see this being different enough that it'd be useful!

@tivac
Copy link
Owner Author

tivac commented Jul 3, 2019

Feedback from a chat:

not sure about the naming "@inherits". Can you only have a single @inherits? chain inheriting allowed? i feel like you may have some tricky edge cases in implementing this ><

can a parent compose from child file?

I think renaming this is probably a good plan, maybe instead of @inherits it could be @composes. I was originally worried about overloading "composes" but the difference between a property in a rule and a top-level at-rule is probably enough? It does a better job of getting at what this does than @inherits at the very least I think.

Other thoughts based on this feedback:

  • You can only have one @composes per file
  • Each @composes can only reference a single other file
  • Circular dependencies are still not allowed, so you can't do something like have the parent also use composes against a rule in the child. I'm not sure what world that would make much sense in, but the obvious solution to my mind is to move the shared rule out into a separate file that both parent & child can use composes against.

@kevinkace
Copy link
Contributor

Not having to do

.rulea {
    composes: rulea from parent;
}

or

import css from "./index.css";
import css2 from "../../someOtherCss.css";

sounds rad!

@tivac tivac mentioned this issue Jul 3, 2019
10 tasks
tivac added a commit that referenced this issue Jul 4, 2019
tivac added a commit that referenced this issue Jul 4, 2019
@tivac tivac mentioned this issue Jul 4, 2019
9 tasks
tivac added a commit that referenced this issue Jul 4, 2019
@tivac tivac closed this as completed in #635 Jul 6, 2019
tivac added a commit that referenced this issue Jul 6, 2019
Fixes #633 

Adds a new `@composes` at-rule that can be used to include all of the exported classes/compositions from one other file.
@tivac
Copy link
Owner Author

tivac commented Jul 6, 2019

Released in v24.2.0 as @composes, see https://m-css.com/guide#composing-files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants