├── .gitignore ├── LICENSE ├── README.md ├── gatsby-config.js ├── package-lock.json ├── package.json ├── src ├── components │ └── HelloWorld │ │ ├── index.js │ │ ├── index.module.css │ │ └── index.stories.js ├── layouts │ ├── index.css │ └── index.js └── pages │ ├── 404.js │ └── index.js └── storybook ├── addons.js ├── config.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Project dependencies 2 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 3 | node_modules 4 | .cache/ 5 | # Build directory 6 | public/ 7 | .DS_Store 8 | yarn-error.log 9 | yarn.lock 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gatsby-storybook-css-modules 2 | 3 | # UPDATE 4 | 5 | This example is for use with Gatsby v1. If you're using Gatsby v2 you should refer to [Gatsby's docs on using Storybook with Gatsby](https://www.gatsbyjs.org/docs/visual-testing-with-storybook/). 6 | 7 | ## About 8 | An example of using [Gatsby](https://www.gatsbyjs.org) with [Storybook](https://storybook.js.org/) and [CSS Modules](https://github.com/css-modules/css-modules). Based on Gatsby's default starter. 9 | 10 | Storybook is configured to match Gatsby's CSS Modules and cssnext setup. This means that CSS files that end with `.module.css` will be processed as CSS Modules, while all other CSS files will be processed as standard CSS. 11 | 12 | ## Requirements 13 | 14 | Built with: 15 | 16 | - NodeJs v8.5.0 or above 17 | - [Yarn](https://github.com/yarnpkg/yarn) v1.1.0 or above 18 | 19 | > Note: You _must_ use Yarn instead of npm, due to usage of Yarn's alias feature to configure Storybook's dependencies. See https://twitter.com/sebmck/status/873958247304232961?lang=en. 20 | 21 | ## Getting started 22 | 23 | - `yarn` 24 | - `yarn run develop` 25 | - In a different terminal: `yarn run storybook` 26 | 27 | Now you can browse to the Gatsby site and the Storybook on your local machine. 28 | 29 | ## Further info 30 | 31 | This config is a little unusual as Gatsby uses webpack version 1, whereas Storybook uses webpack version 3. This means that the versions of the postcss tools used in Gatsby's webpack config won't run correctly in Storybook's webpack config. 32 | 33 | To work around this, Yarn's [alias feature](https://twitter.com/sebmck/status/873958247304232961?lang=en) is used to install newer versions of these tools for Storybook to use, without overriding the older versions used by Gatsby. Note the following in `package.json`'s dependencies: 34 | 35 | ``` 36 | "postcss-cssnext-3": "npm:postcss-cssnext@3", 37 | "postcss-import-11": "npm:postcss-import@11", 38 | "postcss-loader-2": "npm:postcss-loader@2", 39 | ``` 40 | 41 | This allows Storybook to use these tools in `storybook/webpack.config.js`, as `postcss-loader-2`, `postcss-import-11` and `postcss-cssnext-3` 42 | 43 | > Beware of using cssnext features that are available in cssnext v3 (used in Storybook) and cssnext v2.8 (used in Gatsby). 44 | 45 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Gatsby Default Starter`, 4 | }, 5 | plugins: [`gatsby-plugin-react-helmet`], 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-default", 3 | "description": "Gatsby default starter", 4 | "version": "1.0.0", 5 | "author": "m-allanson", 6 | "dependencies": { 7 | "@storybook/addon-options": "^3.2.12", 8 | "@storybook/react": "^3.2.12", 9 | "gatsby": "^1.9.45", 10 | "gatsby-link": "^1.6.17", 11 | "gatsby-plugin-react-helmet": "^1.0.5", 12 | "imports-loader": "^0.7.1", 13 | "postcss-cssnext-3": "npm:postcss-cssnext@3", 14 | "postcss-import-11": "npm:postcss-import@11", 15 | "postcss-loader-2": "npm:postcss-loader@2", 16 | "react": "15", 17 | "react-dom": "15" 18 | }, 19 | "keywords": [ 20 | "gatsby", 21 | "storybook" 22 | ], 23 | "license": "MIT", 24 | "main": "n/a", 25 | "scripts": { 26 | "build": "gatsby build", 27 | "develop": "gatsby develop", 28 | "storybook": "start-storybook -p 9001 -c storybook", 29 | "format": "prettier --trailing-comma es5 --no-semi --single-quote --write 'src/**/*.js'", 30 | "test": "echo \"Error: no test specified\" && exit 1" 31 | }, 32 | "devDependencies": { 33 | "prettier": "^1.6.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/components/HelloWorld/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import styles from "./index.module.css"; 4 | 5 | const HelloWorld = () => ( 6 |
7 |

