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

Sass port #122

Merged
merged 18 commits into from Dec 27, 2017
Merged

Sass port #122

merged 18 commits into from Dec 27, 2017

Conversation

koester
Copy link
Contributor

@koester koester commented Dec 19, 2017

Brief description 🎉

resolves #33
SCSS Port of PaperCSS

Developer Certificate of Origin

Further details

see #122 (comment)

🎉 🎉 🎉

@rhyneav
Copy link
Member

rhyneav commented Dec 19, 2017

Awesome! It looks like only flexbox, border styles, and tabs are the only things I see in a quick pass through are out of wack. But this is stellar for an initial PR and work in progress on such a major overhaul.

I'll take some time to look through the details, but these are just my initial comments. Great stuff!

@TotomInc
Copy link
Contributor

I agree with @rhyneav, this is a great improvement and thank you for making this!

@koester
Copy link
Contributor Author

koester commented Dec 20, 2017

Thanks 😄 👍

@rhyneav radios and checkboxes are not working as intended, too. I'll get those things out of the way as soon as I can.

Things left to do on my list:

  • Fix the broken components
  • Clean up the code and document the _config with comments (since comments will not get compiled we can use them to document the code without increasing the compiled file size)
  • Look into the tests and see if there is an easy way to transition the existing test from less to sass
  • Prepare the README.md and package.json for a 1.4.0 release

@rhyneav
Copy link
Member

rhyneav commented Dec 20, 2017

That all sounds great! @Fraham will know more about the tests, but I believe they are just testing the compiled CSS. Ideally, the tests should still pass after the refactor without needing to alter the tests.

@MunifTanjim
Copy link
Contributor

Just a suggestion. Can we not put everything in the components folder and make a more reasonable directory structure? @koester

@koester
Copy link
Contributor Author

koester commented Dec 23, 2017

Sure.
Maybe something like this?

/* PaperCSS Core */
@import 'core/config';
@import 'core/reset';

/* Layout Styling */
@import 'layout/flexbox';
@import 'layout/fonts';
@import 'layout/container';
@import 'layout/shadows';
@import 'layout/borders';

/* Components */
@import 'components/forms';
@import 'components/buttons';
@import 'components/lists';
@import 'components/code';
@import 'components/tables';
@import 'components/images';
@import 'components/utilities';
@import 'components/popovers';
@import 'components/cards';
@import 'components/badges';
@import 'components/alerts';
@import 'components/tabs';
@import 'components/article';
@import 'components/modals';

Or do you have a better directory structure in mind?

@koester
Copy link
Contributor Author

koester commented Dec 23, 2017

bc1a02a resolves #120

@TotomInc
Copy link
Contributor

I agree with @MunifTanjim and it's clearly better now. Every framework work like this.

@koester
Copy link
Contributor Author

koester commented Dec 23, 2017

Some numbers after the refactor:

LESS

Build time with gulp build

[10:43:31] Starting 'components'...
[10:43:31] Finished 'components' after 9.86 ms
[10:43:31] Starting 'less'...
[10:43:31] Finished 'less' after 3.66 ms
[10:43:31] Starting 'minify-css'...
[10:43:31] Finished 'minify-css' after 825 μs
[10:43:31] Starting 'build'...
[10:43:31] Finished 'build' after 37 μs

Compiled CSS file size

paper.css: 43,8 kB
paper.min.css: 37,5 kB

SCSS

Build time with gulp build

[10:48:59] Starting 'sass'...
[10:48:59] Finished 'sass' after 9.53 ms
[10:48:59] Starting 'minify-css'...
[10:48:59] Finished 'minify-css' after 273 ms
[10:48:59] Starting 'build'...
[10:48:59] Finished 'build' after 23 μs

Compiled CSS file size

paper.css: 40,6 kB
paper.min.css: 34,4 kB


File size of the compiled css is reduced and the build time is a bit faster than before. 🎉

@MunifTanjim
Copy link
Contributor

@koester Looks great. Maybe we can move things around a little more. e.g.

utilities => shadows, borders
content => code, images, lists, tables, typography

It's up to you.

btw, great work! 👍 😃

@koester
Copy link
Contributor Author

koester commented Dec 23, 2017

Thanks 😄

I added your suggested folder structure and regenerated the package-lock.json for a 1.4.0 release.

@koester
Copy link
Contributor Author

