├── .babelrc ├── .editorconfig ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .sass-lint.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── create-flex-components.js ├── create-global-scoped-components.js ├── docs ├── containers │ ├── accordion │ │ └── index.js │ ├── callout │ │ └── index.js │ ├── dropdown │ │ └── index.js │ ├── media-object │ │ └── index.js │ ├── off-canvas │ │ └── index.js │ ├── reveal │ │ └── index.js │ ├── table │ │ └── index.js │ └── tabs │ │ └── index.js ├── controls │ ├── button-group │ │ └── index.js │ ├── button │ │ └── index.js │ ├── close-button │ │ └── index.js │ └── switch │ │ └── index.js ├── custom │ └── toggle-switch │ │ └── index.js ├── docs.scss ├── favicon.ico ├── general │ ├── flex │ │ └── index.js │ ├── float │ │ └── index.js │ ├── forms │ │ └── index.js │ ├── grid-flex │ │ └── index.js │ ├── grid │ │ └── index.js │ └── visibility │ │ └── index.js ├── index.html ├── index.js ├── media │ ├── badge │ │ └── index.js │ ├── flex-video │ │ └── index.js │ ├── label │ │ └── index.js │ ├── progress-bar │ │ └── index.js │ ├── thumbnail │ │ └── index.js │ └── tooltip │ │ └── index.js ├── navigation │ ├── breadcrumb │ │ └── index.js │ ├── menu │ │ └── index.js │ ├── pagination │ │ └── index.js │ └── top-bar │ │ └── index.js ├── typography │ ├── base │ │ └── index.js │ ├── helpers │ │ └── index.js │ ├── print │ │ └── index.js │ └── text-alignment │ │ └── index.js └── webpack.config.js ├── examples ├── cdn-flex │ ├── app.js │ ├── favicon.ico │ ├── index.html │ └── webpack.config.js ├── cdn │ ├── app.js │ ├── favicon.ico │ ├── index.html │ └── webpack.config.js ├── css-modules-custom │ ├── app.js │ ├── favicon.ico │ ├── index.html │ ├── theme.json │ └── webpack.config.js ├── css-modules │ ├── app.js │ ├── favicon.ico │ ├── index.html │ └── webpack.config.js ├── global-flex │ ├── app.js │ ├── app.scss │ ├── favicon.ico │ ├── index.html │ └── webpack.config.js └── global │ ├── app.js │ ├── app.scss │ ├── favicon.ico │ ├── index.html │ └── webpack.config.js ├── package.json ├── server.js └── src ├── _common.scss ├── _foundation.scss ├── _typography.scss ├── accordion ├── _custom.scss ├── _styles.scss └── index.js ├── badge ├── _styles.scss └── index.js ├── breadcrumb ├── _styles.scss └── index.js ├── button-group ├── _styles.scss └── index.js ├── button ├── _styles.scss └── index.js ├── callout ├── _styles.scss └── index.js ├── close-button ├── _styles.scss └── index.js ├── collapse ├── _custom.scss ├── _styles.scss └── index.js ├── dropdown ├── _styles.scss └── index.js ├── fade ├── _custom.scss ├── _styles.scss └── index.js ├── flex-mock ├── _styles.scss └── index.js ├── flex-video ├── _styles.scss └── index.js ├── flex ├── _styles.scss └── index.js ├── flexbox.js ├── float ├── _styles.scss └── index.js ├── forms ├── _custom.scss ├── _styles.scss └── index.js ├── grid-flex ├── _styles.scss └── index.js ├── grid ├── _styles.scss └── index.js ├── index.js ├── label ├── _styles.scss └── index.js ├── media-object ├── _styles.scss └── index.js ├── menu-icon ├── _styles.scss └── index.js ├── menu ├── _custom.scss ├── _styles.scss └── index.js ├── off-canvas ├── _custom.scss ├── _styles.scss └── index.js ├── pagination ├── _styles.scss └── index.js ├── print ├── _styles.scss └── index.js ├── progress-bar ├── _styles.scss └── index.js ├── reveal ├── _styles.scss └── index.js ├── switch ├── _styles.scss └── index.js ├── table ├── _styles.scss └── index.js ├── tabs ├── _styles.scss └── index.js ├── text-alignment ├── _styles.scss └── index.js ├── thumbnail ├── _styles.scss └── index.js ├── title-bar ├── _styles.scss └── index.js ├── toggle-switch ├── _custom.scss ├── _styles.scss └── index.js ├── tooltip ├── _custom.scss ├── _styles.scss └── index.js ├── top-bar ├── _custom.scss ├── _styles.scss └── index.js ├── typography-helpers ├── _styles.scss └── index.js ├── util ├── constants │ └── index.js ├── create-wrapper-component │ └── index.js ├── default-component │ └── index.js ├── key-mirror-array │ └── index.js ├── overlay-trigger │ └── index.js └── screen-size │ └── index.js └── visibility ├── _styles.scss └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-0"], 3 | "plugins": "transform-runtime" 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb", 4 | "rules": { 5 | "react/require-extension": 0, 6 | "react/jsx-filename-extension": 0 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | *.ico binary 4 | *.gif binary 5 | *.jpg binary 6 | *.jpeg binary 7 | *.png binary 8 | *.svg binary 9 | *.woff binary 10 | *.woff2 binary 11 | *.ttf binary 12 | *.eot binary 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | 35 | # Build directories 36 | lib 37 | -------------------------------------------------------------------------------- /.sass-lint.yml: -------------------------------------------------------------------------------- 1 | options: 2 | formatter: stylish 3 | files: 4 | include: '+(src|docs|examples)/**/*.s+(a|c)ss' 5 | rules: 6 | # Extends 7 | extends-before-mixins: 1 8 | extends-before-declarations: 1 9 | placeholder-in-extend: 1 10 | 11 | # Mixins 12 | mixins-before-declarations: 1 13 | 14 | # Line Spacing 15 | one-declaration-per-line: 1 16 | empty-line-between-blocks: 1 17 | single-line-per-selector: 1 18 | 19 | # Disallows 20 | no-color-keywords: 1 21 | no-color-literals: 1 22 | no-css-comments: 1 23 | no-debug: 1 24 | no-duplicate-properties: 1 25 | no-empty-rulesets: 1 26 | no-extends: 0 27 | no-ids: 1 28 | no-important: 1 29 | no-invalid-hex: 1 30 | no-mergeable-selectors: 1 31 | no-misspelled-properties: 1 32 | no-qualifying-elements: 1 33 | no-trailing-zero: 1 34 | no-transition-all: 1 35 | no-url-protocols: 1 36 | no-vendor-prefixes: 1 37 | no-warn: 1 38 | property-units: 1 39 | 40 | # Nesting 41 | force-attribute-nesting: 1 42 | force-element-nesting: 1 43 | force-pseudo-nesting: 1 44 | 45 | # Name Formats 46 | class-name-format: 1 47 | function-name-format: 1 48 | id-name-format: 1 49 | mixin-name-format: 1 50 | placeholder-name-format: 1 51 | variable-name-format: 1 52 | 53 | # Style Guide 54 | bem-depth: 1 55 | border-zero: 1 56 | brace-style: 1 57 | clean-import-paths: 1 58 | empty-args: 1 59 | hex-length: 1 60 | hex-notation: 1 61 | indentation: 1 62 | leading-zero: 1 63 | nesting-depth: 1 64 | property-sort-order: 65 | - 1 66 | - 67 | order: concentric 68 | quotes: 1 69 | shorthand-values: 1 70 | url-quotes: 1 71 | variable-for-property: 1 72 | zero-unit: 1 73 | 74 | # Inner Spacing 75 | space-after-comma: 1 76 | space-before-colon: 1 77 | space-after-colon: 1 78 | space-before-brace: 1 79 | space-before-bang: 1 80 | space-after-bang: 1 81 | space-between-parens: 1 82 | space-around-operator: 1 83 | 84 | # Final Items 85 | trailing-semicolon: 1 86 | final-newline: 1 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Antonio Ruberto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-foundation-components 2 | 3 | Foundation Sites 6 components implemented in React and compatible with CSS Modules! 4 | 5 | ## Why? 6 | 7 | I like [React](https://facebook.github.io/react). I like [CSS Modules](https://github.com/css-modules/css-modules). I like [Foundation Sites](http://foundation.zurb.com/sites.html). This is an experiment to see if it's possible to combine all these tools in a modular way! 8 | 9 | ## Installation 10 | 11 | ``` 12 | npm install --save react-foundation-components 13 | ``` 14 | 15 | Each component uses local scoped CSS by requiring the subset of the Foundation stylesheets it needs. 16 | 17 | Documentation (in progress) or demos of the components are available at http://aruberto.github.io/react-foundation-components. Please look at https://github.com/aruberto/react-foundation-components/tree/master/docs for an example webpack setup and example use of each component. 18 | 19 | You can also look at https://github.com/aruberto/react-foundation-components/tree/master/examples/css-modules as an example project that uses CSS Modules with this library. 20 | 21 | If you want to use CSS modules and customize Foundation at the same time, look at https://github.com/aruberto/react-foundation-components/tree/master/examples/css-modules-custom which uses https://www.npmjs.com/package/jsontosass-loader to inject sass variables that override Foundation's default settings. 22 | 23 | Recommend importing on a per component basis instead of importing the main entry point of package. Importing main entry point will cause final bundle to include all CSS and JS whereas importing on a per component basis will cause your final bundle to only include the CSS and JS you actually need (this may change when tree shaking is introduced in webpack 2)! 24 | 25 | Favor 26 | 27 | ``` 28 | import Button from 'react-foundation-components/lib/button'; 29 | import { ShowForScreenSize, HideForScreenSize } from 'react-foundation-components/lib/visibility'; 30 | ``` 31 | 32 | over 33 | 34 | ``` 35 | import { Button, ShowForScreenSize, HideForScreenSize } from 'react-foundation-components'; 36 | ``` 37 | 38 | If you can't use CSS Modules, a set of components that use Foundation's global scoped class names are also provided. These are located under react-foundation-components/lib/global. To import Button that uses global scoped class names: 39 | 40 | ``` 41 | import Button from 'react-foundation-components/lib/global/button'; 42 | import { ShowForScreenSize, HideForScreenSize } from 'react-foundation-components/lib/global/visibility'; 43 | ``` 44 | 45 | If you use the components under react-foundation-components/lib/global, you are responsible for loading Foundation CSS stylesheet. You can do this in a few ways: 46 | * include stylesheet such as https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.0/foundation.min.css in head of your html with CDN link 47 | * Import/Require react-foundation-components/lib/\_foundation.scss 48 | * Use https://www.npmjs.com/package/foundation-sites-loader 49 | 50 | Here are some example applications that use global scoped class name components: 51 | * Uses Foundation from CDN - https://github.com/aruberto/react-foundation-components/tree/master/examples/cdn 52 | * Uses Foundation (Flexbox Version) from CDN - https://github.com/aruberto/react-foundation-components/tree/master/examples/cdn-flex 53 | * Requires react-foundation-components/lib/\_foundation.scss with global-flexbox set to false - https://github.com/aruberto/react-foundation-components/tree/master/examples/global 54 | * Requires react-foundation-components/lib/\_foundation.scss with global-flexbox set to true - https://github.com/aruberto/react-foundation-components/tree/master/examples/global-flex 55 | 56 | ## Thanks 57 | 58 | A lot of the components are inspired by [React Bootstrap](https://github.com/react-bootstrap/react-bootstrap) and this project even makes heavy use their utility libraries like [react-overlays](https://github.com/react-bootstrap/react-overlays), [dom-helpers](https://github.com/react-bootstrap/dom-helpers), [prop-types-extra](https://github.com/react-bootstrap/prop-types-extra) and [uncontrollable](https://github.com/jquense/uncontrollable). So big thanks to all these project's contributers for all their amazing work! 59 | -------------------------------------------------------------------------------- /create-flex-components.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console, strict */ 2 | 'use strict'; 3 | 4 | const path = require('path'); 5 | const fs = require('fs-extra'); 6 | const s = require('underscore.string'); 7 | 8 | const createFlexSccsContent = (component) => 9 | `$global-flexbox: true; 10 | 11 | @import '../${component}/styles'; 12 | `; 13 | const FLEX_COMPONENTS = [ 14 | 'button-group', 15 | 'forms', 16 | 'media-object', 17 | 'menu', 18 | 'title-bar', 19 | 'top-bar', 20 | ]; 21 | 22 | FLEX_COMPONENTS.forEach((component) => { 23 | const directoryPath = path.join(__dirname, 'lib', component); 24 | const indexPath = path.join(directoryPath, 'index.js'); 25 | const scssPath = path.join(directoryPath, '_styles.scss'); 26 | 27 | try { 28 | fs.accessSync(indexPath, fs.F_OK); 29 | fs.accessSync(scssPath, fs.F_OK); 30 | } catch (e) { 31 | // Not component directory 32 | console.warn(`Skipping component ${component}!`); 33 | return; 34 | } 35 | 36 | const flexDirectoryPath = path.join(__dirname, 'lib', `${component}-flex`); 37 | const flexIndexPath = path.join(flexDirectoryPath, 'index.js'); 38 | const flexScssPath = path.join(flexDirectoryPath, '_styles.scss'); 39 | let flexIndexContent = s(fs.readFileSync(indexPath, 'utf8')); 40 | 41 | FLEX_COMPONENTS.forEach((dependency) => { 42 | flexIndexContent = flexIndexContent.replace(`'../${dependency}'`, `'../${dependency}-flex'`); 43 | }); 44 | 45 | flexIndexContent = flexIndexContent.replace('\'../grid\'', '\'../grid-flex\''); 46 | flexIndexContent = flexIndexContent.replace('\'../flex-mock\'', '\'../flex\''); 47 | flexIndexContent = flexIndexContent.replace('IS_FLEX_MODE = false', 'IS_FLEX_MODE = true'); 48 | 49 | fs.ensureDirSync(flexDirectoryPath); 50 | fs.writeFileSync(flexIndexPath, flexIndexContent.value(), 'utf8'); 51 | fs.writeFileSync(flexScssPath, createFlexSccsContent(component), 'utf8'); 52 | }); 53 | -------------------------------------------------------------------------------- /create-global-scoped-components.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | const path = require('path'); 4 | const fs = require('fs-extra'); 5 | const through2 = require('through2'); 6 | const s = require('underscore.string'); 7 | 8 | const libPath = path.join(__dirname, 'lib'); 9 | const globalPath = path.join(libPath, 'global'); 10 | const packageIndexPath = path.join(libPath, 'index.js'); 11 | const packageFlexboxIndexPath = path.join(libPath, 'flexbox.js'); 12 | const globalPackageIndexPath = path.join(globalPath, 'index.js'); 13 | const globalPackageFlexboxIndexPath = path.join(globalPath, 'flexbox.js'); 14 | 15 | fs.ensureDirSync(path.dirname(globalPath)); 16 | fs.copySync(packageIndexPath, globalPackageIndexPath); 17 | fs.copySync(packageFlexboxIndexPath, globalPackageFlexboxIndexPath); 18 | 19 | const filter = through2.obj(function componentDirectoryFilter(item, enc, next) { 20 | if (item.stats.isFile()) { 21 | const fileName = path.basename(item.path); 22 | 23 | if (fileName === 'index.js') { 24 | const directory = path.dirname(item.path); 25 | const scssPath = path.join(directory, '_styles.scss'); 26 | 27 | try { 28 | fs.accessSync(item.path, fs.F_OK); 29 | fs.accessSync(scssPath, fs.F_OK); 30 | 31 | this.push(item); 32 | } catch (e) { 33 | // Not component directory 34 | } 35 | } 36 | } 37 | 38 | next(); 39 | }); 40 | 41 | fs.walk(libPath) 42 | .pipe(filter) 43 | .on('data', (item) => { 44 | const globalComponentPath = 45 | s(item.path) 46 | .reverse() 47 | .replace( 48 | s(`lib${path.sep}`).reverse().value(), 49 | s(`lib${path.sep}global${path.sep}`).reverse().value() 50 | ) 51 | .reverse() 52 | .value(); 53 | 54 | const content = fs.readFileSync(item.path, 'utf8') 55 | .replace(/require\('\.\/\_styles\.scss'\)/g, '{}') 56 | .replace(/require\('classnames\/bind'\)/, 'require(\'classnames\')') 57 | .replace(/require\('\.\.\/util\//g, 'require(\'../../util/') 58 | 59 | fs.ensureDirSync(path.dirname(globalComponentPath)); 60 | fs.writeFileSync(globalComponentPath, content, 'utf8'); 61 | }); 62 | -------------------------------------------------------------------------------- /docs/containers/callout/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Callout } from '../../../src/callout'; 4 | 5 | const CalloutPage = () => ( 6 |
7 | 8 |
This is a callout.
9 |

It has an easy to override visual style, and is appropriately subdued.

10 | It's dangerous to go alone, take this. 11 |
12 | 13 |
This is a secondary panel.
14 |

It has an easy to override visual style, and is appropriately subdued.

15 | It's dangerous to go alone, take this. 16 |
17 | 18 |
This is a primary panel.
19 |

It has an easy to override visual style, and is appropriately subdued.

20 | It's dangerous to go alone, take this. 21 |
22 | 23 |
This is a success panel.
24 |

It has an easy to override visual style, and is appropriately subdued.

25 | It's dangerous to go alone, take this. 26 |
27 | 28 |
This is a warning panel.
29 |

It has an easy to override visual style, and is appropriately subdued.

30 | It's dangerous to go alone, take this. 31 |
32 | 33 |
This is a alert panel.
34 |

It has an easy to override visual style, and is appropriately subdued.

35 | It's dangerous to go alone, take this. 36 |
37 | 38 |
This is a primary panel.
39 |

It has an easy to override visual style, and is appropriately subdued.

40 | It's dangerous to go alone, take this. 41 |
42 | 43 |
This is a primary panel.
44 |

It has an easy to override visual style, and is appropriately subdued.

45 | It's dangerous to go alone, take this. 46 |
47 |
48 | ); 49 | 50 | export default CalloutPage; 51 | -------------------------------------------------------------------------------- /docs/containers/dropdown/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Dropdown, LinkWithDropdown } from '../../../src/dropdown'; 4 | import { Button } from '../../../src/button'; 5 | 6 | const dropdownStyle = { position: 'relative', top: '20px', left: '50px' }; 7 | 8 | const DropdownPage = () => ( 9 |
10 | I'm a dropdown! 11 |
12 | I'm a tiny dropdown! 13 |
14 | I'm a small dropdown! 15 |
16 | I'm a large dropdown! 17 |
18 |
19 |
20 | 23 | 24 |
25 | 26 |
27 | } 28 | > 29 | 30 | 31 |
32 | 37 | 38 | 39 |
40 | 45 | 46 | 47 |
48 | 52 | 53 | 54 |
55 | 59 | 60 | 61 |
62 | 66 | 67 | 68 |
69 | 73 | 74 | 75 |
76 | 80 | 81 | 82 | 83 | ); 84 | 85 | export default DropdownPage; 86 | -------------------------------------------------------------------------------- /docs/containers/media-object/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { MediaObjectSection, MediaObject } from '../../../src/media-object'; 4 | import { 5 | MediaObjectSection as FlexMediaObjectSection, 6 | MediaObject as FlexMediaObject, 7 | } from '../../../lib/media-object-flex'; // eslint-disable-line import/no-unresolved 8 | 9 | const MediaObjectPage = () => ( 10 |
11 | 12 | 13 | 17 | 18 | 19 |