Hello,

8 |

world!

9 |
10 | ); 11 | 12 | export default HelloWorld; 13 | -------------------------------------------------------------------------------- /src/components/HelloWorld/index.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | border: 1px solid currentColor; 3 | background-color: pink; 4 | color: hotpink; 5 | margin: 0; 6 | text-align: center; 7 | padding: 5px; 8 | } 9 | 10 | .subHeading { 11 | composes: heading; /* composes is a CSS Modules feature */ 12 | border-top: none; 13 | 14 | & span { /* nesting is a cssnext feature */ 15 | color: rebeccapurple; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/components/HelloWorld/index.stories.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { storiesOf } from "@storybook/react"; 3 | 4 | import HelloWorld from "./"; 5 | 6 | const stories = storiesOf("HelloWorld", module); 7 | 8 | stories.add("Default", () => { 9 | const story = ; 10 | return story; 11 | }); 12 | -------------------------------------------------------------------------------- /src/layouts/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: sans-serif; 3 | -ms-text-size-adjust: 100%; 4 | -webkit-text-size-adjust: 100%; 5 | } 6 | body { 7 | margin: 0; 8 | } 9 | article, 10 | aside, 11 | details, 12 | figcaption, 13 | figure, 14 | footer, 15 | header, 16 | main, 17 | menu, 18 | nav, 19 | section, 20 | summary { 21 | display: block; 22 | } 23 | audio, 24 | canvas, 25 | progress, 26 | video { 27 | display: inline-block; 28 | } 29 | audio:not([controls]) { 30 | display: none; 31 | height: 0; 32 | } 33 | progress { 34 | vertical-align: baseline; 35 | } 36 | [hidden], 37 | template { 38 | display: none; 39 | } 40 | a { 41 | background-color: transparent; 42 | -webkit-text-decoration-skip: objects; 43 | } 44 | a:active, 45 | a:hover { 46 | outline-width: 0; 47 | } 48 | abbr[title] { 49 | border-bottom: none; 50 | text-decoration: underline; 51 | text-decoration: underline dotted; 52 | } 53 | b, 54 | strong { 55 | font-weight: inherit; 56 | font-weight: bolder; 57 | } 58 | dfn { 59 | font-style: italic; 60 | } 61 | h1 { 62 | font-size: 2em; 63 | margin: .67em 0; 64 | } 65 | mark { 66 | background-color: #ff0; 67 | color: #000; 68 | } 69 | small { 70 | font-size: 80%; 71 | } 72 | sub, 73 | sup { 74 | font-size: 75%; 75 | line-height: 0; 76 | position: relative; 77 | vertical-align: baseline; 78 | } 79 | sub { 80 | bottom: -.25em; 81 | } 82 | sup { 83 | top: -.5em; 84 | } 85 | img { 86 | border-style: none; 87 | } 88 | svg:not(:root) { 89 | overflow: hidden; 90 | } 91 | code, 92 | kbd, 93 | pre, 94 | samp { 95 | font-family: monospace, monospace; 96 | font-size: 1em; 97 | } 98 | figure { 99 | margin: 1em 40px; 100 | } 101 | hr { 102 | box-sizing: content-box; 103 | height: 0; 104 | overflow: visible; 105 | } 106 | button, 107 | input, 108 | optgroup, 109 | select, 110 | textarea { 111 | font: inherit; 112 | margin: 0; 113 | } 114 | optgroup { 115 | font-weight: 700; 116 | } 117 | button, 118 | input { 119 | overflow: visible; 120 | } 121 | button, 122 | select { 123 | text-transform: none; 124 | } 125 | [type=reset], 126 | [type=submit], 127 | button, 128 | html [type=button] { 129 | -webkit-appearance: button; 130 | } 131 | [type=button]::-moz-focus-inner, 132 | [type=reset]::-moz-focus-inner, 133 | [type=submit]::-moz-focus-inner, 134 | button::-moz-focus-inner { 135 | border-style: none; 136 | padding: 0; 137 | } 138 | [type=button]:-moz-focusring, 139 | [type=reset]:-moz-focusring, 140 | [type=submit]:-moz-focusring, 141 | button:-moz-focusring { 142 | outline: 1px dotted ButtonText; 143 | } 144 | fieldset { 145 | border: 1px solid silver; 146 | margin: 0 2px; 147 | padding: .35em .625em .75em; 148 | } 149 | legend { 150 | box-sizing: border-box; 151 | color: inherit; 152 | display: table; 153 | max-width: 100%; 154 | padding: 0; 155 | white-space: normal; 156 | } 157 | textarea { 158 | overflow: auto; 159 | } 160 | [type=checkbox], 161 | [type=radio] { 162 | box-sizing: border-box; 163 | padding: 0; 164 | } 165 | [type=number]::-webkit-inner-spin-button, 166 | [type=number]::-webkit-outer-spin-button { 167 | height: auto; 168 | } 169 | [type=search] { 170 | -webkit-appearance: textfield; 171 | outline-offset: -2px; 172 | } 173 | [type=search]::-webkit-search-cancel-button, 174 | [type=search]::-webkit-search-decoration { 175 | -webkit-appearance: none; 176 | } 177 | ::-webkit-input-placeholder { 178 | color: inherit; 179 | opacity: .54; 180 | } 181 | ::-webkit-file-upload-button { 182 | -webkit-appearance: button; 183 | font: inherit; 184 | } 185 | html { 186 | font: 112.5%/1.45em georgia, serif; 187 | box-sizing: border-box; 188 | overflow-y: scroll; 189 | } 190 | * { 191 | box-sizing: inherit; 192 | } 193 | *:before { 194 | box-sizing: inherit; 195 | } 196 | *:after { 197 | box-sizing: inherit; 198 | } 199 | body { 200 | color: hsla(0, 0%, 0%, 0.8); 201 | font-family: georgia, serif; 202 | font-weight: normal; 203 | word-wrap: break-word; 204 | font-kerning: normal; 205 | -moz-font-feature-settings: "kern", "liga", "clig", "calt"; 206 | -ms-font-feature-settings: "kern", "liga", "clig", "calt"; 207 | -webkit-font-feature-settings: "kern", "liga", "clig", "calt"; 208 | font-feature-settings: "kern", "liga", "clig", "calt"; 209 | } 210 | 211 | img { 212 | max-width: 100%; 213 | margin-left: 0; 214 | margin-right: 0; 215 | margin-top: 0; 216 | padding-bottom: 0; 217 | padding-left: 0; 218 | padding-right: 0; 219 | padding-top: 0; 220 | margin-bottom: 1.45rem; 221 | } 222 | h1 { 223 | margin-left: 0; 224 | margin-right: 0; 225 | margin-top: 0; 226 | padding-bottom: 0; 227 | padding-left: 0; 228 | padding-right: 0; 229 | padding-top: 0; 230 | margin-bottom: 1.45rem; 231 | color: inherit; 232 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 233 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 234 | font-weight: bold; 235 | text-rendering: optimizeLegibility; 236 | font-size: 2.25rem; 237 | line-height: 1.1; 238 | } 239 | h2 { 240 | margin-left: 0; 241 | margin-right: 0; 242 | margin-top: 0; 243 | padding-bottom: 0; 244 | padding-left: 0; 245 | padding-right: 0; 246 | padding-top: 0; 247 | margin-bottom: 1.45rem; 248 | color: inherit; 249 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 250 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 251 | font-weight: bold; 252 | text-rendering: optimizeLegibility; 253 | font-size: 1.62671rem; 254 | line-height: 1.1; 255 | } 256 | h3 { 257 | margin-left: 0; 258 | margin-right: 0; 259 | margin-top: 0; 260 | padding-bottom: 0; 261 | padding-left: 0; 262 | padding-right: 0; 263 | padding-top: 0; 264 | margin-bottom: 1.45rem; 265 | color: inherit; 266 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 267 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 268 | font-weight: bold; 269 | text-rendering: optimizeLegibility; 270 | font-size: 1.38316rem; 271 | line-height: 1.1; 272 | } 273 | h4 { 274 | margin-left: 0; 275 | margin-right: 0; 276 | margin-top: 0; 277 | padding-bottom: 0; 278 | padding-left: 0; 279 | padding-right: 0; 280 | padding-top: 0; 281 | margin-bottom: 1.45rem; 282 | color: inherit; 283 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 284 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 285 | font-weight: bold; 286 | text-rendering: optimizeLegibility; 287 | font-size: 1rem; 288 | line-height: 1.1; 289 | } 290 | h5 { 291 | margin-left: 0; 292 | margin-right: 0; 293 | margin-top: 0; 294 | padding-bottom: 0; 295 | padding-left: 0; 296 | padding-right: 0; 297 | padding-top: 0; 298 | margin-bottom: 1.45rem; 299 | color: inherit; 300 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 301 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 302 | font-weight: bold; 303 | text-rendering: optimizeLegibility; 304 | font-size: 0.85028rem; 305 | line-height: 1.1; 306 | } 307 | h6 { 308 | margin-left: 0; 309 | margin-right: 0; 310 | margin-top: 0; 311 | padding-bottom: 0; 312 | padding-left: 0; 313 | padding-right: 0; 314 | padding-top: 0; 315 | margin-bottom: 1.45rem; 316 | color: inherit; 317 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 318 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 319 | font-weight: bold; 320 | text-rendering: optimizeLegibility; 321 | font-size: 0.78405rem; 322 | line-height: 1.1; 323 | } 324 | hgroup { 325 | margin-left: 0; 326 | margin-right: 0; 327 | margin-top: 0; 328 | padding-bottom: 0; 329 | padding-left: 0; 330 | padding-right: 0; 331 | padding-top: 0; 332 | margin-bottom: 1.45rem; 333 | } 334 | ul { 335 | margin-left: 1.45rem; 336 | margin-right: 0; 337 | margin-top: 0; 338 | padding-bottom: 0; 339 | padding-left: 0; 340 | padding-right: 0; 341 | padding-top: 0; 342 | margin-bottom: 1.45rem; 343 | list-style-position: outside; 344 | list-style-image: none; 345 | } 346 | ol { 347 | margin-left: 1.45rem; 348 | margin-right: 0; 349 | margin-top: 0; 350 | padding-bottom: 0; 351 | padding-left: 0; 352 | padding-right: 0; 353 | padding-top: 0; 354 | margin-bottom: 1.45rem; 355 | list-style-position: outside; 356 | list-style-image: none; 357 | } 358 | dl { 359 | margin-left: 0; 360 | margin-right: 0; 361 | margin-top: 0; 362 | padding-bottom: 0; 363 | padding-left: 0; 364 | padding-right: 0; 365 | padding-top: 0; 366 | margin-bottom: 1.45rem; 367 | } 368 | dd { 369 | margin-left: 0; 370 | margin-right: 0; 371 | margin-top: 0; 372 | padding-bottom: 0; 373 | padding-left: 0; 374 | padding-right: 0; 375 | padding-top: 0; 376 | margin-bottom: 1.45rem; 377 | } 378 | p { 379 | margin-left: 0; 380 | margin-right: 0; 381 | margin-top: 0; 382 | padding-bottom: 0; 383 | padding-left: 0; 384 | padding-right: 0; 385 | padding-top: 0; 386 | margin-bottom: 1.45rem; 387 | } 388 | figure { 389 | margin-left: 0; 390 | margin-right: 0; 391 | margin-top: 0; 392 | padding-bottom: 0; 393 | padding-left: 0; 394 | padding-right: 0; 395 | padding-top: 0; 396 | margin-bottom: 1.45rem; 397 | } 398 | pre { 399 | margin-left: 0; 400 | margin-right: 0; 401 | margin-top: 0; 402 | padding-bottom: 0; 403 | padding-left: 0; 404 | padding-right: 0; 405 | padding-top: 0; 406 | margin-bottom: 1.45rem; 407 | font-size: 0.85rem; 408 | line-height: 1.42; 409 | background: hsla(0, 0%, 0%, 0.04); 410 | border-radius: 3px; 411 | overflow: auto; 412 | word-wrap: normal; 413 | padding: 1.45rem; 414 | } 415 | table { 416 | margin-left: 0; 417 | margin-right: 0; 418 | margin-top: 0; 419 | padding-bottom: 0; 420 | padding-left: 0; 421 | padding-right: 0; 422 | padding-top: 0; 423 | margin-bottom: 1.45rem; 424 | font-size: 1rem; 425 | line-height: 1.45rem; 426 | border-collapse: collapse; 427 | width: 100%; 428 | } 429 | fieldset { 430 | margin-left: 0; 431 | margin-right: 0; 432 | margin-top: 0; 433 | padding-bottom: 0; 434 | padding-left: 0; 435 | padding-right: 0; 436 | padding-top: 0; 437 | margin-bottom: 1.45rem; 438 | } 439 | blockquote { 440 | margin-left: 1.45rem; 441 | margin-right: 1.45rem; 442 | margin-top: 0; 443 | padding-bottom: 0; 444 | padding-left: 0; 445 | padding-right: 0; 446 | padding-top: 0; 447 | margin-bottom: 1.45rem; 448 | } 449 | form { 450 | margin-left: 0; 451 | margin-right: 0; 452 | margin-top: 0; 453 | padding-bottom: 0; 454 | padding-left: 0; 455 | padding-right: 0; 456 | padding-top: 0; 457 | margin-bottom: 1.45rem; 458 | } 459 | noscript { 460 | margin-left: 0; 461 | margin-right: 0; 462 | margin-top: 0; 463 | padding-bottom: 0; 464 | padding-left: 0; 465 | padding-right: 0; 466 | padding-top: 0; 467 | margin-bottom: 1.45rem; 468 | } 469 | iframe { 470 | margin-left: 0; 471 | margin-right: 0; 472 | margin-top: 0; 473 | padding-bottom: 0; 474 | padding-left: 0; 475 | padding-right: 0; 476 | padding-top: 0; 477 | margin-bottom: 1.45rem; 478 | } 479 | hr { 480 | margin-left: 0; 481 | margin-right: 0; 482 | margin-top: 0; 483 | padding-bottom: 0; 484 | padding-left: 0; 485 | padding-right: 0; 486 | padding-top: 0; 487 | margin-bottom: calc(1.45rem - 1px); 488 | background: hsla(0, 0%, 0%, 0.2); 489 | border: none; 490 | height: 1px; 491 | } 492 | address { 493 | margin-left: 0; 494 | margin-right: 0; 495 | margin-top: 0; 496 | padding-bottom: 0; 497 | padding-left: 0; 498 | padding-right: 0; 499 | padding-top: 0; 500 | margin-bottom: 1.45rem; 501 | } 502 | b { 503 | font-weight: bold; 504 | } 505 | strong { 506 | font-weight: bold; 507 | } 508 | dt { 509 | font-weight: bold; 510 | } 511 | th { 512 | font-weight: bold; 513 | } 514 | li { 515 | margin-bottom: calc(1.45rem / 2); 516 | } 517 | ol li { 518 | padding-left: 0; 519 | } 520 | ul li { 521 | padding-left: 0; 522 | } 523 | li > ol { 524 | margin-left: 1.45rem; 525 | margin-bottom: calc(1.45rem / 2); 526 | margin-top: calc(1.45rem / 2); 527 | } 528 | li > ul { 529 | margin-left: 1.45rem; 530 | margin-bottom: calc(1.45rem / 2); 531 | margin-top: calc(1.45rem / 2); 532 | } 533 | blockquote *:last-child { 534 | margin-bottom: 0; 535 | } 536 | li *:last-child { 537 | margin-bottom: 0; 538 | } 539 | p *:last-child { 540 | margin-bottom: 0; 541 | } 542 | li > p { 543 | margin-bottom: calc(1.45rem / 2); 544 | } 545 | code { 546 | font-size: 0.85rem; 547 | line-height: 1.45rem; 548 | } 549 | kbd { 550 | font-size: 0.85rem; 551 | line-height: 1.45rem; 552 | } 553 | samp { 554 | font-size: 0.85rem; 555 | line-height: 1.45rem; 556 | } 557 | abbr { 558 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 559 | cursor: help; 560 | } 561 | acronym { 562 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 563 | cursor: help; 564 | } 565 | abbr[title] { 566 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 567 | cursor: help; 568 | text-decoration: none; 569 | } 570 | thead { 571 | text-align: left; 572 | } 573 | td, 574 | th { 575 | text-align: left; 576 | border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); 577 | font-feature-settings: "tnum"; 578 | -moz-font-feature-settings: "tnum"; 579 | -ms-font-feature-settings: "tnum"; 580 | -webkit-font-feature-settings: "tnum"; 581 | padding-left: 0.96667rem; 582 | padding-right: 0.96667rem; 583 | padding-top: 0.725rem; 584 | padding-bottom: calc(0.725rem - 1px); 585 | } 586 | th:first-child, 587 | td:first-child { 588 | padding-left: 0; 589 | } 590 | th:last-child, 591 | td:last-child { 592 | padding-right: 0; 593 | } 594 | tt, 595 | code { 596 | background-color: hsla(0, 0%, 0%, 0.04); 597 | border-radius: 3px; 598 | font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono", 599 | "Liberation Mono", Menlo, Courier, monospace; 600 | padding: 0; 601 | padding-top: 0.2em; 602 | padding-bottom: 0.2em; 603 | } 604 | pre code { 605 | background: none; 606 | line-height: 1.42; 607 | } 608 | code:before, 609 | code:after, 610 | tt:before, 611 | tt:after { 612 | letter-spacing: -0.2em; 613 | content: " "; 614 | } 615 | pre code:before, 616 | pre code:after, 617 | pre tt:before, 618 | pre tt:after { 619 | content: ""; 620 | } 621 | @media only screen and (max-width: 480px) { 622 | html { 623 | font-size: 100%; 624 | } 625 | } 626 | -------------------------------------------------------------------------------- /src/layouts/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import Link from 'gatsby-link' 4 | import Helmet from 'react-helmet' 5 | 6 | import './index.css' 7 | 8 | const Header = () => ( 9 |
15 |
22 |

23 | 30 | Gatsby 31 | 32 |

33 |
34 |
35 | ) 36 | 37 | const TemplateWrapper = ({ children }) => ( 38 |
39 | 46 |
47 |
55 | {children()} 56 |
57 |
58 | ) 59 | 60 | TemplateWrapper.propTypes = { 61 | children: PropTypes.func, 62 | } 63 | 64 | export default TemplateWrapper 65 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const NotFoundPage = () => ( 4 |
5 |

NOT FOUND

6 |

You just hit a route that doesn't exist... the sadness.

7 |
8 | ) 9 | 10 | export default NotFoundPage 11 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Link from 'gatsby-link' 3 | import HelloWorld from '../components/HelloWorld' 4 | 5 | const IndexPage = () => ( 6 |
7 | 8 |
9 | ) 10 | 11 | export default IndexPage 12 | -------------------------------------------------------------------------------- /storybook/addons.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Register storybook plugins 3 | * 4 | * https://getstorybook.io/docs/react-storybook/addons/addon-gallery 5 | */ 6 | 7 | import "@storybook/addon-options/register"; 8 | -------------------------------------------------------------------------------- /storybook/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Config file for storybook 3 | */ 4 | 5 | import { addDecorator, configure } from "@storybook/react"; 6 | import { MemoryRouter } from "react-router-dom"; 7 | import { setOptions } from "@storybook/addon-options"; 8 | import React from "react"; 9 | 10 | // Include any global CSS (standard CSS, not CSS Modules) 11 | import "../src/layouts/index.css"; 12 | 13 | setOptions({ 14 | name: "Example", 15 | goFullScreen: false, 16 | showLeftPanel: true, 17 | showDownPanel: false, 18 | showSearchBox: false, 19 | downPanelInRight: false 20 | }); 21 | 22 | const req = require.context("../src/components", true, /stories\.js$/); 23 | 24 | function loadStories() { 25 | req.keys().forEach(filename => req(filename)); 26 | } 27 | 28 | // Wrap all stories in decorator 29 | addDecorator(story => ( 30 | 31 | {story()} 32 | 33 | )); 34 | 35 | configure(loadStories, module); 36 | -------------------------------------------------------------------------------- /storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | require("imports-loader"); 2 | 3 | const path = require("path"); 4 | const genDefaultConfig = require("@storybook/react/dist/server/config/defaults/webpack.config.js"); 5 | 6 | module.exports = (baseConfig, env) => { 7 | const config = genDefaultConfig(baseConfig, env); 8 | 9 | // Find Storybook's default CSS processing rule 10 | const cssLoaderIndex = config.module.rules.findIndex( 11 | rule => rule.test.source === `\\.css$` 12 | ); 13 | 14 | if (!Number.isInteger(cssLoaderIndex)) 15 | throw new Error("Could not find Storybook's CSS loader"); 16 | 17 | // Exclude CSS Modules from Storybook's standard CSS processing 18 | config.module.rules[cssLoaderIndex].exclude = /\.module\.css$/; 19 | 20 | // Add specific loader rule for CSS Modules 21 | config.module.rules.push({ 22 | test: /\.module\.css$/, 23 | use: [ 24 | { loader: `style-loader` }, 25 | { 26 | loader: "css-loader", 27 | options: { 28 | modules: true, 29 | importLoaders: 1, 30 | localIdentName: "[path]-[local]-[hash:base64:5]" 31 | } 32 | }, 33 | { 34 | // Use newer versions of postcss tools 35 | loader: `postcss-loader-2`, 36 | options: { 37 | plugins: loader => [ 38 | require("postcss-import-11")({ root: loader.resourcePath }), 39 | require("postcss-cssnext-3")() 40 | ] 41 | } 42 | } 43 | ], 44 | include: path.resolve(__dirname, "../src") 45 | }); 46 | 47 | // ignore gatsby-link's global `__loader` variable 48 | config.module.rules.push({ 49 | test: require.resolve("gatsby-link"), 50 | loaders: ["imports-loader?___loader=>{enqueue:function(){}}"] 51 | }); 52 | 53 | return config; 54 | }; 55 | --------------------------------------------------------------------------------