├── .storybook
├── preview-head.html
├── addons.js
└── config.js
├── public
├── favicon.ico
├── manifest.json
└── index.html
├── src
├── index.css
├── images
│ ├── fpo-120x60.png
│ ├── fpo-500x300.png
│ └── fpo-1200x650.png
├── css
│ ├── scss
│ │ ├── abstracts
│ │ │ ├── _mixins.scss
│ │ │ └── _variables.scss
│ │ ├── base
│ │ │ ├── _main.scss
│ │ │ ├── _buttons.scss
│ │ │ ├── _media.scss
│ │ │ ├── _lists.scss
│ │ │ ├── _table.scss
│ │ │ ├── _body.scss
│ │ │ ├── _links.scss
│ │ │ ├── _reset.scss
│ │ │ ├── _headings.scss
│ │ │ ├── _text.scss
│ │ │ └── _forms.scss
│ │ ├── components
│ │ │ ├── _icon.scss
│ │ │ ├── _card.scss
│ │ │ ├── _logo.scss
│ │ │ ├── _card-list.scss
│ │ │ ├── _footer.scss
│ │ │ ├── _header.scss
│ │ │ ├── _page-header.scss
│ │ │ ├── _inline-form.scss
│ │ │ ├── _buttons.scss
│ │ │ ├── _field.scss
│ │ │ ├── _primary-nav.scss
│ │ │ ├── _section.scss
│ │ │ ├── _hero.scss
│ │ │ └── _text-passage.scss
│ │ ├── utilities
│ │ │ └── _visibility.scss
│ │ └── layout
│ │ │ └── _layout.scss
│ ├── style.scss
│ ├── style.css.map
│ └── style.css
├── data
│ └── globals.json
├── index.js
├── App.test.js
├── components
│ ├── TextPassage
│ │ ├── TextPassage.js
│ │ └── TextPassage.stories.js
│ ├── Header
│ │ ├── Header.stories.js
│ │ └── Header.js
│ ├── Footer
│ │ ├── Footer.stories.js
│ │ └── Footer.js
│ ├── Logo
│ │ ├── Logo.js
│ │ └── Logo.stories.js
│ ├── Button
│ │ ├── Button.stories.js
│ │ └── Button.js
│ ├── InlineForm
│ │ ├── InlineForm.stories.js
│ │ └── InlineForm.js
│ ├── Hero
│ │ ├── Hero.stories.js
│ │ └── Hero.js
│ ├── Section
│ │ ├── Section.stories.js
│ │ └── Section.js
│ ├── Card
│ │ ├── Card.stories.js
│ │ └── Card.js
│ ├── PrimaryNav
│ │ ├── PrimaryNav.js
│ │ └── PrimaryNav.stories.js
│ └── CardList
│ │ ├── CardList.js
│ │ └── CardLIst.stories.js
└── App.js
├── .gitignore
├── package.json
└── README.md
/.storybook/preview-head.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradfrost/dumb-react-sass/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/src/images/fpo-120x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradfrost/dumb-react-sass/HEAD/src/images/fpo-120x60.png
--------------------------------------------------------------------------------
/src/images/fpo-500x300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradfrost/dumb-react-sass/HEAD/src/images/fpo-500x300.png
--------------------------------------------------------------------------------
/src/images/fpo-1200x650.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradfrost/dumb-react-sass/HEAD/src/images/fpo-1200x650.png
--------------------------------------------------------------------------------
/src/css/scss/abstracts/_mixins.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #MIXINS
3 | \*------------------------------------*/
4 |
--------------------------------------------------------------------------------
/.storybook/addons.js:
--------------------------------------------------------------------------------
1 | import '@storybook/addon-actions/register';
2 | import '@storybook/addon-links/register';
3 | import '@storybook/addon-knobs/register';
4 |
--------------------------------------------------------------------------------
/src/data/globals.json:
--------------------------------------------------------------------------------
1 | {
2 | "company" : {
3 | "name" : "Company Name",
4 | "url" : "http://companyname.com",
5 | "phone" : "555-555-5555"
6 | }
7 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 |
6 | ReactDOM.render(, document.getElementById('root'));
7 |
--------------------------------------------------------------------------------
/src/css/scss/base/_main.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #MAIN ELEMENT
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Main element
7 | */
8 | [role=main] {
9 | display: block;
10 | padding: 1rem;
11 | }
12 |
--------------------------------------------------------------------------------
/src/css/scss/components/_icon.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #ICON
3 | \*------------------------------------*/
4 |
5 | /**
6 | * 1) Small image that represents functionality
7 | */
8 | .c-icon {
9 | height: 16px;
10 | width: 16px;
11 | }
12 |
--------------------------------------------------------------------------------
/src/css/scss/base/_buttons.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #BUTTONS
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Button and submit inputs reset
7 | * 1) These should be styled using c-btn
8 | */
9 | button {
10 | cursor: pointer;
11 | }
12 |
--------------------------------------------------------------------------------
/src/css/scss/components/_card.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #CARD
3 | \*------------------------------------*/
4 |
5 | .c-card {
6 | border: 1px solid #808080;
7 | padding: 1rem;
8 | }
9 |
10 | .c-card--dark {
11 | background: #000;
12 | color: #fff;
13 | }
--------------------------------------------------------------------------------
/.storybook/config.js:
--------------------------------------------------------------------------------
1 | import { configure } from '@storybook/react';
2 | import '../src/css/style.css';
3 |
4 | const req = require.context("../src/components", true, /.stories.js$/);
5 | function loadStories() {
6 | req.keys().forEach(filename => req(filename));
7 | }
8 |
9 | configure(loadStories, module);
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/src/css/scss/base/_media.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #MEDIA
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Responsive image styling
7 | * 1) Allows for images to flex with varying screen size
8 | */
9 | img {
10 | max-width: 100%;
11 | height: auto;
12 | }
13 |
--------------------------------------------------------------------------------
/src/css/scss/base/_lists.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #LISTS
3 | \*------------------------------------*/
4 |
5 | /**
6 | * 1) List base styles
7 | */
8 |
9 | /**
10 | * Remove list styles from unordered and ordered lists
11 | */
12 | ol, ul {
13 | list-style: none;
14 | }
15 |
--------------------------------------------------------------------------------
/src/css/scss/components/_logo.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #LOGO
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Branding image or text of the site
7 | */
8 | .c-logo {
9 | display: inline;
10 | }
11 |
12 | /**
13 | * Logo image
14 | */
15 | .c-logo__img {
16 | display: block;
17 | }
18 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/TextPassage/TextPassage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export class TextPassage extends Component {
5 | render() {
6 | return (
7 |
8 | { this.props.children }
9 |
10 | );
11 | }
12 | }
13 |
14 | TextPassage.propTypes = {
15 | children: PropTypes.node
16 | }
--------------------------------------------------------------------------------
/src/css/scss/components/_card-list.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #CARD LIST
3 | \*------------------------------------*/
4 |
5 | /**
6 | * 1) A collection of cards displayed as a list or grid
7 | */
8 | .c-card-list {
9 | margin: 0;
10 | padding: 0;
11 | display: grid;
12 | grid-gap: 2rem;
13 | grid-template-columns: repeat(auto-fill, minmax(285px, 1fr));
14 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
23 | *.scssc
24 |
25 | .sass-cache
--------------------------------------------------------------------------------
/src/css/scss/components/_footer.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | $FOOTER
3 | \*------------------------------------*/
4 |
5 | /**
6 | * 1) Global footer at the bottom of each page that contains a navigation and other information.
7 | */
8 | .c-footer {
9 | background: #333;
10 | color: #fff;
11 | padding: 2rem;
12 | }
13 |
14 | .c-footer__copyright {
15 | margin-top: 2rem;
16 | text-align: center;
17 | }
--------------------------------------------------------------------------------
/src/css/scss/base/_table.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #TABLES
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Table
7 | */
8 | table {
9 | border-collapse: collapse;
10 | border-spacing: 0;
11 | width: 100%;
12 | }
13 |
14 | /**
15 | * Table header cell
16 | */
17 | th {
18 | text-align: left;
19 | }
20 |
21 | /**
22 | * Table row
23 | */
24 | tr {
25 | vertical-align: top;
26 | }
27 |
--------------------------------------------------------------------------------
/src/css/scss/components/_header.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #HEADER
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Global block at the top of each page containing the navigation, logo, and other potential utility nav
7 | */
8 | .c-header {
9 | background: #ddd;
10 | padding: 1rem 2rem;
11 | display: grid;
12 | grid-template-columns: 1fr;
13 | grid-auto-flow: column;
14 | gap: 10px;
15 | }
--------------------------------------------------------------------------------
/src/css/scss/components/_page-header.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #PAGE HEADER
3 | \*------------------------------------*/
4 |
5 | /**
6 | * 1) Container that consists of of a page header title and description
7 | */
8 |
9 | /**
10 | * Page header title
11 | */
12 | .c-page-header__title {
13 | margin-bottom: 1rem;
14 | }
15 |
16 | /**
17 | * Page description
18 | */
19 | .c-page-header__desc {
20 | margin-bottom: 2rem;
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/Header/Header.stories.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@storybook/react';
3 | import { withKnobs } from '@storybook/addon-knobs/react';
4 | import { withSmartKnobs } from 'storybook-addon-smart-knobs';
5 | import { Header } from './Header';
6 |
7 | let stories = storiesOf('Global/Header', module);
8 |
9 | stories.addDecorator(withSmartKnobs).addDecorator(withKnobs);
10 |
11 | stories.add('Default', () =>
12 |
13 | );
14 |
--------------------------------------------------------------------------------
/src/css/scss/components/_inline-form.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #INLINE FORM
3 | \*------------------------------------*/
4 |
5 | /**
6 | * 1) An inline form displays an input and a button side-by-side.
7 | * 2) Can be used for search, email newsletter signup, and other one-field forms
8 | */
9 | .c-inline-form {
10 | display: flex;
11 | padding: 0.5rem 0;
12 | }
13 |
14 | .c-inline-form__input {
15 | flex: 1;
16 | padding: 0.5rem;
17 | }
--------------------------------------------------------------------------------
/src/css/scss/base/_body.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #BODY
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Body base styles
7 | * 1) Set the body element's height to at least 100vh of the viewport.
8 | * This is used to achieve a sticky footer
9 | * 2) Prevent Mobile Safari from scaling up text: https://blog.55minutes.com/2012/04/iphone-text-resizing/
10 | */
11 | body {
12 | font-family: sans-serif;
13 | background: #fff;
14 | }
15 |
--------------------------------------------------------------------------------
/src/css/scss/components/_buttons.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #BUTTONS
3 | \*------------------------------------*/
4 |
5 | /**
6 | * 1) Button or link that has functionality to it
7 | */
8 | .c-btn {
9 | background: #333;
10 | color: #fff;
11 | border: 0;
12 | }
13 |
14 | /**
15 | * Secondary button
16 | * 1) Different button style
17 | */
18 | .c-btn--secondary {
19 | background: #eee;
20 | color: #222;
21 | border: 1px solid #eee;
22 | }
--------------------------------------------------------------------------------
/src/css/scss/base/_links.scss:
--------------------------------------------------------------------------------
1 | /*------------------------------------*\
2 | #LINKS
3 | \*------------------------------------*/
4 |
5 | /**
6 | * Link base styles
7 | */
8 | a {
9 | color: $color-gray-73;
10 | text-decoration: none;
11 | outline: 0;
12 | transition: color $anim-fade-quick $anim-ease;
13 |
14 | &:hover, &:focus {
15 | color: $color-gray-50;
16 | }
17 |
18 | &:active {
19 | color: $color-gray-93;
20 | }
21 |
22 | &:visited {
23 | color: $color-gray-93;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/Footer/Footer.stories.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@storybook/react';
3 | import { withKnobs } from '@storybook/addon-knobs/react';
4 | import { withSmartKnobs } from 'storybook-addon-smart-knobs';
5 | import { Footer } from './Footer';
6 |
7 | let stories = storiesOf('Global/Footer', module);
8 |
9 | stories.addDecorator(withSmartKnobs).addDecorator(withKnobs);
10 |
11 | stories.add('Default', () =>
12 |
15 | );
16 |
--------------------------------------------------------------------------------
/src/components/Logo/Logo.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export class Logo extends Component {
5 |
6 | render() {
7 | return (
8 |
9 |
10 |
11 | );
12 | }
13 | }
14 |
15 | Logo.propTypes = {
16 | href: PropTypes.string,
17 | src: PropTypes.string.isRequired,
18 | alt: PropTypes.string.isRequired
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/Logo/Logo.stories.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@storybook/react';
3 | import { withKnobs } from '@storybook/addon-knobs/react';
4 | import { withSmartKnobs } from 'storybook-addon-smart-knobs';
5 | import { Logo } from './Logo';
6 |
7 | import logoimg from '../../images/fpo-120x60.png';
8 |
9 | let stories = storiesOf('Global/Logo', module);
10 |
11 | stories.addDecorator(withSmartKnobs).addDecorator(withKnobs);
12 |
13 | stories.add('Default', () =>
14 |
15 | );
--------------------------------------------------------------------------------
/src/components/Button/Button.stories.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import { storiesOf } from '@storybook/react';
3 | import { withKnobs } from '@storybook/addon-knobs/react';
4 | import { withSmartKnobs } from 'storybook-addon-smart-knobs';
5 | import { Button } from './Button';
6 |
7 | let stories = storiesOf('Buttons/Button', module);
8 |
9 | stories.addDecorator(withSmartKnobs).addDecorator(withKnobs);
10 |
11 | stories.add('Default', () =>
12 |