Dreams feel real while we're in them.

20 |

21 | I'm going to improvise. Listen, there's something you should know about me... about 22 | inception. An idea is like a virus, resilient, highly contagious. The smallest seed 23 | of an idea can grow. It can grow to define or destroy you. 24 |

25 |
26 |
27 |
28 | 29 | 30 | 34 | 35 | 36 |

Why is it so important to dream?

37 |

38 | So, once we've made the plant, how do we go out? Hope you have something more elegant 39 | in mind than shooting me in the head? A kick. Whats a kick? This, Ariadne, would be a 40 | kick. 41 |

42 |

43 | What is the most resilient parasite? Bacteria? A virus? An intestinal worm? An idea. 44 | Resilient... highly contagious. Once an idea has taken hold of the brain it's almost 45 | impossible to eradicate. An idea that is fully formed - fully understood - that 46 | sticks; right in there somewhere. 47 |

48 |
49 | 50 | 54 | 55 |
56 |
57 | 58 | 59 | 63 | 64 | 65 |

I Can Stack.

66 |

67 | Shrink the browser width to see me stack. I do tricks for dog treats, but I'm not a 68 | dog. 69 |

70 |
71 |
72 |
73 | 74 | 75 | 79 | 80 | 81 |

Why is it so important to dream?

82 |

83 | So, once we've made the plant, how do we go out? Hope you have something more elegant 84 | in mind than shooting me in the head? A kick. Whats a kick? This, Ariadne, would be a 85 | kick. 86 |

87 |

88 | What is the most resilient parasite? Bacteria? A virus? An intestinal worm? An idea. 89 | Resilient... highly contagious. Once an idea has taken hold of the brain it's almost 90 | impossible to eradicate. An idea that is fully formed - fully understood - that 91 | sticks; right in there somewhere. 92 |