koester commented Dec 27, 2017

After some testing and I'd say the SCSS port looks stable. Everythings working as expected.

SCSS port overview

You can see and test the compiled CSS of this SCSS port at https://deploy-preview-122--astronaut-pig-36111.netlify.com

The refactor for this port got pretty big and the project structure changed quite a bit. I hope this will help maintainers to get a quick overview of the changes and the new additions. Any mentions of 1.4.0 will refer to this SCSS port and 1.3.x to the current LESS version.

Project structure

The structure of the project changed to build upon the modular approach introduced with 1.3.x and further enhance it.

In 1.3.x:

src
├── alerts.less
├── article.less
├── badges.less
├── borders.less
├── boxreset.less
├── buttons.less
├── cards.less
├── code.less
├── colors.less
├── container.less
├── flexbox.less
├── fonts.less
├── forms.less
├── images.less
├── lists.less
├── modals.less
├── popovers.less
├── reset.less
├── shadows.less
├── styles.less
├── tables.less
├── tabs.less
└── utilities.less

0 directories, 23 files

In 1.4.0:

src
├── components
│   ├── _alerts.scss
│   ├── _article.scss
│   ├── _badges.scss
│   ├── _buttons.scss
│   ├── _cards.scss
│   ├── _forms.scss
│   ├── _modals.scss
│   ├── _popovers.scss
│   ├── _tabs.scss
│   └── _utilities.scss
├── content
│   ├── _code.scss
│   ├── _fonts.scss
│   ├── _images.scss
│   ├── _lists.scss
│   └── _tables.scss
├── core
│   ├── _config.scss
│   └── _reset.scss
├── layout
│   ├── _container.scss
│   └── _flexbox.scss
├── utilities
│   ├── _borders.scss
│   └── _shadows.scss
└── styles.scss

5 directories, 22 files

So instead of all .less files in /src we organized the different components and modules into different groups. The entry point for all of those Partials will be styles.scss.

CSS has an import option that lets you split your CSS into smaller, more maintainable portions. The only drawback is that each time you use @import in CSS it creates another HTTP request. Sass builds on top of the current CSS @import but instead of requiring an HTTP request, Sass will take the file that you want to import and combine it with the file you're importing into.

When you import a file you don't need to include the file extension .scss. Sass is smart and will figure it out for you.

When we build the CSS only styles.scss will be compiled. That means the content of this file is directly responsible for the compiled CSS output.

A common problem: Lets say I'm building a wordpress theme and I really like the PaperCSS design of tabs and articles, but dont want to pollute my CSS with all the other components that I will never use. How can we solve this? Easy:

/* PaperCSS core */
@import 'core/config';

/* Utilities */
@import 'utilities/borders';
@import 'utilities/shadows';

/* Components */
@import 'components/article';
@import 'components/tabs';

This will compile only the CSS I really need. If I'm already working with SCSS in my project I could also just @import those files into my existing .scss files and it will just work™.

The other components are still inside the project. But since they are Partials they wont compile into CSS (as long as you dont @import them somewhere).

A partial is simply a Sass file named with a leading underscore. You might name it something like _partial.scss. The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file.

The current project structure is more like a first draft and should be further changed down the road to address our needs. But as it is its working pretty well and should solve most use cases right off the bat.

23 LESS files but only 22 SCSS files??
Great question, mate. colors.less and boxreset.less have been removed. The code of colors.less has moved to core/_config.scss as it was mainly variables used for configuration.boxreset.less has been merged with normalize into core/_reset.scss.

The config

This new core/_config.scss holds pretty much every @mixin and $variable you need to change colors, fonts or build a new feature or component. The variables are set as !default to enable us to overwrite those values, but have a fallback for values that a user didn't change. This could be useful for modular themes. See: #112

Every variable and mixin inside this config will be gloablly accessible from any other component.

Mixins

Mixins in SCSS are not really different from what you know from LESS, except that they provide some added functionality in SCSS. For this refactor I added a bunch of useful mixins. I will explain the important ones as the simple helper mixins like center-all(), hr-after(), or li-buttlet() are pretty self explanatory, I guess.

border-style

