How it works…

Let's create and style a basic component, a colored button, trying to take advantage of as many SASS features as possible. This will be an extreme example, because it's not very likely you'll have such a complex way of creating simple code, but we want to highlight SASS here.

First, the code for the button itself, which we will call SassButton. It has three props: normal (if true, will show normal colors; if false, alert ones); buttonText, which will be displayed by the button; and onSelect, a callback for clicks. I highlighted the CSS-related lines in the following code snippet:

// Source file: /src/components/sassButton/sassButton.js

/* @flow */

import React from "react";
import PropTypes from "prop-types";
import "./styles.css";

export class SassButton extends React.PureComponent<{
normal: boolean,
buttonText: string,
onSelect: void => void
}> {
static propTypes = {
normal: PropTypes.bool.isRequired,
buttonText: PropTypes.string.isRequired,
onSelect: PropTypes.func.isRequired
};

render() {
return (
<div
className={
this.props.normal ? "normalButton" : "alertButton"
}
onClick={this.props.onSelect}
>
<span>{this.props.buttonText}</span>
</div>
);
}
}

Even if working with SASS and .scss files, you'll be importing the preprocessed .css output files, not the .scss original ones. Be careful not to import a .scss file by mistake.

We assume that CSS classes .normalButton and .alertButton do exist; let's now get to creating them. First, let's define a partial SCSS file, _constants.scss, which will define some variables with colors. The filenames of partial files always start with an underscore, and they won't be converted into CSS; rather, they are assumed to be an @import from other SCSS files:

$normalColor: green;
$normalText: yellow;

$alertColor: red;
$alertText: white;

Variables' names start with a dollar sign, and are a very good way to set standard definitions, such as for fonts or colors. If I were to decide that I want to change my normal color to be blue, I would have to change it in just a single place, and it would be replaced everywhere. Note that I could use $normalColor in many places, for backgrounds, texts, and more, and all would be updated with a single edit.

Let's now define some mixins that can be used to include CSS code, even working with parameters. Our darkenBackground() mixin will produce code to set the background-color to a value, and to change the :hover attribute of whatever element it's used in to a 25% darker version. Note the ampersand in &:hover, which stands for the parent element, and also the darken() function, which is just one of many functions that SASS provides, for working with colors, sizes, and so on.

See http://sass-lang.com/documentation/file.SASS_REFERENCE.html#operations for more on this:

@mixin darkenBackground($color) {
background-color: $color;
&:hover {
background-color: darken($color, 25%);
transition: all 0.5s ease;
}
}

@mixin coloredBoldText($color) {
color: $color;
font-weight: bold;
}

Finally, we can build our styles in a styles.scss file. First, we import our partials:

@import "_constants.scss";
@import "_mixins.scss";

Then, to show off other SASS features, let's define a basic placeholder class, %baseButton, that will be extended. The initial % character (similar to class or ID initial characters) means that this code is not meant to be directly used:

%baseButton {
display: inline-block;
text-decoration: none;
padding: 5px 10px;
border-radius: 3px;
}

Now let's extend this base class to create our buttons: we'll use @extend for that, and also @include to add the output of our mixins to the resulting code. We also included some /* ... */ comments, but you can also use // for single-line comments:

/*
A simple button for normal situations
*/
.normalButton {
@extend %baseButton;
@include darkenBackground($normalColor);

span {
@include coloredBoldText($normalText);
}
}

/*
An alert button for warnings or errors
*/
.alertButton {
@extend %baseButton;
@include darkenBackground($alertColor);

span {
@include coloredBoldText($alertText);
}
}

If you are wondering what eventually comes out of all that, the produced styles.css file is as follows: check it out carefully, and you'll see the translated mixins and constants, and also how extended styles are defined, how :hover is used, and so on:

.normalButton, .alertButton {
display: inline-block;
text-decoration: none;
padding: 5px 10px;
border-radius: 3px; }

.normalButton {
background-color: green; }
.normalButton:hover {
background-color: #000100;
transition: all 0.5s ease; }
.normalButton span {
color: yellow;
font-weight: bold; }

.alertButton {
background-color: red; }
.alertButton:hover {
background-color: maroon;
transition: all 0.5s ease; }
.alertButton span {
color: white;
font-weight: bold; }

All we need now is to write a story and check out our buttons in Storybook:

// Source file: /src/components/sassButton/sassButton.story.js

import React from "react";
import { storiesOf } from "@storybook/react";
import { action } from "@storybook/addon-actions";

import { SassButton } from "./";

storiesOf("SASS buttons", module)
.add("normal style", () => (
<SassButton
normal
buttonText={"A normal SASSy button!"}
onSelect={action("click:normal")}
/>
))
.add("alert style", () => (
<SassButton
normal={false}
buttonText={"An alert SASSy button!"}
onSelect={action("click:alert")}
/>
));
When a prop is meant to be true or false, just including its name makes it true. See how in the first story we can just write normal instead of normal={true}; both are equivalent.

We can see the normal button in the following screenshot:

 Our normal button, shown in Storybook

The alert button, with a hovering cursor, is seen in the following screenshot:

 Our alert button, with hovering colors

So, here we have seen a common solution: using SASS to create CSS. In the next section, let's get into a more original way of working, by having the CSS code right within our JS code rather than separated from it!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.40.43