93 |
94 | 95 | 99 | 100 |
101 |
102 | ); 103 | 104 | export default MediaObjectPage; 105 | -------------------------------------------------------------------------------- /docs/containers/off-canvas/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { 4 | OffCanvas, 5 | OffCanvasContent, 6 | OffCanvasContainer, 7 | } from '../../../src/off-canvas'; 8 | import { 9 | TitleBar, 10 | TitleBarItem, 11 | TitleBarTitle, 12 | TitleBarMenuIcon, 13 | } from '../../../src/title-bar'; 14 | import { 15 | TitleBar as FlexTitleBar, 16 | TitleBarItem as FlexTitleBarItem, 17 | TitleBarTitle as FlexTitleBarTitle, 18 | TitleBarMenuIcon as FlexTitleBarMenuIcon, 19 | } from '../../../lib/title-bar-flex'; // eslint-disable-line import/no-unresolved 20 | import { HideForScreenSize } from '../../../src/visibility'; 21 | 22 | export default class OffCanvasPage extends Component { 23 | state = { 24 | open: null, 25 | }; 26 | 27 | handleClose = () => this.setState({ open: null }); 28 | 29 | handleToggle = (position) => { 30 | const { open: prevOpen } = this.state; 31 | const open = prevOpen === position ? null : position; 32 | 33 | this.setState({ open }); 34 | }; 35 | 36 | handleToggleLeft = () => this.handleToggle('left'); 37 | 38 | handleToggleRight = () => this.handleToggle('right'); 39 | 40 | render() { 41 | const { open } = this.state; 42 | 43 | return ( 44 | 45 | 46 | Left Sidebar 47 | 48 | 49 | Right Sidebar 50 | 51 | 52 | 53 | 54 | 60 | Foundation 61 | 62 | 63 | 69 | 70 | 71 |
72 | 73 | 74 | 80 | Foundation 81 | 82 | 83 | 89 | 90 | 91 |
92 |
Main Content
93 |
94 |
95 | ); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /docs/containers/reveal/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { Reveal } from '../../../src/reveal'; 4 | import { Button } from '../../../src/button'; 5 | import { CloseButton } from '../../../src/close-button'; 6 | 7 | export default class RevealPage extends Component { 8 | state = { 9 | showBasic: false, 10 | showTiny: false, 11 | showSmall: false, 12 | showLarge: false, 13 | showFull: false, 14 | showNested1: false, 15 | showNested2: false, 16 | }; 17 | 18 | handleShowHide = (type, show) => this.setState({ [`show${type}`]: show }); 19 | 20 | handleShowBasic = () => this.handleShowHide('Basic', true); 21 | 22 | handleHideBasic = () => this.handleShowHide('Basic', false); 23 | 24 | handleShowTiny = () => this.handleShowHide('Tiny', true); 25 | 26 | handleHideTiny = () => this.handleShowHide('Tiny', false); 27 | 28 | handleShowSmall = () => this.handleShowHide('Small', true); 29 | 30 | handleHideSmall = () => this.handleShowHide('Small', false); 31 | 32 | handleShowLarge = () => this.handleShowHide('Large', true); 33 | 34 | handleHideLarge = () => this.handleShowHide('Large', false); 35 | 36 | handleShowFull = () => this.handleShowHide('Full', true); 37 | 38 | handleHideFull = () => this.handleShowHide('Full', false); 39 | 40 | handleShowNested1 = () => this.handleShowHide('Nested1', true); 41 | 42 | handleHideNested1 = () => this.handleShowHide('Nested1', false); 43 | 44 | handleShowNested2 = () => this.handleShowHide('Nested2', true); 45 | 46 | handleHideNested2 = () => this.handleShowHide('Nested2', false); 47 | 48 | handleShowNoOverlay = () => this.handleShowHide('NoOverlay', true); 49 | 50 | handleHideNoOverlay = () => this.handleShowHide('NoOverlay', false); 51 | 52 | handleShowNoCloseOnClick = () => this.handleShowHide('NoCloseOnClick', true); 53 | 54 | handleHideNoCloseOnClick = () => this.handleShowHide('NoCloseOnClick', false); 55 | 56 | render() { 57 | const { 58 | showBasic, 59 | showTiny, 60 | showSmall, 61 | showLarge, 62 | showFull, 63 | showNested1, 64 | showNested2, 65 | showNoOverlay, 66 | showNoCloseOnClick, 67 | } = this.state; 68 | 69 | return ( 70 |
71 | 72 | 73 | 74 |

Awesome. I Have It.

75 |

Your couch. It is mine.

76 |

I'm a cool paragraph that lives inside of an even cooler modal. Wins!

77 |
78 |
79 | 80 | 81 | 82 |

OH I'M SO TIIINY

83 |
84 |
85 | 86 | 87 | 88 |

I may be small, but I've got a big heart!

89 |
90 |
91 | 92 | 93 | 94 |

I'm big, like bear!

95 |
96 |
97 | 98 | 99 | 100 |

OH I'M SO FUUUUL

101 | Intropsective Cage 102 |
103 |
104 | 105 | 106 | 107 |

Awesome!

108 |

I have another modal inside of me!

109 | 110 |
111 | 112 | 113 |

ANOTHER MODAL!!!

114 |
115 |
116 | 117 | 118 | 119 |

I feel so free!

120 |
121 |
122 | 123 | 124 | 125 |

Click outside : Nothing happens!!!

126 |
127 |
128 | ); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /docs/containers/table/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Table } from '../../../src/table'; 4 | 5 | const TablePage = () => ( 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | 40 |
Table HeaderTable HeaderTable HeaderTable Header
Content Goes HereThis is longer content Donec id elit non mi porta gravida at eget metus.Content Goes HereContent Goes Here
Content Goes Here 26 | This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. 27 | Content Goes HereContent Goes Here
Content Goes Here 34 | This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. 35 | Content Goes HereContent Goes Here
41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 64 | 65 | 66 | 67 | 68 | 71 | 72 | 73 | 74 | 75 |
Table HeaderTable HeaderTable HeaderTable Header
Content Goes HereThis is longer content Donec id elit non mi porta gravida at eget metus.Content Goes HereContent Goes Here
Content Goes Here 61 | This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. 62 | Content Goes HereContent Goes Here
Content Goes Here 69 | This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. 70 | Content Goes HereContent Goes Here
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 |
CookiesTasteCaloriesOverall
Chocolate ChipTastey120cal7.5/10
SnickerdoodleDelicious95cal8/10
Oatmeal RaisinSuperb10cal11/10
107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 |
This is the description!OneTwoThreeFourFiveSixSevenEightNineTenElevenTwelve
129 | These are all the words that people use to describe Foundation 6! 130 | CoolSwagChillKillerRadBallerOMGSweetAwesomeBeastDopeTubular
These are some words that people use to describe other web frameworks.WhatevsUgh.LOLKAightEh.Grrr...Meh.TTYLBleh.Really?Why?
Here are some great super heros.BatmanSupermanSpidermanWonder WomanHulkNicolas CageAntmanAquamanCaptain AmericaWolverineThorIron Man
Here's a footer, just in case
193 |
194 | ); 195 | 196 | export default TablePage; 197 | -------------------------------------------------------------------------------- /docs/containers/tabs/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { Tabs, Tab } from '../../../src/tabs'; 4 | 5 | export default class TabPage extends Component { 6 | state = { 7 | activeKey: '1', 8 | }; 9 | 10 | handleSelect = (activeKey) => this.setState({ activeKey }); 11 | 12 | render() { 13 | const { activeKey } = this.state; 14 | 15 | return ( 16 |
17 | 18 | 19 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 20 | incididunt ut labore et dolore magna aliqua. 21 | 22 | 23 | Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut 24 | eleifend nibh porttitor. Ut in nulla enim. Phasellus molestie magna non est bibendum non 25 | venenatis nisl tempor. Suspendisse dictum feugiat nisl ut dapibus. 26 | 27 | 28 | 32 | 33 | 34 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 35 | incididunt ut labore et dolore magna aliqua. 36 | 37 | 38 | 42 | 43 | 44 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 45 | incididunt ut labore et dolore magna aliqua. 46 | 47 | 48 |
49 | 50 | 51 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 52 | incididunt ut labore et dolore magna aliqua. 53 | 54 | 55 | Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut 56 | eleifend nibh porttitor. Ut in nulla enim. Phasellus molestie magna non est bibendum non 57 | venenatis nisl tempor. Suspendisse dictum feugiat nisl ut dapibus. 58 | 59 | 60 | 64 | 65 | 66 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 67 | incididunt ut labore et dolore magna aliqua. 68 | 69 | 70 | 74 | 75 | 76 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 77 | incididunt ut labore et dolore magna aliqua. 78 | 79 | 80 |
81 | 82 | 83 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 84 | incididunt ut labore et dolore magna aliqua. 85 | 86 | 87 | Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut 88 | eleifend nibh porttitor. Ut in nulla enim. Phasellus molestie magna non est bibendum non 89 | venenatis nisl tempor. Suspendisse dictum feugiat nisl ut dapibus. 90 | 91 | 92 | 96 | 97 | 98 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 99 | incididunt ut labore et dolore magna aliqua. 100 | 101 | 102 | 106 | 107 | 108 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 109 | incididunt ut labore et dolore magna aliqua. 110 | 111 | 112 |
113 | ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /docs/controls/close-button/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { CloseButton } from '../../../src/close-button'; 4 | import { Callout } from '../../../src/callout'; 5 | 6 | const CloseButtonPage = () => ( 7 |
8 |

Close Button

9 |

10 | The close button can be used anywhere you need something to go away on click. 11 |

12 |
13 |

Basics

14 |

Importing the CloseButton component:

15 |
16 |       
17 | {
18 | `// Import with local scoped class names (via CSS Modules)
19 | import { CloseButton } from 'react-foundation-components/lib/close-button';
20 | 
21 | or
22 | 
23 | // Import with global scoped class names
24 | import { CloseButton } from 'react-foundation-components/lib/global/close-button';`
25 | }
26 |       
27 |     
28 |

29 | Clarify the button's purpose using the aria-label prop. 30 |

31 |
32 |       
33 | {
34 | `
35 | 
36 | 

Look at this close button!

37 |
` 38 | } 39 |
40 |
41 | 42 | 43 |

Look at this close button!

44 |
45 |
46 | ); 47 | 48 | export default CloseButtonPage; 49 | -------------------------------------------------------------------------------- /docs/docs.scss: -------------------------------------------------------------------------------- 1 | $color-background: #f4f5f6 !default 2 | 3 | @import '../src/typography'; 4 | 5 | code { 6 | margin: 0 .2rem 1rem; 7 | border-radius: .4rem; 8 | background: $color-background; 9 | padding: .2rem .5rem; 10 | white-space: nowrap; 11 | font-size: 86%; 12 | } 13 | 14 | pre { 15 | font-family: 'Menlo', 'Consolas', 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Monaco', monospace; 16 | 17 | & > code { 18 | display: block; 19 | border-radius: 0; 20 | padding: 1rem 1.5rem; 21 | white-space: pre; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruberto/react-foundation-components/3db1a7a9bae46734089635bffb53d107b43d973b/docs/favicon.ico -------------------------------------------------------------------------------- /docs/general/float/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Float, ClearFix } from '../../../src/float'; 4 | import { Callout } from '../../../src/callout'; 5 | import { Button } from '../../../src/button'; 6 | 7 | const FloatPage = () => ( 8 |
9 |

Float

10 |

11 | Helpful positioning components. 12 |

13 |

Basics

14 |

Importing the Float components:

15 |
16 |       
17 | {
18 | `// Import with local scoped class names (via CSS Modules)
19 | import { Float, ClearFix } from 'react-foundation-components/lib/float';
20 | 
21 | or
22 | 
23 | // Import with global scoped class names
24 | import { Float, ClearFix } from 'react-foundation-components/lib/global/float';`
25 | }
26 |       
27 |     
28 |

29 | Position content by placing it inside the Float component. Set the position 30 | prop to left, right or center to specify the position. Center will only work when Float 31 | has as absolute width. To clear floats, wrap them in the ClearFix component. 32 |

33 |
34 |       
35 |         {
36 | `
37 | 
38 | 
39 | 
40 | 
41 | 
42 | 
43 | 
44 | 
45 | 
46 | `
47 |         }
48 |       
49 |     
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 | ); 63 | 64 | export default FloatPage; 65 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/media/badge/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Badge } from '../../../src/badge'; 4 | import { ShowForScreenReader } from '../../../src/visibility'; 5 | 6 | const BadgePage = () => ( 7 |
8 |

Badge

9 |

10 | The badge is a basic component that displays a number. 11 |

12 |
13 |

Basics

14 |

Importing the Badge component:

15 |
16 |       
17 | {
18 | `// Import with local scoped class names (via CSS Modules)
19 | import { Badge } from 'react-foundation-components/lib/badge';
20 | 
21 | or
22 | 
23 | // Import with global scoped class names
24 | import { Badge } from 'react-foundation-components/lib/global/badge';`
25 | }
26 |       
27 |     
28 |
29 |       
30 | {
31 | '1'
32 | }
33 |       
34 |     
35 |

36 | 1 37 |

38 |
39 |

Coloring

40 |

41 | Give a Badge additional meaning by setting the color prop. Possible values 42 | are primary, secondary, success, alert and warning. 43 |

44 |
45 |       
46 | {
47 | `1
48 | 2
49 | 3
50 | A
51 | B`
52 | }
53 |       
54 |     
55 |

56 | 1 57 |   58 | 2 59 |   60 | 3 61 |   62 | A 63 |   64 | B 65 |

66 |
67 |

Accessibility

68 |

69 | A Badge will typically be describing another element on the page. To bind the two elements 70 | together, give the badge an id, and reference that id in an 71 | aria-describedby attribute on the main element. The Badge content itself 72 | might need more context for users that use screen readers. You can add extra text inside 73 | the badge by wrapping the text with the ShowForScreenReader component. 74 |

75 |
76 |       
77 | {
78 | `
79 | 
80 | 12
81 | Unread Messages
82 | `
83 | }
84 |       
85 |     
86 |

87 | 88 | 89 | 12 90 | Unread Messages 91 | 92 |

93 |
94 | ); 95 | 96 | export default BadgePage; 97 | -------------------------------------------------------------------------------- /docs/media/flex-video/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { FlexVideo } from '../../../src/flex-video'; 4 | 5 | const FlexVideoPage = () => ( 6 |
7 |

Flex Video

8 |

9 | Wrap embedded videos from YouTube, Vimeo, and others in a flex video container to ensure 10 | they maintain the correct aspect ratio regardless of screen size. 11 |

12 |
13 |

Basics

14 |

Importing the FlexVideo component:

15 |
 16 |       
 17 | {
 18 | `// Import with local scoped class names (via CSS Modules)
 19 | import { FlexVideo } from 'react-foundation-components/lib/flex-video';
 20 | 
 21 | or
 22 | 
 23 | // Import with global scoped class names
 24 | import { FlexVideo } from 'react-foundation-components/lib/global/flex-video';`
 25 | }
 26 |       
 27 |     
28 |

29 | All the props you can set on iframe can also be set on the FlexVideo component. 30 |

31 |
 32 |       
 33 | {
 34 | ``
 41 | }
 42 |       
 43 |     
44 | 51 |

52 | The default ratio is 4:3. Set the widescreen prop to change it to 16:9. 53 |

54 |
 55 |       
 56 | {
 57 | ``
 65 | }
 66 |       
 67 |     
68 | 76 |

77 | Embedded Vimeo videos are special snowflakes of their own. Set the vimeo prop 78 | to display a Vimeo video. 79 |

80 |
 81 |       
 82 | {
 83 | ``
 92 | }
 93 |       
 94 |     
95 | 104 |
105 | ); 106 | 107 | export default FlexVideoPage; 108 | -------------------------------------------------------------------------------- /docs/media/label/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Label } from '../../../src/label'; 4 | 5 | const LabelPage = () => ( 6 |
7 |

Label

8 |

9 | Labels are useful to call out certain sections or to attach metadata. 10 |

11 |
12 |

Basics

13 |

Importing the Label component:

14 |
 15 |       
 16 | {
 17 | `// Import with local scoped class names (via CSS Modules)
 18 | import { Label } from 'react-foundation-components/lib/label';
 19 | 
 20 | or
 21 | 
 22 | // Import with global scoped class names
 23 | import { Label } from 'react-foundation-components/lib/global/label';`
 24 | }
 25 |       
 26 |     
27 |
 28 |       
 29 | {
 30 | ''
 31 | }
 32 |       
 33 |     
34 |

35 | 36 |

37 |
38 |

Coloring

39 |

40 | Give a Label additional meaning by setting the color prop. Possible values 41 | are primary, secondary, success, alert and warning. 42 |

43 |
 44 |       
 45 | {
 46 | `
 47 | 
 48 | 
 49 | 
 50 | `
 51 | }
 52 |       
 53 |     
54 |

55 | 56 |   57 | 58 |   59 | 60 |   61 | 62 |   63 | 64 |

65 |
66 |

Accessibility

67 |

68 | A Label will typically be describing another element on the page. To bind the two elements 69 | together, give the badge an id, and reference that id in an 70 | aria-describedby attribute on the main element. 71 |

72 |
 73 |       
 74 | {
 75 | `
 76 | Re: re: re: you won't believe what's in this email!
 77 | 
 78 | 
79 | ` 80 | } 81 |
82 |
83 |

84 | 85 | Re: re: re: you won't believe what's in this email! 86 | 87 |
88 | 89 |

90 |

91 | If an element is described by multiple labels, place multiple IDs inside 92 | of the aria-describedby prop. 93 |

94 |
 95 |       
 96 | {
 97 | `
 98 | Re: re: re: you won't believe what's in this email!
 99 | 
100 | 
101 | `
102 | }
103 |       
104 |     
105 |

106 | 107 | Re: re: re: you won't believe what's in this email! 108 | 109 |
110 | 111 |   112 | 113 |

114 |
115 | ); 116 | 117 | export default LabelPage; 118 | -------------------------------------------------------------------------------- /docs/media/progress-bar/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { ProgressBar } from '../../../src/progress-bar'; 4 | 5 | function percentFormatter(percent) { 6 | const rounded = Math.round(percent * 100); 7 | 8 | return `${rounded}%`; 9 | } 10 | 11 | function complexFormatter(percent, value, min, max) { 12 | return `percent = ${percent}, value = ${value}, min = ${min}, max = ${max}`; 13 | } 14 | 15 | const ProgressBarPage = () => ( 16 |
17 |

Progress Bar

18 |

19 | Show your progress. 20 |

21 |
22 |

Basics

23 |

Importing the ProgressBar component:

24 |
 25 |       
 26 | {
 27 | `// Import with local scoped class names (via CSS Modules)
 28 | import { ProgressBar } from 'react-foundation-components/lib/progress-bar';
 29 | 
 30 | or
 31 | 
 32 | // Import with global scoped class names
 33 | import { ProgressBar } from 'react-foundation-components/lib/global/progress-bar';`
 34 | }
 35 |       
 36 |     
37 |

38 | Set the value prop to specify the current progress value (defaults to 0). 39 | Set the min and/or max props to change the minimum/maximum 40 | possible values for progress bar (defaults to 0 and 100 respectively). 41 |

42 |
 43 |       
 44 | {
 45 | `
 46 | 
 47 | 
 48 | 
 49 | 
 50 | `
 51 | }
 52 |       
 53 |     
54 | 55 | 56 | 57 | 58 | 59 | 60 |
61 |

Coloring

62 |

63 | Give a Badge additional meaning by setting the color prop. Possible values 64 | are primary, secondary, success, alert and warning. 65 |

66 |
 67 |       
 68 |     {
 69 | `
 70 | 
 71 | 
 72 | 
 73 | `
 74 |     }
 75 |       
 76 |     
77 | 78 | 79 | 80 | 81 | 82 |
83 |

With Text

84 |

85 | You can add text inside the meter of a progress bar by providing 86 | a labelFormatter function. The function takes 4 arguments: (1) the calculated 87 | percent, (2) the curent value (adjusted to make sure it falls within the min and max), (3) 88 | the minimum value and (4) the maximum value. 89 |

90 |
 91 |       
 92 |     {
 93 | `function complexFormatter(percent, value, min, max) {
 94 | return \`percent = \${percent}, value = \${value}, min = \${min}, max = \${max}\`;
 95 | }
 96 | 
 97 | function percentFormatter(percent) {
 98 | const rounded = Math.round(percent * 100);
 99 | 
100 | return \`\${rounded}%\`;
101 | }
102 | 
103 | 
104 | `
105 |     }
106 |       
107 |     
108 | 109 | 110 |
111 | ); 112 | 113 | export default ProgressBarPage; 114 | -------------------------------------------------------------------------------- /docs/media/thumbnail/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Thumbnail } from '../../../src/thumbnail'; 4 | 5 | const ThumbnailPage = () => ( 6 |
7 |

Thumbnail

8 |

9 | A reduced size image. 10 |

11 |
12 |

Basics

13 |

Importing the Thumbnail component:

14 |
15 |       
16 | {
17 | `// Import with local scoped class names (via CSS Modules)
18 | import { Thumbnail } from 'react-foundation-components/lib/thumbnail';
19 | 
20 | or
21 | 
22 | // Import with global scoped class names
23 | import { Thumbnail } from 'react-foundation-components/lib/global/thumbnail';`
24 | }
25 |       
26 |     
27 |

28 | Thumbnail behaves similar to an img tag. 29 |

30 |
31 |       
32 | {
33 | `
37 | 
41 | `
45 | }
46 |       
47 |     
48 |

49 | 53 |   54 | 58 |   59 | 63 |

64 |
65 | ); 66 | 67 | export default ThumbnailPage; 68 | -------------------------------------------------------------------------------- /docs/navigation/breadcrumb/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Breadcrumb, BreadcrumbItem } from '../../../src/breadcrumb'; 4 | 5 | const BreadcrumbPage = () => ( 6 |
7 | 8 | Home 9 | Features 10 | Gene Splicing 11 | Cloning 12 | 13 |
14 | ); 15 | 16 | export default BreadcrumbPage; 17 | -------------------------------------------------------------------------------- /docs/navigation/menu/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Menu, MenuItem } from '../../../src/menu'; 4 | import { 5 | Menu as FlexMenu, 6 | MenuItem as FlexMenuItem, 7 | } from '../../../lib/menu-flex'; // eslint-disable-line import/no-unresolved 8 | 9 | const iconStyle = { 10 | fontStyle: 'normal', 11 | }; 12 | 13 | const MenuPage = () => ( 14 |
15 | 16 | One 17 | Two 18 | Three 19 | Four 20 | 21 | 22 | One 23 | Two 24 | Three 25 | Four 26 | 27 | 28 | One 29 | Two 30 | Three 31 | Four 32 | 33 | 34 | One 35 | Two 36 | 37 | 38 | One 39 | Two 40 | Three 41 | 42 | 43 | One 44 | Two 45 | Three 46 | Four 47 | 48 | 49 | One 50 | Two 51 | Three 52 | Four 53 | 54 | 55 | One 56 | Two 57 | Three 58 | Four 59 | 60 | 61 | One 62 | Two 63 | Three 64 | Four 65 | 66 | 67 | 68 | One 69 | 70 | One 71 | Two 72 | Three 73 | Four 74 | 75 | 76 | Two 77 | Three 78 | Four 79 | 80 | 81 | Home 82 | About 83 | Nachos 84 | 85 | 86 | Site Title 87 | One 88 | Two 89 | Three 90 | 91 | 92 | One 93 | Two 94 | Three 95 | Four 96 | 97 | 98 | One 99 | Two 100 | Three 101 | Four 102 | 103 | 104 | One 105 | Two 106 | Three 107 | Four 108 | 109 | 110 | One 111 | Two 112 | Three 113 | Four 114 | 115 | 116 | One 117 | Two 118 | Three 119 | Four 120 | 121 |
122 | ); 123 | 124 | export default MenuPage; 125 | -------------------------------------------------------------------------------- /docs/navigation/pagination/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { Pagination } from '../../../src/pagination'; 4 | 5 | function pageContentFormatter(page, activePage) { 6 | if (page === activePage) { 7 | return You are on {page}; 8 | } 9 | 10 | return Go to {page}; 11 | } 12 | 13 | export default class PaginationPage extends Component { 14 | state = { 15 | activePage: 1, 16 | }; 17 | 18 | handleSelect = (activePage) => this.setState({ activePage }); 19 | 20 | render() { 21 | const { activePage } = this.state; 22 | 23 | return ( 24 |
25 | 30 | 40 |
41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/typography/base/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const BaseTypographyPage = () => ( 4 |
5 |

6 | This is a paragraph. Paragraphs are preset with a font size, line height and spacing to 7 | match the overall vertical rhythm. To show what a paragraph looks like this needs a little 8 | more content so, did you know that there are storms occurring on Jupiter that are larger 9 | than the Earth? Pretty cool. Wrap strong around type to make it bold!. 10 | You can also use em to italicize your words. 11 |

12 |

h1. This is a very large header.

13 |

h2. This is a large header.

14 |

h3. This is a medium header.

15 |

h4. This is a moderate header.

16 |
h5. This is a small header.
17 |
h6. This is a tiny header.
18 |

Foundation for Sites Version 6.0.4

19 |

20 | Links are very standard, and the color is preset to the Foundation primary color. 21 | 22 | Learn more about Foundation's global colors. 23 | 24 |

25 |
26 | 40 |
    41 |
  1. Cheese (essential)
  2. 42 |
  3. Pepperoni
  4. 43 |
  5. Bacon 44 |
      45 |
    1. Normal bacon
    2. 46 |
    3. Canadian bacon
    4. 47 |
    48 |
  6. 49 |
  7. Sausage
  8. 50 |
  9. Onions
  10. 51 |
  11. Mushrooms
  12. 52 |
53 |
54 |
Time
55 |
56 | The indefinite continued progress of existence and events in the past, present, and 57 | future regarded as a whole. 58 |
59 |
Space
60 |
A continuous area or expanse that is free, available, or unoccupied.
61 |
62 | The dimensions of height, depth, and width within which all things exist and move. 63 |
64 |
65 |
66 | Those people who think they know everything are a great annoyance to those of us who do. 67 | Isaac Asimov 68 |
69 |

70 | In my dream last night, I saw J. R. R. Tolkien and 71 | George R. R. Martin hanging out on 72 | Sunset Blvd. 73 |

74 | Remember to escape angle brackets when printing HTML: <div> 75 |

Press Cmd+Q (or Ctrl+Q on Windows) to play Half-Life 3.

76 | Buy now 77 |
78 | ); 79 | 80 | export default BaseTypographyPage; 81 | -------------------------------------------------------------------------------- /docs/typography/helpers/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Subheader, Lead, UnbulletedList, Statistic } from '../../../src/typography-helpers'; 4 | 5 | const TypographyHelpersPage = () => ( 6 |
7 | unspecified subheader 8 |

h1 subheader

9 |

h2 subheader

10 |

h3 subheader

11 |

h4 subheader

12 |
h5 subheader
13 |
h6 subheader
14 |
15 | What are your cats really dreaming about while they sleep? 16 |
17 |
18 | 19 |
  • List item with a much longer description or more content.
  • 20 |
  • List item
  • 21 |
  • List item 22 |
      23 |
    • Nested list item
    • 24 |
    • Nested list item
    • 25 |
    • Nested list item
    • 26 |
    27 |
  • 28 |
  • List item
  • 29 |
  • List item
  • 30 |
  • List item
  • 31 |
    32 |
    33 | Days without merge conflict128 34 |
    35 | ); 36 | 37 | export default TypographyHelpersPage; 38 | -------------------------------------------------------------------------------- /docs/typography/print/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { ShowForPrint, HideForPrint } from '../../../src/print'; 4 | 5 | const PrintPage = () => ( 6 |
    7 | You can see me when printing! 8 |
    9 | You can not see me when printing! 10 |
    11 | ); 12 | 13 | export default PrintPage; 14 | -------------------------------------------------------------------------------- /docs/typography/text-alignment/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { TextAlignment } from '../../../src/text-alignment'; 4 | 5 | const TextAlignmentPage = () => ( 6 |
    7 | 8 | This text is left-aligned. Set in the year 0 F.E. ("Foundation Era"), The 9 | Psychohistorians opens on Trantor, the capital of the 12,000-year-old Galactic Empire. 10 | Though the empire appears stable and powerful, it is slowly decaying in ways that parallel 11 | the decline of the Western Roman Empire. 12 | 13 |
    14 | 15 | This text is right-aligned. Set in the year 0 F.E. ("Foundation Era"), The 16 | Psychohistorians opens on Trantor, the capital of the 12,000-year-old Galactic Empire. 17 | Though the empire appears stable and powerful, it is slowly decaying in ways that parallel 18 | the decline of the Western Roman Empire. 19 | 20 |
    21 | 22 | This text is center-aligned. Set in the year 0 F.E. ("Foundation Era"), The 23 | Psychohistorians opens on Trantor, the capital of the 12,000-year-old Galactic Empire. 24 | Though the empire appears stable and powerful, it is slowly decaying in ways that parallel 25 | the decline of the Western Roman Empire. 26 | 27 |
    28 | 29 | This text is justified. Set in the year 0 F.E. ("Foundation Era"), The 30 | Psychohistorians opens on Trantor, the capital of the 12,000-year-old Galactic Empire. 31 | Though the empire appears stable and powerful, it is slowly decaying in ways that parallel 32 | the decline of the Western Roman Empire. 33 | 34 |
    35 | 36 | This text is right-aligned on large screen or larger. Set in the year 0 F.E. 37 | ("Foundation Era"), The Psychohistorians opens on Trantor, the capital of the 38 | 12,000-year-old Galactic Empire. Though the empire appears stable and powerful, it is 39 | slowly decaying in ways that parallel the decline of the Western Roman Empire. 40 | 41 |
    42 | ); 43 | 44 | export default TextAlignmentPage; 45 | -------------------------------------------------------------------------------- /docs/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | const autoprefixer = require('autoprefixer'); 6 | const parseArgs = require('minimist'); 7 | 8 | const argv = parseArgs(process.argv.slice(2), { 9 | default: { 10 | dev: false, 11 | verbose: false, 12 | }, 13 | }); 14 | 15 | const DEV = argv.dev; 16 | const VERBOSE = argv.verbose; 17 | const GLOBALS = { 18 | 'process.env.NODE_ENV': DEV ? JSON.stringify('development') : JSON.stringify('production'), 19 | }; 20 | const PLUGINS = [ 21 | new webpack.DefinePlugin(GLOBALS), 22 | new HtmlWebpackPlugin({ 23 | title: 'React Foundation Components', 24 | template: path.join(__dirname, 'index.html'), 25 | favicon: path.join(__dirname, 'favicon.ico'), 26 | inject: 'body', 27 | }), 28 | ]; 29 | const DEV_PLUGINS = [ 30 | new webpack.HotModuleReplacementPlugin(), 31 | new webpack.NoErrorsPlugin(), 32 | ]; 33 | const PROD_PLUGINS = [ 34 | new ExtractTextPlugin('main-[contenthash].css'), 35 | new webpack.optimize.OccurenceOrderPlugin(), 36 | new webpack.optimize.DedupePlugin(), 37 | new webpack.optimize.UglifyJsPlugin({ 38 | compress: { 39 | warnings: VERBOSE, 40 | }, 41 | }), 42 | new webpack.optimize.AggressiveMergingPlugin(), 43 | ]; 44 | const ENTRY_MIDDLEWARE = DEV ? ['webpack-hot-middleware/client'] : []; 45 | const BABEL_PLUGINS = []; 46 | const BABEL_DEV_PLUGINS = [ 47 | [ 48 | 'react-transform', 49 | { 50 | transforms: [ 51 | { 52 | transform: 'react-transform-hmr', 53 | imports: ['react'], 54 | locals: ['module'], 55 | }, 56 | { 57 | transform: 'react-transform-catch-errors', 58 | imports: ['react', 'redbox-react'], 59 | }, 60 | ], 61 | }, 62 | ], 63 | ]; 64 | const BABEL_PROD_PLUGINS = []; 65 | const SASS_LOADERS = [ 66 | 'style', 67 | `css?modules${DEV ? '&localIdentName=[path]---[local]' : ''}!postcss!sass`, 68 | ]; 69 | 70 | module.exports = { 71 | entry: ENTRY_MIDDLEWARE.concat(path.join(__dirname)), 72 | 73 | output: { 74 | path: path.join(__dirname, 'lib'), 75 | filename: `[name]-[${DEV ? 'hash' : 'chunkhash'}].js`, 76 | publicPath: '/react-foundation-components', 77 | }, 78 | 79 | plugins: PLUGINS.concat(DEV ? DEV_PLUGINS : PROD_PLUGINS), 80 | 81 | cache: DEV, 82 | debug: DEV, 83 | devtool: DEV ? 'cheap-module-eval-source-map' : false, 84 | 85 | stats: { 86 | colors: true, 87 | reasons: true, 88 | hash: VERBOSE, 89 | version: VERBOSE, 90 | timings: true, 91 | chunks: VERBOSE, 92 | chunkModules: VERBOSE, 93 | cached: VERBOSE, 94 | cachedAssets: VERBOSE, 95 | }, 96 | 97 | babel: { 98 | plugins: BABEL_PLUGINS.concat(DEV ? BABEL_DEV_PLUGINS : BABEL_PROD_PLUGINS), 99 | cacheDirectory: argv.dev, 100 | }, 101 | 102 | sassLoader: { 103 | precision: 8, 104 | }, 105 | 106 | postcss: [ 107 | autoprefixer({ 108 | browsers: [ 109 | 'Android >= 4', 110 | 'Chrome >= 20', 111 | 'Firefox >= 24', 112 | 'Explorer >= 9', 113 | 'Edge >= 1', 114 | 'iOS >= 6', 115 | 'Opera >= 12', 116 | 'Safari >= 6', 117 | ], 118 | }), 119 | ], 120 | 121 | imagemin: { 122 | minimize: !DEV, 123 | gifsicle: { 124 | interlaced: true, 125 | }, 126 | jpegtran: { 127 | progressive: true, 128 | }, 129 | optipng: { 130 | optimizationLevel: 7, 131 | }, 132 | svgo: { 133 | plugins: [ 134 | { 135 | removeTitle: true, 136 | }, 137 | { 138 | convertPathData: false, 139 | }, 140 | { 141 | removeViewBox: false, 142 | }, 143 | ], 144 | }, 145 | }, 146 | 147 | url: { 148 | dataUrlLimit: 10000, 149 | }, 150 | 151 | module: { 152 | loaders: [ 153 | { 154 | test: /\.js$/, 155 | exclude: /node_modules/, 156 | loader: 'babel', 157 | }, 158 | { 159 | test: /\.scss$/, 160 | loader: DEV ? SASS_LOADERS.join('!') : ExtractTextPlugin.extract.apply(null, SASS_LOADERS), 161 | }, 162 | { 163 | test: /\.(gif|jpe?g|png|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 164 | loader: 'url!img', 165 | }, 166 | { 167 | test: /\.(woff2?|ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 168 | loader: 'url', 169 | }, 170 | ], 171 | }, 172 | }; 173 | -------------------------------------------------------------------------------- /examples/cdn-flex/app.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { Button } from '../../lib/global/button'; 7 | import { ButtonGroup } from '../../lib/global/button-group-flex'; 8 | 9 | const App = () => ( 10 |
    11 |

    Welcome to CDN CSS with Flexbox example!

    12 |

    13 | We've imported Foundation from CDN - https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.0/foundation-flex.min.css. 14 |

    15 |

    16 | Make sure to use the components under lib/global. These components use global scoped 17 | class names. 18 |

    19 |

    20 | Also make sure to use the Flexbox components. The non Flexbox components use class names 21 | that don't exist in the flex CDN stylesheet. 22 |

    23 |
    24 |

    Button react-foundation-components/lib/global/button

    25 | 26 |
    27 |
    28 |

    ButtonGroup react-foundation-components/lib/global/button-group-flex

    29 |

    This ButtonGroup uses Flexbox layout

    30 | 31 | 32 | 33 | 34 | 35 |
    36 |
    37 | ); 38 | 39 | ReactDOM.render(, document.getElementById('app')); 40 | -------------------------------------------------------------------------------- /examples/cdn-flex/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruberto/react-foundation-components/3db1a7a9bae46734089635bffb53d107b43d973b/examples/cdn-flex/favicon.ico -------------------------------------------------------------------------------- /examples/cdn-flex/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 | 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/cdn-flex/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, 'app.js'), 7 | 8 | output: { 9 | path: path.join(__dirname, 'lib'), 10 | filename: '[name]-[chunkhash].js', 11 | publicPath: '/', 12 | }, 13 | 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env.NODE_ENV': JSON.stringify('production'), 17 | }), 18 | new HtmlWebpackPlugin({ 19 | title: 'React Foundation Components CSS Modules Example', 20 | template: path.join(__dirname, 'index.html'), 21 | favicon: path.join(__dirname, 'favicon.ico'), 22 | inject: 'body', 23 | }), 24 | new webpack.optimize.OccurenceOrderPlugin(), 25 | new webpack.optimize.DedupePlugin(), 26 | new webpack.optimize.UglifyJsPlugin(), 27 | new webpack.optimize.AggressiveMergingPlugin(), 28 | ], 29 | 30 | module: { 31 | loaders: [ 32 | { 33 | test: /\.js$/, 34 | exclude: /node_modules/, 35 | loader: 'babel', 36 | }, 37 | ], 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /examples/cdn/app.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { Button } from '../../lib/global/button'; 7 | import { ButtonGroup } from '../../lib/global/button-group'; 8 | 9 | const App = () => ( 10 |
    11 |

    Welcome to CDN CSS example!

    12 |

    13 | We've imported Foundation from CDN - https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.0/foundation.min.css. 14 |

    15 |

    16 | Make sure to use the components under lib/global. These components use global scoped 17 | class names. 18 |

    19 |

    20 | Also make sure to use the non Flexbox components. The Flexbox components use class names 21 | that don't exist in the non flex CDN stylesheet. 22 |

    23 |
    24 |

    Button react-foundation-components/lib/global/button

    25 | 26 |
    27 |
    28 |

    ButtonGroup react-foundation-components/lib/global/button-group

    29 |

    This ButtonGroup uses float layout

    30 | 31 | 32 | 33 | 34 | 35 |
    36 |
    37 | ); 38 | 39 | ReactDOM.render(, document.getElementById('app')); 40 | -------------------------------------------------------------------------------- /examples/cdn/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruberto/react-foundation-components/3db1a7a9bae46734089635bffb53d107b43d973b/examples/cdn/favicon.ico -------------------------------------------------------------------------------- /examples/cdn/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 | 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/cdn/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, 'app.js'), 7 | 8 | output: { 9 | path: path.join(__dirname, 'lib'), 10 | filename: '[name]-[chunkhash].js', 11 | publicPath: '/', 12 | }, 13 | 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env.NODE_ENV': JSON.stringify('production'), 17 | }), 18 | new HtmlWebpackPlugin({ 19 | title: 'React Foundation Components CSS Modules Example', 20 | template: path.join(__dirname, 'index.html'), 21 | favicon: path.join(__dirname, 'favicon.ico'), 22 | inject: 'body', 23 | }), 24 | new webpack.optimize.OccurenceOrderPlugin(), 25 | new webpack.optimize.DedupePlugin(), 26 | new webpack.optimize.UglifyJsPlugin(), 27 | new webpack.optimize.AggressiveMergingPlugin(), 28 | ], 29 | 30 | module: { 31 | loaders: [ 32 | { 33 | test: /\.js$/, 34 | exclude: /node_modules/, 35 | loader: 'babel', 36 | }, 37 | ], 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /examples/css-modules-custom/app.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import '../../lib/_typography.scss'; 7 | 8 | import { Button } from '../../lib/button'; 9 | import { ButtonGroup } from '../../lib/button-group'; 10 | import { ButtonGroup as FlexButtonGroup } from '../../lib/button-group-flex'; 11 | 12 | const App = () => ( 13 |
    14 |

    Welcome to CSS Modules Custom example!

    15 |

    16 | Importing a component will import the components required CSS. This means that your final 17 | CSS stylesheet generated by bundler will always contain minimum required amount of class 18 | names. 19 |

    20 |

    21 | We've also imported react-foundation-components/lib/_typography.scss for 22 | general look and feel. 23 |

    24 |

    25 | We are also using https://www.npmjs.com/package/jsontosass-loader to prepend theme.json 26 | to all CSS modules imported. Here theme.json is changing the secondary color to purple. 27 |

    28 |
    29 |

    Button react-foundation-components/lib/button

    30 | 31 | 32 |
    33 |
    34 |

    ButtonGroup react-foundation-components/lib/button-group

    35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 |

    43 | Flexbox ButtonGroup react-foundation-components/lib/button-group-flex 44 |

    45 |

    46 | Because CSS Modules creates class names that are scoped locally to the component, 47 | we can use same Flexbox based and Float based components at same time! CSS Modules FTW! 48 |

    49 | 50 | 51 | 52 | 53 | 54 |
    55 |
    56 | ); 57 | 58 | ReactDOM.render(, document.getElementById('app')); 59 | -------------------------------------------------------------------------------- /examples/css-modules-custom/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruberto/react-foundation-components/3db1a7a9bae46734089635bffb53d107b43d973b/examples/css-modules-custom/favicon.ico -------------------------------------------------------------------------------- /examples/css-modules-custom/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/css-modules-custom/theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "foundation-palette": { 3 | "primary": "#2199e8", 4 | "secondary": "#800080", 5 | "success": "#3adb76", 6 | "warning": "#ffae00", 7 | "alert": "#ec5840" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/css-modules-custom/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | const autoprefixer = require('autoprefixer'); 6 | 7 | const themePath = path.join(__dirname, 'theme.json'); 8 | 9 | module.exports = { 10 | entry: path.join(__dirname, 'app.js'), 11 | 12 | output: { 13 | path: path.join(__dirname, 'lib'), 14 | filename: '[name]-[chunkhash].js', 15 | publicPath: '/', 16 | }, 17 | 18 | plugins: [ 19 | new webpack.DefinePlugin({ 20 | 'process.env.NODE_ENV': JSON.stringify('production'), 21 | }), 22 | new HtmlWebpackPlugin({ 23 | title: 'React Foundation Components CSS Modules Example', 24 | template: path.join(__dirname, 'index.html'), 25 | favicon: path.join(__dirname, 'favicon.ico'), 26 | inject: 'body', 27 | }), 28 | new ExtractTextPlugin('main-[contenthash].css'), 29 | new webpack.optimize.OccurenceOrderPlugin(), 30 | new webpack.optimize.DedupePlugin(), 31 | new webpack.optimize.UglifyJsPlugin(), 32 | new webpack.optimize.AggressiveMergingPlugin(), 33 | ], 34 | 35 | sassLoader: { 36 | precision: 8, 37 | }, 38 | 39 | postcss: [ 40 | autoprefixer({ 41 | browsers: [ 42 | 'Android >= 4', 43 | 'Chrome >= 20', 44 | 'Firefox >= 24', 45 | 'Explorer >= 9', 46 | 'Edge >= 1', 47 | 'iOS >= 6', 48 | 'Opera >= 12', 49 | 'Safari >= 6', 50 | ], 51 | }), 52 | ], 53 | 54 | module: { 55 | loaders: [ 56 | { 57 | test: /\.js$/, 58 | exclude: /node_modules/, 59 | loader: 'babel', 60 | }, 61 | { 62 | test: /\.scss$/, 63 | loader: ExtractTextPlugin.extract( 64 | 'style', 65 | `css?modules!postcss!sass!jsontosass?path=${themePath}` 66 | ), 67 | }, 68 | ], 69 | }, 70 | }; 71 | -------------------------------------------------------------------------------- /examples/css-modules/app.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import '../../lib/_typography.scss'; 7 | 8 | import { Button } from '../../lib/button'; 9 | import { ButtonGroup } from '../../lib/button-group'; 10 | import { ButtonGroup as FlexButtonGroup } from '../../lib/button-group-flex'; 11 | 12 | const App = () => ( 13 |
    14 |

    Welcome to CSS Modules example!

    15 |

    16 | Importing a component will import the components required CSS. This means that your final 17 | CSS stylesheet generated by bundler will always contain minimum required amount of class 18 | names. 19 |

    20 |

    21 | We've also imported react-foundation-components/lib/_typography.scss for 22 | general look and feel. 23 |

    24 |
    25 |

    Button react-foundation-components/lib/button

    26 | 27 |
    28 |
    29 |

    ButtonGroup react-foundation-components/lib/button-group

    30 | 31 | 32 | 33 | 34 | 35 |
    36 |
    37 |

    38 | Flexbox ButtonGroup react-foundation-components/lib/button-group-flex 39 |

    40 |

    41 | Because CSS Modules creates class names that are scoped locally to the component, 42 | we can use same Flexbox based and Float based components at same time! CSS Modules FTW! 43 |

    44 | 45 | 46 | 47 | 48 | 49 |
    50 |
    51 | ); 52 | 53 | ReactDOM.render(, document.getElementById('app')); 54 | -------------------------------------------------------------------------------- /examples/css-modules/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruberto/react-foundation-components/3db1a7a9bae46734089635bffb53d107b43d973b/examples/css-modules/favicon.ico -------------------------------------------------------------------------------- /examples/css-modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/css-modules/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | const autoprefixer = require('autoprefixer'); 6 | 7 | module.exports = { 8 | entry: path.join(__dirname, 'app.js'), 9 | 10 | output: { 11 | path: path.join(__dirname, 'lib'), 12 | filename: '[name]-[chunkhash].js', 13 | publicPath: '/', 14 | }, 15 | 16 | plugins: [ 17 | new webpack.DefinePlugin({ 18 | 'process.env.NODE_ENV': JSON.stringify('production'), 19 | }), 20 | new HtmlWebpackPlugin({ 21 | title: 'React Foundation Components CSS Modules Example', 22 | template: path.join(__dirname, 'index.html'), 23 | favicon: path.join(__dirname, 'favicon.ico'), 24 | inject: 'body', 25 | }), 26 | new ExtractTextPlugin('main-[contenthash].css'), 27 | new webpack.optimize.OccurenceOrderPlugin(), 28 | new webpack.optimize.DedupePlugin(), 29 | new webpack.optimize.UglifyJsPlugin(), 30 | new webpack.optimize.AggressiveMergingPlugin(), 31 | ], 32 | 33 | sassLoader: { 34 | precision: 8, 35 | }, 36 | 37 | postcss: [ 38 | autoprefixer({ 39 | browsers: [ 40 | 'Android >= 4', 41 | 'Chrome >= 20', 42 | 'Firefox >= 24', 43 | 'Explorer >= 9', 44 | 'Edge >= 1', 45 | 'iOS >= 6', 46 | 'Opera >= 12', 47 | 'Safari >= 6', 48 | ], 49 | }), 50 | ], 51 | 52 | module: { 53 | loaders: [ 54 | { 55 | test: /\.js$/, 56 | exclude: /node_modules/, 57 | loader: 'babel', 58 | }, 59 | { 60 | test: /\.scss$/, 61 | loader: ExtractTextPlugin.extract('style', 'css?modules!postcss!sass'), 62 | }, 63 | ], 64 | }, 65 | }; 66 | -------------------------------------------------------------------------------- /examples/global-flex/app.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import './app.scss'; 7 | 8 | import { Button } from '../../lib/global/button'; 9 | import { ButtonGroup } from '../../lib/global/button-group-flex'; 10 | 11 | const App = () => ( 12 |
    13 |

    Welcome to Global CSS with Flexbox example!

    14 |

    15 | We've imported react-foundation-components/lib/_foundation.scss with 16 | global-flexbox set to true to import all Foundation class names into CSS name space. 17 |

    18 |

    19 | Importing _foundation.scss also gives us the ability to 20 | customize Foundation. Here we have changed the secondary color to purple. 21 |

    22 |

    23 | Make sure to use the components under lib/global. These components use global scoped 24 | class names. 25 |

    26 |

    27 | Also make sure to use the Flexbox components. The non Flexbox components use class names 28 | that don't exist when global-flexbox is set to true. 29 |

    30 |
    31 |

    Button react-foundation-components/lib/global/button

    32 | 33 | 34 |
    35 |
    36 |

    ButtonGroup react-foundation-components/lib/global/button-group-flex

    37 |

    This ButtonGroup uses Flexbox layout

    38 | 39 | 40 | 41 | 42 | 43 |
    44 |
    45 | ); 46 | 47 | ReactDOM.render(, document.getElementById('app')); 48 | -------------------------------------------------------------------------------- /examples/global-flex/app.scss: -------------------------------------------------------------------------------- 1 | $global-flexbox: true; 2 | $foundation-palette: ( 3 | primary: #2199e8, 4 | secondary: #800080, 5 | success: #3adb76, 6 | warning: #ffae00, 7 | alert: #ec5840, 8 | ); 9 | 10 | @import '../../lib/foundation'; 11 | -------------------------------------------------------------------------------- /examples/global-flex/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruberto/react-foundation-components/3db1a7a9bae46734089635bffb53d107b43d973b/examples/global-flex/favicon.ico -------------------------------------------------------------------------------- /examples/global-flex/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/global-flex/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | const autoprefixer = require('autoprefixer'); 6 | 7 | module.exports = { 8 | entry: path.join(__dirname, 'app.js'), 9 | 10 | output: { 11 | path: path.join(__dirname, 'lib'), 12 | filename: '[name]-[chunkhash].js', 13 | publicPath: '/', 14 | }, 15 | 16 | plugins: [ 17 | new webpack.DefinePlugin({ 18 | 'process.env.NODE_ENV': JSON.stringify('production'), 19 | }), 20 | new HtmlWebpackPlugin({ 21 | title: 'React Foundation Components CSS Modules Example', 22 | template: path.join(__dirname, 'index.html'), 23 | favicon: path.join(__dirname, 'favicon.ico'), 24 | inject: 'body', 25 | }), 26 | new ExtractTextPlugin('main-[contenthash].css'), 27 | new webpack.optimize.OccurenceOrderPlugin(), 28 | new webpack.optimize.DedupePlugin(), 29 | new webpack.optimize.UglifyJsPlugin(), 30 | new webpack.optimize.AggressiveMergingPlugin(), 31 | ], 32 | 33 | sassLoader: { 34 | precision: 8, 35 | }, 36 | 37 | postcss: [ 38 | autoprefixer({ 39 | browsers: [ 40 | 'Android >= 4', 41 | 'Chrome >= 20', 42 | 'Firefox >= 24', 43 | 'Explorer >= 9', 44 | 'Edge >= 1', 45 | 'iOS >= 6', 46 | 'Opera >= 12', 47 | 'Safari >= 6', 48 | ], 49 | }), 50 | ], 51 | 52 | module: { 53 | loaders: [ 54 | { 55 | test: /\.js$/, 56 | exclude: /node_modules/, 57 | loader: 'babel', 58 | }, 59 | { 60 | test: /\.scss$/, 61 | loader: ExtractTextPlugin.extract('style', 'css!postcss!sass'), 62 | }, 63 | ], 64 | }, 65 | }; 66 | -------------------------------------------------------------------------------- /examples/global/app.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import './app.scss'; 7 | 8 | import { Button } from '../../lib/global/button'; 9 | import { ButtonGroup } from '../../lib/global/button-group'; 10 | 11 | const App = () => ( 12 |
    13 |

    Welcome to Global CSS example!

    14 |

    15 | We've imported react-foundation-components/lib/_foundation.scss with 16 | global-flexbox set to false to import all Foundation class names into CSS name space. 17 |

    18 |

    19 | Importing _foundation.scss also gives us the ability to 20 | customize Foundation. Here we have changed the secondary color to purple. 21 |

    22 |

    23 | Make sure to use the components under lib/global. These components use global scoped 24 | class names. 25 |

    26 |

    27 | Also make sure to use the non Flexbox components. The Flexbox components use class names 28 | that don't exist when global-flexbox is set to false. 29 |

    30 |
    31 |

    Button react-foundation-components/lib/global/button

    32 | 33 | 34 |
    35 |
    36 |

    ButtonGroup react-foundation-components/lib/global/button-group

    37 |

    This ButtonGroup uses float layout

    38 | 39 | 40 | 41 | 42 | 43 |
    44 |
    45 | ); 46 | 47 | ReactDOM.render(, document.getElementById('app')); 48 | -------------------------------------------------------------------------------- /examples/global/app.scss: -------------------------------------------------------------------------------- 1 | $foundation-palette: ( 2 | primary: #2199e8, 3 | secondary: #800080, 4 | success: #3adb76, 5 | warning: #ffae00, 6 | alert: #ec5840, 7 | ); 8 | 9 | @import '../../lib/foundation'; 10 | -------------------------------------------------------------------------------- /examples/global/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruberto/react-foundation-components/3db1a7a9bae46734089635bffb53d107b43d973b/examples/global/favicon.ico -------------------------------------------------------------------------------- /examples/global/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/global/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | const autoprefixer = require('autoprefixer'); 6 | 7 | module.exports = { 8 | entry: path.join(__dirname, 'app.js'), 9 | 10 | output: { 11 | path: path.join(__dirname, 'lib'), 12 | filename: '[name]-[chunkhash].js', 13 | publicPath: '/', 14 | }, 15 | 16 | plugins: [ 17 | new webpack.DefinePlugin({ 18 | 'process.env.NODE_ENV': JSON.stringify('production'), 19 | }), 20 | new HtmlWebpackPlugin({ 21 | title: 'React Foundation Components CSS Modules Example', 22 | template: path.join(__dirname, 'index.html'), 23 | favicon: path.join(__dirname, 'favicon.ico'), 24 | inject: 'body', 25 | }), 26 | new ExtractTextPlugin('main-[contenthash].css'), 27 | new webpack.optimize.OccurenceOrderPlugin(), 28 | new webpack.optimize.DedupePlugin(), 29 | new webpack.optimize.UglifyJsPlugin(), 30 | new webpack.optimize.AggressiveMergingPlugin(), 31 | ], 32 | 33 | sassLoader: { 34 | precision: 8, 35 | }, 36 | 37 | postcss: [ 38 | autoprefixer({ 39 | browsers: [ 40 | 'Android >= 4', 41 | 'Chrome >= 20', 42 | 'Firefox >= 24', 43 | 'Explorer >= 9', 44 | 'Edge >= 1', 45 | 'iOS >= 6', 46 | 'Opera >= 12', 47 | 'Safari >= 6', 48 | ], 49 | }), 50 | ], 51 | 52 | module: { 53 | loaders: [ 54 | { 55 | test: /\.js$/, 56 | exclude: /node_modules/, 57 | loader: 'babel', 58 | }, 59 | { 60 | test: /\.scss$/, 61 | loader: ExtractTextPlugin.extract('style', 'css!postcss!sass'), 62 | }, 63 | ], 64 | }, 65 | }; 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-foundation-components", 3 | "version": "0.14.0", 4 | "description": "Foundation Sites components built with the power of React and CSS Modules", 5 | "main": "lib/index.js", 6 | "files": [ 7 | "lib" 8 | ], 9 | "scripts": { 10 | "clean": "rimraf lib docs/lib", 11 | "lint": "eslint src && eslint docs && eslint examples && sass-lint --verbose", 12 | "build": "npm run clean && babel --quiet src --out-dir lib && cpy \"**/*.scss\" ../lib --parents --cwd=src && node create-flex-components.js && node create-global-scoped-components.js", 13 | "build-docs": "npm run clean && npm run build && webpack --config docs/webpack.config.js", 14 | "start-docs": "npm run build && node server.js docs/webpack.config.js --dev", 15 | "start-examples-css-modules": "npm run build && node server.js examples/css-modules/webpack.config.js", 16 | "start-examples-css-modules-custom": "npm run build && node server.js examples/css-modules-custom/webpack.config.js", 17 | "start-examples-global": "npm run build && node server.js examples/global/webpack.config.js", 18 | "start-examples-global-flex": "npm run build && node server.js examples/global-flex/webpack.config.js", 19 | "start-examples-cdn": "npm run build && node server.js examples/cdn/webpack.config.js", 20 | "start-examples-cdn-flex": "npm run build && node server.js examples/cdn-flex/webpack.config.js", 21 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", 22 | "release-patch": "npm run build && release-it", 23 | "release-minor": "npm run build && release-it minor" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/aruberto/react-foundation-components.git" 28 | }, 29 | "keywords": [ 30 | "react", 31 | "foundation", 32 | "foundation-sites", 33 | "css-modules", 34 | "react-component" 35 | ], 36 | "author": "aruberto", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/aruberto/react-foundation-components/issues" 40 | }, 41 | "homepage": "https://github.com/aruberto/react-foundation-components#readme", 42 | "peerDependencies": { 43 | "react": ">=16", 44 | "react-dom": ">=16" 45 | }, 46 | "dependencies": { 47 | "babel-runtime": "^6.25.0", 48 | "classnames": "^2.2.5", 49 | "dom-helpers": "^2.4.0", 50 | "foundation-sites": "~6.2.4", 51 | "lodash": "^4.17.4", 52 | "prop-types": "^15.6.0", 53 | "react-overlays": "^0.7.0", 54 | "prop-types-extra": "1.0.1", 55 | "uncontrollable": "^5.1.0", 56 | "underscore.string": "^3.3.4" 57 | }, 58 | "devDependencies": { 59 | "autoprefixer": "^6.7.7", 60 | "babel-cli": "^6.24.1", 61 | "babel-core": "^6.25.0", 62 | "babel-eslint": "^6.1.2", 63 | "babel-loader": "^6.4.1", 64 | "babel-plugin-react-transform": "^2.0.2", 65 | "babel-plugin-transform-runtime": "^6.23.0", 66 | "babel-preset-es2015": "^6.24.1", 67 | "babel-preset-react": "^6.24.1", 68 | "babel-preset-stage-0": "^6.24.1", 69 | "conventional-changelog-cli": "^1.3.2", 70 | "cpy-cli": "^1.0.1", 71 | "css-loader": "^0.25.0", 72 | "eslint": "^3.19.0", 73 | "eslint-config-airbnb": "^11.2.0", 74 | "eslint-plugin-import": "^1.16.0", 75 | "eslint-plugin-jsx-a11y": "^2.2.3", 76 | "eslint-plugin-react": "^6.10.3", 77 | "express": "^4.15.3", 78 | "extract-text-webpack-plugin": "^1.0.1", 79 | "file-loader": "^0.9.0", 80 | "fs-extra": "^0.30.0", 81 | "html-webpack-plugin": "^2.29.0", 82 | "img-loader": "^1.3.1", 83 | "jsontosass-loader": "^0.1.9", 84 | "minimist": "^1.2.0", 85 | "node-sass": "^4.5.3", 86 | "postcss-loader": "^0.13.0", 87 | "react": "^16.3.0", 88 | "react-dom": "^16.3.0", 89 | "react-router": "3.2.1", 90 | "react-transform-catch-errors": "^1.0.2", 91 | "react-transform-hmr": "^1.0.4", 92 | "redbox-react": "^1.4.3", 93 | "release-it": "^2.8.2", 94 | "rimraf": "^2.6.1", 95 | "sass-lint": "^1.10.2", 96 | "sass-loader": "^4.1.1", 97 | "style-loader": "^0.13.2", 98 | "through2": "^2.0.3", 99 | "url-loader": "^0.5.9", 100 | "webpack": "^1.15.0", 101 | "webpack-dev-middleware": "^1.11.0", 102 | "webpack-hot-middleware": "^2.18.2" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | const express = require('express'); 6 | const webpackDevMiddleware = require('webpack-dev-middleware'); 7 | const webpackHotMiddleware = require('webpack-hot-middleware'); 8 | 9 | const config = require(path.join(__dirname, process.argv[2])); 10 | 11 | const app = express(); 12 | const compiler = webpack(config); 13 | 14 | app.use(webpackDevMiddleware(compiler, { 15 | noInfo: true, 16 | stats: { colors: true }, 17 | publicPath: config.output.publicPath, 18 | })); 19 | 20 | app.use(webpackHotMiddleware(compiler)); 21 | 22 | app.listen(3000, '0.0.0.0', (err) => { 23 | if (err) { 24 | console.error(err); 25 | return; 26 | } 27 | 28 | console.info('Listening at http://0.0.0.0:3000'); 29 | }); 30 | -------------------------------------------------------------------------------- /src/_common.scss: -------------------------------------------------------------------------------- 1 | $breakpoint-classes: (small medium large xlarge xxlarge); 2 | 3 | @import '~foundation-sites/scss/util/util'; 4 | @import '~foundation-sites/scss/global'; 5 | @import '~foundation-sites/scss/typography/base'; 6 | -------------------------------------------------------------------------------- /src/_foundation.scss: -------------------------------------------------------------------------------- 1 | @import './common'; 2 | 3 | @import './typography'; 4 | @import './typography-helpers/styles'; 5 | @import './text-alignment/styles'; 6 | 7 | @if $global-flexbox { 8 | @import './flex/styles'; 9 | @import './grid-flex/styles'; 10 | } @else { 11 | @import './grid/styles'; 12 | } 13 | 14 | @import './forms/styles'; 15 | @import './float/styles'; 16 | @import './visibility/styles'; 17 | 18 | @import './button/styles'; 19 | @import './button-group/styles'; 20 | @import './close-button/styles'; 21 | @import './switch/styles'; 22 | 23 | @import './menu/styles'; 24 | @import './top-bar/styles'; 25 | 26 | @import './accordion/styles'; 27 | @import './callout/styles'; 28 | @import './dropdown/styles'; 29 | @import './media-object/styles'; 30 | @import './menu-icon/styles'; 31 | @import './off-canvas/styles'; 32 | @import './reveal/styles'; 33 | @import './table/styles'; 34 | @import './tabs/styles'; 35 | @import './title-bar/styles'; 36 | 37 | @import './badge/styles'; 38 | @import './flex-video/styles'; 39 | @import './label/styles'; 40 | @import './progress-bar/styles'; 41 | @import './thumbnail/styles'; 42 | @import './tooltip/styles'; 43 | 44 | @import './toggle-switch/styles'; 45 | 46 | @import './collapse/styles'; 47 | @import './fade/styles'; 48 | -------------------------------------------------------------------------------- /src/_typography.scss: -------------------------------------------------------------------------------- 1 | @import './common'; 2 | @import '~foundation-sites/scss/typography/print'; 3 | 4 | @include foundation-global-styles 5 | @include foundation-typography-base 6 | @include foundation-print-styles; 7 | -------------------------------------------------------------------------------- /src/accordion/_custom.scss: -------------------------------------------------------------------------------- 1 | .accordion-item { 2 | border-bottom: $accordion-content-border; 3 | } 4 | 5 | .accordion-title { 6 | border-bottom: 0; 7 | } 8 | 9 | .accordion-content { 10 | border-top: $accordion-content-border; 11 | border-bottom: 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/accordion/_styles.scss: -------------------------------------------------------------------------------- 1 | @import '../common'; 2 | @import '~foundation-sites/scss/components/accordion'; 3 | 4 | @include foundation-accordion; 5 | 6 | @import './custom'; 7 | -------------------------------------------------------------------------------- /src/accordion/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React, { Children, cloneElement, isValidElement } from 'react'; 3 | import cx from 'classnames'; 4 | import cxBinder from 'classnames/bind'; 5 | import uncontrollable from 'uncontrollable'; 6 | import includes from 'lodash/includes'; 7 | import noop from 'lodash/noop'; 8 | import isBlank from 'underscore.string/isBlank'; 9 | 10 | import { Collapse } from '../collapse'; 11 | import styles from './_styles.scss'; 12 | 13 | const cxStyles = cxBinder.bind(styles); 14 | 15 | const AccordionItemControlled = ({ 16 | active, 17 | children, 18 | className, 19 | contentClassName, 20 | contentStyle, 21 | eventKey, 22 | id, 23 | onClick, 24 | onSelect, 25 | onToggle, 26 | title, 27 | titleClassName, 28 | titleStyle, 29 | ...restProps, 30 | }) => { 31 | const classNames = cx(className, cxStyles('accordion-item', { 'is-active': active })); 32 | const titleClassNames = cx(titleClassName, cxStyles('accordion-title')); 33 | const contentClassNames = cx(contentClassName, cxStyles('accordion-content')); 34 | let titleId = null; 35 | let contentId = null; 36 | 37 | if (!isBlank(id)) { 38 | titleId = `${id}Title`; 39 | contentId = `${id}Content`; 40 | } 41 | 42 | const onTitleClick = (...args) => { 43 | const [event] = args; 44 | 45 | event.preventDefault(); 46 | 47 | if (onClick) { 48 | onClick(...args); 49 | } 50 | 51 | if (onToggle) { 52 | onToggle(!active, ...args); 53 | } 54 | 55 | if (onSelect) { 56 | onSelect(eventKey, ...args); 57 | } 58 | }; 59 | 60 | return ( 61 |
  • 62 | 73 | {title} 74 | 75 | 76 |
    77 |
    85 | {children} 86 |
    87 |
    88 |
    89 |
  • 90 | ); 91 | }; 92 | 93 | AccordionItemControlled.propTypes = { 94 | active: PropTypes.bool, 95 | children: PropTypes.node, 96 | className: PropTypes.string, 97 | contentClassName: PropTypes.string, 98 | contentStyle: PropTypes.object, 99 | eventKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 100 | id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 101 | onClick: PropTypes.func, 102 | onSelect: PropTypes.func, 103 | onToggle: PropTypes.func, 104 | title: PropTypes.node, 105 | titleClassName: PropTypes.string, 106 | titleStyle: PropTypes.object, 107 | }; 108 | 109 | export const AccordionItem = uncontrollable(AccordionItemControlled, { active: 'onToggle' }); 110 | AccordionItem.displayName = 'AccordionItem'; 111 | 112 | const AccordionControlled = ({ 113 | allowAllClosed, 114 | children, 115 | className, 116 | multiExpand, 117 | activeKey: maybeActiveKey = multiExpand ? [] : null, 118 | onSelect, 119 | ...restProps, 120 | }) => { 121 | let activeKey = maybeActiveKey; 122 | 123 | if (!allowAllClosed && (multiExpand && activeKey.length === 0 || isBlank(activeKey))) { 124 | const childArray = 125 | Children.toArray(children) 126 | .filter((child) => isValidElement(child) && !isBlank(child.props.eventKey)); 127 | 128 | if (childArray.length >= 1) { 129 | const firstKey = childArray[0].props.eventKey; 130 | activeKey = multiExpand ? [firstKey] : firstKey; 131 | } 132 | } 133 | 134 | const onChildSelect = (eventKey, ...args) => { 135 | if (multiExpand) { 136 | if (includes(activeKey, eventKey)) { 137 | const filtered = activeKey.filter((item) => item !== eventKey); 138 | 139 | if (!allowAllClosed && filtered.length === 0) { 140 | onSelect([eventKey], ...args); 141 | } else { 142 | onSelect(filtered, ...args); 143 | } 144 | } else { 145 | onSelect([...activeKey, eventKey], ...args); 146 | } 147 | } else { 148 | if (allowAllClosed && activeKey === eventKey) { 149 | onSelect(null, ...args); 150 | } else { 151 | onSelect(eventKey, ...args); 152 | } 153 | } 154 | }; 155 | 156 | const classNames = cx(className, cxStyles('accordion')); 157 | const clonedChildren = Children.map(children, (child) => { 158 | if (isValidElement(child)) { 159 | return cloneElement(child, { 160 | active: 161 | multiExpand 162 | ? includes(activeKey, child.props.eventKey) 163 | : activeKey === child.props.eventKey, 164 | onSelect: onChildSelect, 165 | onToggle: noop, 166 | }); 167 | } 168 | 169 | return child; 170 | }); 171 | 172 | return
      {clonedChildren}
    ; 173 | }; 174 | 175 | AccordionControlled.propTypes = { 176 | activeKey: PropTypes.oneOfType([ 177 | PropTypes.string, 178 | PropTypes.number, 179 | PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), 180 | ]), 181 | allowAllClosed: PropTypes.bool, 182 | children: PropTypes.node, 183 | className: PropTypes.string, 184 | defaultActiveKey: PropTypes.oneOfType([ 185 | PropTypes.string, 186 | PropTypes.number, 187 | PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), 188 | ]), 189 | multiExpand: PropTypes.bool, 190 | onSelect: PropTypes.func, 191 | }; 192 | 193 | export const Accordion = uncontrollable(AccordionControlled, { activeKey: 'onSelect' }); 194 | Accordion.displayName = 'Accordion'; 195 | 196 | Accordion.Item = AccordionItem; 197 | 198 | export default Accordion; 199 | -------------------------------------------------------------------------------- /src/badge/_styles.scss: -------------------------------------------------------------------------------- 1 | @import '../common'; 2 | @import '~foundation-sites/scss/components/badge'; 3 | 4 | @include foundation-badge; 5 | -------------------------------------------------------------------------------- /src/badge/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import includes from 'lodash/includes'; 3 | 4 | import { COMPONENT_COLORS, COMPONENT_ALTERNATIVE_COLORS } from '../util/constants'; 5 | import createWrapperComponent from '../util/create-wrapper-component'; 6 | import styles from './_styles.scss'; 7 | 8 | export const Badge = createWrapperComponent({ 9 | displayName: 'Badge', 10 | styles, 11 | propTypes: { 12 | color: PropTypes.oneOf(COMPONENT_COLORS), 13 | }, 14 | mapProps: ({ color, ...props }) => ({ 15 | props, 16 | classNames: ['badge', { [color]: includes(COMPONENT_ALTERNATIVE_COLORS, color) }], 17 | }), 18 | }); 19 | 20 | export default Badge; 21 | -------------------------------------------------------------------------------- /src/breadcrumb/_styles.scss: -------------------------------------------------------------------------------- 1 | @import '../common'; 2 | @import '~foundation-sites/scss/components/breadcrumbs'; 3 | 4 | @include foundation-breadcrumbs; 5 | -------------------------------------------------------------------------------- /src/breadcrumb/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import cx from 'classnames'; 4 | import cxBinder from 'classnames/bind'; 5 | 6 | import styles from './_styles.scss'; 7 | 8 | const cxStyles = cxBinder.bind(styles); 9 | 10 | export const Breadcrumb = ({ 11 | className, 12 | ...restProps, 13 | }) => { 14 | const classNames = cx(className, cxStyles('breadcrumbs')); 15 | 16 | return