commit eb278167cdedecc41751b0feaa0b4b3aec41f693 Author: Paul O’Shannessy Date: Wed May 29 12:46:11 2013 -0700 Initial public release diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..ecb91bd5 --- /dev/null +++ b/Gemfile @@ -0,0 +1,16 @@ +source 'https://rubygems.org' + +# jekyll, which builds it all +gem 'jekyll', '~>1.0' + +# JSON +gem 'json' + +# SASS for CSS +gem 'sass' + +# For `rake watch` +gem 'rb-fsevent' + +# Redcarpet for Markdown +gem 'redcarpet' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..c83002c5 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,46 @@ +GEM + remote: https://rubygems.org/ + specs: + classifier (1.3.3) + fast-stemmer (>= 1.0.0) + colorator (0.1) + commander (4.1.3) + highline (~> 1.6.11) + directory_watcher (1.4.1) + fast-stemmer (1.0.2) + highline (1.6.19) + jekyll (1.0.2) + classifier (~> 1.3) + colorator (~> 0.1) + commander (~> 4.1.3) + directory_watcher (~> 1.4.1) + kramdown (~> 1.0.2) + liquid (~> 2.3) + maruku (~> 0.5) + pygments.rb (~> 0.5.0) + safe_yaml (~> 0.7.0) + json (1.8.0) + kramdown (1.0.2) + liquid (2.5.0) + maruku (0.6.1) + syntax (>= 1.0.0) + posix-spawn (0.3.6) + pygments.rb (0.5.0) + posix-spawn (~> 0.3.6) + yajl-ruby (~> 1.1.0) + rb-fsevent (0.9.3) + redcarpet (2.2.2) + safe_yaml (0.7.1) + sass (3.2.9) + syntax (1.0.0) + yajl-ruby (1.1.0) + +PLATFORMS + ruby + +DEPENDENCIES + jekyll (~> 1.0) + json + rb-fsevent + redcarpet + sass diff --git a/README.md b/README.md new file mode 100644 index 00000000..4db50f03 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# React Documentation & Website + +We use [Jekyll](http://jekyllrb.com/) to build the site using ([mostly](http://zpao.com/posts/adding-line-highlights-to-markdown-code-fences/)) Markdown, and we host it by pushing HTML to [GitHub Pages](http://pages.github.com/). + +## Installation + +If you are working on the site, you will want to install and run a local copy of it. + +### Dependencies + +In order to use Jekyll, you will need to have Ruby installed. + + - [Ruby](http://www.ruby-lang.org/) (version >= 1.8.7) + - [RubyGems](http://rubygems.org/) (version >= 1.3.7) + - [Bundler](http://gembundler.com/) + +Mac OS X comes pre-installed with Ruby, but you may need to update RubyGems (via `gem update --system`). +Otherwise, [RVM](https://rvm.io/) and [rbenv](https://github.com/sstephenson/rbenv) are popular ways to install Ruby. +Once you have RubyGems and installed Bundler (via `gem install bundler`), use it to install the dependencies: + +```sh +$ cd react/docs +$ bundle install # Might need sudo. +``` + +### Instructions + +The site requires React, so first make sure you've built the project (via `grunt`). + +Use Jekyll to serve the website locally (by default, at `http://localhost:4000`): + +```sh +$ cd react/docs +$ rake +$ jekyll serve -w +$ open http://localhost:4000/react/ +``` + +We use [SASS](http://sass-lang.com/) (with [Bourbon](http://bourbon.io/)) for our CSS, and we use JSX to transform some of our JS. +If you only want to modify the HTML or Markdown, you do not have to do anything because we package pre-compiled copies of the CSS and JS. +If you want to modify the CSS or JS, use [Rake](http://rake.rubyforge.org/) to compile them: + +```sh +$ cd react/docs +$ rake watch # Automatically compiles as needed. +# rake Manually compile CSS and JS. +# rake css Manually compile CSS, only. +# rake js Manually compile JS, only. +``` + +## Afterthoughts + +### Updating `facebook.github.io/react` + +The easiest way to do this is to have a separate clone of this repository, checked out to the `gh-pages` branch. We have a build step that expects this to be in a directory named `react-gh-pages` at the same depth as `react`. Then it's just a matter of running `grunt docs`, which will compile the site and copy it out to this repository. From there you can check it in. + +**Note:** This should only be done for new releases. You should create a tag corresponding to the relase tag in the main repository. + +### Removing the Jekyll / Ruby Dependency + +In an ideal world, we would not be adding a Ruby dependency on part of our project. We would like to move towards a point where we are using React to render the website. diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..e7d64b26 --- /dev/null +++ b/Rakefile @@ -0,0 +1,35 @@ +require('rubygems') +require('json') +require('yaml') + +desc "generate css from sass" +task :css do + system "sass --style=compressed _css/react.scss css/react.css" +end + +desc "generate js from jsx" +task :js do + system "../bin/jsx _js js" +end + +desc "watch css & js" +task :watch => [:update_version] do + Process.spawn "sass --style=compressed --watch _css/react.scss:css/react.css" + Process.spawn "../bin/jsx --watch _js js" + Process.waitall +end + +desc "update version to match ../package.json" +task :update_version do + react_version = JSON.parse(File.read('../package.json'))['version'] + site_config = YAML.load_file('_config.yml') + site_config['react_version'] = react_version + File.open('_config.yml', 'w+') { |f| f.write(site_config.to_yaml) } +end + +desc "build into ../../react-gh-pages" +task :release => [:default] do + system "jekyll build -d ../../react-gh-pages" +end + +task :default => [:update_version, :css, :js] diff --git a/_config.yml b/_config.yml new file mode 100644 index 00000000..2299c474 --- /dev/null +++ b/_config.yml @@ -0,0 +1,14 @@ +--- +markdown: redcarpet +name: React +react_version: 0.3.0 +redcarpet: + extensions: + - fenced_code_blocks +pygments: true +exclude: +- Gemfile +- Gemfile.lock +- README.md +- Rakefile +baseurl: /react diff --git a/_css/_solarized.scss b/_css/_solarized.scss new file mode 100644 index 00000000..a2e22398 --- /dev/null +++ b/_css/_solarized.scss @@ -0,0 +1,173 @@ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + .cm-s-solarized-light { + background-color: #f8f5ec; + color: #637c84; + } + .cm-s-solarized-light .emphasis { + font-weight: bold; + } + .cm-s-solarized-light .dotted { + border-bottom: 1px dotted #cb4b16; + } + .cm-s-solarized-light .CodeMirror-gutter { + background-color: #eee8d5; + border-right: 3px solid #eee8d5; + } + .cm-s-solarized-light .CodeMirror-gutter .CodeMirror-gutter-text { + color: #93a1a1; + } + .cm-s-solarized-light .CodeMirror-cursor { + border-left-color: #002b36 !important; + } + .cm-s-solarized-light .CodeMirror-matchingbracket { + color: #002b36; + background-color: #eee8d5; + box-shadow: 0 0 10px #eee8d5; + font-weight: bold; + } + .cm-s-solarized-light .CodeMirror-nonmatchingbracket { + color: #002b36; + background-color: #eee8d5; + box-shadow: 0 0 10px #eee8d5; + font-weight: bold; + color: #dc322f; + border-bottom: 1px dotted #cb4b16; + } + .cm-s-solarized-light span.cm-keyword { + color: #268bd2; + } + .cm-s-solarized-light span.cm-atom { + color: #2aa198; + } + .cm-s-solarized-light span.cm-number { + color: #586e75; + } + .cm-s-solarized-light span.cm-def { + color: #637c84; + } + .cm-s-solarized-light span.cm-variable { + color: #637c84; + } + .cm-s-solarized-light span.cm-variable-2 { + color: #b58900; + } + .cm-s-solarized-light span.cm-variable-3 { + color: #cb4b16; + } + .cm-s-solarized-light span.cm-comment { + color: #93a1a1; + } + .cm-s-solarized-light span.cm-property { + color: #637c84; + } + .cm-s-solarized-light span.cm-operator { + color: #657b83; + } + .cm-s-solarized-light span.cm-string { + color: #36958e; + } + .cm-s-solarized-light span.cm-error { + font-weight: bold; + border-bottom: 1px dotted #cb4b16; + } + .cm-s-solarized-light span.cm-bracket { + color: #cb4b16; + } + .cm-s-solarized-light span.cm-tag { + color: #657b83; + } + .cm-s-solarized-light span.cm-attribute { + color: #586e75; + font-weight: bold; + } + .cm-s-solarized-light span.cm-meta { + color: #268bd2; + } + .cm-s-solarized-dark { + background-color: #002b36; + color: #839496; + } + .cm-s-solarized-dark .emphasis { + font-weight: bold; + } + .cm-s-solarized-dark .dotted { + border-bottom: 1px dotted #cb4b16; + } + .cm-s-solarized-dark .CodeMirror-gutter { + background-color: #073642; + border-right: 3px solid #073642; + } + .cm-s-solarized-dark .CodeMirror-gutter .CodeMirror-gutter-text { + color: #586e75; + } + .cm-s-solarized-dark .CodeMirror-cursor { + border-left-color: #fdf6e3 !important; + } + .cm-s-solarized-dark .CodeMirror-matchingbracket { + color: #fdf6e3; + background-color: #073642; + box-shadow: 0 0 10px #073642; + font-weight: bold; + } + .cm-s-solarized-dark .CodeMirror-nonmatchingbracket { + color: #fdf6e3; + background-color: #073642; + box-shadow: 0 0 10px #073642; + font-weight: bold; + color: #dc322f; + border-bottom: 1px dotted #cb4b16; + } + .cm-s-solarized-dark span.cm-keyword { + color: #839496; + font-weight: bold; + } + .cm-s-solarized-dark span.cm-atom { + color: #2aa198; + } + .cm-s-solarized-dark span.cm-number { + color: #93a1a1; + } + .cm-s-solarized-dark span.cm-def { + color: #268bd2; + } + .cm-s-solarized-dark span.cm-variable { + color: #cb4b16; + } + .cm-s-solarized-dark span.cm-variable-2 { + color: #cb4b16; + } + .cm-s-solarized-dark span.cm-variable-3 { + color: #cb4b16; + } + .cm-s-solarized-dark span.cm-comment { + color: #586e75; + } + .cm-s-solarized-dark span.cm-property { + color: #b58900; + } + .cm-s-solarized-dark span.cm-operator { + color: #839496; + } + .cm-s-solarized-dark span.cm-string { + color: #6c71c4; + } + .cm-s-solarized-dark span.cm-error { + font-weight: bold; + border-bottom: 1px dotted #cb4b16; + } + .cm-s-solarized-dark span.cm-bracket { + color: #cb4b16; + } + .cm-s-solarized-dark span.cm-tag { + color: #839496; + } + .cm-s-solarized-dark span.cm-attribute { + color: #93a1a1; + font-weight: bold; + } + .cm-s-solarized-dark span.cm-meta { + color: #268bd2; + } diff --git a/_css/_typography.scss b/_css/_typography.scss new file mode 100644 index 00000000..3567209a --- /dev/null +++ b/_css/_typography.scss @@ -0,0 +1,136 @@ +@import 'variables.scss'; + +$textColor: $mediumColor; +$textColorLight: lighten($textColor, 20%); + +html { + font-family: $helvetica; + font-family: proxima-nova, $helvetica; + font-weight: 300; + color: $textColor; + line-height: 1.28; +} + +p { + margin: 0 0 10px; +} + +.subHeader { + font-size: 21px; + font-weight: 200; + line-height: 30px; + margin-bottom: 10px; +} + +em { + font-style: italic; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + color: $textColorLight +} + +h1, +h2, +h3 { + line-height: 40px; +} + +h1 { + font-size: 39px; +} + +h2 { + font-size: 31px; +} + +h3 { + font-size: 23px; +} + +h4 { + font-size: 17px; +} + +h5 { + font-size: 14px; +} + +h6 { + font-size: 11px; +} + +h1 small { + font-size: 24px; +} + +h2 small { + font-size: 18px; +} + +h3 small { + font-size: 16px; +} + +h4 small { + font-size: 14px; +} + +ul, +ol { + margin: 0 0 10px 25px; + padding: 0; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +li { + line-height: 20px; +} + + + +a { + color: $linkColor; + text-decoration: none; + &:hover, + &:focus { + color: $linkInteract; + text-decoration: underline; + } + &:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; + } +} +.center { + text-align: center; +} + + diff --git a/_css/_variables.scss b/_css/_variables.scss new file mode 100644 index 00000000..8cc217f8 --- /dev/null +++ b/_css/_variables.scss @@ -0,0 +1,22 @@ +$primary: #cc7a6f; +$linkColor: darken($primary, 9%); +$linkInteract: darken($linkColor, 9%); +$pageBg: #f9f9f9; + +$lightColor: #e9e9e9; +$mediumestColor: #666; +$mediumColor: #484848; +$darkColor: #2d2d2d; +$darkestColor: #222222; +$blueColor: #61dafb; +$orangeColor: complement($blueColor); + +$lightTextColor: #fafafa; +$mediumTextColor: #aaa; +$darkTextColor: $mediumColor; + +$buttonBlueTop: #77a3d2; +$buttonBlueBottom: #4783c2; +$buttonGreyTop: #9a9a9a; +$buttonGreyBottom: #646464; + diff --git a/_css/bourbon/_bourbon-deprecated-upcoming.scss b/_css/bourbon/_bourbon-deprecated-upcoming.scss new file mode 100644 index 00000000..5332496d --- /dev/null +++ b/_css/bourbon/_bourbon-deprecated-upcoming.scss @@ -0,0 +1,13 @@ +//************************************************************************// +// These mixins/functions are deprecated +// They will be removed in the next MAJOR version release +//************************************************************************// +@mixin box-shadow ($shadows...) { + @include prefixer(box-shadow, $shadows, spec); + @warn "box-shadow is deprecated and will be removed in the next major version release"; +} + +@mixin background-size ($lengths...) { + @include prefixer(background-size, $lengths, spec); + @warn "background-size is deprecated and will be removed in the next major version release"; +} diff --git a/_css/bourbon/_bourbon.scss b/_css/bourbon/_bourbon.scss new file mode 100644 index 00000000..53fbca87 --- /dev/null +++ b/_css/bourbon/_bourbon.scss @@ -0,0 +1,59 @@ +// Custom Helpers +@import "helpers/deprecated-webkit-gradient"; +@import "helpers/gradient-positions-parser"; +@import "helpers/linear-positions-parser"; +@import "helpers/radial-arg-parser"; +@import "helpers/radial-positions-parser"; +@import "helpers/render-gradients"; +@import "helpers/shape-size-stripper"; + +// Custom Functions +@import "functions/compact"; +@import "functions/flex-grid"; +@import "functions/grid-width"; +@import "functions/linear-gradient"; +@import "functions/modular-scale"; +@import "functions/px-to-em"; +@import "functions/radial-gradient"; +@import "functions/tint-shade"; +@import "functions/transition-property-name"; + +// CSS3 Mixins +@import "css3/animation"; +@import "css3/appearance"; +@import "css3/backface-visibility"; +@import "css3/background"; +@import "css3/background-image"; +@import "css3/border-image"; +@import "css3/border-radius"; +@import "css3/box-sizing"; +@import "css3/columns"; +@import "css3/flex-box"; +@import "css3/font-face"; +@import "css3/hidpi-media-query"; +@import "css3/image-rendering"; +@import "css3/inline-block"; +@import "css3/keyframes"; +@import "css3/linear-gradient"; +@import "css3/perspective"; +@import "css3/radial-gradient"; +@import "css3/transform"; +@import "css3/transition"; +@import "css3/user-select"; +@import "css3/placeholder"; + +// Addons & other mixins +@import "addons/button"; +@import "addons/clearfix"; +@import "addons/font-family"; +@import "addons/hide-text"; +@import "addons/html5-input-types"; +@import "addons/position"; +@import "addons/prefixer"; +@import "addons/retina-image"; +@import "addons/size"; +@import "addons/timing-functions"; +@import "addons/triangle"; + +// Soon to be deprecated Mixins +@import "bourbon-deprecated-upcoming"; diff --git a/_css/bourbon/addons/_button.scss b/_css/bourbon/addons/_button.scss new file mode 100644 index 00000000..3ae393c0 --- /dev/null +++ b/_css/bourbon/addons/_button.scss @@ -0,0 +1,273 @@ +@mixin button ($style: simple, $base-color: #4294f0) { + + @if type-of($style) == color { + $base-color: $style; + $style: simple; + } + + // Grayscale button + @if $base-color == grayscale($base-color) { + @if $style == simple { + @include simple($base-color, $grayscale: true); + } + + @else if $style == shiny { + @include shiny($base-color, $grayscale: true); + } + + @else if $style == pill { + @include pill($base-color, $grayscale: true); + } + } + + // Colored button + @else { + @if $style == simple { + @include simple($base-color); + } + + @else if $style == shiny { + @include shiny($base-color); + } + + @else if $style == pill { + @include pill($base-color); + } + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } +} + + +// Simple Button +//************************************************************************// +@mixin simple($base-color, $grayscale: false) { + $color: hsl(0, 0, 100%); + $border: adjust-color($base-color, $saturation: 9%, $lightness: -14%); + $inset-shadow: adjust-color($base-color, $saturation: -8%, $lightness: 15%); + $stop-gradient: adjust-color($base-color, $saturation: 9%, $lightness: -11%); + $text-shadow: adjust-color($base-color, $saturation: 15%, $lightness: -18%); + + @if lightness($base-color) > 70% { + $color: hsl(0, 0, 20%); + $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); + } + + @if $grayscale == true { + $border: grayscale($border); + $inset-shadow: grayscale($inset-shadow); + $stop-gradient: grayscale($stop-gradient); + $text-shadow: grayscale($text-shadow); + } + + border: 1px solid $border; + border-radius: 3px; + box-shadow: inset 0 1px 0 0 $inset-shadow; + color: $color; + display: inline-block; + font-size: 11px; + font-weight: bold; + @include linear-gradient ($base-color, $stop-gradient); + padding: 7px 18px; + text-decoration: none; + text-shadow: 0 1px 0 $text-shadow; + background-clip: padding-box; + + &:hover:not(:disabled) { + $base-color-hover: adjust-color($base-color, $saturation: -4%, $lightness: -5%); + $inset-shadow-hover: adjust-color($base-color, $saturation: -7%, $lightness: 5%); + $stop-gradient-hover: adjust-color($base-color, $saturation: 8%, $lightness: -14%); + + @if $grayscale == true { + $base-color-hover: grayscale($base-color-hover); + $inset-shadow-hover: grayscale($inset-shadow-hover); + $stop-gradient-hover: grayscale($stop-gradient-hover); + } + + box-shadow: inset 0 1px 0 0 $inset-shadow-hover; + cursor: pointer; + @include linear-gradient ($base-color-hover, $stop-gradient-hover); + } + + &:active:not(:disabled) { + $border-active: adjust-color($base-color, $saturation: 9%, $lightness: -14%); + $inset-shadow-active: adjust-color($base-color, $saturation: 7%, $lightness: -17%); + + @if $grayscale == true { + $border-active: grayscale($border-active); + $inset-shadow-active: grayscale($inset-shadow-active); + } + + border: 1px solid $border-active; + box-shadow: inset 0 0 8px 4px $inset-shadow-active, inset 0 0 8px 4px $inset-shadow-active, 0 1px 1px 0 #eee; + } +} + + +// Shiny Button +//************************************************************************// +@mixin shiny($base-color, $grayscale: false) { + $color: hsl(0, 0, 100%); + $border: adjust-color($base-color, $red: -117, $green: -111, $blue: -81); + $border-bottom: adjust-color($base-color, $red: -126, $green: -127, $blue: -122); + $fourth-stop: adjust-color($base-color, $red: -79, $green: -70, $blue: -46); + $inset-shadow: adjust-color($base-color, $red: 37, $green: 29, $blue: 12); + $second-stop: adjust-color($base-color, $red: -56, $green: -50, $blue: -33); + $text-shadow: adjust-color($base-color, $red: -140, $green: -141, $blue: -114); + $third-stop: adjust-color($base-color, $red: -86, $green: -75, $blue: -48); + + @if lightness($base-color) > 70% { + $color: hsl(0, 0, 20%); + $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); + } + + @if $grayscale == true { + $border: grayscale($border); + $border-bottom: grayscale($border-bottom); + $fourth-stop: grayscale($fourth-stop); + $inset-shadow: grayscale($inset-shadow); + $second-stop: grayscale($second-stop); + $text-shadow: grayscale($text-shadow); + $third-stop: grayscale($third-stop); + } + + border: 1px solid $border; + border-bottom: 1px solid $border-bottom; + border-radius: 5px; + box-shadow: inset 0 1px 0 0 $inset-shadow; + color: $color; + display: inline-block; + font-size: 14px; + font-weight: bold; + @include linear-gradient(top, $base-color 0%, $second-stop 50%, $third-stop 50%, $fourth-stop 100%); + padding: 8px 20px; + text-align: center; + text-decoration: none; + text-shadow: 0 -1px 1px $text-shadow; + + &:hover:not(:disabled) { + $first-stop-hover: adjust-color($base-color, $red: -13, $green: -15, $blue: -18); + $second-stop-hover: adjust-color($base-color, $red: -66, $green: -62, $blue: -51); + $third-stop-hover: adjust-color($base-color, $red: -93, $green: -85, $blue: -66); + $fourth-stop-hover: adjust-color($base-color, $red: -86, $green: -80, $blue: -63); + + @if $grayscale == true { + $first-stop-hover: grayscale($first-stop-hover); + $second-stop-hover: grayscale($second-stop-hover); + $third-stop-hover: grayscale($third-stop-hover); + $fourth-stop-hover: grayscale($fourth-stop-hover); + } + + cursor: pointer; + @include linear-gradient(top, $first-stop-hover 0%, + $second-stop-hover 50%, + $third-stop-hover 50%, + $fourth-stop-hover 100%); + } + + &:active:not(:disabled) { + $inset-shadow-active: adjust-color($base-color, $red: -111, $green: -116, $blue: -122); + + @if $grayscale == true { + $inset-shadow-active: grayscale($inset-shadow-active); + } + + box-shadow: inset 0 0 20px 0 $inset-shadow-active, 0 1px 0 #fff; + } +} + + +// Pill Button +//************************************************************************// +@mixin pill($base-color, $grayscale: false) { + $color: hsl(0, 0, 100%); + $border-bottom: adjust-color($base-color, $hue: 8, $saturation: -11%, $lightness: -26%); + $border-sides: adjust-color($base-color, $hue: 4, $saturation: -21%, $lightness: -21%); + $border-top: adjust-color($base-color, $hue: -1, $saturation: -30%, $lightness: -15%); + $inset-shadow: adjust-color($base-color, $hue: -1, $saturation: -1%, $lightness: 7%); + $stop-gradient: adjust-color($base-color, $hue: 8, $saturation: 14%, $lightness: -10%); + $text-shadow: adjust-color($base-color, $hue: 5, $saturation: -19%, $lightness: -15%); + + @if lightness($base-color) > 70% { + $color: hsl(0, 0, 20%); + $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); + } + + @if $grayscale == true { + $border-bottom: grayscale($border-bottom); + $border-sides: grayscale($border-sides); + $border-top: grayscale($border-top); + $inset-shadow: grayscale($inset-shadow); + $stop-gradient: grayscale($stop-gradient); + $text-shadow: grayscale($text-shadow); + } + + border: 1px solid $border-top; + border-color: $border-top $border-sides $border-bottom; + border-radius: 16px; + box-shadow: inset 0 1px 0 0 $inset-shadow, 0 1px 2px 0 #b3b3b3; + color: $color; + display: inline-block; + font-size: 11px; + font-weight: normal; + line-height: 1; + @include linear-gradient ($base-color, $stop-gradient); + padding: 5px 16px; + text-align: center; + text-decoration: none; + text-shadow: 0 -1px 1px $text-shadow; + background-clip: padding-box; + + &:hover:not(:disabled) { + $base-color-hover: adjust-color($base-color, $lightness: -4.5%); + $border-bottom: adjust-color($base-color, $hue: 8, $saturation: 13.5%, $lightness: -32%); + $border-sides: adjust-color($base-color, $hue: 4, $saturation: -2%, $lightness: -27%); + $border-top: adjust-color($base-color, $hue: -1, $saturation: -17%, $lightness: -21%); + $inset-shadow-hover: adjust-color($base-color, $saturation: -1%, $lightness: 3%); + $stop-gradient-hover: adjust-color($base-color, $hue: 8, $saturation: -4%, $lightness: -15.5%); + $text-shadow-hover: adjust-color($base-color, $hue: 5, $saturation: -5%, $lightness: -22%); + + @if $grayscale == true { + $base-color-hover: grayscale($base-color-hover); + $border-bottom: grayscale($border-bottom); + $border-sides: grayscale($border-sides); + $border-top: grayscale($border-top); + $inset-shadow-hover: grayscale($inset-shadow-hover); + $stop-gradient-hover: grayscale($stop-gradient-hover); + $text-shadow-hover: grayscale($text-shadow-hover); + } + + border: 1px solid $border-top; + border-color: $border-top $border-sides $border-bottom; + box-shadow: inset 0 1px 0 0 $inset-shadow-hover; + cursor: pointer; + @include linear-gradient ($base-color-hover, $stop-gradient-hover); + text-shadow: 0 -1px 1px $text-shadow-hover; + background-clip: padding-box; + } + + &:active:not(:disabled) { + $active-color: adjust-color($base-color, $hue: 4, $saturation: -12%, $lightness: -10%); + $border-active: adjust-color($base-color, $hue: 6, $saturation: -2.5%, $lightness: -30%); + $border-bottom-active: adjust-color($base-color, $hue: 11, $saturation: 6%, $lightness: -31%); + $inset-shadow-active: adjust-color($base-color, $hue: 9, $saturation: 2%, $lightness: -21.5%); + $text-shadow-active: adjust-color($base-color, $hue: 5, $saturation: -12%, $lightness: -21.5%); + + @if $grayscale == true { + $active-color: grayscale($active-color); + $border-active: grayscale($border-active); + $border-bottom-active: grayscale($border-bottom-active); + $inset-shadow-active: grayscale($inset-shadow-active); + $text-shadow-active: grayscale($text-shadow-active); + } + + background: $active-color; + border: 1px solid $border-active; + border-bottom: 1px solid $border-bottom-active; + box-shadow: inset 0 0 6px 3px $inset-shadow-active, 0 1px 0 0 #fff; + text-shadow: 0 -1px 1px $text-shadow-active; + } +} diff --git a/_css/bourbon/addons/_clearfix.scss b/_css/bourbon/addons/_clearfix.scss new file mode 100644 index 00000000..ca9903cf --- /dev/null +++ b/_css/bourbon/addons/_clearfix.scss @@ -0,0 +1,29 @@ +// Micro clearfix provides an easy way to contain floats without adding additional markup +// +// Example usage: +// +// // Contain all floats within .wrapper +// .wrapper { +// @include clearfix; +// .content, +// .sidebar { +// float : left; +// } +// } + +@mixin clearfix { + *zoom: 1; + + &:before, + &:after { + content: " "; + display: table; + } + + &:after { + clear: both; + } +} + +// Acknowledgements +// Micro clearfix: [Nicolas Gallagher](http://nicolasgallagher.com/micro-clearfix-hack/) diff --git a/_css/bourbon/addons/_font-family.scss b/_css/bourbon/addons/_font-family.scss new file mode 100644 index 00000000..df8a80dd --- /dev/null +++ b/_css/bourbon/addons/_font-family.scss @@ -0,0 +1,5 @@ +$georgia: Georgia, Cambria, "Times New Roman", Times, serif; +$helvetica: "Helvetica Neue", Helvetica, Arial, sans-serif; +$lucida-grande: "Lucida Grande", Tahoma, Verdana, Arial, sans-serif; +$monospace: "Bitstream Vera Sans Mono", Consolas, Courier, monospace; +$verdana: Verdana, Geneva, sans-serif; diff --git a/_css/bourbon/addons/_hide-text.scss b/_css/bourbon/addons/_hide-text.scss new file mode 100644 index 00000000..68d4bf86 --- /dev/null +++ b/_css/bourbon/addons/_hide-text.scss @@ -0,0 +1,5 @@ +@mixin hide-text { + color: transparent; + font: 0/0 a; + text-shadow: none; +} diff --git a/_css/bourbon/addons/_html5-input-types.scss b/_css/bourbon/addons/_html5-input-types.scss new file mode 100644 index 00000000..b184382d --- /dev/null +++ b/_css/bourbon/addons/_html5-input-types.scss @@ -0,0 +1,56 @@ +//************************************************************************// +// Generate a variable ($all-text-inputs) with a list of all html5 +// input types that have a text-based input, excluding textarea. +// http://diveintohtml5.org/forms.html +//************************************************************************// +$inputs-list: 'input[type="email"]', + 'input[type="number"]', + 'input[type="password"]', + 'input[type="search"]', + 'input[type="tel"]', + 'input[type="text"]', + 'input[type="url"]', + + // Webkit & Gecko may change the display of these in the future + 'input[type="color"]', + 'input[type="date"]', + 'input[type="datetime"]', + 'input[type="datetime-local"]', + 'input[type="month"]', + 'input[type="time"]', + 'input[type="week"]'; + +$unquoted-inputs-list: (); +@each $input-type in $inputs-list { + $unquoted-inputs-list: append($unquoted-inputs-list, unquote($input-type), comma); +} + +$all-text-inputs: $unquoted-inputs-list; + + +// Hover Pseudo-class +//************************************************************************// +$all-text-inputs-hover: (); +@each $input-type in $unquoted-inputs-list { + $input-type-hover: $input-type + ":hover"; + $all-text-inputs-hover: append($all-text-inputs-hover, $input-type-hover, comma); +} + +// Focus Pseudo-class +//************************************************************************// +$all-text-inputs-focus: (); +@each $input-type in $unquoted-inputs-list { + $input-type-focus: $input-type + ":focus"; + $all-text-inputs-focus: append($all-text-inputs-focus, $input-type-focus, comma); +} + +// You must use interpolation on the variable: +// #{$all-text-inputs} +// #{$all-text-inputs-hover} +// #{$all-text-inputs-focus} + +// Example +//************************************************************************// +// #{$all-text-inputs}, textarea { +// border: 1px solid red; +// } diff --git a/_css/bourbon/addons/_position.scss b/_css/bourbon/addons/_position.scss new file mode 100644 index 00000000..faad1cae --- /dev/null +++ b/_css/bourbon/addons/_position.scss @@ -0,0 +1,42 @@ +@mixin position ($position: relative, $coordinates: 0 0 0 0) { + + @if type-of($position) == list { + $coordinates: $position; + $position: relative; + } + + $top: nth($coordinates, 1); + $right: nth($coordinates, 2); + $bottom: nth($coordinates, 3); + $left: nth($coordinates, 4); + + position: $position; + + @if $top == auto { + top: $top; + } + @else if not(unitless($top)) { + top: $top; + } + + @if $right == auto { + right: $right; + } + @else if not(unitless($right)) { + right: $right; + } + + @if $bottom == auto { + bottom: $bottom; + } + @else if not(unitless($bottom)) { + bottom: $bottom; + } + + @if $left == auto { + left: $left; + } + @else if not(unitless($left)) { + left: $left; + } +} diff --git a/_css/bourbon/addons/_prefixer.scss b/_css/bourbon/addons/_prefixer.scss new file mode 100644 index 00000000..6bfd23a1 --- /dev/null +++ b/_css/bourbon/addons/_prefixer.scss @@ -0,0 +1,49 @@ +//************************************************************************// +// Example: @include prefixer(border-radius, $radii, webkit ms spec); +//************************************************************************// +$prefix-for-webkit: true !default; +$prefix-for-mozilla: true !default; +$prefix-for-microsoft: true !default; +$prefix-for-opera: true !default; +$prefix-for-spec: true !default; // required for keyframe mixin + +@mixin prefixer ($property, $value, $prefixes) { + @each $prefix in $prefixes { + @if $prefix == webkit { + @if $prefix-for-webkit { + -webkit-#{$property}: $value; + } + } + @else if $prefix == moz { + @if $prefix-for-mozilla { + -moz-#{$property}: $value; + } + } + @else if $prefix == ms { + @if $prefix-for-microsoft { + -ms-#{$property}: $value; + } + } + @else if $prefix == o { + @if $prefix-for-opera { + -o-#{$property}: $value; + } + } + @else if $prefix == spec { + @if $prefix-for-spec { + #{$property}: $value; + } + } + @else { + @warn "Unrecognized prefix: #{$prefix}"; + } + } +} + +@mixin disable-prefix-for-all() { + $prefix-for-webkit: false; + $prefix-for-mozilla: false; + $prefix-for-microsoft: false; + $prefix-for-opera: false; + $prefix-for-spec: false; +} diff --git a/_css/bourbon/addons/_retina-image.scss b/_css/bourbon/addons/_retina-image.scss new file mode 100644 index 00000000..ed300715 --- /dev/null +++ b/_css/bourbon/addons/_retina-image.scss @@ -0,0 +1,32 @@ +@mixin retina-image($filename, $background-size, $extension: png, $retina-filename: null, $asset-pipeline: false) { + @if $asset-pipeline { + background-image: image_url($filename + "." + $extension); + } + @else { + background-image: url($filename + "." + $extension); + } + + @include hidpi { + + @if $asset-pipeline { + @if $retina-filename { + background-image: image_url($retina-filename + "." + $extension); + } + @else { + background-image: image_url($filename + "@2x" + "." + $extension); + } + } + + @else { + @if $retina-filename { + background-image: url($retina-filename + "." + $extension); + } + @else { + background-image: url($filename + "@2x" + "." + $extension); + } + } + + background-size: $background-size; + + } +} diff --git a/_css/bourbon/addons/_size.scss b/_css/bourbon/addons/_size.scss new file mode 100644 index 00000000..342e41b7 --- /dev/null +++ b/_css/bourbon/addons/_size.scss @@ -0,0 +1,44 @@ +@mixin size($size) { + @if length($size) == 1 { + @if $size == auto { + width: $size; + height: $size; + } + + @else if unitless($size) { + width: $size + px; + height: $size + px; + } + + @else if not(unitless($size)) { + width: $size; + height: $size; + } + } + + // Width x Height + @if length($size) == 2 { + $width: nth($size, 1); + $height: nth($size, 2); + + @if $width == auto { + width: $width; + } + @else if not(unitless($width)) { + width: $width; + } + @else if unitless($width) { + width: $width + px; + } + + @if $height == auto { + height: $height; + } + @else if not(unitless($height)) { + height: $height; + } + @else if unitless($height) { + height: $height + px; + } + } +} diff --git a/_css/bourbon/addons/_timing-functions.scss b/_css/bourbon/addons/_timing-functions.scss new file mode 100644 index 00000000..51b24109 --- /dev/null +++ b/_css/bourbon/addons/_timing-functions.scss @@ -0,0 +1,32 @@ +// CSS cubic-bezier timing functions. Timing functions courtesy of jquery.easie (github.com/jaukia/easie) +// Timing functions are the same as demo'ed here: http://jqueryui.com/demos/effect/easing.html + +// EASE IN +$ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530); +$ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190); +$ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220); +$ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060); +$ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715); +$ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035); +$ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335); +$ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045); + +// EASE OUT +$ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940); +$ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000); +$ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000); +$ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000); +$ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000); +$ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000); +$ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000); +$ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275); + +// EASE IN OUT +$ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955); +$ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000); +$ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000); +$ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000); +$ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950); +$ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000); +$ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860); +$ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550); diff --git a/_css/bourbon/addons/_triangle.scss b/_css/bourbon/addons/_triangle.scss new file mode 100644 index 00000000..0e02aca2 --- /dev/null +++ b/_css/bourbon/addons/_triangle.scss @@ -0,0 +1,45 @@ +@mixin triangle ($size, $color, $direction) { + height: 0; + width: 0; + + @if ($direction == up) or ($direction == down) or ($direction == right) or ($direction == left) { + border-color: transparent; + border-style: solid; + border-width: $size / 2; + + @if $direction == up { + border-bottom-color: $color; + + } @else if $direction == right { + border-left-color: $color; + + } @else if $direction == down { + border-top-color: $color; + + } @else if $direction == left { + border-right-color: $color; + } + } + + @else if ($direction == up-right) or ($direction == up-left) { + border-top: $size solid $color; + + @if $direction == up-right { + border-left: $size solid transparent; + + } @else if $direction == up-left { + border-right: $size solid transparent; + } + } + + @else if ($direction == down-right) or ($direction == down-left) { + border-bottom: $size solid $color; + + @if $direction == down-right { + border-left: $size solid transparent; + + } @else if $direction == down-left { + border-right: $size solid transparent; + } + } +} diff --git a/_css/bourbon/css3/_animation.scss b/_css/bourbon/css3/_animation.scss new file mode 100644 index 00000000..08c3dbf1 --- /dev/null +++ b/_css/bourbon/css3/_animation.scss @@ -0,0 +1,52 @@ +// http://www.w3.org/TR/css3-animations/#the-animation-name-property- +// Each of these mixins support comma separated lists of values, which allows different transitions for individual properties to be described in a single style rule. Each value in the list corresponds to the value at that same position in the other properties. + +// Official animation shorthand property. +@mixin animation ($animations...) { + @include prefixer(animation, $animations, webkit moz spec); +} + +// Individual Animation Properties +@mixin animation-name ($names...) { + @include prefixer(animation-name, $names, webkit moz spec); +} + + +@mixin animation-duration ($times...) { + @include prefixer(animation-duration, $times, webkit moz spec); +} + + +@mixin animation-timing-function ($motions...) { +// ease | linear | ease-in | ease-out | ease-in-out + @include prefixer(animation-timing-function, $motions, webkit moz spec); +} + + +@mixin animation-iteration-count ($values...) { +// infinite | + @include prefixer(animation-iteration-count, $values, webkit moz spec); +} + + +@mixin animation-direction ($directions...) { +// normal | alternate + @include prefixer(animation-direction, $directions, webkit moz spec); +} + + +@mixin animation-play-state ($states...) { +// running | paused + @include prefixer(animation-play-state, $states, webkit moz spec); +} + + +@mixin animation-delay ($times...) { + @include prefixer(animation-delay, $times, webkit moz spec); +} + + +@mixin animation-fill-mode ($modes...) { +// none | forwards | backwards | both + @include prefixer(animation-fill-mode, $modes, webkit moz spec); +} diff --git a/_css/bourbon/css3/_appearance.scss b/_css/bourbon/css3/_appearance.scss new file mode 100644 index 00000000..3eb16e45 --- /dev/null +++ b/_css/bourbon/css3/_appearance.scss @@ -0,0 +1,3 @@ +@mixin appearance ($value) { + @include prefixer(appearance, $value, webkit moz ms o spec); +} diff --git a/_css/bourbon/css3/_backface-visibility.scss b/_css/bourbon/css3/_backface-visibility.scss new file mode 100644 index 00000000..1161fe60 --- /dev/null +++ b/_css/bourbon/css3/_backface-visibility.scss @@ -0,0 +1,6 @@ +//************************************************************************// +// Backface-visibility mixin +//************************************************************************// +@mixin backface-visibility($visibility) { + @include prefixer(backface-visibility, $visibility, webkit spec); +} diff --git a/_css/bourbon/css3/_background-image.scss b/_css/bourbon/css3/_background-image.scss new file mode 100644 index 00000000..17016b91 --- /dev/null +++ b/_css/bourbon/css3/_background-image.scss @@ -0,0 +1,48 @@ +//************************************************************************// +// Background-image property for adding multiple background images with +// gradients, or for stringing multiple gradients together. +//************************************************************************// + +@mixin background-image($images...) { + background-image: _add-prefix($images, webkit); + background-image: _add-prefix($images); +} + +@function _add-prefix($images, $vendor: false) { + $images-prefixed: (); + $gradient-positions: false; + @for $i from 1 through length($images) { + $type: type-of(nth($images, $i)); // Get type of variable - List or String + + // If variable is a list - Gradient + @if $type == list { + $gradient-type: nth(nth($images, $i), 1); // linear or radial + $gradient-pos: null; + $gradient-args: null; + + @if ($gradient-type == linear) or ($gradient-type == radial) { + $gradient-pos: nth(nth($images, $i), 2); // Get gradient position + $gradient-args: nth(nth($images, $i), 3); // Get actual gradient (red, blue) + } + @else { + $gradient-args: nth(nth($images, $i), 2); // Get actual gradient (red, blue) + } + + $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); + $gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); + $images-prefixed: append($images-prefixed, $gradient, comma); + } + // If variable is a string - Image + @else if $type == string { + $images-prefixed: join($images-prefixed, nth($images, $i), comma); + } + } + @return $images-prefixed; +} + +//Examples: + //@include background-image(linear-gradient(top, orange, red)); + //@include background-image(radial-gradient(50% 50%, cover circle, orange, red)); + //@include background-image(url("/images/a.png"), linear-gradient(orange, red)); + //@include background-image(url("image.png"), linear-gradient(orange, red), url("image.png")); + //@include background-image(linear-gradient(hsla(0, 100%, 100%, 0.25) 0%, hsla(0, 100%, 100%, 0.08) 50%, transparent 50%), linear-gradient(orange, red)); diff --git a/_css/bourbon/css3/_background.scss b/_css/bourbon/css3/_background.scss new file mode 100644 index 00000000..766d5d32 --- /dev/null +++ b/_css/bourbon/css3/_background.scss @@ -0,0 +1,103 @@ +//************************************************************************// +// Background property for adding multiple backgrounds using shorthand +// notation. +//************************************************************************// + +@mixin background( + $background-1 , $background-2: false, + $background-3: false, $background-4: false, + $background-5: false, $background-6: false, + $background-7: false, $background-8: false, + $background-9: false, $background-10: false, + $fallback: false +) { + $backgrounds: compact($background-1, $background-2, + $background-3, $background-4, + $background-5, $background-6, + $background-7, $background-8, + $background-9, $background-10); + + $fallback-color: false; + @if (type-of($fallback) == color) or ($fallback == "transparent") { + $fallback-color: $fallback; + } + @else { + $fallback-color: _extract-background-color($backgrounds); + } + + @if $fallback-color { + background-color: $fallback-color; + } + background: _background-add-prefix($backgrounds, webkit); + background: _background-add-prefix($backgrounds); +} + +@function _extract-background-color($backgrounds) { + $final-bg-layer: nth($backgrounds, length($backgrounds)); + @if type-of($final-bg-layer) == list { + @for $i from 1 through length($final-bg-layer) { + $value: nth($final-bg-layer, $i); + @if type-of($value) == color { + @return $value; + } + } + } + @return false; +} + +@function _background-add-prefix($backgrounds, $vendor: false) { + $backgrounds-prefixed: (); + + @for $i from 1 through length($backgrounds) { + $shorthand: nth($backgrounds, $i); // Get member for current index + $type: type-of($shorthand); // Get type of variable - List (gradient) or String (image) + + // If shorthand is a list (gradient) + @if $type == list { + $first-member: nth($shorthand, 1); // Get first member of shorthand + + // Linear Gradient + @if index(linear radial, nth($first-member, 1)) { + $gradient-type: nth($first-member, 1); // linear || radial + $gradient-args: false; + $gradient-positions: false; + $shorthand-start: false; + @if type-of($first-member) == list { // Linear gradient plus additional shorthand values - lg(red,orange)repeat,... + $gradient-positions: nth($first-member, 2); + $gradient-args: nth($first-member, 3); + $shorthand-start: 2; + } + @else { // Linear gradient only - lg(red,orange),... + $gradient-positions: nth($shorthand, 2); + $gradient-args: nth($shorthand, 3); // Get gradient (red, blue) + } + + $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-positions); + $gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); + + // Append any additional shorthand args to gradient + @if $shorthand-start { + @for $j from $shorthand-start through length($shorthand) { + $gradient: join($gradient, nth($shorthand, $j), space); + } + } + $backgrounds-prefixed: append($backgrounds-prefixed, $gradient, comma); + } + // Image with additional properties + @else { + $backgrounds-prefixed: append($backgrounds-prefixed, $shorthand, comma); + } + } + // If shorthand is a simple string (color or image) + @else if $type == string { + $backgrounds-prefixed: join($backgrounds-prefixed, $shorthand, comma); + } + } + @return $backgrounds-prefixed; +} + +//Examples: + //@include background(linear-gradient(top, orange, red)); + //@include background(radial-gradient(circle at 40% 40%, orange, red)); + //@include background(url("/images/a.png") no-repeat, linear-gradient(orange, red)); + //@include background(url("image.png") center center, linear-gradient(orange, red), url("image.png")); diff --git a/_css/bourbon/css3/_border-image.scss b/_css/bourbon/css3/_border-image.scss new file mode 100644 index 00000000..1fff212d --- /dev/null +++ b/_css/bourbon/css3/_border-image.scss @@ -0,0 +1,55 @@ +@mixin border-image($images) { + -webkit-border-image: _border-add-prefix($images, webkit); + -moz-border-image: _border-add-prefix($images, moz); + -o-border-image: _border-add-prefix($images, o); + border-image: _border-add-prefix($images); +} + +@function _border-add-prefix($images, $vendor: false) { + $border-image: null; + $images-type: type-of(nth($images, 1)); + $first-var: nth(nth($images, 1), 1); // Get type of Gradient (Linear || radial) + + // If input is a gradient + @if $images-type == string { + @if ($first-var == "linear") or ($first-var == "radial") { + $gradient-type: nth($images, 1); // Get type of gradient (linear || radial) + $gradient-pos: nth($images, 2); // Get gradient position + $gradient-args: nth($images, 3); // Get actual gradient (red, blue) + $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); + $border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); + } + // If input is a URL + @else { + $border-image: $images; + } + } + // If input is gradient or url + additional args + @else if $images-type == list { + $type: type-of(nth($images, 1)); // Get type of variable - List or String + + // If variable is a list - Gradient + @if $type == list { + $gradient: nth($images, 1); + $gradient-type: nth($gradient, 1); // Get type of gradient (linear || radial) + $gradient-pos: nth($gradient, 2); // Get gradient position + $gradient-args: nth($gradient, 3); // Get actual gradient (red, blue) + $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); + $border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); + + @for $i from 2 through length($images) { + $border-image: append($border-image, nth($images, $i)); + } + } + } + @return $border-image; +} + +//Examples: +// @include border-image(url("image.png")); +// @include border-image(url("image.png") 20 stretch); +// @include border-image(linear-gradient(45deg, orange, yellow)); +// @include border-image(linear-gradient(45deg, orange, yellow) stretch); +// @include border-image(linear-gradient(45deg, orange, yellow) 20 30 40 50 stretch round); +// @include border-image(radial-gradient(top, cover, orange, yellow, orange)); + diff --git a/_css/bourbon/css3/_border-radius.scss b/_css/bourbon/css3/_border-radius.scss new file mode 100644 index 00000000..7c171901 --- /dev/null +++ b/_css/bourbon/css3/_border-radius.scss @@ -0,0 +1,22 @@ +//************************************************************************// +// Shorthand Border-radius mixins +//************************************************************************// +@mixin border-top-radius($radii) { + @include prefixer(border-top-left-radius, $radii, spec); + @include prefixer(border-top-right-radius, $radii, spec); +} + +@mixin border-bottom-radius($radii) { + @include prefixer(border-bottom-left-radius, $radii, spec); + @include prefixer(border-bottom-right-radius, $radii, spec); +} + +@mixin border-left-radius($radii) { + @include prefixer(border-top-left-radius, $radii, spec); + @include prefixer(border-bottom-left-radius, $radii, spec); +} + +@mixin border-right-radius($radii) { + @include prefixer(border-top-right-radius, $radii, spec); + @include prefixer(border-bottom-right-radius, $radii, spec); +} diff --git a/_css/bourbon/css3/_box-sizing.scss b/_css/bourbon/css3/_box-sizing.scss new file mode 100644 index 00000000..f07e1d41 --- /dev/null +++ b/_css/bourbon/css3/_box-sizing.scss @@ -0,0 +1,4 @@ +@mixin box-sizing ($box) { +// content-box | border-box | inherit + @include prefixer(box-sizing, $box, webkit moz spec); +} diff --git a/_css/bourbon/css3/_columns.scss b/_css/bourbon/css3/_columns.scss new file mode 100644 index 00000000..42274a4e --- /dev/null +++ b/_css/bourbon/css3/_columns.scss @@ -0,0 +1,47 @@ +@mixin columns($arg: auto) { +// || + @include prefixer(columns, $arg, webkit moz spec); +} + +@mixin column-count($int: auto) { +// auto || integer + @include prefixer(column-count, $int, webkit moz spec); +} + +@mixin column-gap($length: normal) { +// normal || length + @include prefixer(column-gap, $length, webkit moz spec); +} + +@mixin column-fill($arg: auto) { +// auto || length + @include prefixer(columns-fill, $arg, webkit moz spec); +} + +@mixin column-rule($arg) { +// || || + @include prefixer(column-rule, $arg, webkit moz spec); +} + +@mixin column-rule-color($color) { + @include prefixer(column-rule-color, $color, webkit moz spec); +} + +@mixin column-rule-style($style: none) { +// none | hidden | dashed | dotted | double | groove | inset | inset | outset | ridge | solid + @include prefixer(column-rule-style, $style, webkit moz spec); +} + +@mixin column-rule-width ($width: none) { + @include prefixer(column-rule-width, $width, webkit moz spec); +} + +@mixin column-span($arg: none) { +// none || all + @include prefixer(column-span, $arg, webkit moz spec); +} + +@mixin column-width($length: auto) { +// auto || length + @include prefixer(column-width, $length, webkit moz spec); +} diff --git a/_css/bourbon/css3/_flex-box.scss b/_css/bourbon/css3/_flex-box.scss new file mode 100644 index 00000000..3e741e66 --- /dev/null +++ b/_css/bourbon/css3/_flex-box.scss @@ -0,0 +1,52 @@ +// CSS3 Flexible Box Model and property defaults + +// Custom shorthand notation for flexbox +@mixin box($orient: inline-axis, $pack: start, $align: stretch) { + @include display-box; + @include box-orient($orient); + @include box-pack($pack); + @include box-align($align); +} + +@mixin display-box { + display: -webkit-box; + display: -moz-box; + display: box; +} + +@mixin box-orient($orient: inline-axis) { +// horizontal|vertical|inline-axis|block-axis|inherit + @include prefixer(box-orient, $orient, webkit moz spec); +} + +@mixin box-pack($pack: start) { +// start|end|center|justify + @include prefixer(box-pack, $pack, webkit moz spec); +} + +@mixin box-align($align: stretch) { +// start|end|center|baseline|stretch + @include prefixer(box-align, $align, webkit moz spec); +} + +@mixin box-direction($direction: normal) { +// normal|reverse|inherit + @include prefixer(box-direction, $direction, webkit moz spec); +} + +@mixin box-lines($lines: single) { +// single|multiple + @include prefixer(box-lines, $lines, webkit moz spec); +} + +@mixin box-ordinal-group($int: 1) { + @include prefixer(box-ordinal-group, $int, webkit moz spec); +} + +@mixin box-flex($value: 0.0) { + @include prefixer(box-flex, $value, webkit moz spec); +} + +@mixin box-flex-group($int: 1) { + @include prefixer(box-flex-group, $int, webkit moz spec); +} diff --git a/_css/bourbon/css3/_font-face.scss b/_css/bourbon/css3/_font-face.scss new file mode 100644 index 00000000..029ee8fe --- /dev/null +++ b/_css/bourbon/css3/_font-face.scss @@ -0,0 +1,23 @@ +// Order of the includes matters, and it is: normal, bold, italic, bold+italic. + +@mixin font-face($font-family, $file-path, $weight: normal, $style: normal, $asset-pipeline: false ) { + @font-face { + font-family: $font-family; + font-weight: $weight; + font-style: $style; + + @if $asset-pipeline == true { + src: font-url('#{$file-path}.eot'); + src: font-url('#{$file-path}.eot?#iefix') format('embedded-opentype'), + font-url('#{$file-path}.woff') format('woff'), + font-url('#{$file-path}.ttf') format('truetype'), + font-url('#{$file-path}.svg##{$font-family}') format('svg'); + } @else { + src: url('#{$file-path}.eot'); + src: url('#{$file-path}.eot?#iefix') format('embedded-opentype'), + url('#{$file-path}.woff') format('woff'), + url('#{$file-path}.ttf') format('truetype'), + url('#{$file-path}.svg##{$font-family}') format('svg'); + } + } +} diff --git a/_css/bourbon/css3/_hidpi-media-query.scss b/_css/bourbon/css3/_hidpi-media-query.scss new file mode 100644 index 00000000..111e4009 --- /dev/null +++ b/_css/bourbon/css3/_hidpi-media-query.scss @@ -0,0 +1,10 @@ +// HiDPI mixin. Default value set to 1.3 to target Google Nexus 7 (http://bjango.com/articles/min-device-pixel-ratio/) +@mixin hidpi($ratio: 1.3) { + @media only screen and (-webkit-min-device-pixel-ratio: $ratio), + only screen and (min--moz-device-pixel-ratio: $ratio), + only screen and (-o-min-device-pixel-ratio: #{$ratio}/1), + only screen and (min-resolution: #{round($ratio*96)}dpi), + only screen and (min-resolution: #{$ratio}dppx) { + @content; + } +} diff --git a/_css/bourbon/css3/_image-rendering.scss b/_css/bourbon/css3/_image-rendering.scss new file mode 100644 index 00000000..abc7ee1a --- /dev/null +++ b/_css/bourbon/css3/_image-rendering.scss @@ -0,0 +1,13 @@ +@mixin image-rendering ($mode:optimizeQuality) { + + @if ($mode == optimize-contrast) { + image-rendering: -moz-crisp-edges; + image-rendering: -o-crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: optimize-contrast; + } + + @else { + image-rendering: $mode; + } +} diff --git a/_css/bourbon/css3/_inline-block.scss b/_css/bourbon/css3/_inline-block.scss new file mode 100644 index 00000000..3272a001 --- /dev/null +++ b/_css/bourbon/css3/_inline-block.scss @@ -0,0 +1,8 @@ +// Legacy support for inline-block in IE7 (maybe IE6) +@mixin inline-block { + display: inline-block; + vertical-align: baseline; + zoom: 1; + *display: inline; + *vertical-align: auto; +} diff --git a/_css/bourbon/css3/_keyframes.scss b/_css/bourbon/css3/_keyframes.scss new file mode 100644 index 00000000..dca61f2a --- /dev/null +++ b/_css/bourbon/css3/_keyframes.scss @@ -0,0 +1,43 @@ +// Adds keyframes blocks for supported prefixes, removing redundant prefixes in the block's content +@mixin keyframes($name) { + $original-prefix-for-webkit: $prefix-for-webkit; + $original-prefix-for-mozilla: $prefix-for-mozilla; + $original-prefix-for-microsoft: $prefix-for-microsoft; + $original-prefix-for-opera: $prefix-for-opera; + $original-prefix-for-spec: $prefix-for-spec; + + @if $original-prefix-for-webkit { + @include disable-prefix-for-all(); + $prefix-for-webkit: true; + @-webkit-keyframes #{$name} { + @content; + } + } + @if $original-prefix-for-mozilla { + @include disable-prefix-for-all(); + $prefix-for-mozilla: true; + @-moz-keyframes #{$name} { + @content; + } + } + @if $original-prefix-for-opera { + @include disable-prefix-for-all(); + $prefix-for-opera: true; + @-o-keyframes #{$name} { + @content; + } + } + @if $original-prefix-for-spec { + @include disable-prefix-for-all(); + $prefix-for-spec: true; + @keyframes #{$name} { + @content; + } + } + + $prefix-for-webkit: $original-prefix-for-webkit; + $prefix-for-mozilla: $original-prefix-for-mozilla; + $prefix-for-microsoft: $original-prefix-for-microsoft; + $prefix-for-opera: $original-prefix-for-opera; + $prefix-for-spec: $original-prefix-for-spec; +} diff --git a/_css/bourbon/css3/_linear-gradient.scss b/_css/bourbon/css3/_linear-gradient.scss new file mode 100644 index 00000000..d5b687b0 --- /dev/null +++ b/_css/bourbon/css3/_linear-gradient.scss @@ -0,0 +1,41 @@ +@mixin linear-gradient($pos, $G1, $G2: false, + $G3: false, $G4: false, + $G5: false, $G6: false, + $G7: false, $G8: false, + $G9: false, $G10: false, + $deprecated-pos1: left top, + $deprecated-pos2: left bottom, + $fallback: false) { + // Detect what type of value exists in $pos + $pos-type: type-of(nth($pos, 1)); + $pos-spec: null; + $pos-degree: null; + + // If $pos is missing from mixin, reassign vars and add default position + @if ($pos-type == color) or (nth($pos, 1) == "transparent") { + $G10: $G9; $G9: $G8; $G8: $G7; $G7: $G6; $G6: $G5; + $G5: $G4; $G4: $G3; $G3: $G2; $G2: $G1; $G1: $pos; + $pos: null; + } + + @if $pos { + $positions: _linear-positions-parser($pos); + $pos-degree: nth($positions, 1); + $pos-spec: nth($positions, 2); + } + + $full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10); + + // Set $G1 as the default fallback color + $fallback-color: nth($G1, 1); + + // If $fallback is a color use that color as the fallback color + @if (type-of($fallback) == color) or ($fallback == "transparent") { + $fallback-color: $fallback; + } + + background-color: $fallback-color; + background-image: _deprecated-webkit-gradient(linear, $deprecated-pos1, $deprecated-pos2, $full); // Safari <= 5.0 + background-image: -webkit-linear-gradient($pos-degree $full); // Safari 5.1+, Chrome + background-image: unquote("linear-gradient(#{$pos-spec}#{$full})"); +} diff --git a/_css/bourbon/css3/_perspective.scss b/_css/bourbon/css3/_perspective.scss new file mode 100644 index 00000000..0e4deb80 --- /dev/null +++ b/_css/bourbon/css3/_perspective.scss @@ -0,0 +1,8 @@ +@mixin perspective($depth: none) { + // none | + @include prefixer(perspective, $depth, webkit moz spec); +} + +@mixin perspective-origin($value: 50% 50%) { + @include prefixer(perspective-origin, $value, webkit moz spec); +} diff --git a/_css/bourbon/css3/_placeholder.scss b/_css/bourbon/css3/_placeholder.scss new file mode 100644 index 00000000..22fd92b4 --- /dev/null +++ b/_css/bourbon/css3/_placeholder.scss @@ -0,0 +1,29 @@ +$placeholders: '-webkit-input-placeholder', + '-moz-placeholder', + '-ms-input-placeholder'; + +@mixin placeholder { + @each $placeholder in $placeholders { + @if $placeholder == "-webkit-input-placeholder" { + &::#{$placeholder} { + @content; + } + } + @else if $placeholder == "-moz-placeholder" { + // FF 18- + &:#{$placeholder} { + @content; + } + + // FF 19+ + &::#{$placeholder} { + @content; + } + } + @else { + &:#{$placeholder} { + @content; + } + } + } +} diff --git a/_css/bourbon/css3/_radial-gradient.scss b/_css/bourbon/css3/_radial-gradient.scss new file mode 100644 index 00000000..e87b45a5 --- /dev/null +++ b/_css/bourbon/css3/_radial-gradient.scss @@ -0,0 +1,44 @@ +// Requires Sass 3.1+ +@mixin radial-gradient($G1, $G2, + $G3: false, $G4: false, + $G5: false, $G6: false, + $G7: false, $G8: false, + $G9: false, $G10: false, + $pos: null, + $shape-size: null, + $deprecated-pos1: center center, + $deprecated-pos2: center center, + $deprecated-radius1: 0, + $deprecated-radius2: 460, + $fallback: false) { + + $data: _radial-arg-parser($G1, $G2, $pos, $shape-size); + $G1: nth($data, 1); + $G2: nth($data, 2); + $pos: nth($data, 3); + $shape-size: nth($data, 4); + + $full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10); + + // Strip deprecated cover/contain for spec + $shape-size-spec: _shape-size-stripper($shape-size); + + // Set $G1 as the default fallback color + $first-color: nth($full, 1); + $fallback-color: nth($first-color, 1); + + @if (type-of($fallback) == color) or ($fallback == "transparent") { + $fallback-color: $fallback; + } + + // Add Commas and spaces + $shape-size: if($shape-size, '#{$shape-size}, ', null); + $pos: if($pos, '#{$pos}, ', null); + $pos-spec: if($pos, 'at #{$pos}', null); + $shape-size-spec: if(($shape-size-spec != ' ') and ($pos == null), '#{$shape-size-spec}, ', '#{$shape-size-spec} '); + + background-color: $fallback-color; + background-image: _deprecated-webkit-gradient(radial, $deprecated-pos1, $deprecated-pos2, $full, $deprecated-radius1, $deprecated-radius2); // Safari <= 5.0 && IOS 4 + background-image: -webkit-radial-gradient(unquote(#{$pos}#{$shape-size}#{$full})); + background-image: unquote("radial-gradient(#{$shape-size-spec}#{$pos-spec}#{$full})"); +} diff --git a/_css/bourbon/css3/_transform.scss b/_css/bourbon/css3/_transform.scss new file mode 100644 index 00000000..8cc35963 --- /dev/null +++ b/_css/bourbon/css3/_transform.scss @@ -0,0 +1,15 @@ +@mixin transform($property: none) { +// none | + @include prefixer(transform, $property, webkit moz ms o spec); +} + +@mixin transform-origin($axes: 50%) { +// x-axis - left | center | right | length | % +// y-axis - top | center | bottom | length | % +// z-axis - length + @include prefixer(transform-origin, $axes, webkit moz ms o spec); +} + +@mixin transform-style ($style: flat) { + @include prefixer(transform-style, $style, webkit moz ms o spec); +} diff --git a/_css/bourbon/css3/_transition.scss b/_css/bourbon/css3/_transition.scss new file mode 100644 index 00000000..180cde6c --- /dev/null +++ b/_css/bourbon/css3/_transition.scss @@ -0,0 +1,34 @@ +// Shorthand mixin. Supports multiple parentheses-deliminated values for each variable. +// Example: @include transition (all, 2.0s, ease-in-out); +// @include transition ((opacity, width), (1.0s, 2.0s), ease-in, (0, 2s)); +// @include transition ($property:(opacity, width), $delay: (1.5s, 2.5s)); + +@mixin transition ($properties...) { + @if length($properties) >= 1 { + @include prefixer(transition, $properties, webkit moz spec); + } + + @else { + $properties: all 0.15s ease-out 0; + @include prefixer(transition, $properties, webkit moz spec); + } +} + +@mixin transition-property ($properties...) { + -webkit-transition-property: transition-property-names($properties, 'webkit'); + -moz-transition-property: transition-property-names($properties, 'moz'); + transition-property: transition-property-names($properties, false); +} + +@mixin transition-duration ($times...) { + @include prefixer(transition-duration, $times, webkit moz spec); +} + +@mixin transition-timing-function ($motions...) { +// ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier() + @include prefixer(transition-timing-function, $motions, webkit moz spec); +} + +@mixin transition-delay ($times...) { + @include prefixer(transition-delay, $times, webkit moz spec); +} diff --git a/_css/bourbon/css3/_user-select.scss b/_css/bourbon/css3/_user-select.scss new file mode 100644 index 00000000..1380aa8b --- /dev/null +++ b/_css/bourbon/css3/_user-select.scss @@ -0,0 +1,3 @@ +@mixin user-select($arg: none) { + @include prefixer(user-select, $arg, webkit moz ms spec); +} diff --git a/_css/bourbon/functions/_compact.scss b/_css/bourbon/functions/_compact.scss new file mode 100644 index 00000000..871500e3 --- /dev/null +++ b/_css/bourbon/functions/_compact.scss @@ -0,0 +1,11 @@ +// Remove `false` values from a list + +@function compact($vars...) { + $list: (); + @each $var in $vars { + @if $var { + $list: append($list, $var, comma); + } + } + @return $list; +} diff --git a/_css/bourbon/functions/_flex-grid.scss b/_css/bourbon/functions/_flex-grid.scss new file mode 100644 index 00000000..3bbd8665 --- /dev/null +++ b/_css/bourbon/functions/_flex-grid.scss @@ -0,0 +1,39 @@ +// Flexible grid +@function flex-grid($columns, $container-columns: $fg-max-columns) { + $width: $columns * $fg-column + ($columns - 1) * $fg-gutter; + $container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter; + @return percentage($width / $container-width); +} + +// Flexible gutter +@function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) { + $container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter; + @return percentage($gutter / $container-width); +} + +// The $fg-column, $fg-gutter and $fg-max-columns variables must be defined in your base stylesheet to properly use the flex-grid function. +// This function takes the fluid grid equation (target / context = result) and uses columns to help define each. +// +// The calculation presumes that your column structure will be missing the last gutter: +// +// -- column -- gutter -- column -- gutter -- column +// +// $fg-column: 60px; // Column Width +// $fg-gutter: 25px; // Gutter Width +// $fg-max-columns: 12; // Total Columns For Main Container +// +// div { +// width: flex-grid(4); // returns (315px / 995px) = 31.65829%; +// margin-left: flex-gutter(); // returns (25px / 995px) = 2.51256%; +// +// p { +// width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%; +// float: left; +// margin: flex-gutter(4); // returns (25px / 315px) = 7.936508%; +// } +// +// blockquote { +// float: left; +// width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%; +// } +// } \ No newline at end of file diff --git a/_css/bourbon/functions/_grid-width.scss b/_css/bourbon/functions/_grid-width.scss new file mode 100644 index 00000000..8e63d83d --- /dev/null +++ b/_css/bourbon/functions/_grid-width.scss @@ -0,0 +1,13 @@ +@function grid-width($n) { + @return $n * $gw-column + ($n - 1) * $gw-gutter; +} + +// The $gw-column and $gw-gutter variables must be defined in your base stylesheet to properly use the grid-width function. +// +// $gw-column: 100px; // Column Width +// $gw-gutter: 40px; // Gutter Width +// +// div { +// width: grid-width(4); // returns 520px; +// margin-left: $gw-gutter; // returns 40px; +// } diff --git a/_css/bourbon/functions/_linear-gradient.scss b/_css/bourbon/functions/_linear-gradient.scss new file mode 100644 index 00000000..c8454d83 --- /dev/null +++ b/_css/bourbon/functions/_linear-gradient.scss @@ -0,0 +1,13 @@ +@function linear-gradient($pos, $gradients...) { + $type: linear; + $pos-type: type-of(nth($pos, 1)); + + // if $pos doesn't exist, fix $gradient + @if ($pos-type == color) or (nth($pos, 1) == "transparent") { + $gradients: zip($pos $gradients); + $pos: false; + } + + $type-gradient: $type, $pos, $gradients; + @return $type-gradient; +} diff --git a/_css/bourbon/functions/_modular-scale.scss b/_css/bourbon/functions/_modular-scale.scss new file mode 100644 index 00000000..dddccb52 --- /dev/null +++ b/_css/bourbon/functions/_modular-scale.scss @@ -0,0 +1,40 @@ +@function modular-scale($value, $increment, $ratio) { + @if $increment > 0 { + @for $i from 1 through $increment { + $value: ($value * $ratio); + } + } + + @if $increment < 0 { + $increment: abs($increment); + @for $i from 1 through $increment { + $value: ($value / $ratio); + } + } + + @return $value; +} + +// div { +// Increment Up GR with positive value +// font-size: modular-scale(14px, 1, 1.618); // returns: 22.652px +// +// Increment Down GR with negative value +// font-size: modular-scale(14px, -1, 1.618); // returns: 8.653px +// +// Can be used with ceil(round up) or floor(round down) +// font-size: floor( modular-scale(14px, 1, 1.618) ); // returns: 22px +// font-size: ceil( modular-scale(14px, 1, 1.618) ); // returns: 23px +// } +// +// modularscale.com + +@function golden-ratio($value, $increment) { + @return modular-scale($value, $increment, 1.618) +} + +// div { +// font-size: golden-ratio(14px, 1); // returns: 22.652px +// } +// +// goldenratiocalculator.com diff --git a/_css/bourbon/functions/_px-to-em.scss b/_css/bourbon/functions/_px-to-em.scss new file mode 100644 index 00000000..2eb1031c --- /dev/null +++ b/_css/bourbon/functions/_px-to-em.scss @@ -0,0 +1,8 @@ +// Convert pixels to ems +// eg. for a relational value of 12px write em(12) when the parent is 16px +// if the parent is another value say 24px write em(12, 24) + +@function em($pxval, $base: 16) { + @return ($pxval / $base) * 1em; +} + diff --git a/_css/bourbon/functions/_radial-gradient.scss b/_css/bourbon/functions/_radial-gradient.scss new file mode 100644 index 00000000..75584060 --- /dev/null +++ b/_css/bourbon/functions/_radial-gradient.scss @@ -0,0 +1,23 @@ +// This function is required and used by the background-image mixin. +@function radial-gradient($G1, $G2, + $G3: false, $G4: false, + $G5: false, $G6: false, + $G7: false, $G8: false, + $G9: false, $G10: false, + $pos: null, + $shape-size: null) { + + $data: _radial-arg-parser($G1, $G2, $pos, $shape-size); + $G1: nth($data, 1); + $G2: nth($data, 2); + $pos: nth($data, 3); + $shape-size: nth($data, 4); + + $type: radial; + $gradient: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10); + + $type-gradient: $type, $shape-size $pos, $gradient; + @return $type-gradient; +} + + diff --git a/_css/bourbon/functions/_tint-shade.scss b/_css/bourbon/functions/_tint-shade.scss new file mode 100644 index 00000000..f7172004 --- /dev/null +++ b/_css/bourbon/functions/_tint-shade.scss @@ -0,0 +1,9 @@ +// Add percentage of white to a color +@function tint($color, $percent){ + @return mix(white, $color, $percent); +} + +// Add percentage of black to a color +@function shade($color, $percent){ + @return mix(black, $color, $percent); +} diff --git a/_css/bourbon/functions/_transition-property-name.scss b/_css/bourbon/functions/_transition-property-name.scss new file mode 100644 index 00000000..54cd4228 --- /dev/null +++ b/_css/bourbon/functions/_transition-property-name.scss @@ -0,0 +1,22 @@ +// Return vendor-prefixed property names if appropriate +// Example: transition-property-names((transform, color, background), moz) -> -moz-transform, color, background +//************************************************************************// +@function transition-property-names($props, $vendor: false) { + $new-props: (); + + @each $prop in $props { + $new-props: append($new-props, transition-property-name($prop, $vendor), comma); + } + + @return $new-props; +} + +@function transition-property-name($prop, $vendor: false) { + // put other properties that need to be prefixed here aswell + @if $vendor and $prop == transform { + @return unquote('-'+$vendor+'-'+$prop); + } + @else { + @return $prop; + } +} \ No newline at end of file diff --git a/_css/bourbon/helpers/_deprecated-webkit-gradient.scss b/_css/bourbon/helpers/_deprecated-webkit-gradient.scss new file mode 100644 index 00000000..cd17e283 --- /dev/null +++ b/_css/bourbon/helpers/_deprecated-webkit-gradient.scss @@ -0,0 +1,39 @@ +// Render Deprecated Webkit Gradient - Linear || Radial +//************************************************************************// +@function _deprecated-webkit-gradient($type, + $deprecated-pos1, $deprecated-pos2, + $full, + $deprecated-radius1: false, $deprecated-radius2: false) { + $gradient-list: (); + $gradient: false; + $full-length: length($full); + $percentage: false; + $gradient-type: $type; + + @for $i from 1 through $full-length { + $gradient: nth($full, $i); + + @if length($gradient) == 2 { + $color-stop: color-stop(nth($gradient, 2), nth($gradient, 1)); + $gradient-list: join($gradient-list, $color-stop, comma); + } + @else if $gradient != null { + @if $i == $full-length { + $percentage: 100%; + } + @else { + $percentage: ($i - 1) * (100 / ($full-length - 1)) + "%"; + } + $color-stop: color-stop(unquote($percentage), $gradient); + $gradient-list: join($gradient-list, $color-stop, comma); + } + } + + @if $type == radial { + $gradient: -webkit-gradient(radial, $deprecated-pos1, $deprecated-radius1, $deprecated-pos2, $deprecated-radius2, $gradient-list); + } + @else if $type == linear { + $gradient: -webkit-gradient(linear, $deprecated-pos1, $deprecated-pos2, $gradient-list); + } + @return $gradient; +} diff --git a/_css/bourbon/helpers/_gradient-positions-parser.scss b/_css/bourbon/helpers/_gradient-positions-parser.scss new file mode 100644 index 00000000..07d30b6c --- /dev/null +++ b/_css/bourbon/helpers/_gradient-positions-parser.scss @@ -0,0 +1,13 @@ +@function _gradient-positions-parser($gradient-type, $gradient-positions) { + @if $gradient-positions + and ($gradient-type == linear) + and (type-of($gradient-positions) != color) { + $gradient-positions: _linear-positions-parser($gradient-positions); + } + @else if $gradient-positions + and ($gradient-type == radial) + and (type-of($gradient-positions) != color) { + $gradient-positions: _radial-positions-parser($gradient-positions); + } + @return $gradient-positions; +} diff --git a/_css/bourbon/helpers/_linear-positions-parser.scss b/_css/bourbon/helpers/_linear-positions-parser.scss new file mode 100644 index 00000000..d26383ed --- /dev/null +++ b/_css/bourbon/helpers/_linear-positions-parser.scss @@ -0,0 +1,61 @@ +@function _linear-positions-parser($pos) { + $type: type-of(nth($pos, 1)); + $spec: null; + $degree: null; + $side: null; + $corner: null; + $length: length($pos); + // Parse Side and corner positions + @if ($length > 1) { + @if nth($pos, 1) == "to" { // Newer syntax + $side: nth($pos, 2); + + @if $length == 2 { // eg. to top + // Swap for backwards compatability + $degree: _position-flipper(nth($pos, 2)); + } + @else if $length == 3 { // eg. to top left + $corner: nth($pos, 3); + } + } + @else if $length == 2 { // Older syntax ("top left") + $side: _position-flipper(nth($pos, 1)); + $corner: _position-flipper(nth($pos, 2)); + } + + @if ("#{$side} #{$corner}" == "left top") or ("#{$side} #{$corner}" == "top left") { + $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); + } + @else if ("#{$side} #{$corner}" == "right top") or ("#{$side} #{$corner}" == "top right") { + $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); + } + @else if ("#{$side} #{$corner}" == "right bottom") or ("#{$side} #{$corner}" == "bottom right") { + $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); + } + @else if ("#{$side} #{$corner}" == "left bottom") or ("#{$side} #{$corner}" == "bottom left") { + $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); + } + $spec: to $side $corner; + } + @else if $length == 1 { + // Swap for backwards compatability + @if $type == string { + $degree: $pos; + $spec: to _position-flipper($pos); + } + @else { + $degree: -270 - $pos; //rotate the gradient opposite from spec + $spec: $pos; + } + } + $degree: unquote($degree + ","); + $spec: unquote($spec + ","); + @return $degree $spec; +} + +@function _position-flipper($pos) { + @return if($pos == left, right, null) + if($pos == right, left, null) + if($pos == top, bottom, null) + if($pos == bottom, top, null); +} diff --git a/_css/bourbon/helpers/_radial-arg-parser.scss b/_css/bourbon/helpers/_radial-arg-parser.scss new file mode 100644 index 00000000..3466695b --- /dev/null +++ b/_css/bourbon/helpers/_radial-arg-parser.scss @@ -0,0 +1,69 @@ +@function _radial-arg-parser($G1, $G2, $pos, $shape-size) { + @each $value in $G1, $G2 { + $first-val: nth($value, 1); + $pos-type: type-of($first-val); + $spec-at-index: null; + + // Determine if spec was passed to mixin + @if type-of($value) == list { + $spec-at-index: if(index($value, at), index($value, at), false); + } + @if $spec-at-index { + @if $spec-at-index > 1 { + @for $i from 1 through ($spec-at-index - 1) { + $shape-size: $shape-size nth($value, $i); + } + @for $i from ($spec-at-index + 1) through length($value) { + $pos: $pos nth($value, $i); + } + } + @else if $spec-at-index == 1 { + @for $i from ($spec-at-index + 1) through length($value) { + $pos: $pos nth($value, $i); + } + } + $G1: false; + } + + // If not spec calculate correct values + @else { + @if ($pos-type != color) or ($first-val != "transparent") { + @if ($pos-type == number) + or ($first-val == "center") + or ($first-val == "top") + or ($first-val == "right") + or ($first-val == "bottom") + or ($first-val == "left") { + + $pos: $value; + + @if $pos == $G1 { + $G1: false; + } + } + + @else if + ($first-val == "ellipse") + or ($first-val == "circle") + or ($first-val == "closest-side") + or ($first-val == "closest-corner") + or ($first-val == "farthest-side") + or ($first-val == "farthest-corner") + or ($first-val == "contain") + or ($first-val == "cover") { + + $shape-size: $value; + + @if $value == $G1 { + $G1: false; + } + + @else if $value == $G2 { + $G2: false; + } + } + } + } + } + @return $G1, $G2, $pos, $shape-size; +} diff --git a/_css/bourbon/helpers/_radial-positions-parser.scss b/_css/bourbon/helpers/_radial-positions-parser.scss new file mode 100644 index 00000000..6a5b4777 --- /dev/null +++ b/_css/bourbon/helpers/_radial-positions-parser.scss @@ -0,0 +1,18 @@ +@function _radial-positions-parser($gradient-pos) { + $shape-size: nth($gradient-pos, 1); + $pos: nth($gradient-pos, 2); + $shape-size-spec: _shape-size-stripper($shape-size); + + $pre-spec: unquote(if($pos, "#{$pos}, ", null)) + unquote(if($shape-size, "#{$shape-size},", null)); + $pos-spec: if($pos, "at #{$pos}", null); + + $spec: "#{$shape-size-spec} #{$pos-spec}"; + + // Add comma + @if ($spec != ' ') { + $spec: "#{$spec}," + } + + @return $pre-spec $spec; +} diff --git a/_css/bourbon/helpers/_render-gradients.scss b/_css/bourbon/helpers/_render-gradients.scss new file mode 100644 index 00000000..57656768 --- /dev/null +++ b/_css/bourbon/helpers/_render-gradients.scss @@ -0,0 +1,26 @@ +// User for linear and radial gradients within background-image or border-image properties + +@function _render-gradients($gradient-positions, $gradients, $gradient-type, $vendor: false) { + $pre-spec: null; + $spec: null; + $vendor-gradients: null; + @if $gradient-type == linear { + @if $gradient-positions { + $pre-spec: nth($gradient-positions, 1); + $spec: nth($gradient-positions, 2); + } + } + @else if $gradient-type == radial { + $pre-spec: nth($gradient-positions, 1); + $spec: nth($gradient-positions, 2); + } + + @if $vendor { + $vendor-gradients: -#{$vendor}-#{$gradient-type}-gradient(#{$pre-spec} $gradients); + } + @else if $vendor == false { + $vendor-gradients: "#{$gradient-type}-gradient(#{$spec} #{$gradients})"; + $vendor-gradients: unquote($vendor-gradients); + } + @return $vendor-gradients; +} diff --git a/_css/bourbon/helpers/_shape-size-stripper.scss b/_css/bourbon/helpers/_shape-size-stripper.scss new file mode 100644 index 00000000..ee5eda42 --- /dev/null +++ b/_css/bourbon/helpers/_shape-size-stripper.scss @@ -0,0 +1,10 @@ +@function _shape-size-stripper($shape-size) { + $shape-size-spec: null; + @each $value in $shape-size { + @if ($value == "cover") or ($value == "contain") { + $value: null; + } + $shape-size-spec: "#{$shape-size-spec} #{$value}"; + } + @return $shape-size-spec; +} diff --git a/_css/react.scss b/_css/react.scss new file mode 100644 index 00000000..83e8b5b2 --- /dev/null +++ b/_css/react.scss @@ -0,0 +1,630 @@ +@import 'bourbon/bourbon'; +@import '_variables'; +@import '_typography'; +@import '_solarized'; + +$skinnyContentWidth: 650px; +$contentWidth: 920px; +$contentPadding: 20px; +$columnWidth: 280px; +$columnGutter: 40px; +$twoColumnWidth: 2 * $columnWidth + $columnGutter; + + + +// basic reset +* { + @include box-sizing(border-box); + border: none; + margin: 0; + padding: 0; +} + +html { + background: $pageBg; +} + + + +.left { + float: left; +} + +.right { + float: right; +} + + +.container { + padding-top: 50px; + min-width: $contentWidth + (2 * $contentPadding); +} + +.wrap { + width: $contentWidth + (2 * $contentPadding); + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; +} + +.skinnyWrap { + width: $skinnyContentWidth + (2 * $contentPadding); + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; +} + +hr { + height: 0; + border-top: 1px solid #ccc; + border-bottom: 1px solid #eee; +} + +ul, +li { + margin-left: 20px; +} + +// Main Nav + +.nav-main { + @include clearfix; + background: $darkestColor; + color: $lightTextColor; + position: fixed; + top: 0; + height: 50px; + box-shadow: 0 0 5px rgba(0, 0, 0, .5); + width: 100%; + z-index: 100; + + a { + color: $lightColor; + text-decoration: none; + } + + .nav-site { + float: right; + margin: 0; + + li { + margin: 0; + } + + a { + padding: 0 8px; + text-transform: uppercase; + letter-spacing: 1px; + line-height: 50px; + display: inline-block; + height: 50px; + color: $mediumTextColor; + + &:hover { + color: $lightTextColor; + } + + &.active { + color: $lightTextColor; + border-bottom: 3px solid $primary; + background: #333; + } + } + } + + .nav-home { + color: #00d8ff; + font-size: 24px; + line-height: 50px; + } + + .nav-logo { + @include retina-image('../img/logo_small', 38px 38px); + vertical-align: middle; + } + + ul { + display: inline; + } + + li { + display: inline; + } +} + +// Hero! + +.hero { + height: 300px; + // background: $darkColor url(../img/header.png) no-repeat center; + background: $darkColor; + padding-top: 50px; + color: $lightColor; + font-weight: 300; + + .text { + font-size: 64px; + text-align: center; + } + + .minitext { + font-size: 16px; + text-align: center; + text-transform: uppercase; + } + + strong { + color: $blueColor; + font-weight: 400; + } +} + +.buttons-unit { + margin-top: 60px; + text-align: center; + + a { + color: $blueColor; + } + + .button { + font-size: 24px; + background: $primary; + color: $lightTextColor; + + &:active { + background: darken($primary, 5%); + } + } +} + +// Downloads + +.buttons-unit.downloads { + margin: 30px 0; +} + +// Docs Nav + +.nav-docs { + color: $darkColor; + font-size: 14px; + // position: fixed; + float: left; + top: 100px; + width: 180px; + + ul { + list-style: none; + margin: 0; + } + li { + margin: 0; + } + h3 { + text-transform: uppercase; + font-size: 14px; + } + a { + color: $mediumestColor; + display: block; + + &:hover { + text-decoration: none; + color: $primary; + } + + &.active { + color: $primary; + } + } + + .nav-docs-section { + border-bottom: 1px solid #ccc; + border-top: 1px solid #eee; + padding: 12px 0; + + &:first-child { + padding-top: 0; + border-top: 0; + } + + &:last-child { + padding-bottom: 0; + border-bottom: 0; + } + } + +} + +// Home Page specifics + +.home-section { + margin: 50px 0; +} + +.home-divider { + border-top-color: #bbb; + margin: 0 auto; + width: 400px; +} + +.marketing-row { + @include clearfix; + margin: 50px 0; +} + +.marketing-col { + float: left; + margin-right: 40px; + width: $columnWidth; + + h3 { + color: $darkColor; + font-size: 24px; + font-weight: normal; + text-transform: uppercase; + } + p { + font-size: 16px; + } +} + +.marketing-col:last-child { + margin-right: 0; +} + +#examples { + h3 { + color: $darkColor; + font-size: 24px; + font-weight: normal; + margin-bottom: 5px; + } + + p { + margin: 0 0 25px 0; + max-width: $twoColumnWidth; + } + + .example { + margin-top: 60px; + } + + #todoExample { + font-size: 14px; + ul { + list-style-type: square; + margin: 0 0 10px 0; + } + input { + border: 1px solid #ccc; + font: 14px proxima-nova, $helvetica; + padding: 3px; + width: 150px; + } + button { + font: 14px proxima-nova, $helvetica; + margin-left: 5px; + padding: 4px 10px; + } + } + + #markdownExample { + textarea { + border: 1px solid #ccc; + font: 14px proxima-nova, $helvetica; + margin-bottom: 10px; + padding: 5px; + } + } +} + +.home-bottom-section { + margin-bottom: 100px; +} + +.docs-nextprev { + @include clearfix; +} + +.docs-prev { + float: left; +} + +.docs-next { + float: right; +} + +footer { + font-size: 13px; + font-weight: 600; + margin-top: 36px; + margin-bottom: 18px; + overflow: auto; +} + +section.black content { + padding-bottom: 18px; +} + +/** + * Docs + */ + +.documentationContent { + @include clearfix; + + .subHeader { + font-size: 24px; + } + + // H2s form documentation topic dividers. Extra space helps. + h2 { + margin-top: 30px; + } + + padding-top: 20px; + + // Make a notice box out of blockquotes in the documetation: + blockquote { + padding: 15px 30px 15px 15px; + margin: 20px 0; + background-color: rgba(204, 122, 111, 0.09999999999999998); + border-left: 5px solid rgba(191, 87, 73, 0.19999999999999996); + h4 { + margin-top: 0; + } + p:last-child { + margin-bottom: 0; + } + // Treat first child as the title - promote to H4. + p:first-child { + font-weight: bold; + font-size: 17.5px; + line-height: 20px; + margin-top: 0; + text-rendering: optimizelegibility; + } + } +} + +.docs-prevnext { + padding-top: 40px; + padding-bottom: 40px; +} + + +/* Button */ + +.button { + @include background(linear-gradient($buttonGreyTop, $buttonGreyBottom)); + // border: 1px solid $darkestColor; + border-radius: 4px; + padding: 8px 16px; + font-size: 18px; + font-weight: 400; + margin: 0 12px; + // word-spacing: -2px; + // letter-spacing: 1px; + display: inline-block; + color: $lightTextColor; + text-decoration: none; + text-shadow: 0 1px 3px rgba(0, 0, 0, .3); + box-shadow: 0 1px 1px rgba(0, 0, 0, .2); + text-decoration: none; + + &:hover { + text-decoration: none; + } + + &:active { + box-shadow: none; + } +} + +.hero { + .button { + box-shadow: 1px 3px 3px rgba(0, 0, 0, .3); + } +} + +.button.blue { + @include background(linear-gradient($buttonBlueTop, $buttonBlueBottom)); +} + + +/* Row */ + +.row { + padding-bottom: 4px; +} + +.row .span4 { + width: 33.33%; + display: table-cell; +} + +.row .span8 { + width: 66.66%; + display: table-cell; +} + +.row .span6 { + width: 50%; + display: table-cell; +} + + +/* Content */ + +p { + margin: 10px 0; +} + +.highlight { + padding: 10px; + margin-bottom: 20px; +} + +.inner-content { + float: right; + width: $skinnyContentWidth; +} + +.nosidebar .inner-content { + float: none; + margin: 0 auto; +} + +/* Code Mirror */ + +div.CodeMirror pre, div.CodeMirror-linenumber, code { + font-family: 'source-code-pro', Menlo, 'Courier New', Consolas, monospace; + font-size: 13px; + line-height: 20px; +} + +div.CodeMirror-linenumber:after { + content: '.'; +} + +.CodeMirror, div.CodeMirror-gutters, div.highlight { + border: none; +} + +small code, +li code, +p code { + color: #555; + background-color: rgba(0, 0, 0, .04); + padding: 1px 3px; +} + +.cm-s-default span.cm-string-2 { + color: inherit; +} + +.playground { + @include clearfix; +} + +.playground::before { + border-bottom: none !important; + border-radius: 3px 3px 0 0; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #c2c0bc; + background-color: #f1ede4; + content: 'Live editor'; +} + +.playground::before, +.playgroundCode, +.playgroundPreview { + border: 1px solid rgba(16,16,16,0.1); +} + +.playgroundCode { + border-radius: 0 3px 3px 3px; + float: left; + overflow: hidden; + width: $twoColumnWidth; +} + +.playgroundPreview { + background-color: white; + border-radius: 3px; + float: right; + padding: 15px 20px; + width: $columnWidth; +} + +.MarkdownEditor textarea { + width: 100%; + height: 100px +} + +.hll { + background-color: #f7ebc6; + border-left: 5px solid #f7d87c; + display: block; + margin-left: -14px; + margin-right: -14px; + padding-left: 9px; +} + +/* Codemirror doesn't support syntax. Instead of highlighting it + as error, just ignore it */ +.highlight .javascript .err { + background-color: transparent; + color: inherit; +} + +.highlight { + position: relative; + margin-bottom: 14px; + padding: 30px 14px 14px; + border: none; + border-radius: 0; + overflow: auto; +} + + +.highlight pre { + padding: 0; + margin-top: 0; + margin-bottom: 0; + background-color: transparent; + border: 0; +} + +.highlight pre code { + font-size: inherit; +} + +.highlight pre .lineno { + display: inline-block; + width: 22px; + padding-right: 5px; + margin-right: 10px; + color: #bebec5; + text-align: right; +} + +/* Echo out a label for the example */ + +.highlight:after { + position: absolute; + top: 0; + right: 0; + left: 0; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #c2c0bc; + background-color: #f1ede4; + content: "Code"; +} + +.downloadCenter { + text-align: center; + margin-top: 20px; + margin-bottom: 25px; +} + +.downloadSection:hover { + text-decoration: none !important; +} + +@media screen and (max-width: 960px) { + .nav-main { + position: static; + } + .container { + padding-top: 0; + } +} diff --git a/_includes/nav_docs.html b/_includes/nav_docs.html new file mode 100644 index 00000000..e896ac8e --- /dev/null +++ b/_includes/nav_docs.html @@ -0,0 +1,23 @@ + diff --git a/_js/examples/hello.js b/_js/examples/hello.js new file mode 100644 index 00000000..019281bd --- /dev/null +++ b/_js/examples/hello.js @@ -0,0 +1,19 @@ +/** + * @jsx React.DOM + */ + +var HELLO_COMPONENT = "\ +/** @jsx React.DOM */\n\ +var HelloMessage = React.createClass({\n\ + render: function() {\n\ + return
{'Hello ' + this.props.name}
;\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + , + document.getElementById('helloExample') +); diff --git a/_js/examples/markdown.js b/_js/examples/markdown.js new file mode 100644 index 00000000..ec4363f5 --- /dev/null +++ b/_js/examples/markdown.js @@ -0,0 +1,42 @@ +/** + * @jsx React.DOM + */ + +var MARKDOWN_COMPONENT = "\ +/** @jsx React.DOM */\n\ +\n\ +var converter = new Showdown.converter();\n\ +\n\ +var MarkdownEditor = React.createClass({\n\ + getInitialState: function() {\n\ + return {value: 'Type some *markdown* here!'};\n\ + },\n\ + handleKeyUp: React.autoBind(function() {\n\ + this.setState({value: this.refs.textarea.getDOMNode().value});\n\ + }),\n\ + render: function() {\n\ + return (\n\ +
\n\ +

