Friends With Benefits

Becoming a Valuable Member of the Sass Community

"It doesn't matter if your code is ugly. Put it out there!"

— Miriam Suzanne, SassConf 2013

Contributing to the Community

Teaches

Inspires

Workshop Goals

  • Write code for an audience

  • Share your code with the world

  • Contribute to other people's projects

Part 1: Github Basics

Getting Started

Download GitHub for Desktop

(And create a GitHub account if you don't have one.)

Install Grunt

npm install -g grunt-cli

What is GitHub?

Git

Track changes to your files

GitHub

Share code & contribute to projects

Git Concepts

Clone

Branch

Commit

Merge

Fork

Clone

Cloning copies a project from GitHub to your computer.

If you're starting a project from scratch, you can create it directly in the GitHub app.

Branch

All code is on a branch, master by default.

Creating a new branch allows you to make changes without affecting other people's work.

All development should be done in a branch other than master.

Commit

Changes you make aren't saved to the branch until you commit them.

Making a commit takes a snapshot of the code. This allows you to see when changes were made and revert your code if needed.

Crafting Commit Messages

  1. Separate the subject from body.

  2. Limit the subject to 50 characters.

  3. Use imperative mood in subject.

    If applied, commit will _____.

  4. Use the body to explain why instead of how.

Merge

Merging combines the code from one branch into another.

Usually you merge code into the master branch, but you can merge into any branch.

Fork

A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project.

A great example of using forks to propose changes is for bug fixes. Rather than logging an issue for a bug you've found, you can:

  • Fork the repository.
  • Make the fix.
  • Submit a pull request to the project owner.

Code Exercise

Cloning the Workshop Repo

  1. Go to the workshop project page:
    https://github.com/timhettler/sassconf-workshop

  2. Follow the instructions in the README

Part 2:
Writing Code for an Audience

The 7 Healthy Habits of an Open Source Sass Developer

Who is Your Audience?

Your Future Self

Teammates / Coworkers

Strangers on the Internet

An Unoptimized Mixin

@mixin fpo() {
  background-color: slategray;
  position: relative;

  &:before {
    content: '';
    display: block;
    padding-bottom: 100%;
  }
  
  &:after {
    content: 'FPO';
    color: #fff;
    font: 20px/1 Helvetica;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

@include fpo();

Habit

Provide arguments for mixins, and give them sensible default values.

Mixin Arguments

Arguments allow you to customize the behavior of a mixin.

@mixin button($bg-color) {
  background-color: $bg-color;
}
.button { @include button(violet); }
.button {
  background-color: violet;
}

Multiple arguments are separated by commas:

@mixin button($bg-color, $text-color: #fff) {
  background-color: $bg-color;
  color: $text-color;
}
.button-1 { @include button(violet);
.button-2 { @include button(violet, black);  }
.button-1 {
  background-color: violet;
  color: #fff;
}

.button-2 {
  background-color: violet;
  color: black;
}

Mixin Arguments, Continued

For truly optional arguments, use null as the default value.

@mixin button($bg-color, $text-color:#FFF, $border: null) {
  background-color: $bg-color;
  color: $text-color;
  border: $border;
}

.button { @include button(#C0FFEE); }

Compiles to:

.button {
  background-color: #C0FFEE;
  color: #FFF;
}

Habit

Favor clarity over brevity in naming anything.

On Naming Things

Clarity over cleverness over brevity

@mixin search($x, $y) { … }
@mixin search($needle, $haystack) { … }
@mixin search($key, $map) { … }

Follow established conventions

@function to-upper-case($string)

Name modularly

$color: #24f089;
$bg-color: #333;
$orange: #fa5400;

$transition: 300ms;
$quick-transition: $transition / 2;

$gutter-width: 50px;
$color--text: #24f089;
$color--bg: #333;
$color--orange: #fa5400;

$timing--default: 300ms;
$timing--quick: $timing--default / 2;

$size--gutter: 50px;

Code Exercise

Abstracting Our Mixin

  1. Create a new branch in your GitHub repo called "fpo-mixin"

  2. Open: sass/_fpo.scss

  3. Add arguments to the mixin for any CSS properties that you think a user would want to change. Make sure to give the arguments default values.

  4. Run grunt server to see your work

  5. Commit your changes, and sync them to GitHub.

@mixin fpo() {
  background-color: slategray;
  position: relative;

  &:before {
    content: '';
    display: block;
    padding-bottom: 100%;
  }
  
  &:after {
    content: 'FPO';
    color: #fff;
    font: 20px/1 Helvetica;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

A Slightly Optimized Mixin

@mixin fpo(
  $size: 100%, $color--bg: slategray, $color--text: #fff, $text: 'FPO'
) {
  background-color: $color--bg;
  position: relative;

  &:before {
    content: '';
    display: block;
    padding-bottom: $size;
  }
  
  &:after {
    content: $text;
    color: $color--text;
    font: 20px/1 Helvetica;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

@include fpo(50%, tomato);

Habit

Allow developers to override default values on a per-project basis.

Guarded Variables

$color--bg: slategray !default;

From the Sass documentation:

You can assign to variables if they aren’t already assigned by adding the !default flag to the end of the value. This means that if the variable has already been assigned to, it won’t be re-assigned, but if it doesn’t have a value yet, it will be given one.

Habit

Namespace your variables to avoid collisions.

Code Exercise

Guarded Variables

  1. Change the default mixin values to be guarded variables.

  2. As always, commit your changes, and sync them to GitHub.


$fpo-color--bg: slategray !default;
             

A Mixin With Namespaced & Guarded Variables

$fpo-size: 100% !default;
$fpo-color--bg: slategray !default;
$fpo-color--text: #fff !default;
$fpo-text: 'FPO' !default;

@mixin fpo(
  $size: $fpo-size, 
  $color--bg: $fpo-color--bg, 
  $color--text: $fpo-color--text, 
  $text: $fpo-text
) {
  …
}

Using Guarded Variables

$fpo-color--bg: tomato;

@import "_fpo.scss";

.dummy-image {
  @include fpo();
}

Habit

Minimize the code you output to CSS.

Code Exercise

Minimizing Filesize

  • Find the parts of the FPO mixin that don't change and move them to a placeholder

  • Use the FPO mixin to extend the placeholder

%fpo {
  …
}

@mixin fpo (…) {
  @extend %fpo;
  …
}

Habit

Anticipate & correct common errors.

Code Exercise

Fixing Common Errors

  • What if the user enters a decimal number instead of a percentage for the size?

  • What if the user wants to use a background gradient, or an image?

Hint: There are built-in Sass functions that can help us

A Super-Optimized Mixin

$fpo-size: 100% !default;
$fpo-bg: slategray !default;
$fpo-color--text: #fff !default;
$fpo-text: 'FPO' !default;

%fpo {
  …
}

@mixin fpo(
  $size: $fpo-size, 
  $bg: $fpo-bg, 
  $color--text: $fpo-color--text, 
  $text: $fpo-text
) {
  @extend %fpo;
  background: $bg;

  &:before {
    padding-bottom: if(unitless($size), percentage($size), $size);
  }
  
  &:after {
    content: $text;
    color: $color--text;
  }
}

@include fpo(0.75, linear-gradient(to bottom, $patina, $midnight-blue));

Habit

Give detailed feedback when a developer messes up.

Feedback Directives

@error
@warn
@debug

Critical Fail

@error "Expected a string, got a number";

Errors stop the Sass compiler completely and sends a message to the user.

Your Attention, Please

@warn "This function will be removed in the next release";

Warnings send a message to the user, but allows Sass to compile.

Good for deprecation notices, best practices, and other non-critical information.

Peeking Under the Hood

@function complicated-math { @return 1+1; }
@debug "The result was: #{complicated-math()}";
//DEBUG: "The results was: 2"

Useful during development to expose values that don't get output to CSS.

Code Exercise

Informing the User

  • Throw an error if the user tries to set $size to something other than a number or percentage.

  • Output the lightness difference between the text color and the background color as a debug statement.

  • Warn the user if a light text color is being used on a light background, or a dark text color is being used on a dark background.

Part 2 Review:

Coding for an audience means:

  • Providing arguments to extend mixin functionality,

  • Giving those arguments default values (that can be overridden),

  • Namespacing variables to avoid naming collisions,

  • Minimizing the size of your output,

  • Anticipating common user errors.

Choosing a License

Without a license, code is protected under copyright law. This means that you retain all rights to your source code and that nobody else may reproduce, distribute, or create derivative works from your work.

The MIT License is the most common license for open source code. it lets people do anything they want with your code as long as they provide attribution back to you and don’t hold you liable.

Learn more about the different types of licenses at choosealicense.com.

Documenting your code with SassDoc

Sassdoc uses special comment conventions ("annotations") to build beautiful & easy to understand documentation.

/// Set an element's height to a percentage of it's width.
/// @arg {Number} $height-ratio [1] - How tall the element should be compared to its width
/// @output An :after pseudo-element with padding-bottom equal to the $height-ratio percentage
@mixin ratioHeight ($height-ratio:1) {
  …
              

Automatically keep documentation up-to-date with the command line tool, or integrations with build systems. (Grunt, Gulp, etc.)

sassdoc src/sass/

Essential Annotations

Variables:

@type

@prop

/// Output a warning if an FPO element is being used
/// @type Bool
$fpo-warn: true !default;

/// Default parameters for the fpo mixin.
/// @type Map
/// @prop {Number} ratio [1] - The height percentage (to be used by ratioHeight)
/// @prop {Color} color [random] - The background color of the element
/// @prop {List} font [bold 20px/1 sans-serif] The font property of the element
/// @prop {String} text [FPO] The text to be displayed in the element
$fpo-defaults: (
  ratio: 1,
  color: rgb(random(255), random(255), random(255)),
  font: bold 20px/1 sans-serif,
  text: 'FPO'
) !default;

Essential Annotations, Continued

Mixins & Functions:

@arg

@outputs / @returns

@example

/// Sets the specified background color and calculates a dark or light contrasted text color
/// @arg {Color} $base - The color to be tested
/// @arg {Color} $dark [$yiq-dark] - The color to return if $base is light
/// @arg {Color} $light [$yiq-light] - The color to return if $base is dark
/// @outputs a background-color/text color combination with proper contrast
/// @example
///   .headline {
///     @include yiq-contrasted(#FA5400, #FFF, #000);
///   }
///   
///   // CSS output:
///   .headline {
///     background-color: #FA5400;
///     color: #FFF;
///   }
@mixin yiq-contrasted(
  $base,
  $dark: $yiq-dark,
  $light: $yiq-light
) {
  …
            

Essential Annotations, Continued

File-Level Annotations:

@group

@author

See the full list on the SassDoc site

////
/// @group Put A Bird On It
/// @author Tim Hettler
////

/// The fill color of the birds.
/// @type Color
$scu-bird-color: #231F20 !default;

/// The size of the element that the birds will be contained in.
/// @type Number
$scu-bird-size: 100px !default;
…
            

Code Exercise

Creating Documentation

  1. Check out the docs-and-tests branch.

  2. Create documentation for the fpo and put-a-bird-on-it modules by adding SassDoc annotations.

  3. View your documentation: grunt sassdoc-server

Viewing Documentation with GitHub Pages

GitHub will generate a site for your project if you create a special branch called
"gh-pages".

You can create your own files, or use GitHub's site generator for quick (and beautiful) results.

Code Exercise

Creating a Project Site

  1. Create a new branch called gh-pages, and sync it to GitHub

  2. View your documentation at
    http://{username}.github.io/sassconf-workshop/sassdoc/

  3. Launch the automatic page generator, found in the repo settings page.

  4. Update the README file with a link to the SassDoc site, and choose a theme for your GitHub Page.

Unit Testing With True

Unit Tests make sure a "unit" of code produces an expected output with a given input.

Functions & Mixins are units of code that can be tested.

Anatomy of a Test

Test Module

A way of grouping similar tests.

The Test & Expectation

The actual code we are testing, and an assumption about what the test should do

Assertion

Does the actual code match the assumption we made?

If working correctly, this unit of code will ___

@include test-module('Example Test') {
  @include test('Invert Color [function]') {
    $test: invert(#000);
    $expect: white;

    @include assert-equal($test, $expect, 'The color should be inverted');
  }

  @include test('Invert Color [mixin]') {
    @include assert('The text color should be the opposite of the background color') {
      @mixin invert ($color) {
        background-color: $color;
        color: invert($color);
      }

      @include input {
        @include invert(#000);
      }

      @include expect {
        background-color: #000;
        color: white;
      }
    }
  }
}

Running Tests

With Ruby Sass

true-cli test/tests.scss

With libSass

Requires a JS test runner (like Mocha) with a shim, and runs as part of your build process.

grunt test

This is not as scary as it sounds.

Code Exercise: Testing Your Code

  1. Open test/tests.scss and create tests for the code you previously created, and the new code in_put-a-bird-on-it.scss.

  2. Run your tests by entering grunt test into the Terminal.

  3. Once your tests run properly, commit your changes and sync them to GitHub.

Advanced Git

Pull Request

Pull Request

Pull Requests start a discussion about the changes you made in a branch.

You're requesting that the project owners "pull" changes from your fork into the main repository.

You can continue making changes to a branch after a pull request has been created.

Pull Request Etiquette

  • Create and issue before submitting a pull request

  • Provide an overview of the work that's being done.

  • @mention people to involve them in the discussion

  • Reference the issue(s) that the pull requests fixes

    Fixes #2

  • Be nice!

Code Exercise

Contributing to an Open Source Project

  1. Fork the SassConf Utility Library to make your own copy of it.

  2. Clone it in GitHub Desktop, and create a new branch called "{your name}-contribution"

  3. Follow the contribution guidelines.

  4. Submit a Pull Request

If your having trouble thinking of contributions, check out the project's issue page.