/**
  Assign a border style to a component selector.
  @param    integer
  @default  1
*/
@mixin border-style($style: 1) {
  @if $style==1 {
    border-top-left-radius: 255px 15px;
    border-top-right-radius: 15px 225px;
    border-bottom-right-radius: 225px 15px;
    border-bottom-left-radius: 15px 255px;
  }
  @if $style==2 {
    border-top-left-radius: 125px 25px;
    border-top-right-radius: 10px 205px;
    border-bottom-right-radius: 20px 205px;
    border-bottom-left-radius: 185px 25px;
  }
  @if $style==3 {
    border-top-left-radius: 15px 225px;
    border-top-right-radius: 255px 15px;
    border-bottom-left-radius: 225px 15px;
    border-bottom-right-radius: 15px 255px;
  }
  @if $style==4 {
    border-top-left-radius: 15px 225px;
    border-top-right-radius: 25px 150px;
    border-bottom-left-radius: 25px 115px;
    border-bottom-right-radius: 155px 25px;
  }
  @if $style==5 {
    border-top-left-radius: 250px 15px;
    border-top-right-radius: 25px 80px;
    border-bottom-left-radius: 20px 115px;
    border-bottom-right-radius: 15px 105px;
  }
  @if $style==6 {
    border-top-left-radius: 28px 125px;
    border-top-right-radius: 100px 30px;
    border-bottom-right-radius: 20px 205px;
    border-bottom-left-radius: 15px 225px;
  }
}

This mixin is used for the different border styles. It helps us to set the border-style of a component on the fly.

Input:

button,
.paper-btn,
[type="button"] {
  @include border-style();
}

Output:

button,
.paper-btn,
[type="button"] {
  border-top-left-radius: 255px 15px;
  border-top-right-radius: 15px 225px;
  border-bottom-right-radius: 225px 15px;
  border-bottom-left-radius: 15px 255px;
}

The default value is set to 1. You can include this mixin with any number from 1-6 or add a new border-style to the project. This will also ensure that border-styles will always stay consistent throughout the project. If you change any of the border-radius inside this mixin it will reflect for every import its used. I mainly used this for utilities/_borders.scss.

resp

// Responsive breakpoints
$large-screen: 1200px !default;
$medium-screen: 992px !default;
$small-screen: 768px !default;
$xsmall-screen: 480px !default;

/**
  Mixin for setting responsive breakpoints
  @param string | integer
  @default null
*/
@mixin resp($max:null, $min:null) {
  @if $max == large or $max == lg  { $max: $large-screen; }
  @if $max == medium or $max == md { $max: $medium-screen; }
  @if $max == small or $max == sm { $max: $small-screen; }
  @if $max == xsmall or $max == xs { $max: $xsmall-screen; }
  @if ($min != null and $max != null) {@media only screen and (max-width: $max) and (min-width: $min) { @content; }}
  @else if($max != null and $min == null){@media only screen and (max-width: $max) { @content; }}
  @else if($min != null and $max == null){@media only screen and (min-width: $min) { @content; }}
  @else { @error "no matching size found";}
}

Who likes to write those tedious @media only screen and bla bla rules? Nobody. To make working with media-queries great again I wrote this little handy mixin. It also uses the screen-size variables. So instead of writing 768px every time you can just include it with the keyword sm (just like the class names of the flexbox grid) or include it with a px value.

The usage is pretty straight forward:

Input:

.parent {
  width: 50%;

  @include resp(md) {
    width: 25%;
  }

  .custom-breakpoint {
    @include resp(666px) {
      width: 66%;
    }
  }
}

Output:

.parent {
  width: 50%;
}

@media only screen and (max-width: 992px) {
  .parent {
    width: 25%;
  }
}

@media only screen and (max-width: 666px) {
  .parent .custom-breakpoint {
    width: 66%;
  }
}

I already used this mixin to set every responsive breakpoint we need. Another cool side effect that comes with this is that you could change the values of the screen-size variables and it will automagically reflect for the whole project. Your sm breakpoint is not at 768px but 800px? Change the $small-screen variable and it will change for the whole project. Bonus: The flexbox .sm-classes will now use this 800px breakpoint, too. Easy.

shadow

/**
  Set the shadow type for a component
  @param    string
  @default  regular
*/
@mixin shadow($type: regular) {
  @if $type == hover {
    box-shadow: $shadow-hover;
    @include translate(0, 2px);
  } @else if $type == small {
    transition: all .5s ease;
    box-shadow: $shadow-small;
  } @else if $type == regular {
    transition: all .5s ease;
    box-shadow: $shadow-regular;
  } @else if $type == large {
    transition: all .5s ease;
    box-shadow: $shadow-large;
  } @else {
    @error "@mixin shadow(input) does not exist"
  }
}