Input

\n\ + \n\ +

Output

\n\ + \n\ +
\n\ + );\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + , + document.getElementById('markdownExample') +); diff --git a/_js/examples/timer.js b/_js/examples/timer.js new file mode 100644 index 00000000..0dfc2c3a --- /dev/null +++ b/_js/examples/timer.js @@ -0,0 +1,32 @@ +/** + * @jsx React.DOM + */ + +var TIMER_COMPONENT = "\ +/** @jsx React.DOM */\n\ +var Timer = React.createClass({\n\ + getInitialState: function() {\n\ + return {secondsElapsed: 0};\n\ + },\n\ + tick: React.autoBind(function() {\n\ + this.setState({secondsElapsed: this.state.secondsElapsed + 1});\n\ + }),\n\ + componentDidMount: function() {\n\ + setInterval(this.tick, 1000);\n\ + },\n\ + render: function() {\n\ + return (\n\ +
\n\ + {'Seconds Ellapsed: ' + this.state.secondsElapsed}\n\ +
\n\ + );\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + , + document.getElementById('timerExample') +); diff --git a/_js/examples/todo.js b/_js/examples/todo.js new file mode 100644 index 00000000..fa2c5dc1 --- /dev/null +++ b/_js/examples/todo.js @@ -0,0 +1,57 @@ +/** + * @jsx React.DOM + */ + +var TODO_COMPONENT = "\ +/** @jsx React.DOM */\n\ +var TodoList = React.createClass({\n\ + render: function() {\n\ + var items = this.props.items.map(function(item) {\n\ + return
  • {item}
  • ;\n\ + });\n\ + return
      {items}
    ;\n\ + }\n\ +});\n\ +\n\ +var TodoCreate = React.createClass({\n\ + handleSubmit: function() {\n\ + var textInput = this.refs.textInput.getDOMNode();\n\ + this.props.onCreate(textInput.value);\n\ + textInput.value = '';\n\ + return false;\n\ + },\n\ + render: function() {\n\ + return (\n\ +
    \n\ + \n\ + \n\ +
    \n\ + );\n\ + }\n\ +});\n\ +\n\ +var TodoApp = React.createClass({\n\ + getInitialState: function() {\n\ + return {items: []};\n\ + },\n\ + onItemCreate: function(value) {\n\ + this.setState({items: this.state.items.concat([value])});\n\ + },\n\ + render: function() {\n\ + return (\n\ +
    \n\ +

    TODO

    \n\ + \n\ + \n\ +
    \n\ + );\n\ + }\n\ +});\n\ +\n\ +React.renderComponent(, mountNode);\ +"; + +React.renderComponent( + , + document.getElementById('todoExample') +); diff --git a/_js/live_editor.js b/_js/live_editor.js new file mode 100644 index 00000000..0b7bc868 --- /dev/null +++ b/_js/live_editor.js @@ -0,0 +1,98 @@ +/** + * @jsx React.DOM + */ + +var CodeMirrorEditor = React.createClass({ + componentDidMount: function(root) { + this.editor = CodeMirror.fromTextArea(this.refs.editor.getDOMNode(), { + mode: 'javascript', + lineNumbers: false, + matchBrackets: true, + theme: 'solarized-light' + }); + this.editor.on('change', this.onChange.bind(this)); + this.onChange(); + }, + onChange: function() { + if (this.props.onChange) { + var content = this.editor.getValue(); + this.props.onChange(content); + } + }, + render: function() { + // wrap in a div to fully contain CodeMirror + return ( +
    + +
    + ); + } +}); + +var ReactPlayground = React.createClass({ + MODES: {XJS: 'XJS', JS: 'JS'}, //keyMirror({XJS: true, JS: true}), + + getInitialState: function() { + return {mode: this.MODES.XJS, code: this.props.codeText}; + }, + + bindState: function(name) { + return function(value) { + var newState = {}; + newState[name] = value; + this.setState(newState); + }.bind(this); + }, + + getDesugaredCode: function() { + return JSXTransformer.transform(this.state.code).code; + }, + + render: function() { + var content; + if (this.state.mode === this.MODES.XJS) { + content = + ; + } else if (this.state.mode === this.MODES.JS) { + content = +
    + {this.getDesugaredCode()} +
    ; + } + + return ( +
    +
    + {content} +
    +
    +
    +
    +
    + ); + }, + componentDidMount: function() { + this.executeCode(); + }, + componentDidUpdate: function() { + this.executeCode(); + }, + executeCode: function() { + var mountNode = this.refs.mount.getDOMNode(); + + try { + React.unmountAndReleaseReactRootNode(mountNode); + } catch (e) { } + + try { + eval(this.getDesugaredCode()); + } catch (e) { + React.renderComponent(
    , mountNode); + } + } +}); + diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 00000000..c430d9bf --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,75 @@ + + + + + + React | {{ page.title }} + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + {% if page.id == 'home' %} +
    +
    +
    React
    +
    + A JavaScript library for building user interfaces +
    + + +
    +
    + {% endif %} + + {{ content }} + +
    +
    A Facebook & Instagram collaboration.
    +
    © 2013 Facebook Inc.
    +
    +
    + + + diff --git a/_layouts/docs.html b/_layouts/docs.html new file mode 100644 index 00000000..bda55583 --- /dev/null +++ b/_layouts/docs.html @@ -0,0 +1,23 @@ +--- +layout: default +sectionid: docs +--- + +
    + {% include nav_docs.html %} + +
    +

    {{ page.title }}

    +
    {{ page.description }}
    + {{ content }} + +
    + {% if page.prev %} + ← Prev + {% endif %} + {% if page.next %} + Next → + {% endif %} +
    +
    +
    diff --git a/_layouts/page.html b/_layouts/page.html new file mode 100644 index 00000000..bb172b22 --- /dev/null +++ b/_layouts/page.html @@ -0,0 +1,7 @@ +--- +layout: default +--- + +
    + {{ content }} +
    diff --git a/_layouts/post.html b/_layouts/post.html new file mode 100644 index 00000000..822eadba --- /dev/null +++ b/_layouts/post.html @@ -0,0 +1,12 @@ +--- +layout: default +--- + +
    +

    {{ page.title }}

    +

    {{ page.date | date_to_string }}

    + +
    + {{ content }} +
    +
    diff --git a/_layouts/single.html b/_layouts/single.html new file mode 100644 index 00000000..deb71709 --- /dev/null +++ b/_layouts/single.html @@ -0,0 +1,20 @@ +--- +layout: default +--- + +
    +
    +

    {{ page.title }}

    +
    {{ page.description }}
    + {{ content }} + +
    + {% if page.prev %} + ← Prev + {% endif %} + {% if page.next %} + Next → + {% endif %} +
    +
    +
    diff --git a/_plugins/highlight_lines.rb b/_plugins/highlight_lines.rb new file mode 100644 index 00000000..f0e27498 --- /dev/null +++ b/_plugins/highlight_lines.rb @@ -0,0 +1,39 @@ +# Replace Jekyll's handling of the Redcarpet code_block (which already adds +# support for highlighting, but needs support for the very non-standard +# "code fences with line highlights" extension). +# Since this is currently depending on Redcarpet to cooperate, we are going to +# be naive, and only allow line highlighting when a language is specified. If +# you don't want any syntax highlighting but want to highlight lines, then you +# need to specify text as your language, like: +# ```text{4} + + +module Jekyll + module Converters + class Markdown + class RedcarpetParser + module WithPygments + def block_code(code, lang) + require 'pygments' + lang_parts = lang && lang.split('{') + lang = lang_parts && !lang_parts[0].empty? && lang_parts[0] || 'text' + hl_lines = '' + if lang_parts && lang_parts.size >= 2 + hl_lines = lang_parts[1].gsub(/[{}]/, '').split(',').map do |ln| + if matches = /(\d+)-(\d+)/.match(ln) + ln = Range.new(matches[1], matches[2]).to_a.join(' ') + end + ln + end.join(' ') + end + output = add_code_tags( + Pygments.highlight(code, :lexer => lang, + :options => { :encoding => 'utf-8', :hl_lines => hl_lines }), + lang + ) + end + end + end + end + end +end diff --git a/css/codemirror.css b/css/codemirror.css new file mode 100644 index 00000000..91138663 --- /dev/null +++ b/css/codemirror.css @@ -0,0 +1,239 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; +} +.CodeMirror-scroll { + /* Set scrolling behaviour here */ + overflow: auto; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 14px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 14px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; +} + +/* CURSOR */ + +.CodeMirror div.CodeMirror-cursor { + border-left: 1px solid black; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { + width: auto; + border: 0; + background: transparent; + background: rgba(0, 200, 0, .4); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800); +} +/* Kludge to turn off filter in ie9+, which also accepts rgba */ +.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor:not(#nonsense_id) { + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {} + +/* DEFAULT THEME */ + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable {color: black;} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-property {color: black;} +.cm-s-default .cm-operator {color: black;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-error {color: #f00;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-emstrong {font-style: italic; font-weight: bold;} +.cm-link {text-decoration: underline;} + +.cm-invalidchar {color: #f00;} + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + line-height: 1; + position: relative; + overflow: hidden; +} + +.CodeMirror-scroll { + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; padding-right: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actuall scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; + z-index: 6; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + height: 100%; + z-index: 3; +} +.CodeMirror-gutter { + height: 100%; + display: inline-block; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} + +.CodeMirror-lines { + cursor: text; +} +.CodeMirror pre { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; +} +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + overflow: auto; +} + +.CodeMirror-wrap .CodeMirror-scroll { + overflow-x: hidden; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; height: 0px; + overflow: hidden; + visibility: hidden; +} +.CodeMirror-measure pre { position: static; } + +.CodeMirror div.CodeMirror-cursor { + position: absolute; + visibility: hidden; + border-right: none; + width: 0; +} +.CodeMirror-focused div.CodeMirror-cursor { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } + +.cm-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursor { + visibility: hidden; + } +} diff --git a/css/main.css b/css/main.css new file mode 100755 index 00000000..ffd46418 --- /dev/null +++ b/css/main.css @@ -0,0 +1,165 @@ +/*****************************************************************************/ +/* +/* Common +/* +/*****************************************************************************/ + +/* Global Reset */ +* { + margin: 0; + padding: 0; +} + +html, body { height: 100%; } + +body { + background-color: #FFF; + font: 13.34px Helvetica, Arial, sans-serif; + font-size: small; + text-align: center; +} + +h1, h2, h3, h4, h5, h6 { + font-size: 100%; } + +h1 { margin-bottom: 1em; } +p { margin: 1em 0; } + +a { color: #00a; } +a:hover { color: #000; } +a:visited { color: #a0a; } + +table { + font-size: inherit; + font: 100%; +} + +/*****************************************************************************/ +/* +/* Home +/* +/*****************************************************************************/ +ul.posts { + list-style-type: none; + margin-bottom: 2em; +} + +ul.posts li { + line-height: 1.75em; +} + +ul.posts span { + color: #aaa; + font-family: Monaco, "Courier New", monospace; + font-size: 80%; +} + +/*****************************************************************************/ +/* +/* Site +/* +/*****************************************************************************/ + +.site { + font-size: 115%; + text-align: justify; + width: 42em; + margin: 3em auto 2em; + line-height: 1.5em; +} + +.site .header a { + font-weight: bold; + text-decoration: none; +} + +.site .header h1.title { + display: inline-block; + margin-bottom: 2em; +} + +.site .header h1.title a { + color: #a00; +} + +.site .header h1.title a:hover { + color: #000; +} + +.site .header a.extra { + color: #aaa; + margin-left: 1em; +} + +.site .header a.extra:hover { + color: #000; +} + +.site .meta { + color: #aaa; +} + +.site .footer { + font-size: 80%; + color: #666; + border-top: 4px solid #eee; + margin-top: 2em; + overflow: hidden; +} + +.site .footer .contact { + float: left; + margin-right: 3em; +} + +.site .footer .contact a { + color: #8085C1; +} + +.site .footer .rss { + margin-top: 1.1em; + margin-right: -.2em; + float: right; +} + +.site .footer .rss img { + border: 0; +} + +/*****************************************************************************/ +/* +/* Posts +/* +/*****************************************************************************/ + +/* standard */ +#post pre { + border: 1px solid #ddd; + background-color: #eef; + padding: 0 .4em; +} + +#post ul, #post ol { + margin-left: 1.35em; +} + +#post code { + border: 1px solid #ddd; + background-color: #eef; + padding: 0 .2em; +} + +#post pre code { + border: none; +} + +/* terminal */ +#post pre.terminal { + border: 1px solid #000; + background-color: #333; + color: #FFF; +} + +#post pre.terminal code { + background-color: #333; +} \ No newline at end of file diff --git a/css/syntax.css b/css/syntax.css new file mode 100644 index 00000000..2728fc0e --- /dev/null +++ b/css/syntax.css @@ -0,0 +1,409 @@ +.highlight pre code { + color: #637c84; +} + +.highlight { + color: #333333; + background: #f8f5ec; +} + +.highlight .c { + color: #93a1a1; +} + + +.highlight .g { + color: #637c84; +} + +/* Generic */ + +.highlight .k { + color: #859900; +} + +/* Keyword */ + +.highlight .l { + color: #637c84; +} + +/* Literal */ + +.highlight .n { + color: #637c84; +} + +/* Name */ + +.highlight .o { + color: #859900; +} + +/* Operator */ + +.highlight .x { + color: #cc7a6f; +} + +/* Other */ + +.highlight .p { + color: #637c84; +} + +/* Punctuation */ + +.highlight .cm { + color: #93a1a1; +} + +/* Comment.Multiline */ + +.highlight .cp { + color: #859900; +} + +/* Comment.Preproc */ + +.highlight .c1 { + color: #93a1a1; +} + +/* Comment.Single */ + +.highlight .cs { + color: #859900; +} + +/* Comment.Special */ + +.highlight .gd { + color: #36958e; +} + +/* Generic.Deleted */ + +.highlight .ge { + font-style: italic; + color: #637c84; +} + +/* Generic.Emph */ + +.highlight .gr { + color: #dc322f; +} + +/* Generic.Error */ + +.highlight .gh { + color: #cc7a6f; +} + +/* Generic.Heading */ + +.highlight .gi { + color: #859900; +} + +/* Generic.Inserted */ + +.highlight .go { + color: #637c84; +} + +/* Generic.Output */ + +.highlight .gp { + color: #637c84; +} + +/* Generic.Prompt */ + +.highlight .gs { + font-weight: bold; + color: #637c84; +} + +/* Generic.Strong */ + +.highlight .gu { + color: #cc7a6f; +} + +/* Generic.Subheading */ + +.highlight .gt { + color: #637c84; +} + +/* Generic.Traceback */ + +.highlight .kc { + color: #cc7a6f; +} + +/* Keyword.Constant */ + +.highlight .kd { + color: #268bd2; +} + +/* Keyword.Declaration */ + +.highlight .kn { + color: #859900; +} + +/* Keyword.Namespace */ + +.highlight .kp { + color: #859900; +} + +/* Keyword.Pseudo */ + +.highlight .kr { + color: #268bd2; +} + +/* Keyword.Reserved */ + +.highlight .kt { + color: #dc322f; +} + +/* Keyword.Type */ + +.highlight .ld { + color: #637c84; +} + +/* Literal.Date */ + +.highlight .m { + color: #36958e; +} + +/* Literal.Number */ + +.highlight .s { + color: #36958e; +} + +/* Literal.String */ + +.highlight .na { + color: #637c84; +} + +/* Name.Attribute */ + +.highlight .nb { + color: #b58900; +} + +/* Name.Builtin */ + +.highlight .nc { + color: #268bd2; +} + +/* Name.Class */ + +.highlight .no { + color: #cc7a6f; +} + +/* Name.Constant */ + +.highlight .nd { + color: #268bd2; +} + +/* Name.Decorator */ + +.highlight .ni { + color: #cc7a6f; +} + +/* Name.Entity */ + +.highlight .ne { + color: #cc7a6f; +} + +/* Name.Exception */ + +.highlight .nf { + color: #268bd2; +} + +/* Name.Function */ + +.highlight .nl { + color: #637c84; +} + +/* Name.Label */ + +.highlight .nn { + color: #637c84; +} + +/* Name.Namespace */ + +.highlight .nx { + color: #637c84; +} + +/* Name.Other */ + +.highlight .py { + color: #637c84; +} + +/* Name.Property */ + +.highlight .nt { + color: #268bd2; +} + +/* Name.Tag */ + +.highlight .nv { + color: #268bd2; +} + +/* Name.Variable */ + +.highlight .ow { + color: #859900; +} + +/* Operator.Word */ + +.highlight .w { + color: #637c84; +} + +/* Text.Whitespace */ + +.highlight .mf { + color: #36958e; +} + +/* Literal.Number.Float */ + +.highlight .mh { + color: #36958e; +} + +/* Literal.Number.Hex */ + +.highlight .mi { + color: #36958e; +} + +/* Literal.Number.Integer */ + +.highlight .mo { + color: #36958e; +} + +/* Literal.Number.Oct */ + +.highlight .sb { + color: #93a1a1; +} + +/* Literal.String.Backtick */ + +.highlight .sc { + color: #36958e; +} + +/* Literal.String.Char */ + +.highlight .sd { + color: #637c84; +} + +/* Literal.String.Doc */ + +.highlight .s2 { + color: #36958e; +} + +/* Literal.String.Double */ + +.highlight .se { + color: #cc7a6f; +} + +/* Literal.String.Escape */ + +.highlight .sh { + color: #637c84; +} + +/* Literal.String.Heredoc */ + +.highlight .si { + color: #36958e; +} + +/* Literal.String.Interpol */ + +.highlight .sx { + color: #36958e; +} + +/* Literal.String.Other */ + +.highlight .sr { + color: #dc322f; +} + +/* Literal.String.Regex */ + +.highlight .s1 { + color: #36958e; +} + +/* Literal.String.Single */ + +.highlight .ss { + color: #36958e; +} + +/* Literal.String.Symbol */ + +.highlight .bp { + color: #268bd2; +} + +/* Name.Builtin.Pseudo */ + +.highlight .vc { + color: #268bd2; +} + +/* Name.Variable.Class */ + +.highlight .vg { + color: #268bd2; +} + +/* Name.Variable.Global */ + +.highlight .vi { + color: #268bd2; +} + +/* Name.Variable.Instance */ + +.highlight .il { + color: #36958e; +} diff --git a/docs/advanced-components.md b/docs/advanced-components.md new file mode 100644 index 00000000..6a63b8f3 --- /dev/null +++ b/docs/advanced-components.md @@ -0,0 +1,119 @@ +--- +id: docs-advanced-components +title: Advanced Components +description: How to build advanced composite components. +layout: docs +prev: event-handling.html +next: api.html +--- + +Composite components extend a `ReactCompositeComponent` base class that provides +a very powerful API that makes React flexible and able to easily work with other +libraries and frameworks. + +## Lifecycle Methods + +Composite components can optionally implement lifecycle methods that are invoked +at various stages in the [component lifecycle](component-lifecycle.html) that +each have unique guarantees. + +### Mounting + + - `getInitialState(): object` is invoked before a component is mounted. + Stateful components should implement this and return the initial state data. + - `componentWillMount()` is invoked immediately before mounting occurs. + - `componentDidMount(DOMElement rootNode)` is invoked immediately after + mounting occurs. Initialization that requires DOM nodes should go here. + +### Updating + + - `componentWillReceiveProps(object nextProps)` is invoked when a mounted + component receives new props. This method should be used to compare + `this.props` and `nextProps` to perform state transitions using + `this.setState()`. + - `shouldComponentUpdate(object nextProps, object nextState): boolean` is + invoked when a component decides whether any changes warrant an update to the + DOM. Implement this as an optimization to compare `this.props` with + `nextProps` and `this.state` with `nextState` and return false if React + should skip updating. + - `componentWillUpdate(object nextProps, object nextState)` is invoked + immediately before updating occurs. You cannot call `this.setState()` here. + - `componentDidUpdate(object prevProps, object prevState, DOMElement rootNode)` + is invoked immediately after updating occurs. + +### Unmounting + + - `componentWillUnmount()` is invoked immediately before a component is + unmounted and destroyed. Cleanup should go here. + +## Mounted Methods + +_Mounted_ composite components also support the following methods: + + - `getDOMNode(): DOMElement` can be invoked on any mounted component in order + to obtain a reference to its rendered DOM node. + - `forceUpdate()` can be invoked on any mounted component when you know that + some deeper aspect of the component's state has changed without using + `this.setState()`. + +> Note: +> +> The `DOMElement rootNode` argument of `componentDidMount()` and +> `componentDidUpdate()` is a convenience. The same node can be obtained by +> calling `this.getDOMNode()`. + +## Component Refs + +A common use case of event callbacks or the lifecycle methods is to operate on a +component returned by `render()`. For example, consider a search component that +should auto-focus the input once mounted: + +```javascript +var SearchForm = React.createClass({ + render: function() { + return ( +
    + +
    + ); + }, + componentDidMount: function(rootNode) { + var searchInput = rootNode.firstChild; + searchInput.focus(); + } +}); +``` + +Although this implementation works, it is fragile because `componentDidMount()` +now relies on `render()` returning a particular DOM structure. + +React provides a better way for composite components to reference components +that it constructs in its `render()` method through the use of refs. A component +can assign a `ref` to any component it constructs. This will create a reference +to those components on `this.refs`. For example: + +```javascript{5,10} +var SearchForm = React.createClass({ + render: function() { + return ( +
    + +
    + ); + }, + componentDidMount: function(rootNode) { + var searchInput = this.refs.searchInput.getDOMNode(); + searchInput.focus(); + } +}); +``` + +In this example, `this.refs.searchInput` will reference the `` component +and is available in most lifecycle methods and event callbacks. We obtain a +reference to the ``'s DOM node using `getDOMNode()`. + +> Note: +> +> If you want to preserve compatibility with Google Closure Compiler's +> property crushing in `ADVANCED_OPTIMIZATIONS` mode, make sure to use string +> literals with `this.refs`. diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 00000000..6b5f0ab9 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,104 @@ +--- +id: docs-api +title: React API +layout: docs +prev: advanced-components.html +--- + +## React + +`React` is the entry point to the React framework. If you're using one of the prebuilt packages it's available as a global; if you're using CommonJS modules you can `require()` it. + +### DOM + +`React.DOM` provides all of the standard HTML tags needed to build a React app. You generally don't use it directly; instead, just include it as part of the `/** @jsx React.DOM */` docblock. + +### initializeTouchEvents(boolean shouldUseTouch) + +Configure React's event system to handle touch events on mobile devices. + +### function autoBind(function method) + +Marks the provided function to be automatically bound to each React component instance created. This allows React components to define automatically bound methods and ensure that when called they will always reference their current instance. + +Example: + +```javascript +React.createClass({ + click: React.autoBind(function(evt) { + this.setState({jumping: true}); + }), + render: function() { + // Look: no bind! + return Jump; + } +}); +``` + +### function createClass(object specification) + +Creates a component given a specification. A component implements a `render` method which returns a single child. That child may have an arbitrarily deep child structure. One thing that makes components different than a standard prototypal classes is that you don't need to call new on them. They are convenience wrappers that construct backing instances (via new) for you. + +### ReactComponent renderComponent(ReactComponent container, DOMElement mountPoint) + +Renders a React component into the DOM in the supplied `container`. + +If the React component was previously rendered into `container`, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React component. + +## AbstractEvent + +Your event handlers will be passed instances of `AbstractEvent`, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event (such as `stopPropagation()` and `preventDefault()`) except they work exactly the same across all browsers. + +If you find that you need the underlying browser event for some reason, simply use the `nativeEvent` attribute to get it. + +## ReactComponent + +Component classses created by `createClass()` return instances of `ReactComponent` when called. Most of the time when you're using React you're either creating or consuming `ReactComponent`s. + +### DOMElement getDOMNode() + +If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements. + +### setProps(object nextProps) + +When you're integrating with an external JavaScript application you may want to signal a change to a React component rendered with `renderComponent()`. Simply call `setProps()` to change its properties and trigger a re-render. + +**Note:** This method can only be called on a root-level component. That is, it's only available on the component passed directly to `renderComponent()` and none of its children. If you're inclined to use `setProps()` on a child component, instead take advantage of reactive updates and pass the new prop to the child component when it's created in `render()`. + +### replaceProps(object nextProps) + +Like `setProps()` but deletes any pre-existing props that are not in nextProps. + +### ReactComponent transferPropsTo(ReactComponent targetComponent) + +Transfer properties from this component to a target component that have not already been set on the target component. This is usually used to pass down properties to the returned root component. `targetComponent`, now updated with some new props is returned as a convenience. + +### setState(object nextState) + +Merges nextState with the current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks. + +**Note:** *NEVER* mutate `this.state` directly. As calling `setState()` afterwards may replace the mutation you made. Treat `this.state` as if it were immutable. + +**Note:** `setState()` does not immediately mutate `this.state` but creates a pending state transition. Accessing `this.state` after calling this method can potentially return the existing value. + +### replaceState(object nextState) + +Like `setState()` but deletes any pre-existing state keys that are not in nextState. + +### forceUpdate() + +If your `render()` method reads from something other than `this.props` or `this.state` you'll need to tell React when it needs to re-run `render()`. Use `forceUpdate()` to cause React to automatically re-render. This will cause `render()` to be called on the component and all of its children but React will only update the DOM if the markup changes. + +Normally you should try to avoid all uses of `forceUpdate()` and only read from `this.props` and `this.state` in `render()`. This makes your application much simpler and more efficient. + +### object getInitialState() +### componentWillMount() +### componentDidMount(DOMElement domNode) +### componentWillReceiveProps(object nextProps) +### boolean shouldComponentUpdate(object nextProps, object nextState) +### componentWillUpdate(object nextProps, object nextState) +### ReactComponent render() +### componentDidUpdate(object prevProps, object prevState, DOMElement domNode) +### componentWillUnmount() + +These are overridable lifecycle methods; see the [lifecycle methods](lifecycle.html) documentation for more information. diff --git a/docs/common-questions.md b/docs/common-questions.md new file mode 100644 index 00000000..b0b42687 --- /dev/null +++ b/docs/common-questions.md @@ -0,0 +1,22 @@ +--- +id: docs-common-questions +title: Common Questions +layout: docs +prev: tutorial.html +next: syntax.html +--- +### What browsers does React support? + +React supports the latest two Chrome, Firefox, Safari, and Internet Explorer versions. React can work with Internet Explorer 8 with polyfills. + +### How do I get React to support Internet Explorer 8? + +React requires ES5 JavaScript shims to run in Internet Explorer 8. Include the [ES5 Shims](https://github.com/kriskowal/es5-shim) to implement these shims. + +### Who uses React? + +The [Instagram](http://instagram.com/) website is built entirely in React. The [Facebook](https://www.facebook.com/) website is also increasingly using React, including the common commenting plugin across the site. + +### Can I integrate with other JavaScript libraries? + +Absolutely! In fact, we encourage it! See [our GitHub repo](http://github.com/facebook/react/) for a [TodoMVC example using Backbone](https://github.com/facebook/react/tree/master/examples/todomvc-backbone) and a [jQuery + Bootstrap modal demo](https://github.com/facebook/react/tree/master/examples/jquery-bootstrap). diff --git a/docs/component-basics.md b/docs/component-basics.md new file mode 100644 index 00000000..eacd2aa3 --- /dev/null +++ b/docs/component-basics.md @@ -0,0 +1,73 @@ +--- +id: docs-component-basics +title: Component Basics +description: What are components? +layout: docs +next: component-data.html +prev: syntax.html +--- + +_Components_ are the basic units of composition in React. Components encapsulate +the logic necessary to take input parameters and render markup. Components can +be rendered into an existing DOM element on the page by using +`React.renderComponent`: + +```javascript +// Replaces everything in `document.body` with
    Hello, world!
    ; +React.renderComponent(
    Hello, world!
    , document.body); +``` + +Keep in mind that `
    ` is **not** a DOM element! Keep reading... + +## Types of Components + +There are two types of components: + + - **Composite Components** + - **DOM Components** + +### Composite Components such as `TodoApp` and `Typeahead`. + +The majority of your React code will be implementing composite components. + +Composite components are higher-level components with custom rendering logic +that may compose other composite components or DOM components. + +```javascript +/** @jsx React.DOM */ +var LinkButton = React.createClass({ + render: function() { + return ; + } +}); + +var myButton = ; +``` + +This example defines a `LinkButton` component class using `React.createClass()`, +and its `render()` method composes the `` DOM component. + +### DOM Components such as `div` and `span`. + +DOM components are the set of classes that correspond to browser DOM elements. +They are defined in `React.DOM` and can be brought "into scope" by setting +`@jsx React.DOM` in the docblock. See [JSX Syntax](syntax.html) for more +details. + +Although `React.DOM` components look like browser DOM elements, they differ in a +few ways: + +- All property names, including event handlers, are camelCased. +- JavaScript identifiers should be used, namely `className` and `htmlFor`. +- The `style` prop expects an object instead of a string. The object should map + camelCased style properties to values, e.g. `{backgroundColor: '#fff'}`. + +Here is an example of a React link styled as a button with a click handler: + +```javascript +/** @jsx React.DOM */ +var handleClick = function() {alert('Clicked!');}; +var inlineStyle = {textDecoration: 'none'}; + +var myLink = ; +``` diff --git a/docs/component-data.md b/docs/component-data.md new file mode 100644 index 00000000..43ac6cc7 --- /dev/null +++ b/docs/component-data.md @@ -0,0 +1,145 @@ +--- +id: docs-component-data +title: Component Data +description: How is data passed into a component? +layout: docs +prev: component-basics.html +next: component-lifecycle.html +--- + +## Props + +Components use data to determine what should be rendered. For example: + +```javascript +var LikeLink = React.createClass({ + render: function() { + var text = this.props.liked ? 'Liked' : 'Like'; + return {text}; + } +}); +var myLikeLink = ; +``` + +In this example, `LikeLink` takes `liked` as boolean data. This type of data +that is passed in is called a "prop". Examples of props on DOM components +include `className` and `onClick`. + +Whenever a component's props change, its `render()` function will be +re-evaluated and the DOM will be updated. React will ensure that the DOM is +always kept up-to-date. + +## State + +Let's build a small `LikeApp` application that makes use of the `` +component from above. It should start off unliked and we should be able to like +it by clicking the link: + +```javascript +var LikeApp = React.createClass({ + render: function() { + var isClicked = false; + return ; + }, + handleClick: function() { + // Somehow update `isClicked`. + } +}); +``` + +This renders a `` with a click listener. However, it is not clear how +`handleClick` should update `isClicked` to true. `LikeApp` needs a way to store +**state** about whether or not it has been clicked. + +### State vs. Props + +State is data that is managed _internally_ by a composite component. Like props, +the `render()` function will be re-evaluated whenever state changes. Props and +state differ in that: + + - Props are passed in from the creator. + - State is private to and managed by the component. + +### Managing State + +Let's update our `LikeApp` component using state: + +```javascript{2-4,6,10} +var LikeApp = React.createClass({ + getInitialState: function() { + return {isClicked: false}; + }, + render: function() { + var isClicked = this.state.isClicked; + return ; + }, + handleClick: function() { + this.setState({isClicked: true}); + } +}); +``` + +There's a lot going on here, so let's work our way from top to bottom: + + - `getInitialState()` describes what state data looks like when the component + is created. + - In `render()`, state data can be accessed via `this.state`. + - When the link is clicked, we update state using `setState()`. + +Now when we click the link, the `` will get updated, right? Wrong. + +## Transferring Props + +If you have been following carefully, you may have noticed that although we pass +a click handler into `` as a prop, `LikeLink` does not do anything +with `this.props.onClick`! Let's fix that. + +```javascript{4} +var LikeLink = React.createClass({ + render: function() { + var text = this.props.liked ? 'Liked' : 'Like'; + return {text}; + } +}); +``` + +Although this works, realize that this would quickly become tedious if we wanted +to also transfer `href`, `title`, `target`, and other events from `this` to the +rendered ``. React provides a convenience method, `transferPropsTo()`, for +transferring props: + +```javascript{4} +var LikeLink = React.createClass({ + render: function() { + var text = this.props.liked ? 'Liked' : 'Like'; + return this.transferPropsTo({text}); + } +}); +``` + +This will transfer all props from `this` to the specified component (including +`onClick`). + +## Summary + +Now we are done. `LikeApp` renders an unliked link which, when clicked, will: + +1. Update the internal state of `LikeApp`. +2. Change the props passed into `LikeLink`. +3. Change the return value of `render()`. +4. Trigger an update to the DOM. + +It's worth noting that React will handle new return values of `render()` by +making the mininal set of mutations necessary to bring the DOM up-to-date. In +this case, only the `textContent` of the rendered link will be mutated. + +In summary: + + - Props are passed in whereas state is managed internally by a component. + - Never mutate `this.props` or `this.state`. You should pass props into other + components and mutate state using `setState()`. + - State is private. Never read `state` or call `setState()` on + anything but `this`. + - Whenever props or state changes, `render()` will be re-evaluated and the DOM + updated. Also, `render()` should not depend on anything besides `this.props` + and `this.state`. diff --git a/docs/component-lifecycle.md b/docs/component-lifecycle.md new file mode 100644 index 00000000..1998f180 --- /dev/null +++ b/docs/component-lifecycle.md @@ -0,0 +1,85 @@ +--- +id: docs-component-lifecycle +title: Component Lifecycle +description: What happens when I render a React component? +layout: docs +prev: component-data.html +next: event-handling.html +--- + +## Mounting + +[We have previously seen](component-basics.html) how to render components into +existing DOM elements on the page: + +```javascript +React.renderComponent(
    Hello, world!
    , document.body); +``` + +In this one simple line, we have accomplished the following: + + - A `
    ` (defined by `React.DOM.div`) component is instantiated. + - The component is **mounted** into `document.body`. + +**Mounting** is the process of initializing a React component by creating its +DOM nodes and inserting the them into a supplied container node. + +At this point, the entire page consists of a single `
    ` with "Hello, +world!". + +## Updating + +Let's add a second call to `React.renderComponent()` after three +seconds: + +```javascript{2-4} +React.renderComponent(
    Hello, world!
    , document.body); +setTimeout(function() { + React.renderComponent(
    Goodbye, world.
    , document.body); +}, 3000); +``` + +The second call to `React.renderComponent()` will trigger the following: + + - The `
    ` component will check the new props to see if anything changed. + - The set of changes are used to **update** the DOM node as necessary. + +**Updating** is the process of mutating the rendered DOM nodes and occurs +whenever either props or state has changed. This ensures that the rendered DOM +is consistent with the data. + +## Unmounting + +Let's add one final call to `React.renderComponent()` after another three +seconds: + +```javascript{5-7} +React.renderComponent(
    Hello, world!
    , document.body); +setTimeout(function() { + React.renderComponent(
    Goodbye, world.
    , document.body); +}, 3000); +setTimeout(function() { + React.renderComponent(, document.body); +}, 6000); +``` + +The third call to `React.renderComponent()` will trigger the following: + + - An `` (defined by `React.DOM.img`) component is instantiated. + - React will compare the `
    ` component with the `` component. + - Since the component class is different, the `
    ` component will be + **unmounted**. + - The `` component will then be mounted into `document.body`. + +**Unmounting** is the process of releasing resources that have been allocated by +a component. This allows user interfaces built with React to live long without +memory leaks. + +Components can also be unmounted using +`React.unmountAndReleaseReactRootNode()`: + +```javascript +React.unmountAndReleaseReactRootNode(document.body); +``` + +This will unmount any components mounted immediately within `document.body`. diff --git a/docs/event-handling.md b/docs/event-handling.md new file mode 100644 index 00000000..fc554855 --- /dev/null +++ b/docs/event-handling.md @@ -0,0 +1,124 @@ +--- +id: docs-event-handling +title: Event Handling +description: How do events work with React components? +layout: docs +prev: component-lifecycle.html +next: advanced-components.html +--- + +Events in React work the way they do with HTML, except the event names are +camelCased. + +```javascript +var Clicker = React.createClass({ + render: function() { + return Click me!; + }, + handleClick: function(event) { + alert('You clicked me!'); + } +}); +``` + +When `` is clicked, the `handleClick()` function will get fired. Under +the hood, React uses top-level event delegation to achieve high performance. + +## Automatically Binding Callbacks + +Just like any callback in JavaScript, if you want to refer to the component as +`this` from the callback, you need to bind the callback to the component: + +```javascript{3} +var Clicker = React.createClass({ + render: function() { + var handleClick = this.handleClick.bind(this); + return Click me!; + }, + handleClick: function(event) { + alert(this.ALERT_MESSAGE); + }, + ALERT_MESSAGE: 'You clicked me!' +}); +``` + +React provides a convenient and _efficient_ way to bind methods using +`React.autoBind()`: + +```javascript{3,5-7} +var Clicker = React.createClass({ + render: function() { + return Click me!; + }, + handleClick: React.autoBind(function(event) { + alert(this.ALERT_MESSAGE); + }), + ALERT_MESSAGE: 'You clicked me!' +}); +``` + +> Note: +> +> Binding a function allocates memory to create a new bound function. Since +> `render()` may be invoked many times, it is a bad place to bind functions. +> `React.autoBind()` sidesteps this issue by only binding once at instantiation +> time. + +## DOM Events + +React uses [top-level event delegation](http://davidwalsh.name/event-delegate) +to achieve high performance when implementing DOM events. For each type of DOM +event, React adds a single top-level listener and determines which event +handlers to execute by simulating event capturing and bubbling. + +DOM event handlers are called with a normalized `AbstractEvent` object that has +cross-browser compatible implementations of `stopPropagation` and +`preventDefault()`. If you need access to the raw browser event, you can use the +`nativeEvent` property. + +> Note: +> +> The `AbstractEvent` object is JSON serializable so that React applications can +> be executed inside web workers. + +### Touch Events + +If you want to use touch events, you must configure React's event system to +initialize them: + +```javascript +// Invoke before calling `React.renderComponent()`. +React.initializeTouchEvents(true); +``` + +## Custom Events + +Notice that event listeners are attached by simply passing them into components +as props. For DOM components, events are handled using top-level event +delegation. For composite components, event handling is up to the component's +implementation. + +Here is an example of a toggle link that fires a custom `onToggle` event: + +```javascript +var ToggleLink = React.createClass({ + getInitialState: function() { + return {isEnabled: false}; + }, + render: function() { + return Toggle; + }, + handleClick: React.autoBind(function() { + var willEnable = !this.state.isEnabled; + if (this.props.onToggle) { + this.props.onToggle(willEnable) + } + this.setState({isEnabled: willEnable}); + }) +}); + +var handleToggle = function(enabled) { + alert(enabled ? 'Enabled.' : 'Disabled.'); +}; +var myToggleLink = ; +``` diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 00000000..f2057e30 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,106 @@ +--- +id: docs-getting-started +title: Getting Started +layout: docs +next: tutorial.html +--- +Download the starter kit to get started. + + + +## Hello, world! + +In the root directory of the starter kit, create a `helloworld.html` with the following contents. + +```html + + + + + + + +
    + + + +``` + +The XML syntax inside of JavaScript is called JSX; check out the [JSX syntax](syntax.html) to learn more about it. In order to translate it to vanilla JavaScript we use ` +``` + +### Offline Transform + +First install the command-line tools (requires [npm](http://npmjs.org/)): + +``` +npm install -g react-tools +``` + +Then, translate your `src/helloworld.js` file to plain JavaScript: + +``` +jsx --watch src/ build/ + +``` + +The file `build/helloworld.js` is autogenerated whenever you make a change. + +```javascript{3} +/** @jsx React.DOM */ +React.renderComponent( + React.DOM.h1(null, 'Hello, world!'), + document.getElementyById('example') +); +``` + +Update your HTML file as below: + +```html{6,10} + + + + Hello React! + + + + +
    + + + +``` + +## Want CommonJS? + +If you want to use React within a module system, [fork our repo](http://github.com/facebook/react), `npm install` and run `grunt`. A nice set of CommonJS modules will be generated. Our `jsx` build tool can be integrated into most packaging systems (not just CommonJS) quite easily. + +## Next Steps + +Check out [the tutorial](tutorial.html) and the other examples in the `/examples` directory to learn more. Good luck, and welcome! diff --git a/docs/syntax.md b/docs/syntax.md new file mode 100644 index 00000000..9714f32f --- /dev/null +++ b/docs/syntax.md @@ -0,0 +1,151 @@ +--- +id: docs-syntax +title: JSX Syntax +description: Writing JavaScript with XML syntax. +layout: docs +prev: common-questions.html +next: component-basics.html +--- + +JSX is a JavaScript XML syntax extension recommended (but not required) for use +with React. + +JSX makes code that deeply nested React components more readable, and writing it +feels like writing HTML. React documentation examples make use of JSX. + +## The Transform + +JSX transforms XML-like syntax into native JavaScript. It turns XML elements and +attributes into function calls and objects, respectively. + +```javascript +var Nav; +// Input (JSX): +var app =