This is pretty much the same as border-styles(), just for the different shadow types.

Input:

.shadow {
  @include shadow();

  &.shadow-large {
    @include shadow(large);
  }

  &.shadow-small {
    @include shadow(small);
  }

  &.shadow-hover {
    &:hover {
      @include shadow(hover);
    }
  }
}

Output:

.shadow {
  transition: all .5s ease;
  box-shadow: 15px 28px 25px -18px rgba(0, 0, 0, 0.2);
}

.shadow.shadow-large {
  transition: all .5s ease;
  box-shadow: 20px 38px 34px -26px rgba(0, 0, 0, 0.2);
}

.shadow.shadow-small {
  transition: all .5s ease;
  box-shadow: 10px 19px 17px -13px rgba(0, 0, 0, 0.2);
}

.shadow.shadow-hover:hover {
  box-shadow: 2px 8px 8px -5px rgba(0, 0, 0, 0.3);
  -webkit-transform: translate(0, 2px);
  -ms-transform: translate(0, 2px);
  transform: translate(0, 2px);
}

Themes

As mentioned earlier the new approach of this refactor does enable us to do some pretty neat shit. When I saw #112 I immediately thought why not do modular themes?

My idea for this looks something like this:

  • Create a new /themes folder in /src/core or /src/layout.
  • Add a _theme-xyz.scss file and add the new settings there. xyz would be a name for the theme.
  • Include the file inside styles.scss above @import 'core/config' to overwrite the default variables inside the config and have a completely new color scheme in just a few lines of code.
  • ???
  • Profit

To test this idea I created new light-theme branch and added the changes:
https://github.com/koester/papercss/blob/light-theme/src/layout/_theme-light.scss

Thats all the code it takes to change the appearance of every component and it took me about 5 minutes to create this.

Preparations for 1.4.0

I already prepared a few things for a 1.4.0 release:

  • In README.MD: Change every mention of LESS to SCSS
  • Add new Gulp-Sass dependencies and created the gulp task to compile SCSS
  • Bump up package.json version number to 1.4.0 and upadated the package-lock.json

Maybe someone could check the README.md and add a new section with more informations about the scss refactor and the new possibilities (like themes)?

So whats left to do now?
@rhyneav can you merge this into develop to test everything? When the README.md is ready this could be merged into master without problems.

Also: @afzalsayed96 the accordion component should be refactored to SCSS so we don't lose a component on the way. I can do this later today or you could do it yourself to get familiar with the new scss approach.

Any questions left? Ask away, I'm happy to help. 🎉 🎉 👍

@rhyneav
Copy link
Member

rhyneav commented Dec 27, 2017

My jaw is on the floor @koester! Amazing work, and your write up about the changes is pure gold!

I'll spend some time today (now that the holidays are over) going through more of the details, but I think this is just about ready to go!

Once merged into master, I think it would be really interesting if you published a write up on Medium or a blog on how you tackled the refactor from LESS to SCSS. I'd definitely read it, and it might be something worth submitting to freeCodeCamp to publish :)

@rhyneav
Copy link
Member

rhyneav commented Dec 27, 2017

I am seeing no issues with merging this with develop, could you please update the base branch? Since this is the only branch with the port, it doesn't make sense to merge it into papercss:scss-conversion and then develop. Thank you for all of your hard work on this!

The workflow for getting it into master will be

  1. Merge into develop
  2. Create release branch 1.4
  3. Double check everything
  4. Merge into master
  5. Publish to Github and NPM
  6. ???
  7. Profit

@koester koester changed the base branch from scss-conversion to develop December 27, 2017 14:54
@koester koester changed the title [WIP] Sass port Sass port Dec 27, 2017
@rhyneav rhyneav merged commit bc1a02a into papercss:develop Dec 27, 2017
@rhyneav
Copy link
Member

rhyneav commented Dec 27, 2017

And she is merged into develop! I went ahead and got the accordion bits converted as well :)

@koester
Copy link
Contributor Author

koester commented Dec 27, 2017

Ballin

@koester koester deleted the sass-port branch December 30, 2017 11:36
@rhyneav rhyneav mentioned this pull request Jan 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants