├── .cfignore ├── .eslintrc ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── Staticfile ├── babel.config.js ├── bin ├── deploy-staging.sh └── deploy.sh ├── docs ├── 404 │ └── 1.404.md ├── 1.Get_Started │ ├── 1.Installation.md │ ├── 2.Usage_with_Create_React_App.md │ ├── 3.Using_CSS_only.md │ ├── 4.Unit_testing_with_Jasmine.md │ └── 5.Linting.md ├── 2.FAQ │ └── 1.Index.md ├── 3.Upgrade_Guide │ ├── -10.v10.md │ ├── -11.v11.md │ ├── -12.v12.md │ ├── -13.v13.md │ ├── -14.v14.md │ ├── -15.v15.md │ ├── -16.v16.md │ ├── -17.v17.md │ └── -9.v9.md ├── 4.Contribute │ └── 1.Index.md ├── 5.Versions │ └── Index.md ├── components │ ├── Alerts │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Autocomplete │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Back_to_Top │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Button_Group │ │ └── 1.Usage.md │ ├── Buttons │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Checkbox_Dropdowns │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Checkboxes │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Code │ │ └── 1.Usage.md │ ├── Collapsible │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Copy_to_Clipboard │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Dividers │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Draggable_Lists │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Dropdowns │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Flyout │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Forms │ │ ├── 1.Usage.md │ │ ├── 2.Using_the_FormUnit.md │ │ └── 3.Props.md │ ├── Grids │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Icons │ │ ├── 1.Usage.md │ │ ├── 2.Icon_List.md │ │ └── 3.Props.md │ ├── Images │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Inputs │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Links │ │ └── 1.Usage.md │ ├── Lists │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Media │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Modal │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Notifications │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Overlay_Trigger │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Pagination │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Panels │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Portals │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Progress_Bars │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Radios │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Select │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Siteframe │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Svg │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Tables │ │ ├── 1.Usage.md │ │ ├── 2.Using_Plugins.md │ │ ├── 3.Writing_Plugins.md │ │ ├── 4.Table_Modifiers.md │ │ └── 5.Props.md │ ├── Tabs │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Text_Filter │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Toggle │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ ├── Tooltips │ │ ├── 1.Usage.md │ │ └── 2.Props.md │ └── Wizard │ │ ├── 1.Usage.md │ │ └── 2.Props.md ├── concepts │ ├── 8-Point_Grid │ │ └── 1.Index.md │ ├── Accessibility │ │ ├── 1.Guidelines.md │ │ └── 2.Color_Contrast_Tool.md │ └── Modifier_Classes │ │ └── 1.Index.md └── modifiers │ ├── Alignment │ └── 1.Usage.md │ ├── Border │ └── 1.Usage.md │ ├── Box_Shadows │ └── 1.Usage.md │ ├── Colors │ ├── 1.Usage.md │ └── 2.Palette.md │ ├── Ellipsis │ └── 1.Usage.md │ ├── Links │ └── 1.Usage.md │ ├── Positioning │ └── 1.Usage.md │ ├── Selection │ └── 1.Usage.md │ ├── Typography │ └── 1.Usage.md │ ├── Vertical_Alignment │ └── 1.Usage.md │ └── Whitespace │ └── 1.Usage.md ├── frontend_webpack.config.babel.js ├── index.html ├── manifest.yml ├── package.json ├── public ├── nginx.conf ├── robots.txt └── sitemap.txt ├── push.sh ├── spec ├── components │ ├── editor_spec.js │ ├── error_boundary_spec.js │ ├── import_preview_spec.js │ ├── page_spec.js │ └── renderers │ │ ├── heading_renderer_spec.js │ │ ├── image_renderer_spec.js │ │ ├── link_renderer_spec.js │ │ ├── pre_renderer_spec.js │ │ └── table_renderer_spec.js ├── helpers │ ├── markdown_file_helper_spec.js │ └── routes_helper_spec.js ├── spec_helper.js └── support │ ├── matchers │ ├── common.js │ ├── jest_dom.js │ └── jest_react.js │ ├── react_helper.js │ └── style_mock.js ├── src ├── app.js ├── components │ ├── code_example.js │ ├── editor.js │ ├── error_boundary.js │ ├── import_preview.js │ ├── page.js │ ├── renderers │ │ ├── heading_renderer.js │ │ ├── image_renderer.js │ │ ├── link_renderer.js │ │ ├── pre_renderer.js │ │ └── table_renderer.js │ ├── search_bar.js │ ├── search_result.js │ └── sidebar.js ├── config.js ├── helpers │ ├── markdown_file_helper.js │ ├── markdown_loader.js │ ├── markdown_processor.js │ └── routes_helper.js └── index.js ├── static ├── add_circle.svg ├── cf-logo.png ├── close.svg ├── download.svg ├── favicon.ico ├── help.svg └── such-awesome.jpg ├── stylesheets ├── app.scss ├── code_example.scss ├── page.scss ├── search_bar.scss ├── search_result.scss └── sidebar.scss └── yarn.lock /.cfignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "es6": true, 5 | "node": true, 6 | "jest": true, 7 | "browser": true 8 | }, 9 | "globals": { 10 | "spyOnRender": true, 11 | "testRender": true, 12 | "React": true 13 | }, 14 | "plugins": [ 15 | "react", 16 | "jest", 17 | "markdown" 18 | ], 19 | "settings": { 20 | "react": { 21 | "version": "detect" 22 | } 23 | }, 24 | "rules": { 25 | "arrow-parens": ["error", "as-needed"], 26 | "block-scoped-var": 2, 27 | "camelcase": 0, 28 | "complexity": 2, 29 | "comma-dangle": ["error", "never"], 30 | "consistent-return": 0, 31 | "curly": 0, 32 | "default-case": 2, 33 | "dot-notation": 2, 34 | "eqeqeq": 2, 35 | "eol-last": 0, 36 | "jest/no-focused-tests": 2, 37 | "key-spacing": 2, 38 | "no-caller": 2, 39 | "no-console": [2, {"allow": ["warn", "error"]}], 40 | "no-div-regex": 2, 41 | "no-else-return": 0, 42 | "no-eq-null": 2, 43 | "no-eval": 2, 44 | "no-extend-native": 2, 45 | "no-extra-bind": 2, 46 | "no-fallthrough": 2, 47 | "no-floating-decimal": 2, 48 | "no-implied-eval": 2, 49 | "no-iterator": 2, 50 | "no-labels": 2, 51 | "no-lone-blocks": 2, 52 | "no-loop-func": 2, 53 | "no-multi-spaces": 2, 54 | "no-multi-str": 2, 55 | "no-native-reassign": 2, 56 | "no-new": 2, 57 | "no-new-func": 2, 58 | "no-new-wrappers": 2, 59 | "no-octal": 2, 60 | "no-octal-escape": 2, 61 | "no-path-concat": 0, 62 | "no-process-env": 0, 63 | "no-proto": 2, 64 | "no-redeclare": 2, 65 | "no-return-assign": 0, 66 | "no-script-url": 0, 67 | "no-self-compare": 2, 68 | "no-sequences": 0, 69 | "no-shadow": 0, 70 | "no-trailing-spaces": 2, 71 | "no-underscore-dangle": 0, 72 | "no-unused-expressions": 0, 73 | "no-unused-vars": ["error", { "varsIgnorePattern": "React" }], 74 | "no-void": 2, 75 | "no-warning-comments": 2, 76 | "no-with": 2, 77 | "quotes": [2, "single"], 78 | "radix": 2, 79 | "react/jsx-uses-react": 2, 80 | "react/jsx-uses-vars": 2, 81 | "react/jsx-tag-spacing": [2, {"beforeClosing": "never", "beforeSelfClosing": "never"}], 82 | "jsx-quotes": [2, "prefer-double"], 83 | "react/no-did-mount-set-state": 0, 84 | "react/no-did-update-set-state": 0, 85 | "react/prop-types": [2, {"ignore": ["children", "className", "id", "style"], "skipUndeclared": true}], 86 | "react/self-closing-comp": 2, 87 | "react/jsx-wrap-multilines": 2, 88 | "semi": 2, 89 | "strict": 0, 90 | "vars-on-top": 0, 91 | "wrap-iife": [2, "inside"], 92 | "yoda": 2 93 | } 94 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | gemini-report 2 | *.gem 3 | *.rbc 4 | /.config 5 | /coverage/ 6 | /InstalledFiles 7 | /pkg/ 8 | tmp/ 9 | .sass-cache/ 10 | node_modules/ 11 | /vendor/ 12 | .idea/ 13 | build/ 14 | dist/ 15 | pui-dist/ 16 | *.zip 17 | npm-debug.log 18 | .DS_Store 19 | package-lock.json 20 | yarn-error.log 21 | 22 | ## CssCritic 23 | 24 | spec/css/components/ 25 | spec/css/regressionRunner.js 26 | 27 | ## Specific to RubyMotion: 28 | .dat* 29 | .repl_history 30 | 31 | 32 | ## Documentation cache and generated files: 33 | /.yardoc/ 34 | /_yardoc/ 35 | /doc/ 36 | /rdoc/ 37 | 38 | ## Environment normalisation: 39 | /.bundle/ 40 | /lib/bundler/man/ 41 | .vscode 42 | 43 | # for a library or gem, you might want to ignore these files since the code is 44 | # intended to run in multiple environments; otherwise, check them in: 45 | # Gemfile.lock 46 | # .ruby-version 47 | # .ruby-gemset 48 | 49 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 50 | .rvmrc 51 | vendor/ruby 52 | 53 | ## Sinopia storage 54 | /.sinopia/storage -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Redistribution and use in source and binary forms, with or without 2 | modification, are permitted provided that the following conditions are 3 | met: 4 | 5 | 1. Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above 9 | copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided 11 | with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2022 VMware, Inc. 2 | 3 | This product is licensed to you under the BSD 2 clause (the "License"). You may not use this product except in compliance with the License. 4 | 5 | This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pivotal UI Style Guide 2 | 3 | ## This repository has moved 4 | 5 | The style guide code has moved into a subdirectory of the [`pivotal-ui` repository](https://github.com/pivotal-cf/pivotal-ui). 6 | 7 | Look there for all documentation-related changes/issues/pull requests going forward. -------------------------------------------------------------------------------- /Staticfile: -------------------------------------------------------------------------------- 1 | pushstate: enabled 2 | root: dist -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@babel/preset-env', 4 | '@babel/preset-react' 5 | ], 6 | plugins: [ 7 | '@babel/plugin-proposal-class-properties', 8 | '@babel/plugin-proposal-function-bind' 9 | ] 10 | }; -------------------------------------------------------------------------------- /bin/deploy-staging.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | if [ -z "$1" ]; then 5 | echo "Usage: bin/deploy.sh [appName]" 6 | exit 1 7 | fi 8 | 9 | appName=$2 10 | 11 | if [ -z "$2" ]; then 12 | appName='styleguide-staging' 13 | fi 14 | 15 | cf api api.run.pivotal.io 16 | cf auth pivotal-ui@pivotal.io $1 17 | cf target -o pivotal -s pivotal-ui-staging 18 | 19 | yarn install --no-progress 20 | ./node_modules/.bin/webpack --config ./backend_webpack.config.babel.js --progress -p 21 | ./node_modules/.bin/webpack --config ./frontend_webpack.config.babel.js --progress -p 22 | 23 | cf push $appName 24 | -------------------------------------------------------------------------------- /bin/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | if [ -z "$1" ]; then 5 | echo "Usage: bin/deploy.sh " 6 | exit 1 7 | fi 8 | 9 | cf api api.run.pivotal.io 10 | cf auth pivotal-ui@pivotal.io $1 11 | cf target -o pivotal -s pivotal-ui 12 | 13 | yarn install --no-progress 14 | ./node_modules/.bin/webpack --config ./backend_webpack.config.babel.js --progress -p 15 | ./node_modules/.bin/webpack --config ./frontend_webpack.config.babel.js --progress -p 16 | cf push 17 | -------------------------------------------------------------------------------- /docs/1.Get_Started/1.Installation.md: -------------------------------------------------------------------------------- 1 | To use Pivotal UI in a Node.js project, first install the latest version of Node LTS. [See here for instructions.](https://docs.npmjs.com/getting-started/installing-node) 2 | 3 | Then, install the `pivotal-ui` Node module: 4 | 5 | ```bash 6 | # if using yarn: 7 | yarn add pivotal-ui 8 | 9 | # if using npm: 10 | npm install --save pivotal-ui 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/1.Get_Started/2.Usage_with_Create_React_App.md: -------------------------------------------------------------------------------- 1 | To get started using Pivotal UI with Create React App (CRA), follow these steps: 2 | 3 | 1. Install the latest version of Node LTS. [See here for instructions.](https://docs.npmjs.com/getting-started/installing-node) 4 | 5 | 2. Create a new CRA project with this command: 6 | 7 | ```bash 8 | npx create-react-app some-directory 9 | ``` 10 | 11 | At this point, you'll be able to start up the default CRA app locally: 12 | 13 | ```bash 14 | cd some-directory 15 | yarn start 16 | ``` 17 | 18 | For more information on Create React App, see the [CRA readme](https://github.com/facebook/create-react-app). 19 | 20 | 3. Install the `pivotal-ui` node module: 21 | 22 | ```bash 23 | yarn add pivotal-ui 24 | ``` 25 | 26 | 4. Open `src/App.js` and replace the contents with: 27 | 28 | ```jsx harmony 29 | //nonInteractive 30 | import React, {Component} from 'react'; 31 | import {DefaultButton} from 'pivotal-ui/react/buttons'; 32 | 33 | export default class App extends Component { 34 | render() { 35 | return Click Me; 36 | } 37 | } 38 | ``` 39 | 40 | ## Sass 41 | 42 | Please refer to the [create-react-app docs](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-css-preprocessor-sass-less-etc) -------------------------------------------------------------------------------- /docs/1.Get_Started/3.Using_CSS_only.md: -------------------------------------------------------------------------------- 1 | For non-React projects, Pivotal UI's styles can be included in two different ways. 2 | 3 | ## With Webpack 4 | 5 | For projects that are using Webpack and the [css-loader](https://github.com/webpack-contrib/css-loader), the CSS for each component can be imported directly into JavaScript files like this: 6 | 7 | ```jsx harmony 8 | //nonInteractive 9 | import 'pivotal-ui/css/alerts'; 10 | ``` 11 | 12 | See the documentation of individual components for how to import each one. 13 | 14 | ## With a link tag 15 | 16 | For projects that are not using Webpack, our compiled CSS is made available via a CDN: 17 | 18 | `http://d2bsvk2etkq8vr.cloudfront.net/pui-css/pui-components-.css` 19 | 20 | For example, CSS for version 16.0.0 is available at http://d2bsvk2etkq8vr.cloudfront.net/pui-css/pui-components-16.0.0.css 21 | 22 | These files can be included with a `` tag in an HTML file like this: 23 | 24 | ```html 25 | //nonInteractive 26 | 27 | ``` 28 | 29 | ## Implementing components with only CSS 30 | 31 | When only using CSS you'll have to re-create the DOM structure of our components and apply CSS classes to the correct elements. 32 | 33 | Click "Show HTML" to to see how the React components render. Use this as a guide to re-create the structure. 34 | 35 | ```jsx harmony 36 | //noToolbar 37 | 38 | 39 | 40 | 41 | Click to see CSS classes 42 | 43 | 44 | 45 | ; 46 | ``` 47 | 48 | ```jsx harmony 49 | //title=Primary button 50 | Create Thing; 51 | ``` 52 | -------------------------------------------------------------------------------- /docs/1.Get_Started/5.Linting.md: -------------------------------------------------------------------------------- 1 | - Install pui-react-tools, `yarn add --dev pui-react-tools` 2 | 3 | - Install gulp@next (Make sure its version is ^4.0.0), `yarn add --dev gulp@next` 4 | 5 | - Create a `.babelrc` file in your project root 6 | 7 | ```json 8 | //nonInteractive 9 | { 10 | "presets": [["es2015", {"loose": true}], "react"] 11 | } 12 | ``` 13 | 14 | - Create gulpfile.babel.js to install the link task 15 | 16 | ```jsx harmony 17 | //nonInteractive 18 | import {Lint} from 'pui-react-tools'; 19 | Lint.install({globs: ['src/**/*.js']}); 20 | ``` 21 | 22 | - Create an .eslintrc file, see the [pivotal-ui example](https://github.com/pivotal-cf/pivotal-ui/blob/master/.eslintrc) 23 | -------------------------------------------------------------------------------- /docs/2.FAQ/1.Index.md: -------------------------------------------------------------------------------- 1 | ## What browsers are supported? 2 | 3 | On the desktop, Pivotal UI supports recent versions of Chrome, Firefox, Edge, and Safari as well as IE11. Pivotal UI also supports recent versions of mobile Chrome and Safari. 4 | 5 | ## How do I customize my components? 6 | 7 | Sometimes, the props available on a component will not provide the customization needed for a particular requirement. In those cases, there are a few options: 8 | 9 | - Writing a new component to encapsulate custom requirements and styles is often a good idea. New components can usually be built using simple Pivotal UI components like the `Grid` or `Panel`. If this new component could be useful to other teams, reach out to the Pivotal UI maintainers to see about incorporating this component into Pivotal UI. 10 | 11 | - To some extent, modifier classes can be used to customize components. They are especially good for changing aspects like colors, text emphasis, and spacing around components. 12 | 13 | - Many Pivotal UI styles can be overridden by writing custom CSS, but this is rarely recommended. It will often make code more difficult to maintain through future changes to Pivotal UI and can make UIs look inconsistent across Pivotal products. 14 | 15 | If none of these options will work, reach out to the Pivotal UI team via a GitHub issue or in the Slack channel. We may be able to help find the right solution and/or to improve Pivotal UI to meet your needs. -------------------------------------------------------------------------------- /docs/3.Upgrade_Guide/-10.v10.md: -------------------------------------------------------------------------------- 1 | ## Goals 2 | 3 | The goals of the 10.0 release are: 4 | 5 | - Upgrade to React 16. 6 | 7 | ## The Big Changes 8 | 9 | ### React 10 | - Upgraded to React 16. 11 | 12 | ### Positioning 13 | - Added new positioning and display classes. See the `Positioning` page in the docs. 14 | 15 | ### Iconography, SVG 16 | - Fixed the path to custom SVGs 17 | 18 | ## Conversion Guide 19 | 20 | ### React 21 | - Run `npm i react@^16.0.0` or `yarn upgrade react@^16.0.0` to install React 16. Other changes 22 | may be required. -------------------------------------------------------------------------------- /docs/3.Upgrade_Guide/-11.v11.md: -------------------------------------------------------------------------------- 1 | ## Goals 2 | 3 | The goals of the 11.0 release are: 4 | 5 | - Introduce new Form component 6 | 7 | ## The Big Changes 8 | 9 | ### Removed 10 | - Label component 11 | - `.form-group` class has been removed. 12 | 13 | ### Input, Toggle 14 | - Moved some functionality (e.g. labels, tooltips, help text) out of these components 15 | and into the Form component. 16 | 17 | ### TextFilter 18 | - Introduced the TextFilter component 19 | 20 | ### Forms 21 | 22 | ```jsx harmony 23 | //nonInteractive 24 |
25 | 26 | 31 | 32 | 33 | 37 | 38 | 39 | 40 | 41 | 46 | 47 | 48 | 49 |
; 50 | ``` 51 | 52 | #### Form Unit 53 | 54 | - it's a layered cake 55 | - top is for labels (green) 56 | - middle is for content (blue) 57 | - the bottom is for messages/help text/ error text (red) 58 | - the goal is to make it easy to build rhythmic 8pt grid conforming forms 59 | 60 | ## Conversion Guide 61 | 62 | ### Input, Toggle 63 | - Use the new Form component to obtain functionality such as field labels, tooltips, and help text. 64 | 65 | ### Select 66 | - The `onChange` callback will now receive the new `value` as a second argument, instead of putting it on `event.target.value`. -------------------------------------------------------------------------------- /docs/3.Upgrade_Guide/-12.v12.md: -------------------------------------------------------------------------------- 1 | ## Goals 2 | 3 | The goals of the 12.0 release are: 4 | 5 | - Fix Form alignment issues 6 | - Namespace the CSS of new components with `pui-` 7 | - Redesign the Checkbox and Radio component 8 | - Fix the `Icon` component to be `create-react-app` compatible 9 | - Enhance the Table component to determine column headers from the data 10 | 11 | ## The Big Changes 12 | 13 | ### Table 14 | - When no `columns` prop is given, the table will automatically determine the columns and column headers based on the keys of `data`. 15 | - See the [Tables](/tables#examples) example 16 | 17 | ### Checkbox 18 | - CSS selectors prefixed with `pui-`, eg. `pui-checkbox` 19 | - Update the styling 20 | - Remove props related to forms: `displayError`, `errorMessage` and `label`. 21 | 22 | ### Radio 23 | - CSS selectors prefixed with `pui-`, eg. `pui-radio` 24 | - Update the styling 25 | 26 | ## Conversion Guide 27 | 28 | ### Checkbox 29 | - Use the new [Form](forms) component to obtain functionality such as field labels, tooltips, and help text. -------------------------------------------------------------------------------- /docs/3.Upgrade_Guide/-13.v13.md: -------------------------------------------------------------------------------- 1 | ## Goals 2 | 3 | The goals of the 13.0 release are: 4 | 5 | - New interface and design of Panels 6 | - Redesign of Dropdown and CheckboxDropdown 7 | 8 | ## The Big Changes 9 | 10 | ### Panels 11 | 12 | - Panels have been redesigned to have a title, header, body, and footer section. You can insert components in the title and header sections. See the [Panels](/panels#examples) examples. 13 | - The panel title appears outside the rounded box 14 | - The panel header appears within the rounded box, separated from the content by a border 15 | - The panel body appears within the rounded box, below the header (if any) 16 | - The panel footer appears at the bottom of the rounded box. 17 | - The panel body now has rounded corners and a box shadow by default. 18 | - Previously, the panel `header` prop took a `Node`. Now, it takes a `string`, which it will place in the top left corner of the panel. This is intended to make panel headers more consistent by default. To get the old behavior back, do not pass a `header`, and use `headerCols={[{someNode}]}`. 19 | - Panel CSS classes are now prefixed with `pui-`. 20 | - The classes `panel`, `panel-body`, `panel-header` and `panel-footer` have been removed. You can either: 21 | - update your CSS by prepending `pui-` OR 22 | - you can pass those classes in via the `bodyClassName`, `headerClassName`, or `footerClassName` props. 23 | 24 | ```jsx harmony 25 | //nonInteractive 26 | ; 32 | ``` 33 | 34 | ### Dropdown/CheckboxDropdown 35 | 36 | - Icon no longer positioned absolutely -------------------------------------------------------------------------------- /docs/3.Upgrade_Guide/-14.v14.md: -------------------------------------------------------------------------------- 1 | ## Goals 2 | 3 | The goals of the 14.0 release are: 4 | 5 | - Remove dependency on Bootstrap from all PUI components 6 | - Remove all Bootstrap files from PUI 7 | 8 | ## The Big Changes 9 | 10 | ### Code component 11 | 12 | All CSS from Bootstrap that styled `code`, `kbd`, `pre`, and `samp` elements has been moved to `pivotal-ui/css/code`. If these tags are no longer styled as expected, add `import 'pivotal-ui/css/code'` alongside your other CSS. 13 | 14 | ### Grids component 15 | 16 | This component was based on Bootstrap Grids, and has been removed. Use our Flex Grids component and/or CSS classes instead. Here are some examples of the changes required to migrate from the older, Bootstrap-based component: 17 | 18 | #### React 19 | 20 | Deprecated Bootstrap-based Grid: 21 | 22 | ```jsx harmony 23 | //nonInteractive 24 | 25 | ... 26 | ... 27 | ; 28 | ``` 29 | 30 | FlexGrid: 31 | 32 | ```jsx harmony 33 | 34 | ... 35 | ... 36 | ; 37 | ``` 38 | 39 | #### CSS-only 40 | 41 | Deprecated Bootstrap-based Grid: 42 | 43 | ```html 44 | //nonInteractive 45 |
46 |
...
47 |
...
48 |
49 | ``` 50 | 51 | FlexGrid: 52 | 53 | ```html 54 | //nonInteractive 55 |
56 |
...
57 |
...
58 |
59 | ``` 60 | 61 | ### Other Bootstrap CSS/utility classes 62 | 63 | Any Bootstrap CSS that was not a part of any PUI component, but which was included by PUI, will no longer work. Install Bootstrap CSS separately if needed. 64 | 65 | ### Removed 66 | 67 | The following components were deprecated several releases ago, and are no longer documented. They have now been removed: 68 | - Bootstrap Grids component (`pivotal-ui/react/grids` and `pivotal-ui/css/grids`) 69 | - Google Maps component (`pivotal-ui/css/google-maps`) 70 | - Avatars component (`pivotal-ui/css/avatars`) -------------------------------------------------------------------------------- /docs/3.Upgrade_Guide/-15.v15.md: -------------------------------------------------------------------------------- 1 | ## Goals 2 | 3 | The goals of the 15.0 release are: 4 | 5 | - Rewrite & redesign Pagination component 6 | - Rewrite Dropdown component to be less opinionated on its contents 7 | - Make Autocomplete component easier to use 8 | - Make font rendering crisper 9 | 10 | ## The Big Changes 11 | 12 | ### Pagination 13 | We rewrote the Pagination component from the ground up, but its API has remained, mostly, the same. 14 | 15 | Details: 16 | - New design (rewritten CSS) 17 | - Show up to 5 pages, always including the first and last, with ellipses in between if necessary. 18 | - `onSelect` callback gets called with an object containing `newActivePage`, 19 | the page number of the newly selected page (either the number that was clicked, `activePage + 1` if next button was clicked, 20 | or `activePage - 1` if previous button was clicked). 21 | - Removed `large` and `small` props. 22 | 23 | ### Dropdown 24 | The changes to the Dropdown make it less opinionated about its children. Previously, it was necessary to have all children 25 | of a Dropdown be DropdownItems, and the Dropdown would handle `onClick`-like events on these items. Now, any child node 26 | can be passed as a child, and if a child needs an `onClick`, it should be set on that child directly. 27 | 28 | Details: 29 | - Removed DropdownItem component entirely 30 | - Removed props: `href`, `labelAriaLabel`, `onSelect`, `onSplitClick`, `splitClassName` 31 | - Added prop: `itemClassName` which provides a class to the `li` element that wraps each child of the dropdown 32 | 33 | ### Autocomplete 34 | The changes to Autocomplete are meant to make it easier to control when and how the data in the list gets updated 35 | from the outside. 36 | 37 | Details: 38 | - Add a new public method `updateList`, which updates the list of search results without showing the list. To see how this 39 | this might be used, see the [Autocomplete](/autocomplete) page. 40 | - Change the callback that is passed in to `onInitializeItems` to return a Promise, so that it can be awaited from 41 | the outside if desired. This means that an outer component can wait for the inner trie data structure to be built 42 | before calling `updateList` to update the list. 43 | 44 | ### Font Rendering 45 | We removed CSS in PUI that was disabling subpixel antialising (see [here](http://usabilitypost.com/2011/02/08/please-stop-disabling-subpixel-rendering/) for more information). 46 | The effect of this is that fonts appear crisper, brighter, and more vibrant. -------------------------------------------------------------------------------- /docs/3.Upgrade_Guide/-9.v9.md: -------------------------------------------------------------------------------- 1 | ## Goals 2 | 3 | The goals of the 9.0 release are: 4 | 5 | - Update components to use the 8 point grid 6 | - Adding some new components (Flyout, Wizard) 7 | - Overhaul the existing Table component to make it easier to contribute new features 8 | 9 | ## The Big Changes 10 | 11 | ### Packaging 12 | - All react and CSS components are now in the `pivotal-ui` package 13 | 14 | ### Deprecated 15 | - The CopyToClipboardButton component has been deprecated 16 | - The Label component has been deprecated 17 | 18 | ### Button Groups 19 | - Can now be large or small 20 | 21 | ### Button Groups, Draggable List, Left-Tabs, Progress Bar, Tabs 22 | - Updates to use the 8 point grid system 23 | 24 | ### CopyToClipboard 25 | - Can now be large or small 26 | - No longer uses the CopyToClipboardButton component 27 | 28 | ### Flex Grid 29 | - `col-fixed` now uses `flex: 0 1 auto` so that it works in IE11 30 | 31 | ### Flyout 32 | - Added component that allows a modal to slide in from the right side of the page 33 | 34 | ### Links 35 | - Added new underline CSS classes 36 | 37 | ### Notifications 38 | - CSS refactor 39 | 40 | ### Pagination 41 | - Can now be large or small 42 | - Uses the Button Group component to render its page elements 43 | 44 | ### Select 45 | - The `onChange` callback will now pass the underlying click event as its first argument, instead of the selected value 46 | 47 | ### Table 48 | - Re-architected the Table component to make it easier to contribute new features 49 | - SortableTable: rows can be sorted ascending or descending by a chosen column. 50 | - FlexTable: uses `div` tags to compose a table rather than traditional HTML tags. 51 | - SortableFlexTable: a SortableTable that is composed of `div` tags. 52 | - AdvancedTable: offers many additional features for advanced customization. 53 | - The base Table is no longer sortable. Use SortableTable for this purpose. 54 | - Added a plugin system, see the Table component documentation for details. 55 | 56 | ### Wizard 57 | - Added component that allows a user to click through a series of wizard pages 58 | 59 | ## Conversion Guide 60 | 61 | ### Packaging 62 | - In `package.json`, add `pivotal-ui` as a dependency, and remove all old `pui-css-{component}` and `pui-react-{component}` dependencies. (CAUTION: make sure you only remove PUI components) 63 | - Update all files that required/imported PUI components to import from the new `pivotal-ui` package. 64 | - React example: import {DefaultButton} from 'pivotal-ui/react/buttons'; 65 | - CSS example: import 'pivotal-ui/css/buttons'; 66 | 67 | ### Button Group, Draggable List, Left-Tabs, Notifications, Pagination, Progress Bar, Tabs 68 | - Positioning changes may be required as a result of underlying CSS changes 69 | 70 | ### Select 71 | - `onChange` callbacks should be updated to uses the new `event` object as the first argument 72 | 73 | ### Table 74 | - Use `SortableTable` if sorting behavior is required. 75 | - Use `AdvancedTable` if advanced `FlexTable` features are needed -------------------------------------------------------------------------------- /docs/4.Contribute/1.Index.md: -------------------------------------------------------------------------------- 1 | We encourage and appreciate all contributions, large and small, from the Pivotal community. If you're interested in getting involved, here are some ways you can help: 2 | 3 | ## Improving components and styles 4 | 5 | All of Pivotal UI's components and styles live in the [Pivotal UI GitHub repo](https://github.com/pivotal-cf/pivotal-ui). If you have a feature request, or if you want to report a bug in one of our components, [file an issue](https://github.com/pivotal-cf/pivotal-ui/issues/new). 6 | 7 | If you would like to submit a pull request, it's a good idea to reach out to the maintainers as early as possible to help us understand the change you'd like to make. This will make the process much easier for all involved. 8 | 9 | If your team has built a component that you feel would be a good fit for Pivotal UI (i.e. it could be useful to several Pivotal teams), let the maintainers know so we can figure out the best way to help. 10 | 11 | ## Improving documentation 12 | 13 | If you would like to help improve the styleguide, feel free to submit a pull request to the [styleguide GitHub repo](https://github.com/pivotal-cf/pui-styleguide). 14 | 15 | All of the text content is written in Markdown files located in the [`docs` directory](https://github.com/pivotal-cf/pui-styleguide/tree/master/docs). Smaller changes to the text can be made directly on GitHub. Each page on this site also has a link to edit it on GitHub. 16 | 17 | ## Getting in touch 18 | 19 | If you have questions or suggestions, or if you just want to chat about Pivotal UI, reach out to the maintainers on our Slack channel ([#pivotal-ui](https://pivotal.slack.com/messages/C055JEPQQ)). -------------------------------------------------------------------------------- /docs/404/1.404.md: -------------------------------------------------------------------------------- 1 | Page not found -------------------------------------------------------------------------------- /docs/5.Versions/Index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Older Versions of Pivotal UI 3 | menu: info 4 | route: versions 5 | --- 6 | 7 | View archived styleguides for past versions of Pivotal UI: 8 | 9 | - [Version 9](https://styleguide-v9.cfapps.io/) 10 | - [Version 10](https://styleguide-v10.cfapps.io/) 11 | - [Version 11](https://styleguide-v11.cfapps.io/) 12 | - [Version 12](https://styleguide-v12.cfapps.io/) 13 | - [Version 13](https://styleguide-v13.cfapps.io/) 14 | - [Version 14](https://styleguide-v14.cfapps.io/) 15 | - [Version 15](https://styleguide-v15.cfapps.io/) 16 | - [Version 16](https://styleguide-v16.cfapps.io/) -------------------------------------------------------------------------------- /docs/components/Alerts/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/alerts 3 | reactComponents: 4 | - SuccessAlert 5 | - InfoAlert 6 | - WarningAlert 7 | - ErrorAlert 8 | reactPath: pivotal-ui/react/alerts 9 | --- 10 | 11 | Use the `SuccessAlert`, `ErrorAlert`, `InfoAlert`, and `WarningAlert` components to alert the user of some change in state. 12 | 13 | For example, here are alerts for various outcomes of uploading a file: 14 | 15 | ```jsx harmony 16 | //title=Various alerts 17 |
18 | File 'abc.txt' uploaded successfully! 19 | File 'abc.txt' failed to upload. 20 | Upload started: 'abc.txt' 21 | 'abc.txt' is now publicly available 22 |
; 23 | ``` 24 | 25 | To allow the user to hide the alert after reading it, set the `dismissable` prop to add a clickable close icon: 26 | 27 | ```jsx harmony 28 | //title=Dismissable alert 29 | File 'abc.txt' uploaded successfully!; 30 | ``` 31 | 32 | To perform some action when the user dismisses an alert, set the `onDismiss` prop: 33 | 34 | ```jsx harmony 35 | //title=Dismissable alert with callback 36 | alert('Alert dismissed')}>File 'abc.txt' failed to upload.; 37 | ``` 38 | 39 | Use the `withIcon` prop to add an icon to the alert: 40 | 41 | ```jsx harmony 42 | //title=Alert with icon 43 |
44 | File 'abc.txt' uploaded successfully! 45 | File 'abc.txt' failed to upload. 46 | Upload started: 'abc.txt' 47 | 'abc.txt' is now publicly available 48 |
; 49 | ``` 50 | 51 | Alerts can contain any content. To have links within this content styled correctly, apply the `pui-alert-link` class to any `` tag that appears inside the alert. 52 | 53 | ```jsx harmony 54 | //title=Alert with complex content 55 | 56 | The following items need review: 57 | 61 | ; 62 | ``` 63 | 64 | By default, alerts maintain their dismissed/not dismissed state internally. To hold this state at a higher level (in a parent component), pass the `show` prop to the alert. 65 | 66 | ```jsx harmony 67 | //title=Controlled alert 68 | class AlertController extends React.Component { 69 | constructor(props) { 70 | super(props); 71 | this.state = {alertVisible: true}; 72 | } 73 | 74 | render() { 75 | const {alertVisible} = this.state; 76 | 77 | if (!alertVisible) { 78 | return this.setState({alertVisible: true})}>Show alert; 79 | } 80 | 81 | return ( 82 | this.setState({alertVisible: false})}>Visible alert 83 | ); 84 | } 85 | } 86 | 87 | ; 88 | ``` -------------------------------------------------------------------------------- /docs/components/Alerts/2.Props.md: -------------------------------------------------------------------------------- 1 | The `SuccessAlert`, `ErrorAlert`, `InfoAlert`, and `WarningAlert` components all take the following props: 2 | 3 | Property | Required | Type | Default | Description 4 | ---------|----------|------|---------|------------ 5 | `closeLabel` | no | Node | 'Close alert' | Screen reader label attached to close button 6 | `dismissable` | no | Boolean | false | If true, render a close button 7 | `onDismiss` | no | Function | | Callback that is called when the user clicks the close button 8 | `show` | no | Boolean | | If set, overrides the close button. True shows the alert, false hides the alert. 9 | `withIcon` | no | Boolean | false | If true, render alert with an icon 10 | -------------------------------------------------------------------------------- /docs/components/Autocomplete/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ----------------------|----------|------|---------|------------- 3 | `className` | no | String | | `className` to add to autocomplete 4 | `disabled` | no | Boolean | | whether the input is disabled 5 | `input` | no | Object | autocompleteinput | overrides the input for autocomplete 6 | `maxItems` | no | Number | 50 | the maximum number of items in the autocomplete list 7 | `onClick` | no | Function | | `onClick` to add to the input 8 | `onFilter` | no | Function | | lets you apply an additional filter to the autocomplete list 9 | `onFocus` | no | Function | | `onFocus` to add to the input 10 | `onInitializeItems` | no | Function | done => done([]) | returns the values to initially populate the autocomplete list 11 | `onPick` | no | Function | | callback when something is picked from the list 12 | `onSearch` | no | Function | | To override the default search algorithm, pass your custom function to the autocomplete as the prop onSearch. 13 | `placeholder` | no | String | 'search' | placeholder text for the input 14 | `showNoSearchResults` | no | Boolean | false | If true, will display 'No search results' when no results are matched. Valid only if no list child is passed. Eg. If you want to provide a custom search results list component, this flag will be ignored. 15 | `trieOptions` | no | Object | | Options for the default TrieSearch algorithm (e.g. `ignoreCase`: a boolean is set to true by default, `splitOnRegEx`: a RegEx) 16 | `value` | no | String | | used when the input is a controlled input 17 | -------------------------------------------------------------------------------- /docs/components/Back_to_Top/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/back-to-top 3 | reactComponents: 4 | - BackToTop 5 | reactPath: pivotal-ui/react/back-to-top 6 | --- 7 | 8 | You can use this component to scroll to the top of a document (or another scrollable element). 9 | 10 | By default the button will be fixed to the bottom right hand corner of the page. See below for an example of how to override the positioning. 11 | 12 | To apply the `BackToTop` component to a specific element, use the `scrollableId` prop. To use the `BackToTop` component to scroll the entire page, do not set the `scrollableId` prop. 13 | 14 | ```jsx harmony 15 | //title=Scrollable container example 16 | //description=By setting `position: relative` on a parent element, and `position: absolute` on the `BackToTop`, we can position the button within the parent. 17 |
18 |
19 | 22 |

Scroll down at least 400 pixels to see the button!

23 | {[1, 2, 3, 4, 5, 6, 7, 8].map(n => ( 24 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Interdum velit laoreet id donec. Adipiscing vitae proin sagittis nisl rhoncus. Maecenas volutpat blandit aliquam etiam erat velit. Rutrum tellus pellentesque eu tincidunt tortor aliquam nulla facilisi. Ac ut consequat semper viverra nam libero justo laoreet sit. Sed tempus urna et pharetra pharetra massa massa. Arcu dictum varius duis at consectetur. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Ac felis donec et odio pellentesque diam volutpat commodo. At risus viverra adipiscing at. Dui accumsan sit amet nulla facilisi. Tristique senectus et netus et malesuada fames ac. Iaculis urna id volutpat lacus laoreet non. Nullam non nisi est sit amet. Lectus sit amet est placerat in. Velit egestas dui id ornare arcu odio ut sem. Viverra nibh cras pulvinar mattis nunc sed blandit libero. Hendrerit gravida rutrum quisque non. Duis ultricies lacus sed turpis tincidunt id.

25 | ))} 26 |
27 |
; 28 | ``` 29 | 30 | By default, the button will appear when the container's `scrollTop` is greater than 400 pixels. To make it always visible, set the `alwaysVisible` prop. 31 | 32 | ```jsx harmony 33 | //title=Always visible example 34 |
35 | 36 | See the bottom right corner of your screen! 37 |
; 38 | ``` -------------------------------------------------------------------------------- /docs/components/Back_to_Top/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ---------------|----------|--------|---------|------------ 3 | `alwaysVisible` | no | Boolean | false | If `alwaysVisible` is not set, the component will only appear after the window has been scrolled. 4 | `scrollableId` | no | String | | If `scrollableId` is set, the component will update this element's scrollTop property. Otherwise, document.body will be scrolled. 5 | -------------------------------------------------------------------------------- /docs/components/Button_Group/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/button-group 3 | --- 4 | 5 | Button groups wrap a series of buttons to clearly indicate their relation. 6 | 7 | ```html 8 | //title=Basic example 9 |
10 | 11 | 12 | 13 |
14 | ``` 15 | 16 | ```html 17 | //title=Selected button example 18 | //description=You can also mark buttons in the group as selected by swapping between alt button styles. 19 |
20 | 21 | 22 | 23 |
24 | ``` 25 | 26 | ```html 27 | //title=Flat button example 28 | //description=If you are using flat buttons, there is a thinner, flat button group 29 |
30 | 31 | 32 | 33 |
34 | ``` -------------------------------------------------------------------------------- /docs/components/Buttons/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ---------------|----------|---------|---------|------------ 3 | `alt` | no | Boolean | false | Whether to render as 'alternate' button 4 | `flat` | no | Boolean | false | Whether to render as a 'flat' button 5 | `fullWidth` | no | Boolean | false | Whether to render the button full width 6 | `href` | no | String | | If specified, button clicks will redirect to this href 7 | `iconOnly` | no | Boolean | false | If specified, will render as an icon button 8 | `iconPosition` | no | String | | If specified, places the icon to the left or the right of the text and or children 9 | `large` | no | Boolean | false | Whether to render the button large 10 | `small` | no | Boolean | false | Whether to render the button small 11 | -------------------------------------------------------------------------------- /docs/components/Checkbox_Dropdowns/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/checkbox-dropdown 3 | reactComponents: 4 | - CheckboxDropdown 5 | reactPath: pivotal-ui/react/checkbox-dropdown 6 | --- 7 | 8 | ```jsx harmony 9 | //title=Basic checkbox dropdown 10 | ; 13 | ``` 14 | 15 | ```jsx harmony 16 | //title=Checkbox dropdown with onChange 17 | 18 | class Example extends React.Component { 19 | constructor(props) { 20 | super(props); 21 | this.state = {selected: null}; 22 | } 23 | 24 | render() { 25 | return ( 26 |
27 |
{JSON.stringify(this.state.selected, null, 2)}
28 | this.setState({selected}) 31 | }}/> 32 |
33 | ); 34 | } 35 | } 36 | 37 | ; 38 | ``` -------------------------------------------------------------------------------- /docs/components/Checkbox_Dropdowns/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ------------------|----------|-------------------------------------|----------------|------------ 3 | `buttonAriaLabel` | no | String | | aria-label for the button 4 | `buttonClassName` | no | String | | Classname to add to the button 5 | `flat` | no | Boolean | | If true, dropdown toggle has no borders and is transparent 6 | `labelAriaLabel` | no | String | | aria-label for the label 7 | `labels` | yes | oneOf([Array, Object]) | | Labels for the checkboxes 8 | `onChange` | no | Function | | Callback that fires after clicking a checkbox 9 | `size` | no | oneOf(['normal', 'large', 'small']) | 'normal' | Sets the size 10 | `split` | no | Boolean | | If true, separates the button text from the toggle 11 | -------------------------------------------------------------------------------- /docs/components/Checkboxes/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/checkbox 3 | reactComponents: 4 | - Checkbox 5 | reactPath: pivotal-ui/react/checkbox 6 | --- 7 | 8 | Checkboxes can be either checked, unchecked or indeterminate. 9 | 10 | ```jsx harmony 11 | //title=Checkboxes 12 |
13 | Checkbox one (click me) 14 | Checkbox two (disabled) 15 | Checkbox three (indeterminate) 16 |
; 17 | ``` 18 | 19 | ```jsx harmony 20 | //title=Using indeterminate state 21 |
( 29 | setValues({chicken: !meat, beef: !meat}) 32 | }}/> 33 | ) 34 | }, 35 | chicken: { 36 | inline: true, 37 | hideHelpRow: true, 38 | labelPosition: 'after', 39 | label: 'Chicken', 40 | children: ({state: {current: {chicken, beef}}, setValues}) => 41 | setValues({meat: !chicken && beef})}/> 42 | }, 43 | beef: { 44 | inline: true, 45 | hideHelpRow: true, 46 | labelPosition: 'after', 47 | label: 'Beef', 48 | children: ({state: {current: {chicken, beef}}, setValues}) => 49 | setValues({meat: chicken && !beef})}/> 50 | } 51 | } 52 | }}> 53 | {({fields: {meat, chicken, beef}}) => ( 54 |
55 | {meat} 56 |
57 | {chicken} 58 | {beef} 59 |
60 |
61 | )} 62 | ; 63 | ``` -------------------------------------------------------------------------------- /docs/components/Checkboxes/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | -----------------|----------|---------|---------|------------ 3 | `checked` | false | boolean | | Whether the checkbox is checked, when controlled 4 | `children` | false | node | | Content to place within `label` to the right of the checkbox 5 | `className` | false | string | | Class name to put on outer `div` element 6 | `defaultChecked` | false | boolean | | Whether the checkbox is checked, when uncontrolled 7 | `disabled` | false | boolean | | Whether the checkbox is disabled 8 | `id` | false | string | Auto-generated unique ID with prefix "checkbox" | ID to put on the inner `input[type="checkbox"]` 9 | `indeterminate` | false | boolean | | Puts checkbox into an indeterminate state 10 | `labelClassName` | false | string | | Class name to put on the checkbox label 11 | `name` | false | string | | Name to set on inner `input[type="checkbox"]` 12 | `noSelect` | false | boolean | | When `true`, prevents the label text from being selectable 13 | `onChange` | false | func | | onChange callback to set on inner `input[type="checkbox"]` 14 | `style` | false | object | | Style to put on outer `div` element 15 | 16 | All other props will be put onto the inner `input[type="checkbox"]`. -------------------------------------------------------------------------------- /docs/components/Code/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/code 3 | --- 4 | 5 | ```html 6 | //title=Basic unstyled 7 |
class Foo
  8 |   def bar
  9 |     puts 'hi'
 10 |   end
 11 | end
12 | ``` 13 | 14 | ```html 15 | //title=Inline 16 |

This is an example of a paragraph with an inline code snippet within it.

17 | ``` 18 | 19 | ```html 20 | //title=Inline dark 21 |

This is an example of a paragraph with a dark inline code snippet within it.

22 | ``` 23 | 24 | #### Styled Code 25 | In order to show syntax-highlighted code, you will need to apply a language specific class to the code tag. For example, `.language-ruby`. 26 | 27 | There are several languages already available (and others available from the [Prismjs.com](http://prismjs.com 28 | ) website), including: 29 | 30 | * Markup 31 | * CSS 32 | * C-like 33 | * JavaScript 34 | * Java 35 | * PHP 36 | * CoffeeScript 37 | * Sass 38 | * Bash 39 | * Python 40 | * HTTP 41 | * Ruby 42 | * Go 43 | 44 | 45 | ```html 46 |
class Foo
 47 |   def bar
 48 |     puts 'hi'
 49 |   end
 50 | end
51 | ``` 52 | 53 | ```html 54 | //title=Scrollable 55 |
class Foo
 56 |   def bar
 57 |     puts 'hi'
 58 |   end
 59 | 
 60 |   def bar
 61 |     puts 'hi'
 62 |   end
 63 | 
 64 |   def bar
 65 |     puts 'hi'
 66 |   end
 67 | 
 68 |   def bar
 69 |     puts 'hi'
 70 |   end
 71 | 
 72 |   def bar
 73 |     puts 'hi'
 74 |   end
 75 | 
 76 |   def bar
 77 |     puts 'hi'
 78 |   end
 79 | 
 80 |   def bar
 81 |     puts 'hi'
 82 |   end
 83 | end
84 | ``` 85 | 86 | ```html 87 | //title=Terminal window 88 | //description=Use the `terminal` class around a `
    ` that has class `terminal-dots` to wrap code blocks in a terminal window. 89 |
    90 |
    91 |
    ~/my/computer
     92 | $ echo 'Hello World!';
    93 |
    94 | ``` 95 | 96 | ```html 97 | //title=Terminal window with Mac-styled buttons 98 | //description=Apply the `color` class to the `terminal-dots` to give them the colors they have in Mac OS X. 99 |
    100 |
    101 |
    ~/my/computer
    102 | $ echo 'Hello World!';
    103 |
    104 | ``` -------------------------------------------------------------------------------- /docs/components/Collapsible/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | reactComponents: 3 | - Collapsible 4 | reactPath: pivotal-ui/react/collapsible 5 | --- 6 | 7 | The `Collapsible` component can be used to hide and show elements. By default, 8 | it animates the expanding and collapsing of its content, but this can be configured 9 | through props. 10 | 11 | ```jsx harmony 12 | //title=Basic example 13 | //description=The `Collapsible`'s `expanded` prop comes from the outer component's `state`. 14 | 15 | class CollapsibleExample extends React.Component { 16 | constructor(props) { 17 | super(props); 18 | this.state = {expanded: false}; 19 | } 20 | 21 | render() { 22 | return (
    23 | this.setState({expanded: evt.target.checked})}/> 24 | 25 |
    Button 1
    26 |
    Button 2
    27 |
    28 |
    ); 29 | } 30 | } 31 | 32 | ; 33 | ``` -------------------------------------------------------------------------------- /docs/components/Collapsible/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ------------|----------|----------|---------|------------ 3 | `delay` | no | Number | 200 | Duration (in milliseconds) of expand/collapse animation 4 | `expanded` | no | Boolean | | Whether the component is expanded 5 | `onEntered` | no | Function | | Callback called when animation begins 6 | `onExited` | no | Function | | Callback called when animation ends 7 | -------------------------------------------------------------------------------- /docs/components/Copy_to_Clipboard/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/copy-to-clipboard 3 | reactComponents: 4 | - CopyToClipboard 5 | reactPath: pivotal-ui/react/copy-to-clipboard 6 | --- 7 | 8 | The copy to clipboard functionality can be applied to a variety of elements. 9 | 10 | ```jsx harmony 11 | //title=Copy options 12 |
    13 | Click Me To Copy 14 |
    15 | 16 | 20 | }}/> 21 | 22 |
    23 | 24 | Click Me To Copy 28 | 29 |
    ; 30 | ``` 31 | 32 | ```jsx harmony 33 | //title=Readonly input and copy button 34 |
    35 | 36 |
    37 | 38 | 41 | }}/> 42 | 43 |
    44 |
    ; 45 | ``` -------------------------------------------------------------------------------- /docs/components/Copy_to_Clipboard/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ----------|----------|----------|----------|------------ 3 | `onClick` | no | Function | () => () | Click handler 4 | `text` | yes | String | | Text that is copied when the user clicks 5 | `tooltip` | no | String | "Copied" | Text to show in tooltip after click 6 | -------------------------------------------------------------------------------- /docs/components/Dividers/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/dividers 3 | reactComponents: 4 | - Divider 5 | reactPath: pivotal-ui/react/dividers 6 | --- 7 | 8 | ```jsx harmony 9 | //title=Large divider example 10 | //description=Dividers draw horizontal lines between different content groupings 11 |
    12 | 13 | Content 14 | 15 |
    ; 16 | ``` 17 | 18 | ```jsx harmony 19 | //title=Inverse dividers 20 | //description=On a dark background, use these inverse dividers 21 |
    22 |
    23 | I am some content 24 | 25 | Me too 26 |
    27 | 28 |
    29 | Here's some stuff above the divider 30 | 31 | Here's some stuff below the divider 32 |
    33 |
    ; 34 | ``` -------------------------------------------------------------------------------- /docs/components/Dividers/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ----------|----------|------|---------|------------ 3 | `inverse` | no | Boolean | | Specifying this prop inverses the divider 4 | `size` | no | String | | Changes the size of the component. Either 'large' or leave undefined for default size. -------------------------------------------------------------------------------- /docs/components/Draggable_Lists/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | reactComponents: 3 | - DraggableList 4 | - DraggableListItem 5 | reactPath: pivotal-ui/react/draggable-list 6 | --- 7 | 8 | ```jsx harmony 9 | //title=Draggable 10 | 11 | 12 | Item 1 13 | 14 | 15 | 16 | Item 5 17 | 18 | 19 | 20 | Item 4 21 | 22 | 23 | 24 | Item 6 25 | 26 | 27 | 28 | Item 3 29 | 30 | 31 | 32 | Item 2 33 | 34 | ; 35 | ``` -------------------------------------------------------------------------------- /docs/components/Draggable_Lists/2.Props.md: -------------------------------------------------------------------------------- 1 | ## DraggableList props 2 | 3 | Property | Required | Type | Default | Description 4 | ----------|----------|------|---------|------------ 5 | `children` | no | node | | Draggable items in list 6 | `innerClassName` | no | string | | CSS class to apply to all items in list 7 | `onDragEnd` | no | function | | Callback called with the item indices when a drag completes 8 | 9 | ## DraggableListItem props 10 | 11 | _No props taken._ -------------------------------------------------------------------------------- /docs/components/Dropdowns/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | -------------------|----------|-------------------------------------|----------------|------------ 3 | `blockingScrim` | no | Boolean | false | If true, blocks mouse events outside of the dropdown. Clicking outside of the dropdown will still close the dropdown. 4 | `buttonAriaLabel` | no | String | | aria-label for the button 5 | `buttonClassName` | no | String | | Classname to add to the button 6 | `closeOnMenuClick` | no | Boolean | true | If false, do not close the menu when clicking in the dropdown menu 7 | `disableScrim` | no | Boolean | false | If true, do not close the menu when clicking outside the dropdown 8 | `flat` | no | Boolean | | If true, dropdown toggle has no borders and is transparent 9 | `floatMenu` | no | Boolean | false | If true, float the dropdown menu. This only applies to the basic dropdown 10 | `icon` | no | String | 'chevron_down' | Name of the icon to use for the toggle icon 11 | `itemClassName` | no | String | | Classname to add to each child `li` 12 | `link` | no | Boolean | | If true, color the dropdown toggle like a link 13 | `menuAlign` | no | oneOf(['none', 'left', 'right']) | 'none' | Sets the alignment of the menu with the button 14 | `onClick` | no | Function | | Callback that fires after clicking the button 15 | `onEntered` | no | Function | | Callback that fires after opening the dropdown 16 | `onExited` | no | Function | | Callback that fires after closing the dropdown 17 | `scroll` | no | Boolean | false | Enables scrolling in the dropdown menu when enabled 18 | `showIcon` | no | Boolean | true | If false, do not render an icon in the dropdown toggle. Icon can not be hidden if split or leaving out title. 19 | `size` | no | oneOf(['normal', 'large', 'small']) | 'normal' | Sets the size 20 | `split` | no | Boolean | | If true, separates the button text from the toggle 21 | `title` | no | Node | | The button contents 22 | -------------------------------------------------------------------------------- /docs/components/Flyout/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/flyout 3 | reactComponents: 4 | - Flyout 5 | reactPath: pivotal-ui/react/flyout 6 | --- 7 | 8 | The flyout appears from the right side of the window and overlays all other content until it is closed. Its 9 | visibility is controlled with the `show` property. It can take a custom `width`. The contents of the header 10 | and the body are set with the `header` and `children` properties, respectively. The behavior of the icon 11 | button is defined through the `onHide` callback. 12 | 13 | The flyout will overlay its first parent that has position `relative`. 14 | 15 | ```jsx harmony 16 | //title=Basic example 17 | class Page extends React.Component { 18 | constructor(props) { 19 | super(props); 20 | this.state = {}; 21 | } 22 | 23 | render() { 24 | const {created, show, disableAnimation} = this.state; 25 | 26 | return ( 27 |
    28 | 29 | 30 | this.setState({show: true})}> 31 | Open Flyout 32 | 33 | 34 | 35 | 36 | this.setState({disableAnimation: !disableAnimation})}/> 37 | 38 | 39 | 40 | {created &&

    Last task created: {created.toLocaleString()}

    } 41 | 42 | Flyout header, 46 | headerClassName: 'header-class', 47 | bodyClassName: 'body-class', 48 | onHide: () => this.setState({show: false}) 49 | }}> 50 |

    Flyout content

    51 |
    52 |
    53 | ); 54 | } 55 | } 56 | 57 | ; 58 | ``` -------------------------------------------------------------------------------- /docs/components/Flyout/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ---------------------|-------------|-------------|---------------------------------------|------------- 3 | `animationDuration` | no | Number | 200 | Animation duration in milliseconds (Set to <= 0 to disable animations) 4 | `animationEasing` | no | String | cubic-bezier(0.25, 0.46, 0.45, 0.94) | Animation easing function 5 | `bodyClassName` | no | String | | Class(es) to apply to the body 6 | `children` | no | Any | | Contents of the flyout body 7 | `dialogClassName` | no | String | | Class(es) to apply to the modal dialog 8 | `header` | no | Any | | Contents of the flyout header 9 | `headerClassName` | no | String | | Class(es) to apply to the header 10 | `iconSrc` | no | String | 'close' | Icon to use for the close button 11 | `onHide` | yes | Function | | Callback that fires as soon as the modal begins closing 12 | `show` | no | Boolean | false | Whether or not the flyout is visible 13 | `width` | no | String | 480px | Width of flyout content 14 | -------------------------------------------------------------------------------- /docs/components/Forms/2.Using_the_FormUnit.md: -------------------------------------------------------------------------------- 1 | To lay out a single form field without using a whole `Form` component, you can use the `FormUnit` 2 | component. The `FormUnit` component can decorate a field with a label, a tooltip, an "optional" indicator, and help text. 3 | 4 | Note that state management and other `Form` features are not handled by the `FormUnit`. 5 | 6 | ## Examples 7 | 8 | ```jsx harmony 9 | //title=Basic form unit 10 | Enter a value in the field above 18 | }}> 19 | 20 | ; 21 | ``` 22 | 23 | ```jsx harmony 24 | //title=Inline form unit 25 | //description=When `inline` is `true`, the label will be placed on the same line as the field. 26 |
    27 | 35 | 40 | 41 | 50 | 51 | 52 |
    ; 53 | ``` 54 | 55 | ```jsx harmony 56 | //title=Form unit with error 57 | //description=When `hasError` is `true`, the field border and help text become red to indicate an error. 58 | 64 | 65 | ; 66 | ``` 67 | 68 | ```jsx harmony 69 | //title=Form unit with postLabel 70 | //description=The `postLabel` can contain any node and will be positioned in the top-right corner of a non-inline form unit. 71 | alert('Thanks for clicking me!')}>I am a postLabel!, 75 | help: 'Username must be more than 8 characters' 76 | }}> 77 | 78 | ; 79 | ``` 80 | 81 | ```jsx harmony 82 | //title=Form unit with composite field 83 | 86 | }, 88 | {name: 'Two', enabled: }, 89 | {name: 'Three', enabled: } 90 | ]}/> 91 | ; 92 | ``` -------------------------------------------------------------------------------- /docs/components/Grids/2.Props.md: -------------------------------------------------------------------------------- 1 | ## Grid props 2 | 3 | | Property | Required | Type | Default | Description | 4 | | ----------------- | ---------- | --------- | --------- | ------------ | 5 | | `gutter` | no | boolean | true | When true, adds spacing between `FlexCol`s | 6 | | `flexDirection` | no | oneOf(['row', 'row-reverse', 'column', 'column-reverse']) | | Sets the flex direction | 7 | | `justifyContent` | no | oneOf(['flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly']) | | Sets the `justify-content` CSS property | 8 | 9 | ## FlexCol props 10 | 11 | Property | Required | Type | Default | Description 12 | -------------------|----------|------------------------------------|---------|------------ 13 | `alignment` | no | oneOf(['top', 'middle', 'bottom']) | | Alignment of the column within the `Grid` 14 | `breakpoint` | no | oneOf(['sm', 'md', 'lg']) | | Width of window at which column will expand to take up full width of `Grid` (`sm` = `768px`, `md` = `992px`, `lg` = `1200px`) 15 | `col` | no | number | | Fraction out of 24 that this column's width should be in its `Grid` 16 | `contentAlignment` | no | oneOf(['top', 'middle', 'bottom']) | | Alignment of the column's contents within itself 17 | `fixed` | no | boolean | false | When true, column width is fixed to the width of its content 18 | `grow` | no | number | 1 | The ratio of the column's width relative to other columns in the same `Grid` 19 | -------------------------------------------------------------------------------- /docs/components/Icons/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/iconography 3 | reactComponents: 4 | - Icon 5 | reactPath: pivotal-ui/react/iconography 6 | --- 7 | 8 | Use the `Icon` component to insert one of Pivotal UI's SVG icons. The full list of icons that Pivotal UI provides, along with their names, can be found [here](/components/icons/icon_list). 9 | 10 | To use an icon, specify the name of the icon as the `src` prop. 11 | 12 | ```jsx harmony 13 | //title=Icon examples 14 |
    15 | 16 | 17 | 18 |
    ; 19 | ``` 20 | 21 | By default, the icons are quite small. They inherit the font size of their parent. This means they can be resized by, for example, wrapping them in an `

    ` or explicitly setting a font size on the parent. 22 | 23 | ```jsx harmony 24 | //title=Larger icon examples 25 |
    26 | 27 | 28 | 29 |
    ; 30 | ``` 31 | 32 | When styling the SVGs, use the `fill` or `stroke` attributes instead of `color`. These can be set directly on the `Icon` as a `style` prop or via CSS. A useful trick is to set `fill` to `currentColor`, so that the fill color is inherited from the text color of the icon's container. 33 | 34 | ```jsx harmony 35 | //title=Color icon examples 36 |
    37 | 38 | 39 | 40 |
    ; 41 | ``` 42 | 43 | Set the `verticalAlign` prop to `"baseline"` to align the icon to the text baseline. 44 | 45 | ```jsx harmony 46 | //title=Alignment with text 47 |

    Exit

    ; 48 | ``` 49 | 50 | Images can be used like icons by wrapping them in a container with the `icon` class. 51 | 52 | ```html 53 | //title=Images as icons 54 | The following image is wrapped as an icon
    55 | 56 |
    . 57 |
    58 | ``` 59 | 60 | Pivotal UI provides three variations on the spinner icon, differing in their speed. 61 | 62 | `spinner-lg` is the slowest, `spinner-md` is the default, and `spinner-sm` is the fastest. Use `spinner-md` in most cases. 63 | 64 | ```jsx harmony 65 | //title=Spinner icons 66 |
    67 |
    68 |
    spinner-lg
    69 | 70 |
    71 |
    72 |
    spinner-md
    73 | 74 |
    75 |
    76 |
    spinner-sm
    77 | 78 |
    79 |
    ; 80 | ``` 81 | 82 | To use icons in buttons, see the [Buttons](/components/buttons/usage) page. -------------------------------------------------------------------------------- /docs/components/Icons/2.Icon_List.md: -------------------------------------------------------------------------------- 1 | ```jsx harmony 2 | //noToolbar 3 | 9 | No matching icons 10 | 11 | ), 12 | filter: (iconNames, filterText) => iconNames.filter(iconName => iconName.indexOf(filterText.toLowerCase()) > -1), 13 | renderFilteredData: iconNames => ( 14 | 15 | {iconNames.map(iconName => { 16 | return ( 17 | 18 | 19 |
    {iconName}
    20 |
    21 | ); 22 | })} 23 |
    24 | ) 25 | }}/>; 26 | ``` -------------------------------------------------------------------------------- /docs/components/Icons/3.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | -------------------|----------|------------------------------------|----------|------------ 3 | `src` | yes | String | | The name of the icon 4 | `style` | no | Object | | Styles to apply 5 | `verticalAlign` | no | oneOf(['middle', 'baseline']) | 'middle' | Vertical alignment 6 | -------------------------------------------------------------------------------- /docs/components/Images/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | -------------|----------|------|---------|------------ 3 | `alt` | no | String | | Alt text 4 | `href` | no | String | | If set, image becomes a link 5 | `responsive` | no | Boolean | false | Whether this image should resize responsively 6 | `src` | yes | String | | Image src 7 | -------------------------------------------------------------------------------- /docs/components/Inputs/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/inputs 3 | reactComponents: 4 | - Input 5 | reactPath: pivotal-ui/react/inputs 6 | --- 7 | 8 | Most common form control, text-based input fields. Includes support for all HTML5 types: `text`, `password`, `datetime`, `datetime-local`, `date`, `month`, `time`, `week`, `number`, `email`, `url`, `search`, `tel`, and `color`. 9 | 10 | Inputs will only be fully styled if their type is properly declared. 11 | 12 | ```jsx harmony 13 | //title=Text field 14 | ; 15 | ``` 16 | 17 | ```jsx harmony 18 | //title=Password field 19 | ; 20 | ``` 21 | 22 | ```jsx harmony 23 | //title=Size 24 | //description=Input has a `size` attribute that takes three options: small, medium (default), and large. 25 |
    26 | 27 | 28 | 29 |
    ; 30 | ``` 31 | 32 | ```jsx harmony 33 | //title=With icon 34 |
    35 | 36 | 37 |
    ; 38 | ``` -------------------------------------------------------------------------------- /docs/components/Inputs/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ---------|----------|-----------------------------------|----------|------------ 3 | `icon` | no | String | | See [Icons](/icons) for valid icon names 4 | `size` | no | oneOf('small', 'medium', 'large') | 'medium' | Size variations 5 | All other props are passed to the internal `` tag. 6 | -------------------------------------------------------------------------------- /docs/components/Links/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/links 3 | --- 4 | 5 | Use the link modifiers on `` tags to control link underline color and hover state. By default, links are not underlined. 6 | 7 | Modifier | Purpose 8 | -------- | ------- 9 | `no-underline` | No text decoration or background image 10 | `underline` | Adds text decoration underline 11 | `underline-hover` | Adds text decoration underline when the state is hover 12 | `underline-blue` | Utilizes background image to define a blue underline 13 | `underline-blue-hover` | Utilizes background image to define a blue underline when the state is hover 14 | `underline-gray` | Utilizes background image to define a gray underline 15 | `underline-gray-hover` | Utilizes background image to define a gray underline when the state is hover 16 | 17 | ```html 18 | //title=Link examples 19 |

    a default link (no modifiers)

    20 |

    no underline

    21 |

    underline

    22 |

    underline on hover

    23 |

    underline blue

    24 |

    underline blue on hover

    25 |

    underline gray

    26 |

    underline gray on hover

    27 | ``` 28 | 29 | ```html 30 | //title=Link with icon 31 |

    32 | 33 |

    38 | A link with an icon 39 | 40 |

    41 | ``` -------------------------------------------------------------------------------- /docs/components/Lists/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/lists 3 | reactComponents: 4 | - BreadcrumbList 5 | - InlineList 6 | - ListItem 7 | reactPath: pivotal-ui/react/lists 8 | --- 9 | 10 | ```jsx harmony 11 | //title=Breadcrumb 12 | 13 | Home 14 | React 15 | Lists 16 | ; 17 | ``` 18 | 19 | ```html 20 | //title=Breadcrumb CSS 21 | //description=The `.list-breadcrumb` can be used to provide additional page navigation. Breadcrumbs use their own monospace font-family. 22 |
      23 |
    • 24 | Parent 25 |
    • 26 |
    • 27 | Child 28 |
    • 29 |
    • 30 | Current Page 31 |
    • 32 |
    33 | ``` 34 | 35 | ```jsx harmony 36 | //title=Inline 37 | 38 | Item 1 39 | Item 2 40 | Item 3 41 | ; 42 | ``` -------------------------------------------------------------------------------- /docs/components/Lists/2.Props.md: -------------------------------------------------------------------------------- 1 | ## BreadcrumbList props 2 | 3 | Property | Required | Type | Default | Description 4 | ------------|----------|------|---------|------------ 5 | `className` | no | String | | Classname of the list 6 | `divider` | no | Boolean | false | Whether to include a divider between items 7 | `unstyled` | no | Boolean | false | Whether to style the list 8 | 9 | ## InlineList props 10 | 11 | Property | Required | Type | Default | Description 12 | ------------|----------|------|---------|------------ 13 | `className` | no | String | | Classname of the list 14 | `divider` | no | Boolean | false | Whether to include a divider between items 15 | `unstyled` | no | Boolean | false | Whether to style the list 16 | 17 | ## ListItem props 18 | 19 | _All props passed directly to inner `li` element._ -------------------------------------------------------------------------------- /docs/components/Media/2.Props.md: -------------------------------------------------------------------------------- 1 | ## Media/Flag props 2 | 3 | Property | Required | Type | Default | Description 4 | ---------|----------|------|---------|------------ 5 | `className` | no | String | | The classname of the element 6 | `image` | yes | Node | | The image displayed 7 | `innerClassName` | no | String | | The classname of the inner element 8 | `mediaSpacing` | no | oneOf('small', 'medium', 'large', 'xlarge') | | Amount of whitespace between media and body 9 | `placement` | no | oneOf('left', 'right') | 'left' | Horizontal placement of the media 10 | `stackSize` | no | oneOf('xsmall', 'small', 'medium', 'large') | | At what breakpoint should the media object stack 11 | `vAlign` | no | oneOf('middle', 'bottom') | | Vertical alignment of the body (used for large images with small content next to it, usually centered) 12 | -------------------------------------------------------------------------------- /docs/components/Modal/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/modal 3 | reactComponents: 4 | - Modal 5 | reactPath: pivotal-ui/react/modal 6 | --- 7 | 8 | The `Modal` component provides a way to put content in a pop-up dialog that must be closed before interacting with 9 | the main content again. 10 | 11 | ```jsx harmony 12 | //title=Basic example with custom size and duration 13 | class MyModal extends React.Component { 14 | constructor(props) { 15 | super(props); 16 | this.state = {show: false, disableAnimation: false}; 17 | } 18 | 19 | render() { 20 | return ( 21 |
    22 | this.setState({show: true})}> 23 | Open Modal 24 | 25 | this.setState({show: false})} 30 | footer={ this.setState({show: false})}>Close}> 31 |

    Text in a body

    32 |
    33 |
    34 | ); 35 | } 36 | } 37 | 38 | ; 39 | ``` -------------------------------------------------------------------------------- /docs/components/Modal/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description | 2 | --------------------| ---------- | ---------- | ---------- | ------------ | 3 | `animationDuration` | no | Number | 300 | Animation duration in milliseconds (Set to <= 0 to disable animations) | 4 | `animationEasing` | no | String | cubic-bezier(0.25, 0.46, 0.45, 0.94) | Animation easing function | 5 | `dialogClassName` | no | String | | Class(es) to apply to the modal dialog | 6 | `onHide` | yes | Function | | Callback that fires as soon as the modal begins closing | 7 | `show` | no | Boolean | | Whether the modal should be opened or closed | 8 | `size` | no | String, oneOf(['sm', 'small', 'large', 'lg']) or a valid css width value, eg. '44%', '900px' | | Size variations | 9 | `title` | no | Node | | Title of the modal, shown at the top of the modal | 10 | -------------------------------------------------------------------------------- /docs/components/Notifications/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/notifications 3 | reactComponents: 4 | - Notifications 5 | - AlertNotifications 6 | - NotificationItem 7 | reactPath: pivotal-ui/react/notifications 8 | --- 9 | 10 | ```jsx harmony 11 | //title=No notifications 12 | ; 13 | ``` 14 | 15 | ```jsx harmony 16 | //title=With notifications 17 | 18 | 19 | New}> 20 |
    Notification
    21 |

    Click for Gif

    22 |
    23 |
    24 |
    ; 25 | ``` 26 | 27 | ```jsx harmony 28 | //title=Notification sizing 29 |
    30 | 31 | Stuff 32 | 33 | 34 | 35 | Stuff 36 | Stuff 37 | Stuff 38 | Stuff 39 | Stuff 40 | 41 | 42 | 43 | Stuff 44 | 45 | 46 | 47 | Stuff 48 | Stuff 49 | Stuff 50 | Stuff 51 | Stuff 52 | 53 | 54 | 55 | Stuff 56 | 57 |
    ; 58 | ``` 59 | 60 | ```jsx harmony 61 | //title=No alerts 62 | ; 63 | ``` 64 | 65 | ```jsx harmony 66 | //title=With alerts 67 |
    68 | 69 | 70 | }> 71 |
    WARNING
    72 |

    Click for Cute Gif

    73 |
    74 |
    75 |
    76 |
    ; 77 | ``` 78 | 79 | If you want to customize the notification dropdown, you can use `className` to 80 | add a modifier class to the `btn-group`. `id` and `style` will be applied to 81 | the notification button. -------------------------------------------------------------------------------- /docs/components/Notifications/2.Props.md: -------------------------------------------------------------------------------- 1 | ## Notifications/AlertNotifications props 2 | 3 | Property | Required | Type | Default | Description 4 | ---------|----------|------|---------|------------ 5 | `size` | no | oneOf('h1', 'h2', 'h3', 'h4', 'h5', 'h6') | | Size of the notification -------------------------------------------------------------------------------- /docs/components/Overlay_Trigger/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | reactComponents: 3 | - OverlayTrigger 4 | reactPath: pivotal-ui/react/overlay-trigger 5 | --- 6 | 7 | OverlayTriggers are highly configurable. Their associated overlays do not show up in the DOM until triggered. 8 | This makes them ideal for highly repeated layouts such as lists. 9 | 10 | ```jsx harmony 11 | //title=Basic example 12 | //description=To create a tooltip where the contents are not inlined with the triggering element itself, use the OverlayTrigger component. If the `overlay` property passed into the `OverlayTrigger` will be displayed on hover, this is where the `Tooltip` can be used. This can be useful in situations where you want to have many different elements trigger the same tooltip. Tooltips are placed using the `placement` property on `OverlayTrigger`. 13 |
    14 |

    15 | Check out this 16 | I should be on the left}> 17 | tooltip on the left. 18 | 19 |

    20 |

    21 | Check out this 22 | I should be on the right}> 23 | tooltip on the right. 24 | 25 |

    26 |

    27 | Check out this 28 | I should be on the top}> 29 | tooltip on the top. 30 | 31 |

    32 |

    33 | Check out this 34 | I should be on the bottom}> 35 | tooltip on the bottom. 36 | 37 |

    38 |

    39 | Check out this 40 | light tooltip}> 41 | light tooltip. 42 | 43 |

    44 |
    ; 45 | ``` 46 | 47 | ```html 48 | //title=Resizable tooltips 49 |
    50 |
    51 | 54 |
    55 |
    Lorem ipsum dolor sit amet, consec
    56 |
    57 |
    58 | 59 |
    60 | 63 |
    64 |
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
    65 |
    66 |
    67 | 68 |
    69 | 72 |
    73 |
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    74 |
    75 |
    76 |
    77 | ``` 78 | 79 | If `trigger` is set to `manual`, display of the tooltip is entirely determined by the `display` prop, 80 | which is controlled by the end user and not by `OverlayTrigger`. -------------------------------------------------------------------------------- /docs/components/Overlay_Trigger/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | ---------------|----------|--------------------------------------------|---------|--------------------------------------- 3 | `delay` | no | Number | | Number of milliseconds to delay show and hide 4 | `delayHide` | no | Number | | Number of milliseconds to delay hide 5 | `delayShow` | no | Number | | Number of milliseconds to delay show 6 | `disableScrim` | no | Boolean | false | Set to true to make tooltips stay open when clicking outside 7 | `display` | no | Boolean | false | Whether or not to show the overlay 8 | `isSticky` | no | Boolean | false | Whether the tooltip hover is sticky or not 9 | `onEntered` | no | Function | | Callback that is called after the overlay is shown 10 | `onExited` | no | Function | | Callback that is called after the overlay is hidden 11 | `overlay` | no | Node | | An element or text to overlay next to the target 12 | `pin` | no | Boolean | true | Whether or not to reposition overlays to stay in the window 13 | `placement` | no | oneOf('top', 'bottom', 'left', 'right') | 'right' | Placement of overlay in relation to target 14 | `theme` | no | oneOf(['light', 'dark']) | dark | Theme of tooltip background and text 15 | `trigger` | no | oneOf('hover', 'click', 'focus', 'manual') | 'hover' | Action to trigger showing overlay 16 | -------------------------------------------------------------------------------- /docs/components/Pagination/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/pagination 3 | reactComponents: 4 | - Pagination 5 | reactPath: pivotal-ui/react/pagination 6 | --- 7 | 8 | Pagination is a method for allowing a user to view a subset of sorted data into a more comprehensible format. It allows a user to progress to the next or previous view, or choose a page number you want manually. 9 | 10 | The `Pagination` component provides a styled list of links used to navigate through a paginated list. By default, 11 | the component includes a 'previous page' button, a 'next page' button, and one link. 12 | 13 | The pagination component will display a maximum of five pages. When more than five are provided, the component will shrink with ellipses to show the first, last, active, and pages adjacent to the active page. 14 | 15 | Do's | Don'ts 16 | -------------|---------- 17 | Use when it is unsuitable to display all the data on a single page/screen. | Do not use when you don’t want the user to pause for navigating to the next page. Instead consider simply having a scrolling vertical view. 18 | Use when the dataset is in some way ordered. | 19 | 20 | ```jsx harmony 21 | //title=Without extra props 22 | ; 23 | ``` 24 | 25 | ```jsx harmony 26 | //title=With extra props 27 | //description=The following is an example of pagination with extra props: 28 | class PaginationAdvanced extends React.Component { 29 | constructor(props) { 30 | super(props); 31 | this.handleSelect = this.handleSelect.bind(this); 32 | this.state = {activePage: 1}; 33 | } 34 | 35 | handleSelect(event, selectedEvent) { 36 | const newActivePage = selectedEvent.newActivePage; 37 | this.setState({activePage: newActivePage}); 38 | } 39 | 40 | render() { 41 | return ( 42 |
    43 | 46 |
    Current Page: {this.state.activePage}
    47 |
    48 | ); 49 | } 50 | } 51 | 52 | ; 53 | ``` -------------------------------------------------------------------------------- /docs/components/Pagination/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | -------------|----------|----------|---------|------------ 3 | `activePage` | no | Number | | The selected page number (starts at 1) 4 | `items` | no | Number | 1 | The number of page links displayed 5 | `next` | no | Boolean | true | Option to display a 'next page' button 6 | `onSelect` | no | Function | | Callback that is called when a page number or next/previous button is clicked. It receives an object containing `newActivePage`. 7 | `prev` | no | Boolean | true | Option to display a 'previous page' button 8 | -------------------------------------------------------------------------------- /docs/components/Panels/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/panels 3 | reactComponents: 4 | - Panel 5 | reactPath: pivotal-ui/react/panels 6 | --- 7 | 8 | Use a `Panel` to contain content that has a logical grouping. Panels always have either a `header` or a `title`. 9 | 10 | Set the `title` or `header` prop to give a name to the panel. Use whichever is more appropriate for your application. 11 | 12 | ```jsx harmony 13 | //title=Panel with title 14 |
    15 | 16 | These are the domains. 17 | 18 |
    ; 19 | ``` 20 | 21 | ```jsx harmony 22 | //title=Panel with header 23 |
    24 | 25 | These are the domains. 26 | 27 |
    ; 28 | ``` 29 | 30 | Use the footer for information that does not belong in the panel body. 31 | 32 | ```jsx harmony 33 | //title=Panel with header and footer 34 |
    35 | Click here for more info}}> 36 | These are the domains. 37 | 38 |
    ; 39 | ``` 40 | 41 | When the panel has associated calls-to-action, set the `titleCols` or `headerCols` prop to include buttons to the right of the panel name. 42 | 43 | Because the panel is built on the `Grid` component, these buttons should be wrapped in `FlexCol` components. 44 | 45 | ```jsx harmony 46 | //title=Panel with call-to-action in title 47 |
    48 | Add Domain] 51 | }}> 52 | These are the domains. 53 | 54 |
    ; 55 | ``` 56 | 57 | When including a button in a panel header, make it small to keep the panel header size the same. 58 | 59 | ```jsx harmony 60 | //title=Panel with call-to-action in header 61 |
    62 | Add Domain] 65 | }}> 66 | These are the domains. 67 | 68 |
    ; 69 | ``` 70 | 71 | When the panel has content loading, set the `loading` prop to add a loading indicator to the top of the panel body. 72 | 73 | ```jsx harmony 74 | //title=Panel with loading animation 75 |
    76 | 77 | Loading apps... 78 | 79 |
    ; 80 | ``` 81 | 82 | When using multiple panels that are related, the first panel should have a title that names the grouping. Each panel header should name its subgroups. 83 | 84 | ```jsx harmony 85 | //title=Multiple related panels 86 |
    87 | 88 | monkey, mouse 89 | 90 | 91 | alligator, snake 92 | 93 |
    ; 94 | ``` -------------------------------------------------------------------------------- /docs/components/Panels/2.Props.md: -------------------------------------------------------------------------------- 1 | Property | Required | Type | Default | Description 2 | -------------------|----------|---------|---------|------------ 3 | `bodyClassName` | no | String | | Class(es) to apply to the body 4 | `className` | no | String | | Class(es) to apply to the panel container 5 | `footer` | no | Node | | Node to render in the footer 6 | `footerClassName` | no | String | | Class(es) to apply to the footer 7 | `header` | no | String | | String to render in the header 8 | `headerClassName` | no | String | | Class(es) to apply to the header 9 | `headerCols` | no | Array | [] | An array of nodes to render on the header row, each element should be wrapped in a `FlexCol` 10 | `loading` | no | Boolean | | If true, will render a pulsing loading bar 11 | `panelClassName` | no | String | | Class(es) to apply to the area containing the header, body and footer 12 | `title` | no | String | | String to render in the title 13 | `titleClassName` | no | String | | Class(es) to apply to the title 14 | `titleCols` | no | Array | [] | An array of nodes to render on the title row, each element should be wrapped in a `FlexCol` 15 | -------------------------------------------------------------------------------- /docs/components/Portals/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | reactComponents: 3 | - PortalSource 4 | - PortalDestination 5 | reactPath: pivotal-ui/react/portals 6 | --- 7 | 8 | The `Portal` components render DOM nodes elsewhere on the page. This is useful for things like 9 | modals, tooltips, and dropdowns, when you want to define the content near the trigger, but have 10 | it display at the bottom of the page (generally to solve z-index and overflow incompatibilities). 11 | 12 | For example, modals can be rendered at the bottom of ``, but the React component that creates 13 | the modal content (e.g. a ` 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ; 35 | ``` 36 | 37 | ```jsx harmony 38 | //title=Markup example 39 | //description=Since the tooltip property is of type Node, you may add markup to the tooltip, such as links. 40 | clickable link} theme="light"> 41 | 42 | ; 43 | ``` 44 | 45 | ```jsx harmony 46 | //title=Manual trigger example 47 | //description=The trigger is manual, so the visibility of the tooltip is controlled by the display prop. 48 | class ManualTooltipExample extends React.Component { 49 | constructor(props) { 50 | super(props); 51 | this.state = { 52 | displayTooltip: false 53 | }; 54 | } 55 | 56 | render() { 57 | return ( 58 |
    59 | this.setState({displayTooltip: !this.state.displayTooltip}) 61 | }}>show/hide tooltip 62 | 69 | Check the checkbox to display my tooltip 70 | 71 |
    72 | ); 73 | } 74 | } 75 | 76 | ; 77 | ``` -------------------------------------------------------------------------------- /docs/components/Tooltips/2.Props.md: -------------------------------------------------------------------------------- 1 | ## Tooltip props 2 | 3 | Property | Required | Type | Default | Description 4 | ---------------|----------|-------------------------------------------|----------|---------------------------------- 5 | `isSticky` | no | Boolean | false | Whether the tooltip hover is sticky or not 6 | `size` | no | oneOf(['auto', 'sm', 'md', 'lg']) | auto | Size of the tooltip 7 | `visible` | no | Boolean | true | Whether the tooltip contents are visible 8 | 9 | ## TooltipTrigger props 10 | 11 | Property | Required | Type | Default | Description 12 | -----------------|----------|-------------------------------------------|----------|---------------------------------- 13 | `clickHideDelay` | no | Number | 1000 | How long (in milliseconds) to wait before hiding after click 14 | `display` | no | Boolean | false | if `trigger` is set to `manual` controls whether or not the tooltip is visible 15 | `isSticky` | no | Boolean | false | Whether the tooltip hover is sticky or not 16 | `onEntered` | no | Func | () => {} | Callback that is called after the tooltip is shown 17 | `onExited` | no | Func | () => {} | Callback that is called after the tooltip is hidden 18 | `placement` | no | oneOf(['left', 'right', 'bottom', 'top']) | top | Placement of tooltip in relation to target 19 | `size` | no | oneOf(['auto', 'sm', 'md', 'lg']) | auto | Size of the tooltip 20 | `theme` | no | oneOf(['light', 'dark']) | dark | Theme of tooltip background and text 21 | `tooltip` | yes | Node | | Tooltip content - will be wrapped in a Tooltip component 22 | `trigger` | no | oneOf(['hover', 'click', 'manual']) | hover | Action to trigger showing tooltip 23 | -------------------------------------------------------------------------------- /docs/components/Wizard/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | reactComponents: 3 | - Wizard 4 | reactPath: pivotal-ui/react/wizard 5 | --- 6 | 7 | The `Wizard` component allows the user to navigate through a series of Wizard pages. Each page has a render function which returns the JSX required to show the page. Various callbacks can be provided as props to customize the Wizard's behavior. 8 | 9 | ```jsx harmony 10 | //title=Basic example 11 | const pages = [{ 12 | render() { return This is the first page of the wizard. By default, the wizard cannot be cancelled. The user cannot go back from the first page. Click the Next button to proceed.;} 13 | }, { 14 | render() { return This is the second page of the wizard. The user can click Back or Next.;} 15 | }, { 16 | render() { return This is the third and final page of the wizard. The user can click Back or Finish;} 17 | }]; 18 | 19 | alert('All done!')}/>; 20 | ``` 21 | 22 | ```jsx harmony 23 | //title=With saving and savingText 24 | const pages = [{ 25 | render() { return This is the first page of the wizard. The user can click Next.;} 26 | }, { 27 | render() { return This is the last page of the wizard. The Back button is disabled and the Finish button shows a spinner icon.;} 28 | }]; 29 | 30 | alert('All done!')}/>; 31 | ``` 32 | 33 | ```jsx harmony 34 | //title=With custom back and finish components 35 | const pages = [{ 36 | render() { return This is the first page of the wizard, click the Next button to see the custom back and finish components.;} 37 | }, { 38 | render() { return This is the last page of the wizard with custom back and finish components.;}, 39 | backComponent: Custom back component, 40 | finishComponent: Custom finish component 41 | }]; 42 | 43 | ; 44 | ``` -------------------------------------------------------------------------------- /docs/components/Wizard/2.Props.md: -------------------------------------------------------------------------------- 1 | ## Wizard props 2 | 3 | Property | Required | Type | Default | Description 4 | -------------|----------|----------|---------|------------ 5 | `cancel` | no | Function | | Callback to call when the user cancels the Wizard. 6 | `cancelText` | no | String | Cancel | Text for the Cancel button. 7 | `finish` | no | Function | | Callback to call when the user finishes the Wizard. 8 | `finishText` | no | String | Finish | Text for the Finish button. 9 | `pages` | yes | Array | [] | An array of Wizard Pages. 10 | `saving` | no | Boolean | false | When true, renders the Finish button with a spinner icon and disables the Back button. 11 | `savingText` | no | String | Saving | Text for the Finish button when `saving` is true. 12 | 13 | ## Page object props 14 | 15 | Property | Required | Type | Default | Description 16 | -------------------|----------|----------|---------|------------ 17 | `backComponent` | no | Node | | Replaces the standard Back button. 18 | `finishComponent` | no | Node | | Replaces the standard Finish button. 19 | `hideFinishButton` | no | Boolean | | Hides the Finish button. 20 | `hideNextButton` | no | Boolean | false | Whether to hide the Next button. 21 | `nextEnabled` | no | Function | | Callback to determine whether to enable the Next button. The Wizard's `getPage` function is passed as an argument to the callback. 22 | `nextText` | no | Function | | Callback to determine the text for the Next button. 23 | `onClickBack` | no | Function | | Called when the user clicks the Back button. Can optionally return a page index to go back to. 24 | `onClickNext` | no | Function | | Called when the user clicks the Next button. 25 | `render` | yes | Function | | Function that returns JSX for a page. 26 | -------------------------------------------------------------------------------- /docs/concepts/8-Point_Grid/1.Index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 8-Point Grid 3 | menu: concepts 4 | --- 5 | 6 | Pivotal UI uses an 8-point grid system for sizing, spacing, and laying out components relative to one another. This means that any padding, margin, button height, etc. is always a **multiple of 8 pixels**. This makes it easy to compose Pivotal UI components together neatly and consistently. For a deeper dive into how Pivotal arrived at the 8-point grid, [read this article](https://builttoadapt.io/intro-to-the-8-point-grid-system-d2573cde8632). 7 | 8 | ![consistent spacing with a grid vs. inconsistent spacing without a grid](https://cdn-images-1.medium.com/max/2000/1*Kcx60oAWZioon-V_RR-IQA.png) 9 | 10 | ## Using the 8-point grid 11 | 12 | Pivotal UI incorporates the 8-point grid in several ways for different use cases. 13 | 14 | ### Form, Panel & Table components 15 | 16 | Components like the `Form`, `Panel` and `Table` have the 8-point grid built in, so using them means getting the benefits of the 8-point grid for free. For example, the `Form` lays out all of its fields and labels according to the grid. For more information, see the individual component pages. 17 | 18 | ### Grid & FlexCol components 19 | 20 | When more control is needed over layout, or when implementing custom components, the `Grid` and `FlexCol` components can be used to lay out content according to the 8-point grid. For more information, see the [Grids page](/grids). 21 | 22 | ### Margin & padding modifiers 23 | 24 | The margin and padding CSS modifier classes (e.g. `mtxl`, `paxxl`) make it simple to add spacing around elements in increments of 8 pixels. The `l` indicates 8 pixels, `xl` indicates 16 pixels, and so on. For more information, see the [Whitespace page](/whitespace). -------------------------------------------------------------------------------- /docs/concepts/Accessibility/1.Guidelines.md: -------------------------------------------------------------------------------- 1 | When it comes to building accessible user interfaces, Pivotal UI aims to help designers and engineers wherever it can. Still, there are several guidelines to keep in mind when implementing accessibility, both with and without Pivotal UI. 2 | 3 | Some good resources for learning more about accessibility are the [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/TR/2008/REC-WCAG20-20081211/), which are the standards by which accessibility is often measured on the web, and the [WCAG Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/?versions=2.0), which lists patterns and techniques for meeting each of the WCAG standards. 4 | 5 | ## Do not rely on color to convey meaning 6 | 7 | Be careful of relying solely on color to convey information. If users are not able to distinguish between colors easily, they could miss this information. 8 | 9 | For example, an icon changing color from green to red should not be the only indication of an error. In this case, maybe there could be accompanying error text. 10 | 11 | ## Keep color contrast easy to see 12 | 13 | When choosing colors to use for UI elements, we must consider the contrast between text color and the background color behind it. If this contrast is too low, the text will be hard to see over the background. 14 | 15 | To measure this, we can calculate the contrast ratio between a foreground color and a background color. Contrast ratios range from 1:1 (same exact colors) to 21:1 (pure black on pure white). 16 | 17 | According to [WCAG](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html), a minimum contrast ratio of 4.5:1 achieves level AA compliance for normal-sized text and is recommended to account for users with less-than-perfect vision. See [here](https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast) for detailed acceptance criteria and exceptions to this rule. 18 | 19 | To ease the process of finding accessible combinations of Pivotal UI colors, use [this tool](/concepts/accessibility/color_contrast_tool). 20 | 21 | ## Support keyboard navigation 22 | 23 | Some users may use the keyboard to navigate through a website, rather than a mouse. For this reason, it should be possible to focus on and active any interactive elements using only the keyboard (buttons, links, inputs, anything clickable). 24 | 25 | The easiest way to do this is to use native HTML elements whenever possible, since browsers already understand how to make these elements focusable and accessible to assistive technologies. 26 | 27 | For example, do not create a styled `div` element with `onClick` behavior instead of a `button`. A custom interactive element like this will not be keyboard-focusable by default, and it will be much harder to ensure it is exposed to assistive technologies properly. 28 | -------------------------------------------------------------------------------- /docs/concepts/Modifier_Classes/1.Index.md: -------------------------------------------------------------------------------- 1 | Pivotal UI provides several CSS "modifier" classes. A modifier is a tiny CSS class that has **one** job (e.g., it sets a single CSS property). They are sometimes called utility classes or atomic classes by other front-end libraries. Modifiers help avoid writing repetitive CSS and make it easy to incorporate Pivotal UI's colors, typography, and other common patterns. 2 | 3 | It is very often possible to achieve a desired effect just by composing modifier classes, without writing any new CSS. Prefer this approach whenever it is feasible, since it decreases the amount of CSS to maintain in your team's codebase and makes styling more consistent across codebases. 4 | 5 | ## Anatomy of a modifier 6 | 7 | The CSS for a modifier class looks like this: 8 | 9 | ```css 10 | .underline { 11 | text-decoration: underline; 12 | } 13 | ``` 14 | 15 | The `underline` class does exactly one thing: gives any text with this class an underline. On its own, this is not very impressive. The real power of modifiers becomes clear when composing multiple modifiers together. 16 | 17 | ## Composing modifiers 18 | 19 | To demonstrate how modifier classes can be composed, consider this unstyled content that displays the current year: 20 | 21 | ```jsx harmony 22 | //title=With no modifiers 23 |
    24 | current year: {new Date().getFullYear()} 25 |
    ; 26 | ``` 27 | 28 | Now, let's add a bunch of modifier classes to the outer `div` and inner `span` elements to center the text and add some style: 29 | 30 | ```jsx harmony 31 | //title=With several modifiers 32 |
    33 | current year: {new Date().getFullYear()} 34 |
    ; 35 | ``` 36 | 37 | Without writing any CSS, the content looks completely different. 38 | 39 | ## Modifier list 40 | 41 | For details about all of the available modifiers, see the modifier documentation pages: 42 | 43 | - [Alignment](/modifiers/alignment/usage) 44 | - [Border](/modifiers/border/usage) 45 | - [Box Shadows](/modifiers/box-shadows/usage) 46 | - [Colors](/modifiers/colors/usage) 47 | - [Ellipsis](/modifiers/ellipsis/usage) 48 | - [Links](/modifiers/links/usage) 49 | - [Positioning](/modifiers/positioning/usage) 50 | - [Typography](/modifiers/typography/usage) 51 | - [Vertical Alignment](/modifiers/vertical-alignment/usage) 52 | - [Whitespace](/modifiers/whitespace/usage) -------------------------------------------------------------------------------- /docs/modifiers/Alignment/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/alignment 3 | --- 4 | 5 | Use alignment modifier classes to control the horizontal and vertical alignment of an element's contents. 6 | 7 | ## Classes 8 | 9 | Modifier | Purpose 10 | ---------|-------- 11 | `txt-l` | Align contents to the left 12 | `txt-c` | Center contents horizontally 13 | `txt-r` | Align contents to the right 14 | `txt-t` | Align contents to the top 15 | `txt-m` | Center contents vertically 16 | `txt-b` | Align contents to the bottom 17 | 18 | Note that the vertical alignment classes listed here (`txt-t`, `txt-m`, `txt-b`) will only work when applied to elements with `display: inline` or `display: table-cell`. For vertical alignment within `display: block` elements, [these modifiers](/vertical-alignment) might be more useful. 19 | 20 | ```jsx harmony 21 | //title=Horizontal alignment 22 |
    23 |

    txt-l

    24 |

    txt-c

    25 |

    txt-r

    26 |
    ; 27 | ``` 28 | 29 | ```jsx harmony 30 | //title=Vertical alignment 31 |
    32 | 33 | 34 | 39 | 42 | 45 | 48 | 49 | 50 |
    35 | This long text is used to expand the height of this 36 | table so that we can demonstrate our vertical alignment classes 37 | to the right. 38 | 40 | txt-t 41 | 43 | txt-m 44 | 46 | txt-b 47 |
    ; 51 | ``` 52 | -------------------------------------------------------------------------------- /docs/modifiers/Border/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/border 3 | --- 4 | 5 | Use border modifiers to control borders around an element. Whenever possible, use these instead of defining custom borders in CSS. 6 | 7 | ## Classes 8 | 9 | Modifier | Purpose 10 | ---------|-------- 11 | `border` | Add borders on all sides 12 | `border-top` | Add a border on the top 13 | `border-right` | Add a border on the right 14 | `border-bottom` | Add a border on the bottom 15 | `border-left` | Add a border on the left 16 | `border-none` | Remove borders from all sides 17 | `border-top-0` | Remove border from the top 18 | `border-right-0` | Remove border from the right 19 | `border-bottom-0` | Remove border from the bottom 20 | `border-left-0` | Remove border from the left 21 | `border-rounded` | Make borders rounded 22 | `border-not-rounded` | Make borders not rounded 23 | 24 | ```html 25 | //title=Adding borders 26 |
    border
    27 |
    border-top
    28 |
    border-right
    29 |
    border-bottom
    30 |
    border-left
    31 | ``` 32 | 33 | ```html 34 | //title=Adding borders in tables 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 |
    border-bottom
    border
    border-right
    border-top
    border-left
    64 | ``` 65 | 66 | ```html 67 | //title=Removing borders 68 |
    border-none
    69 |
    border-top-0
    70 |
    border-right-0
    71 |
    border-bottom-0
    72 |
    border-left-0
    73 | ``` 74 | 75 | ```html 76 | //title=Rounded borders 77 |
    border-rounded
    78 |
    border-not-rounded
    79 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Box_Shadows/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/box-shadows 3 | --- 4 | 5 | Use box shadow modifiers to add shadows to elements. Box shadows are used to to describe the visual hierarchy of objects. 6 | 7 | `box-shadow-key-*` modifiers add directional shadows (heavier on the bottom than the top). `box-shadow-amb-*` modifiers add shadows that are even on all sides, emulating ambient light. `box-shadow-*` modifiers combine them both. 8 | 9 | ## Classes 10 | 11 | Modifier | Purpose 12 | ---------|-------- 13 | `box-shadow-key-1` | Add light key shadow 14 | `box-shadow-key-2` | Add medium key shadow 15 | `box-shadow-key-3` | Add heavy key shadow 16 | `box-shadow-amb-1` | Add light ambient shadow 17 | `box-shadow-amb-2` | Add medium ambient shadow 18 | `box-shadow-amb-3` | Add heavy ambient shadow 19 | `box-shadow-1` | Add light shadow 20 | `box-shadow-2` | Add medium shadow 21 | `box-shadow-3` | Add heavy shadow 22 | 23 | ```html 24 | //title=Basic example 25 |
    26 |
    box-shadow-key-1
    27 |
    box-shadow-amb-1
    28 |
    box-shadow-1
    29 |
    30 |
    31 |
    box-shadow-key-2
    32 |
    box-shadow-amb-2
    33 |
    box-shadow-2
    34 |
    35 |
    36 |
    box-shadow-key-3
    37 |
    box-shadow-amb-3
    38 |
    box-shadow-3
    39 |
    40 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Colors/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/colors 3 | --- 4 | 5 | Use color modifiers to to give elements background and text colors drawn from the Pivotal UI color palette. 6 | 7 | Our color palette is composed of several different colors. At any given point it captures the current 8 | evolution of our design and likely includes old and new colors. Whenever possible, evolve the old 9 | colors rather than adding new ones. 10 | 11 | ## Classes 12 | 13 | The full list of colors can be found [here](/modifiers/colors/palette). 14 | 15 | Prepend any color name with `bg-` to apply that color to an element's background. 16 | 17 | Prepend any color name with `type-` to apply that color to an element's text. 18 | 19 | ```html 20 | //title=Text colors 21 |

    I'm a brand color!

    22 |

    I'm an error color!

    23 | ``` 24 | 25 | ```html 26 | //title=Background colors 27 |

    I'm a brand color!

    28 |

    I'm a warning color!

    29 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Colors/2.Palette.md: -------------------------------------------------------------------------------- 1 | ```jsx harmony 2 | //noToolbar 3 | 4 |
    5 | {colorPalette.map(group => { 6 | return ( 7 |
    8 | {group.map(colorName => { 9 | const rgbValueToHex = value => { 10 | return parseInt(value, 10).toString(16).padStart(2, '0'); 11 | }; 12 | 13 | const calculateHexCodes = () => { 14 | const selector = document.querySelector(`.grid .bg-${colorName}`); 15 | const rbgCode = window.getComputedStyle(selector).backgroundColor; 16 | const rbgElems = rbgCode.substring(4, rbgCode.length-1).split(','); 17 | const hexCode = '#' + rgbValueToHex(rbgElems[0]) + rgbValueToHex(rbgElems[1]) + rgbValueToHex(rbgElems[2]); 18 | document.getElementById(`hex-${colorName}`).innerHTML = hexCode; 19 | }; 20 | 21 | return ( 22 | 23 | 24 | {colorName} 25 | 26 | 27 | ); 28 | } 29 | )} 30 |
    31 | ); 32 | })} 33 |
    ; 34 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Ellipsis/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/ellipsis 3 | --- 4 | 5 | Use the `type-ellipsis` modifier to cause text within an element to be truncated with ellipses ("...") when it is too long to be displayed fully. 6 | 7 | ## Classes 8 | 9 | Modifier | Purpose 10 | ---------|-------- 11 | `type-ellipsis` | Truncate inner text with ellipses 12 | 13 | ```jsx harmony 14 | //title=Basic example 15 |
    16 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 17 |
    ; 18 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Links/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/links 3 | --- 4 | 5 | Use the link modifiers on `` tags to control link underline color and hover state. By default, links are not underlined. 6 | 7 | Modifier | Purpose 8 | -------- | ------- 9 | `no-underline` | No text decoration or background image 10 | `underline` | Adds text decoration underline 11 | `underline-hover` | Adds text decoration underline when the state is hover 12 | `underline-blue` | Utilizes background image to define a blue underline 13 | `underline-blue-hover` | Utilizes background image to define a blue underline when the state is hover 14 | `underline-gray` | Utilizes background image to define a gray underline 15 | `underline-gray-hover` | Utilizes background image to define a gray underline when the state is hover 16 | 17 | ```html 18 | //title=Link examples 19 |

    a default link (no modifiers)

    20 |

    no underline

    21 |

    underline

    22 |

    underline on hover

    23 |

    underline blue

    24 |

    underline blue on hover

    25 |

    underline gray

    26 |

    underline gray on hover

    27 | ``` 28 | 29 | ```html 30 | //title=Link with icon 31 |

    32 | 33 |

    38 | A link with an icon 39 | 40 |

    41 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Positioning/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/positioning 3 | --- 4 | 5 | Use the positioning modifiers to control the CSS `display`, `float`, and `position` properties. 6 | 7 | ## Classes 8 | 9 | Modifier | Purpose 10 | ---------|-------- 11 | `display-block` | Sets `display: block` on element 12 | `display-flex` | Sets `display: flex` on element 13 | `display-inline` | Sets `display: inline` on element 14 | `display-inline-block` | Sets `display: inline-block` on element 15 | `display-none` | Sets `display: none` on element 16 | `float-left` | Floats content to the left 17 | `float-right` | Floats content to the right 18 | `position-absolute` | Sets `position: absolute` on element 19 | `position-fixed` | Sets `position: fixed` on element 20 | `position-relative` | Sets `position: relative` on element 21 | 22 | ```html 23 | //title=Floats 24 |
    25 |
    floating left
    26 |
    floating right
    27 |
    not floating
    28 |
    29 | ``` 30 | 31 | ```html 32 | //title=Position Absolute 33 |
    34 | Parent element 35 |
    36 | Child element 37 |
    38 |
    39 | ``` 40 | 41 | ```html 42 | //title=Position Relative 43 |
    47 | Parent element 48 |
    55 | Child element 56 |
    57 |
    58 | ``` 59 | 60 | ```html 61 | //title=Position Fixed 62 |
    63 | This example places a green box in the bottom-right corner of this page. 64 |
    66 | I am fixed! 67 |
    68 |
    69 | ``` 70 | 71 | ```html 72 | //title=Display Flex 73 |
    74 |
    child1
    75 |
    child2
    76 |
    child3
    77 |
    78 | ``` 79 | 80 | ```html 81 | //title=Display Block 82 | 83 | This span tag takes up all available width 84 | 85 | ``` 86 | 87 | ```html 88 | //title=Display Inline 89 |
    90 | This div tag takes up only the space it needs 91 |
    92 | ``` 93 | 94 | ```html 95 | //title=Display Inline-Block 96 |
    97 | This div tag takes up a fixed amount of space (600px) 98 |
    99 | ``` 100 | 101 | ```html 102 | //title=Display None 103 |
    104 | The div below this text has been hidden with the "display-none" class. 105 | 108 |
    109 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Selection/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/selection 3 | --- 4 | 5 | Use the `pui-no-select` modifier to prevent text from being selectable. This is useful to prevent accidental selection of the labels on checkboxes when clicking them. 6 | 7 | It is generally not recommended to use this modifier on its own, since preventing the selection of some text may worsen the user experience. Instead of adding the class directly, use the `noSelect` prop on the `Checkbox` or `Radio`, which will automatically add this modifier to the text next to the input. 8 | 9 | For the `noSelect` prop to take effect, you will need to import this modifier as shown below. 10 | 11 | ## Classes 12 | 13 | Modifier | Purpose 14 | ---------|-------- 15 | `pui-no-select` | Prevent selection of text within an element 16 | 17 | ```jsx harmony 18 | //title=Using the noSelect prop on a Checkbox 19 |
    20 |
    Try highlighting and clicking rapidly on the labels below.
    21 | This is an unselectable checkbox label. 22 | This is a selectable checkbox label. 23 |
    ; 24 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Typography/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/typography 3 | --- 4 | 5 | Use the typography modifiers to control text sizing, emphasis, and color. 6 | 7 | [Source Sans Pro](https://fonts.google.com/specimen/Source+Sans+Pro) is Pivotal UI's default font family. It is packaged with the typography CSS, so the import statement below includes it in your site. 8 | 9 | ## Classes 10 | 11 | In addition to the modifiers listed here, importing typography CSS gives you the `type-{color-name}` modifiers listed on the [Colors page](/colors). 12 | 13 | Modifier | Purpose 14 | ---------|-------- 15 | `em-low` | Makes font weight thin 16 | `em-default` | Makes font weight default 17 | `em-high` | Makes font weight bold 18 | `em-max` | Makes font weight extra bold 19 | `em-alt` | Makes text uppercase 20 | `h1` | Sets font size, family, and spacing to be the same as an `

    ` tag 21 | `h2` | Sets font size, family, and spacing to be the same as an `

    ` tag 22 | `h3` | Sets font size, family, and spacing to be the same as an `

    ` tag 23 | `h4` | Sets font size, family, and spacing to be the same as an `

    ` tag 24 | `h5` | Sets font size, family, and spacing to be the same as an `

    ` tag 25 | `h6` | Sets font size, family, and spacing to be the same as an `
    ` tag 26 | `type-lg` | Makes font size larger than the default 27 | `type-sm` | Makes font size smaller than the default 28 | `type-xs` | Makes font size much smaller than the default 29 | 30 | ```html 31 | //title=Default font sizes 32 |

    an h1 (32px)

    33 |

    an h2 (24px)

    34 |

    an h3 (20px)

    35 |

    an h4 (18px)

    36 |
    an h5 (16px)
    37 |
    an h6 (13px)
    38 |

    base font size (16px)

    39 | ``` 40 | 41 | ```html 42 | //title=Size modifiers 43 |

    large font size (18px)

    44 |

    base font size (16px)

    45 |

    small font size (14px)

    46 |

    extra small font size (12px)

    47 | ``` 48 | 49 | ```html 50 | //title=Emphasis modifiers 51 |

    Low emphasis

    52 |

    Default emphasis

    53 |

    High emphasis

    54 |

    Max emphasis

    55 |

    Alternate emphasis (all-caps)

    56 | ``` 57 | 58 | ```html 59 | //title=Separating code and visual semantics 60 | //description=Sometimes you may need to use a heading which has different visual and code semantics. You can accomplish this by combining classes with elements (classes take visual precedence over elements in this case). 61 |

    I am an h1!

    62 |

    I am an h2!

    63 | ``` 64 | 65 | ```html 66 | //title=Using heading classes 67 | //description=If it's not a heading but you need similar visual treatment, you can add just the class to any element. However, use headings when possible since they add semantic value. 68 |
    Heading level 2 on a div
    69 | ``` 70 | 71 | ```html 72 | //title=Multiline headings 73 | //description=Headings are spaced so their line height and padding are consistent on one or many lines. 74 |

    One line heading

    75 | 76 |

    I am a
    multiline heading

    77 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Vertical_Alignment/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/vertical-alignment 3 | --- 4 | 5 | Use the `aligner` class on a container element to help vertically align the element's children to the top, center, or bottom. Use the `aligner-item` and `aligner-item-*` classes on the children of the container element to position them within the container. 6 | 7 | The height of the `aligner` element is set to 230 pixels by default but can be customized via CSS or inline styles. 8 | 9 | ## Classes 10 | 11 | Modifier | Purpose 12 | ---------|-------- 13 | `aligner` | Makes an element into a container with vertically-aligned children 14 | `aligner-item` | Makes an element int a child of the `aligner` container (centered vertically by default) 15 | `aligner-item-top` | Aligns an item to the top of the container 16 | `aligner-item-bottom` | Aligns an item to the bottom of the container 17 | 18 | ```html 19 | //title=Default example 20 |
    21 | On Top 22 | Center 23 | Bottom 24 |
    25 | ``` 26 | 27 | ```html 28 | //title=Custom height example 29 | //description=You can override the default height with an inline style (or with CSS). 30 |
    31 | Center 32 |
    33 | ``` 34 | 35 | ```html 36 | //title=Combination example 37 | //description=You can position both vertically and horizontally by combining the `aligner` with grids, or the text-alignment classes (`txt-l`, `txt-r`, and `txt-c`). 38 |
    39 | Centered content 40 |
    41 | ``` -------------------------------------------------------------------------------- /docs/modifiers/Whitespace/1.Usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | cssPath: pivotal-ui/css/whitespace 3 | --- 4 | 5 | Use the whitespace modifiers to control the spacing around elements (margin) and within elements (padding). 6 | 7 | ## Classes 8 | 9 | Whitespace class names are composed of three parts, following this format: `{spacing-type}{direction}{size}`. The tables below list the possible values for each part. Some examples: 10 | 11 | - `mtxl`: margin-top-extra-large (add a 32-pixel margin on top) 12 | - `pan`: padding-all-none (remove padding on all sides) 13 | - `mvs`: margin-vertical-small (add 2-pixel margins on the top and bottom) 14 | 15 | Spacing type | Description 16 | -------------|------------ 17 | `p` | Padding (spacing within an element's borders) 18 | `m` | Margin (spacing outside of an element's borders) 19 | 20 | Direction | Description 21 | ----------|------------ 22 | `a` | All sides 23 | `t` | Top only 24 | `r` | Right side only 25 | `b` | Bottom only 26 | `l` | Left side only 27 | `h` | Left and right sides (horizontal) 28 | `v` | Top and bottom (vertical) 29 | 30 | Size | Description 31 | -----|------------ 32 | `n` | None (0px) 33 | `s` | Small (2px) 34 | `m` | Medium (4px) 35 | `l` | Large (8px) 36 | `xl` | Extra large (16px) 37 | `xxl` | Extra extra large (24px) 38 | `xxxl` | Extra extra extra large (32px) 39 | 40 | ```html 41 | //title=Padding modification example 42 |

    A normal paragraph

    43 |

    A paragraph with large padding

    44 | ``` -------------------------------------------------------------------------------- /frontend_webpack.config.babel.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 3 | const CompressionPlugin = require('compression-webpack-plugin'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const {NamedModulesPlugin, HotModuleReplacementPlugin} = require('webpack'); 6 | 7 | const prod = process.argv.indexOf('-p') !== -1; 8 | 9 | const htmlPlugin = new HtmlWebpackPlugin({template: 'index.html'}); 10 | 11 | const prodConfig = { 12 | mode: 'production', 13 | entry: ['@babel/polyfill', './src/index.js'], 14 | plugins: [ 15 | new NamedModulesPlugin(), 16 | new ExtractTextPlugin('app.css'), 17 | new CompressionPlugin(), 18 | htmlPlugin 19 | ] 20 | }; 21 | 22 | const devConfig = { 23 | mode: 'development', 24 | entry: ['@babel/polyfill', 'react-hot-loader/patch', './src/index.js'], 25 | devServer: { 26 | host: '0.0.0.0', 27 | hot: true, 28 | historyApiFallback: true, 29 | publicPath: '/', 30 | clientLogLevel: 'error', 31 | contentBase: path.resolve(__dirname, 'dist'), 32 | stats: { 33 | warningsFilter: /Module not found: Error: Can't resolve .*.css/ 34 | } 35 | }, 36 | plugins: [ 37 | htmlPlugin, 38 | new HotModuleReplacementPlugin() 39 | ], 40 | devtool: 'cheap-module-source-map' 41 | }; 42 | 43 | module.exports = { 44 | ...(prod ? prodConfig : devConfig), 45 | output: { 46 | path: path.resolve(__dirname, 'dist'), 47 | filename: 'bundle.js', 48 | publicPath: '/' 49 | }, 50 | resolve: { 51 | alias: { 52 | 'node_modules/pivotal-ui': path.resolve(__dirname, '../pivotal-ui/src'), 53 | 'pivotal-ui': path.resolve(__dirname, '../pivotal-ui/src') 54 | } 55 | }, 56 | module: { 57 | rules: [ 58 | { 59 | test: /\.jsx?$/, 60 | exclude: /node_modules/, 61 | loader: require.resolve('babel-loader'), 62 | options: { 63 | // This is necessary to make sure babel-loader knows 64 | // to load the .babelrc both here and in ../pivotal-ui. 65 | // see: https://babeljs.io/docs/en/options#babelrcroots 66 | babelrcRoots: ['.', '../pivotal-ui'] 67 | } 68 | }, 69 | { 70 | test: /\.(eot|ttf|woff)$/, 71 | use: 'url-loader' 72 | }, 73 | { 74 | test: /\.md$/, 75 | use: ['json-loader', './src/helpers/markdown_loader.js'] 76 | }, 77 | { 78 | test: /\.s?css$/, 79 | use: prod 80 | ? ExtractTextPlugin.extract({ 81 | fallback: 'style-loader', 82 | use: ['css-loader', 'sass-loader'] 83 | }) 84 | : ['style-loader', 'css-loader', 'sass-loader'] 85 | }, 86 | { 87 | test: /\.(jpe?g|png|gif|svg)$/i, 88 | use: ['file-loader', 'image-webpack-loader'] 89 | } 90 | ] 91 | }, 92 | node: { 93 | fs: 'empty' // so that babel doesn't blow up with weird error messages occasionally 94 | } 95 | }; -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Pivotal UI Styleguide 4 | 5 | 6 | 7 | 8 |
    9 | 10 | -------------------------------------------------------------------------------- /manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | applications: 3 | - name: styleguide-master 4 | buildpack: staticfile_buildpack 5 | path: dist 6 | memory: 64MB -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pivotal-ui-styleguide", 3 | "license": "ISC", 4 | "version": "0.0.0", 5 | "description": "Pivotal UI Styleguide", 6 | "repository": "https://github.com/pivotal-cf/pui-styleguide", 7 | "main": "dist/bundle.js", 8 | "devDependencies": { 9 | "@babel/core": "^7.0.0", 10 | "@babel/plugin-proposal-class-properties": "^7.0.0", 11 | "@babel/plugin-proposal-function-bind": "^7.0.0", 12 | "@babel/preset-env": "^7.0.0", 13 | "@babel/preset-react": "^7.0.0", 14 | "@babel/register": "^7.0.0", 15 | "babel-core": "^7.0.0-bridge.0", 16 | "babel-eslint": "^10.0.1", 17 | "babel-jest": "^23.6.0", 18 | "babel-loader": "^8.0.0", 19 | "compression-webpack-plugin": "^2.0.0", 20 | "css-loader": "^2.1.0", 21 | "enzyme": "^3.8.0", 22 | "enzyme-adapter-react-15": "^1.2.0", 23 | "eslint": "^5.12.0", 24 | "eslint-plugin-jest": "^22.1.3", 25 | "eslint-plugin-markdown": "^1.0.0", 26 | "eslint-plugin-react": "^7.12.3", 27 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 28 | "file-loader": "^3.0.1", 29 | "html-entities": "^1.2.0", 30 | "html-loader": "^0.5.5", 31 | "html-webpack-plugin": "^3.2.0", 32 | "image-webpack-loader": "^4.6.0", 33 | "jest": "^23.6.0", 34 | "jquery": "^3.2.1", 35 | "json-loader": "^0.5.7", 36 | "mock-promises": "^0.8.2", 37 | "node-sass": "^4.11.0", 38 | "path": "^0.12.7", 39 | "pretty": "^2.0.0", 40 | "react-hot-loader": "^4.6.3", 41 | "react-test-renderer": "^15.5.0", 42 | "remark-frontmatter": "^1.2.0", 43 | "remark-parse-yaml": "^0.0.1", 44 | "sass-loader": "^7.1.0", 45 | "style-loader": "^0.23.1", 46 | "url-loader": "^1.1.2", 47 | "webpack": "^4.28.4", 48 | "webpack-cli": "^3.2.1", 49 | "webpack-dev-server": "^3.1.14", 50 | "webpack-uglify-js-plugin": "^1.1.9" 51 | }, 52 | "dependencies": { 53 | "@babel/polyfill": "^7.0.0", 54 | "@babel/standalone": "^7.0.0", 55 | "classnames": "^2.2.5", 56 | "prismjs": "^1.11.0", 57 | "prop-types": "^15.6.1", 58 | "react": "^15.0.0", 59 | "react-ace": "^6.3.2", 60 | "react-dom": "^15.0.0", 61 | "react-router-dom": "^4.3.1", 62 | "remark-parse": "^5.0.0", 63 | "remark-react": "^4.0.3", 64 | "unified": "^7.1.0" 65 | }, 66 | "scripts": { 67 | "copy-files": "mkdir -p dist && cp public/* dist/ && cp -R static dist/", 68 | "start": "npm run copy-files && webpack-dev-server --config ./frontend_webpack.config.babel.js", 69 | "build": "webpack --config ./frontend_webpack.config.babel.js -p && npm run copy-files", 70 | "build-dev": "webpack --config ./frontend_webpack.config.babel.js && npm run copy-files", 71 | "test": "jest", 72 | "lint": "eslint src docs spec --ext .js,.md --fix" 73 | }, 74 | "jest": { 75 | "moduleNameMapper": { 76 | "^pivotal-ui/react/iconography/icons$": "/../pivotal-ui/src/iconography/icons.js", 77 | "^pivotal-ui/(.*)": "/../pivotal-ui/src/$1", 78 | "\\.(css|scss)$": "/spec/support/style_mock.js" 79 | }, 80 | "setupTestFrameworkScriptFile": "/spec/spec_helper.js", 81 | "testRegex": ".*_spec\\.js$" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /public/nginx.conf: -------------------------------------------------------------------------------- 1 | # inspired by https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf 2 | 3 | worker_processes 1; 4 | daemon off; 5 | 6 | error_log <%= ENV["APP_ROOT"] %>/nginx/logs/error.log; 7 | events { worker_connections 1024; } 8 | 9 | http { 10 | charset utf-8; 11 | log_format cloudfoundry '$http_x_forwarded_for - $http_referer - [$time_local] "$request" $status $body_bytes_sent'; 12 | access_log <%= ENV["APP_ROOT"] %>/nginx/logs/access.log cloudfoundry; 13 | default_type application/octet-stream; 14 | include mime.types; 15 | 16 | sendfile on; 17 | 18 | gzip on; 19 | gzip_disable "msie6"; 20 | gzip_comp_level 6; 21 | gzip_min_length 1100; 22 | gzip_buffers 16 8k; 23 | gzip_proxied any; 24 | gzip_types text/plain text/css text/js text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss; 25 | 26 | tcp_nopush on; 27 | keepalive_timeout 30; 28 | port_in_redirect off; # Ensure that redirects don't include the internal container PORT - <%= ENV["PORT"] %> 29 | server_tokens off; 30 | 31 | server { 32 | listen <%= ENV["PORT"] %>; 33 | root <%= ENV["APP_ROOT"] %>/public; 34 | server_name localhost; 35 | large_client_header_buffers 4 16k; 36 | proxy_ssl_server_name on; 37 | 38 | location ~ /static/(.*) { 39 | try_files $uri /static/$1; 40 | } 41 | 42 | location / { 43 | try_files $uri /index.html; 44 | if ($http_x_forwarded_proto != "https") { 45 | return 301 https://$host$request_uri; 46 | } 47 | index index.html; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | Sitemap: https://styleguide.pivotal.io/sitemap.txt 2 | Disallow: /static/versions -------------------------------------------------------------------------------- /public/sitemap.txt: -------------------------------------------------------------------------------- 1 | https://styleguide.pivotal.io/ 2 | https://styleguide.pivotal.io/getstarted 3 | https://styleguide.pivotal.io/faq 4 | https://styleguide.pivotal.io/upgradeguide 5 | https://styleguide.pivotal.io/versions 6 | https://styleguide.pivotal.io/contribute 7 | https://styleguide.pivotal.io/404 8 | https://styleguide.pivotal.io/alerts 9 | https://styleguide.pivotal.io/alignment 10 | https://styleguide.pivotal.io/autocomplete 11 | https://styleguide.pivotal.io/backtotop 12 | https://styleguide.pivotal.io/border 13 | https://styleguide.pivotal.io/box_shadows 14 | https://styleguide.pivotal.io/button_group 15 | https://styleguide.pivotal.io/buttons 16 | https://styleguide.pivotal.io/code 17 | https://styleguide.pivotal.io/collapse 18 | https://styleguide.pivotal.io/colors 19 | https://styleguide.pivotal.io/copy_to_clipboard 20 | https://styleguide.pivotal.io/dividers 21 | https://styleguide.pivotal.io/dropdowns 22 | https://styleguide.pivotal.io/ellipsis 23 | https://styleguide.pivotal.io/expander 24 | https://styleguide.pivotal.io/forms 25 | https://styleguide.pivotal.io/flyout 26 | https://styleguide.pivotal.io/grids 27 | https://styleguide.pivotal.io/icons 28 | https://styleguide.pivotal.io/images 29 | https://styleguide.pivotal.io/links 30 | https://styleguide.pivotal.io/lists 31 | https://styleguide.pivotal.io/media 32 | https://styleguide.pivotal.io/modals 33 | https://styleguide.pivotal.io/notifications 34 | https://styleguide.pivotal.io/pagination 35 | https://styleguide.pivotal.io/panels 36 | https://styleguide.pivotal.io/portals 37 | https://styleguide.pivotal.io/progress_bars 38 | https://styleguide.pivotal.io/select 39 | https://styleguide.pivotal.io/svg 40 | https://styleguide.pivotal.io/tables 41 | https://styleguide.pivotal.io/tabs 42 | https://styleguide.pivotal.io/tile_layout 43 | https://styleguide.pivotal.io/tooltips 44 | https://styleguide.pivotal.io/typography 45 | https://styleguide.pivotal.io/vertical_alignment 46 | https://styleguide.pivotal.io/whitespace 47 | https://styleguide.pivotal.io/wizard -------------------------------------------------------------------------------- /push.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash -e 2 | 3 | yarn 4 | echo "git pulling with rebase" 5 | git pull -r 6 | yarn lint 7 | yarn test 8 | git status 9 | printf 'push commit(s)? [y/N]: ' 10 | read input 11 | if [[ "$input" == "y" || "$input" == "Y" ]]; then 12 | git push 13 | else 14 | echo "commit(s) not pushed" 15 | fi 16 | -------------------------------------------------------------------------------- /spec/components/editor_spec.js: -------------------------------------------------------------------------------- 1 | import AceEditor from 'react-ace'; 2 | import Editor from '../../src/components/editor'; 3 | 4 | describe('Editor', () => { 5 | let code, changeHandler, mode, readOnly; 6 | 7 | beforeEach(() => { 8 | spyOnRender(AceEditor,
    ); 9 | code = 'i++'; 10 | mode = 'js'; 11 | readOnly = true; 12 | changeHandler = jest.fn(); 13 | testRender(); 14 | }); 15 | 16 | it('renders the editor inside a div', () => { 17 | expect('div.pal.border-top > .mock-editor').toExist(); 18 | }); 19 | 20 | it('renders the AceEditor with the correct props', () => { 21 | expect(AceEditor).toHaveBeenRenderedWithProps(expect.objectContaining({ 22 | editorProps: {$blockScrolling: Infinity}, 23 | height: '200px', 24 | mode, 25 | onChange: changeHandler, 26 | readOnly, 27 | setOptions: { 28 | showGutter: false, 29 | showPrintMargin: false, 30 | highlightActiveLine: false, 31 | maxLines: 15 32 | }, 33 | theme: 'clouds', 34 | value: code, 35 | width: '100%' 36 | })); 37 | }); 38 | }); -------------------------------------------------------------------------------- /spec/components/error_boundary_spec.js: -------------------------------------------------------------------------------- 1 | import ErrorBoundary from '../../src/components/error_boundary'; 2 | 3 | describe('ErrorBoundary', () => { 4 | let subject, error, info; 5 | 6 | beforeEach(() => { 7 | error = new Error('some error'); 8 | info = {ComponentStack: 'here'}; 9 | subject = testRender(
    hello
    ); 10 | }); 11 | 12 | describe('when an error was caught', () => { 13 | beforeEach(() => { 14 | subject.setState({hasError: true, error, info}); 15 | }); 16 | 17 | it('renders an error pre tag', () => { 18 | expect('pre').toHaveText('some error'); 19 | }); 20 | }); 21 | 22 | describe('when no error was caught', () => { 23 | it('renders the children', () => { 24 | expect('.hello').toHaveText('hello'); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /spec/components/page_spec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Page from '../../src/components/page'; 3 | import {testRender} from '../support/matchers/jest_react'; 4 | import MarkdownFileHelper from '../../src/helpers/markdown_file_helper'; 5 | 6 | describe('Page', () => { 7 | let match, routes; 8 | 9 | beforeEach(() => { 10 | match = { 11 | path: '/my-component' 12 | }; 13 | 14 | routes = { 15 | '/my-component': { 16 | file: '/my-component.md', 17 | metadata: { 18 | } 19 | } 20 | }; 21 | 22 | jest.spyOn(MarkdownFileHelper, 'getParentTitle').mockImplementation(() => 'Test Title'); 23 | 24 | testRender(); 25 | }); 26 | 27 | it('renders a page', () => { 28 | expect('.styleguide-page').toExist(); 29 | }); 30 | 31 | it('places the correct title', () => { 32 | expect('.styleguide-page h1.em-high').toHaveText('Test Title'); 33 | }); 34 | 35 | it('no deprecation alert if not deprecated', () => { 36 | expect('.alert.pui-alert.alert-warning.pui-alert-warning').not.toExist(); 37 | }); 38 | 39 | describe('Component is deprecated and no deprecation message is given', () => { 40 | beforeEach(() => { 41 | routes['/my-component'].metadata.deprecationMessage = true; 42 | 43 | testRender(); 44 | }); 45 | 46 | it('renders a warning alert', () => { 47 | expect('.alert.pui-alert.alert-warning.pui-alert-warning').toExist(); 48 | }); 49 | it('renders the default deprecation message', () => { 50 | expect('.alert.pui-alert.alert-warning.pui-alert-warning').toContainText('This component has been deprecated and will be removed in the next major version of Pivotal UI. Reach out to the Pivotal UI team if you have any questions.'); 51 | }); 52 | }); 53 | 54 | describe('Component is deprecated and deprecation message is given', () => { 55 | beforeEach(() => { 56 | routes['/my-component'].metadata.deprecationMessage = 'custom deprecation message'; 57 | 58 | testRender(); 59 | }); 60 | 61 | it('renders a warning alert', () => { 62 | expect('.alert.pui-alert.alert-warning.pui-alert-warning').toExist(); 63 | }); 64 | 65 | it('renders the custom deprecation message', () => { 66 | expect('.alert.pui-alert.alert-warning.pui-alert-warning').toContainText('custom deprecation message'); 67 | }); 68 | }); 69 | }); -------------------------------------------------------------------------------- /spec/components/renderers/heading_renderer_spec.js: -------------------------------------------------------------------------------- 1 | import HeadingRenderer from '../../../src/components/renderers/heading_renderer'; 2 | import {testRender} from '../../support/matchers/jest_react'; 3 | 4 | describe('HeadingRenderer', () => { 5 | let Heading, subject; 6 | 7 | beforeEach(() => { 8 | Heading = HeadingRenderer(6); 9 | subject = testRender(); 13 | }); 14 | 15 | it('renders a heading with correct class names', () => { 16 | expect('h6.test-heading').toHaveClass(['md-heading', 'em-high', 'mvxl']); 17 | }); 18 | 19 | it('renders heading with text', () => { 20 | expect('h6.test-heading').toHaveText('I am a heading!'); 21 | }); 22 | 23 | it('gives heading an id based on its text', () => { 24 | expect('h6.test-heading').toHaveAttr('id', 'i-am-a-heading'); 25 | }); 26 | 27 | describe('without children', () => { 28 | beforeEach(() => { 29 | subject.setProps({children: undefined}); 30 | }); 31 | 32 | it('renders an empty heading', () => { 33 | expect('h6.test-heading').toHaveText(''); 34 | }); 35 | }); 36 | }); -------------------------------------------------------------------------------- /spec/components/renderers/image_renderer_spec.js: -------------------------------------------------------------------------------- 1 | import ImageRenderer from '../../../src/components/renderers/image_renderer'; 2 | import {testRender} from '../../support/matchers/jest_react'; 3 | 4 | describe('ImageRenderer', () => { 5 | beforeEach(() => { 6 | testRender(); 11 | }); 12 | 13 | it('renders an image', () => { 14 | expect('img.md-image').toHaveClass('test-img-class'); 15 | expect('img.md-image').toHaveAttr('id', 'test-img-id'); 16 | expect('img.md-image').toHaveAttr('title', 'Test title'); 17 | }); 18 | }); -------------------------------------------------------------------------------- /spec/components/renderers/link_renderer_spec.js: -------------------------------------------------------------------------------- 1 | import LinkRenderer from '../../../src/components/renderers/link_renderer'; 2 | import {Link} from 'react-router-dom'; 3 | import {BrowserRouter as Router} from 'react-router-dom'; 4 | import {testRender} from '../../support/matchers/jest_react'; 5 | 6 | describe('LinkRenderer', () => { 7 | let href, children; 8 | 9 | beforeEach(() => { 10 | spyOnRender(Link); 11 | }); 12 | 13 | describe('when the href is external', () => { 14 | beforeEach(() => { 15 | href = 'http://www.some_website.com'; 16 | children = ['external link']; 17 | testRender(); 18 | }); 19 | 20 | it('renders an tag', () => { 21 | expect('a').toHaveAttr('href', 'http://www.some_website.com'); 22 | expect('a').toHaveText('external link'); 23 | }); 24 | }); 25 | 26 | describe('when the href starts with /static/', () => { 27 | beforeEach(() => { 28 | href = '/static/versions/v205'; 29 | children = ['Version 205']; 30 | testRender(); 31 | }); 32 | 33 | it('renders an tag', () => { 34 | expect('a').toHaveAttr('href', '/static/versions/v205'); 35 | expect('a').toHaveText('Version 205'); 36 | }); 37 | }); 38 | 39 | describe('when the href is internal to the styleguide', () => { 40 | beforeEach(() => { 41 | href = '/some/page/on/this/domain'; 42 | children = ['name of page']; 43 | testRender(); 44 | }); 45 | 46 | it('renders a react router Link', () => { 47 | expect(Link).toHaveBeenRenderedWithProps({to: href, replace: false, children: 'name of page'}); 48 | }); 49 | }); 50 | }); -------------------------------------------------------------------------------- /spec/components/renderers/table_renderer_spec.js: -------------------------------------------------------------------------------- 1 | import TableRenderer from '../../../src/components/renderers/table_renderer'; 2 | import {testRender} from '../../support/matchers/jest_react'; 3 | 4 | describe('TableRenderer', () => { 5 | beforeEach(() => { 6 | testRender( 11 | 12 | col1 13 | col2 14 | 15 | , 16 | 17 | 18 | A 19 | B 20 | 21 | 22 | C 23 | D 24 | 25 | 26 | ] 27 | }}/>); 28 | }); 29 | 30 | it('renders a table', () => { 31 | expect('table.md-table').toHaveClass('test-table-class'); 32 | expect('table.md-table').toHaveAttr('id', 'test-table-id'); 33 | }); 34 | 35 | it('gives correct class names to thead rows', () => { 36 | expect('table.md-table thead tr').toHaveClass(['tr-no-h-borders', 'bg-white']); 37 | }); 38 | 39 | it('gives correct class names to tbody rows', () => { 40 | expect('table.md-table tbody tr').toHaveLength(2); 41 | expect('table.md-table tbody tr:eq(0)').toHaveClass('tr-no-h-borders'); 42 | expect('table.md-table tbody tr:eq(1)').toHaveClass('tr-no-h-borders'); 43 | }); 44 | }); -------------------------------------------------------------------------------- /spec/spec_helper.js: -------------------------------------------------------------------------------- 1 | import './support/matchers/jest_dom'; 2 | import jQuery from 'jquery'; 3 | import React from 'react'; 4 | import {testRender, testReset} from './support/matchers/jest_react'; 5 | 6 | function spyOnRender(componentClass, returnValue = null) { 7 | return jest.spyOn(componentClass.prototype, 'render').mockReturnValue(returnValue); 8 | } 9 | 10 | const globals = { 11 | $: jQuery, 12 | React, 13 | testRender, 14 | spyOnRender 15 | }; 16 | 17 | Object.assign(global, globals); 18 | 19 | afterEach(() => { 20 | testReset(); 21 | jest.clearAllMocks(); 22 | }); 23 | 24 | afterAll(() => { 25 | Object.keys(globals).forEach(key => delete global[key]); 26 | }); -------------------------------------------------------------------------------- /spec/support/matchers/common.js: -------------------------------------------------------------------------------- 1 | export function matcherResult({matcher, pass, notMessage, message}) { 2 | return { 3 | pass, 4 | message: pass 5 | ? () => `${this.utils.matcherHint('.not.' + matcher)}\n\n${notMessage}` 6 | : () => `${this.utils.matcherHint('.' + matcher)}\n\n${message}` 7 | }; 8 | } -------------------------------------------------------------------------------- /spec/support/matchers/jest_react.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {configure as configureEnzyme, mount} from 'enzyme'; 3 | import Adapter from 'enzyme-adapter-react-15'; 4 | configureEnzyme({adapter: new Adapter()}); 5 | import {matcherResult} from './common'; 6 | import jestDiff from 'jest-diff'; 7 | 8 | const root = document.createElement('div'); 9 | document.body.appendChild(root); 10 | 11 | let lastRendered; 12 | const testRender = element => { 13 | lastRendered = mount(element, {attachTo: root}); 14 | // eslint-disable-next-line no-console 15 | lastRendered.print = () => console.log(lastRendered.debug()); 16 | return lastRendered; 17 | }; 18 | 19 | const testReset = () => { 20 | lastRendered && lastRendered.unmount(); 21 | lastRendered = undefined; 22 | }; 23 | 24 | const getComponent = element => { 25 | if (typeof element === 'object') return element; 26 | if (!lastRendered) throw new Error('No last rendered component found. ' 27 | + 'Did you forget to render with `testRender`?'); 28 | return lastRendered.find(element); 29 | }; 30 | 31 | expect.extend({ 32 | toHaveBeenRendered(component) { 33 | const wrapper = getComponent(component); 34 | const pass = wrapper.exists(); 35 | 36 | const message = pass 37 | ? () => this.utils.matcherHint('.not.toHaveBeenRendered') + '\n\n' 38 | + 'Expected component not to have been rendered, but it was.' 39 | : () => this.utils.matcherHint('.toHaveBeenRendered') + '\n\n' 40 | + 'Expected component to have been rendered, but it was not.'; 41 | 42 | return {pass, message}; 43 | }, 44 | 45 | toHaveBeenRenderedWithProps(component, expectedProps) { 46 | const wrapper = getComponent(component); 47 | const actualProps = wrapper.length > 1 ? wrapper.map(w => w.props()) : [wrapper.props()]; 48 | const pass = actualProps.some(actual => this.equals(expectedProps, actual)); 49 | const diff = actualProps.map(actual => jestDiff(expectedProps, actual)).join('\n\n'); 50 | 51 | return matcherResult.call(this, { 52 | matcher: 'toHaveBeenRenderedWithProps', 53 | pass, 54 | notMessage: 'Expected component not to have been rendered with given props:\n\n' 55 | + `${diff}`, 56 | message: 'Expected component to have been rendered with given props' 57 | + `${actualProps.length > 1 ? ' at least once': ''}:\n\n` 58 | + `${diff}` 59 | }); 60 | } 61 | }); 62 | 63 | export {testRender, testReset}; -------------------------------------------------------------------------------- /spec/support/react_helper.js: -------------------------------------------------------------------------------- 1 | import TestUtils from 'react-dom/test-utils'; 2 | import jQuery from 'jquery'; 3 | 4 | TestUtils.Simulate.check = function(node) { 5 | TestUtils.Simulate.change(node, {target: {checked: true}}); 6 | }; 7 | 8 | TestUtils.Simulate.uncheck = function(node) { 9 | TestUtils.Simulate.change(node, {target: {checked: false}}); 10 | }; 11 | 12 | (function($) { 13 | $.fn.simulate = function(eventName, ...args) { 14 | if (!this.length) { 15 | throw new Error(`jQuery Simulate has an empty selection for '${this.selector}'`); 16 | } 17 | $.each(this, function() { 18 | if (['mouseOver', 'mouseOut'].includes(eventName)) { 19 | TestUtils.SimulateNative[eventName](this, ...args); 20 | } else { 21 | TestUtils.Simulate[eventName](this, ...args); 22 | } 23 | }); 24 | return this; 25 | }; 26 | })(jQuery); -------------------------------------------------------------------------------- /spec/support/style_mock.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import Sidebar from './components/sidebar'; 3 | import {Route, Switch, Redirect} from 'react-router-dom'; 4 | import Page from './components/page'; 5 | import '../stylesheets/app.scss'; 6 | import {getRoutes} from './helpers/routes_helper'; 7 | import processor from './helpers/markdown_processor'; 8 | 9 | const requirePuiCss = require.context('pivotal-ui/css/', true, /\.scss$/); 10 | requirePuiCss.keys().map(requirePuiCss); 11 | 12 | const requirePuiReact = require.context('pivotal-ui/react/', true, /index\.js$/); 13 | requirePuiReact.keys().map(file => Object.entries(requirePuiReact(file)) 14 | .forEach(([key, value]) => window[key] = value)); 15 | 16 | const routes = getRoutes({processor, requireFunc: require.context('../docs', true, /\.md$/)}); 17 | 18 | window.Icons = require('pivotal-ui/react/iconography/icons'); 19 | window.colorPalette = [ 20 | ['black', 'dark-gray', 'gray', 'accent-gray', 'light-gray', 'white'], 21 | ['teal', 'accent-teal', 'light-teal'], 22 | ['dark-blue', 'blue', 'accent-blue', 'light-blue'], 23 | ['dark-red', 'red', 'light-red'], 24 | ['green', 'accent-green', 'light-green'], 25 | ['decorative-yellow', 'light-yellow'] 26 | ]; 27 | 28 | const ScrollToTop = () => { 29 | window.scrollTo(0, 0); 30 | return null; 31 | }; 32 | 33 | export default class App extends Component { 34 | render() { 35 | const {location} = this.props; 36 | const currentDate = new Date(); 37 | const year = currentDate.getFullYear(); 38 | 39 | return ( 40 | 64 | ); 65 | } 66 | } -------------------------------------------------------------------------------- /src/components/editor.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import AceEditor from 'react-ace'; 3 | import PropTypes from 'prop-types'; 4 | import 'brace/mode/jsx'; 5 | import 'brace/mode/html'; 6 | import 'brace/theme/clouds'; 7 | 8 | export default class Editor extends PureComponent { 9 | static propTypes = { 10 | code: PropTypes.string, 11 | changeHandler: PropTypes.func, 12 | mode: PropTypes.string, 13 | readOnly: PropTypes.bool 14 | }; 15 | 16 | render() { 17 | const {code, mode, readOnly, changeHandler} = this.props; 18 | 19 | return ( 20 |
    21 | 37 |
    38 | ); 39 | } 40 | } -------------------------------------------------------------------------------- /src/components/error_boundary.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | export default class ErrorBoundary extends Component { 4 | state = {hasError: false}; 5 | 6 | componentWillReceiveProps() { 7 | this.setState({hasError: false}); 8 | } 9 | 10 | componentDidCatch(error, info) { 11 | this.setState({hasError: true, error, info}); 12 | } 13 | 14 | render() { 15 | const {hasError, error} = this.state; 16 | if (hasError) return
    {error.message}
    ; 17 | return this.props.children; 18 | } 19 | } -------------------------------------------------------------------------------- /src/components/import_preview.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classnames from 'classnames'; 4 | 5 | export default class ImportPreview extends PureComponent { 6 | static propTypes = { 7 | cssPath: PropTypes.string, 8 | reactPath: PropTypes.string, 9 | reactComponents: PropTypes.array 10 | }; 11 | 12 | static defaultProps = { 13 | reactComponents: [] 14 | }; 15 | 16 | render() { 17 | const {cssPath, reactPath, reactComponents} = this.props; 18 | if (!cssPath && !reactPath) return null; 19 | 20 | const reactImport = reactPath && `import {${reactComponents.join(', ')}} from '${reactPath}';`; 21 | const cssImport = cssPath && `import '${cssPath}';`; 22 | const multipleComponents = reactComponents.length > 1; 23 | 24 | const preview = (label, code, className) => ( 25 |
    26 |
    {label}
    27 |
    {code}
    28 |
    29 | ); 30 | 31 | return ( 32 |
    33 | {reactPath && preview(`Import React component${multipleComponents ? 's' : ''}`, reactImport)} 34 | {cssPath && preview(`Import CSS${reactPath ? ' only' : ''}`, cssImport, {'mtxl': reactPath})} 35 |
    36 | ); 37 | } 38 | } -------------------------------------------------------------------------------- /src/components/renderers/heading_renderer.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classnames from 'classnames'; 4 | 5 | const kebabCase = text => text 6 | .replace(/[^A-Za-z0-9 ]/g, '') 7 | .replace(/([a-z])([A-Z])/g, '$1-$2') 8 | .replace(/\s+/g, '-').toLowerCase(); 9 | 10 | export default level => class extends PureComponent { 11 | static propTypes = { 12 | children: PropTypes.array, 13 | className: PropTypes.string, 14 | level: PropTypes.oneOf([1, 2, 3, 4, 5, 6]) 15 | }; 16 | 17 | static defaultProps = { 18 | children: [] 19 | }; 20 | 21 | render() { 22 | const Heading = `h${level}`; 23 | const {children: [text = ''], className} = this.props; 24 | const id = kebabCase(text.toLowerCase()); 25 | 26 | return ( 27 | 31 | ); 32 | } 33 | }; -------------------------------------------------------------------------------- /src/components/renderers/image_renderer.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | export default class extends PureComponent { 5 | render() { 6 | const {className, ...props} = this.props; 7 | return ; 8 | } 9 | }; -------------------------------------------------------------------------------- /src/components/renderers/link_renderer.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import {Link} from 'react-router-dom'; 3 | import PropTypes from 'prop-types'; 4 | 5 | export default class LinkRenderer extends PureComponent { 6 | static propTypes = { 7 | href: PropTypes.string.isRequired, 8 | children: PropTypes.array.isRequired 9 | }; 10 | 11 | render() { 12 | const {href, children = []} = this.props; 13 | if (/^https?:\/\//.test(href) || href.startsWith('/static/')) return {children[0]}; 14 | return {children[0]}; 15 | } 16 | } -------------------------------------------------------------------------------- /src/components/renderers/pre_renderer.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import classnames from 'classnames'; 3 | import CodeExample from '../code_example'; 4 | 5 | const customRenderLanguages = ['language-js', 'language-jsx', 'language-html']; 6 | 7 | export default class PreRenderer extends PureComponent { 8 | render() { 9 | const {className = '', children} = this.props.children[0].props; 10 | const matches = className.match(/language-js|language-jsx|language-html/) || []; 11 | const lang = matches[0]; 12 | 13 | if (customRenderLanguages.indexOf(lang) !== -1) { 14 | const rawContent = children[0]; 15 | const lines = rawContent.split('\n'); 16 | let title = ''; 17 | let description = ''; 18 | let noToolbar = false; 19 | let nonInteractive = false; 20 | 21 | if (lines[0].indexOf('//title=') === 0) { 22 | title = lines[0].replace('//title=', ''); 23 | lines.splice(0, 1); 24 | } 25 | 26 | if (lines[0].indexOf('//description=') === 0) { 27 | description = lines[0].replace('//description=', ''); 28 | lines.splice(0, 1); 29 | } 30 | 31 | if (lines[0].indexOf('//noToolbar') === 0) { 32 | noToolbar = true; 33 | lines.splice(0, 1); 34 | } 35 | 36 | if (lines[0].indexOf('//nonInteractive') === 0) { 37 | nonInteractive = true; 38 | lines.splice(0, 1); 39 | } 40 | 41 | const code = lines.join('\n').trim(); 42 | 43 | if (!nonInteractive) return ; 44 | 45 | return ( 46 |
    47 |           {{lines.join('\n').trim()}}
    48 |         
    49 | ); 50 | } 51 | 52 | return ( 53 |
    54 |         {React.Children.map(this.props.children, (child, key) => React.cloneElement(child, {key}))}
    55 |       
    56 | ); 57 | } 58 | }; -------------------------------------------------------------------------------- /src/components/renderers/table_renderer.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | export default class TableRenderer extends PureComponent { 5 | render() { 6 | const {className, ...props} = this.props; 7 | const thead = this.props.children.find(child => child.type === 'thead'); 8 | const tbody = this.props.children.find(child => child.type === 'tbody'); 9 | 10 | return ( 11 | 12 | 13 | {React.Children.map(thead.props.children, child => { 14 | return React.cloneElement(child, {className: 'tr-no-h-borders bg-white'}); 15 | })} 16 | 17 | 18 | {React.Children.map(tbody.props.children, child => { 19 | return React.cloneElement(child, {className: 'tr-no-h-borders'}); 20 | })} 21 | 22 |
    23 | ); 24 | } 25 | } -------------------------------------------------------------------------------- /src/components/search_bar.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import {Autocomplete, AutocompleteInput} from 'pivotal-ui/react/autocomplete'; 3 | import {Input} from 'pivotal-ui/react/inputs'; 4 | import SearchResult from './search_result'; 5 | import {withRouter} from 'react-router-dom'; 6 | 7 | let searchItems; 8 | 9 | class SearchBar extends PureComponent { 10 | constructor(props) { 11 | super(props); 12 | searchItems = Object.values(props.routes).filter(({route}) => route !== '/' && route !== '/404'); 13 | } 14 | 15 | onPick = route => { 16 | this.props.history.push(route.route); 17 | this.el && this.el.setState({value: ''}); 18 | }; 19 | 20 | onSearch = (input, callback) => { 21 | const searchText = input.toLowerCase(); 22 | const titleMatches = []; 23 | const subtitleMatches = []; 24 | 25 | searchItems.forEach(({parentTitle: title, pageTitle: subtitle, category, route, text}) => { 26 | if (titleMatches.length + subtitleMatches.length > 50) return; 27 | const matchLength = searchText.length; 28 | const resultProps = {title, subtitle, text, category, matchLength}; 29 | 30 | if (title) { 31 | const matchIndex = title.toLowerCase().indexOf(searchText); 32 | if (matchIndex > -1) return titleMatches.push({ 33 | route, value: 34 | }); 35 | } 36 | 37 | if (subtitle) { 38 | const matchIndex = subtitle.toLowerCase().indexOf(searchText); 39 | if (matchIndex > -1) return subtitleMatches.push({ 40 | route, value: 41 | }); 42 | } 43 | 44 | if (text) { 45 | const matchIndex = text.toLowerCase().indexOf(searchText); 46 | if (matchIndex > -1) return subtitleMatches.push({ 47 | route, value: 48 | }); 49 | } 50 | }); 51 | 52 | callback([...titleMatches, ...subtitleMatches]); 53 | }; 54 | 55 | render() { 56 | return ( 57 |
    58 | this.el = el, 60 | onInitializeItems: callback => callback(searchItems), 61 | placeholder: 'Search', 62 | input: , 63 | onPick: this.onPick, 64 | onSearch: this.onSearch 65 | }}/> 66 |
    67 | ); 68 | } 69 | } 70 | 71 | export default withRouter(SearchBar); -------------------------------------------------------------------------------- /src/components/search_result.js: -------------------------------------------------------------------------------- 1 | import React, {PureComponent} from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const underlineMatch = (text, matchIndex, matchLength, truncate) => { 5 | const beforeMatch = truncate ? '...' + text.substring(matchIndex - 10, matchIndex) : text.substring(0, matchIndex); 6 | const match = text.substr(matchIndex, matchLength); 7 | const afterMatch = text.substr(matchIndex + matchLength); 8 | return {beforeMatch}{match}{afterMatch}; 9 | }; 10 | 11 | const underlineTextMatch = (text, matchIndex, matchLength) => { 12 | const startIndex = Math.max(0, matchIndex - 4); 13 | const beforeMatch = (startIndex > 0 ? '...' : '') + text.substring(startIndex, matchIndex); 14 | const match = text.substr(matchIndex, matchLength); 15 | const afterMatch = text.substr(matchIndex + matchLength); 16 | return {beforeMatch}{match}{afterMatch}; 17 | }; 18 | 19 | export default class SearchResult extends PureComponent { 20 | static propTypes = { 21 | title: PropTypes.string, 22 | subtitle: PropTypes.string, 23 | text: PropTypes.string, 24 | category: PropTypes.string, 25 | matchIndex: PropTypes.number, 26 | matchLength: PropTypes.number, 27 | matched: PropTypes.oneOf(['title', 'subtitle', 'text']) 28 | }; 29 | 30 | render() { 31 | const {title, subtitle, text, category, matchIndex, matchLength, matched} = this.props; 32 | const renderedTitle = matched === 'title' ? underlineMatch(title, matchIndex, matchLength) : title; 33 | const renderedSubtitle = matched === 'subtitle' ? underlineMatch(subtitle, matchIndex, matchLength) : subtitle; 34 | const renderedText = matched === 'text' ? underlineTextMatch(text, matchIndex, matchLength) : null; 35 | 36 | return ( 37 |
    38 |
    {category}
    39 |
    40 | {renderedTitle}{subtitle && {'>'}}{renderedSubtitle} 41 |
    42 | {renderedText} 43 |
    44 | ); 45 | } 46 | }; -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | import {version as puiVersion, homepage as puiRepository} from '../../pivotal-ui/package.json'; 2 | import {repository} from '../package.json'; 3 | 4 | const config = { 5 | puiVersion, 6 | puiRepository: puiRepository || 'https://github.com/pivotal-cf/pivotal-ui', 7 | repository: repository || 'https://github.com/pivotal-cf/pui-styleguide' 8 | }; 9 | 10 | const get = key => config[key]; 11 | 12 | export default {get}; -------------------------------------------------------------------------------- /src/helpers/markdown_file_helper.js: -------------------------------------------------------------------------------- 1 | export default { 2 | process: ({processor, json}) => processor.stringify(processor.runSync(json)), 3 | 4 | getRoute: fileName => { 5 | const pathElements = fileName.replace(/^\./, '').replace(/\.md$/i, '').split('/'); 6 | const mappedElemenets = pathElements.map(path => path.replace(/^-?\d+\./, '')); 7 | return mappedElemenets.join('/').toLowerCase(); 8 | }, 9 | 10 | getTabHeaderIndex: file => parseInt(/^-?\d+/.exec(file.split('/').pop()), 10) || -1, 11 | 12 | getParentTitle: file => { 13 | const parts = file.split('/'); 14 | return parts[parts.length - 2].replace(/^-?\d+\./, '').replace(/_/g, ' '); 15 | }, 16 | 17 | getPageTitle: file => file.split('/').pop().replace(/^-?\d+\./, '').replace(/_/g, ' ').replace(/\.md$/i, ''), 18 | 19 | getTabRoutes: (routes, currentRoute) => { 20 | const directoryPath = currentRoute.substring(0, currentRoute.lastIndexOf('/')); 21 | return Object.entries(routes) 22 | .filter(entry => entry[0].startsWith(directoryPath)) 23 | .sort((a, b) => a[1].tabHeaderIndex - b[1].tabHeaderIndex) 24 | .map(entry => entry[0]); 25 | }, 26 | 27 | getCategory: file => { 28 | const category = file.split('/')[1]; 29 | return ['components', 'modifiers', 'concepts'].indexOf(category) === -1 30 | ? 'info' 31 | : category; 32 | }, 33 | 34 | getText: mdAst => { 35 | const getTextNodes = childNodes => { 36 | return childNodes.reduce((memo, {type, value, children}) => { 37 | if (type === 'text' || type === 'inlineCode') return [...memo, value.trim()]; 38 | if (children) return [...memo, ...getTextNodes(children)]; 39 | return memo; 40 | }, []); 41 | }; 42 | 43 | return getTextNodes(mdAst.children).join(' '); 44 | }, 45 | 46 | getMetadata: mdAst => { 47 | const yamlNode = (mdAst.children || []).find(node => node.type === 'yaml'); 48 | if (!yamlNode) return {}; 49 | return yamlNode.data.parsedValue; 50 | } 51 | }; -------------------------------------------------------------------------------- /src/helpers/markdown_loader.js: -------------------------------------------------------------------------------- 1 | import unified from 'unified'; 2 | import parse from 'remark-parse'; 3 | import frontmatter from 'remark-frontmatter'; 4 | import parseYaml from 'remark-parse-yaml'; 5 | 6 | export default function(source) { 7 | const processor = unified().use(parse).use(frontmatter).use(parseYaml); 8 | try { 9 | return processor.runSync(processor.parse(source)); 10 | } catch (err) { 11 | console.error(err.message); 12 | return '{}'; 13 | } 14 | }; -------------------------------------------------------------------------------- /src/helpers/markdown_processor.js: -------------------------------------------------------------------------------- 1 | import unified from 'unified'; 2 | import reactRenderer from 'remark-react'; 3 | import HeadingRenderer from '../components/renderers/heading_renderer'; 4 | import PreRenderer from '../components/renderers/pre_renderer'; 5 | import TableRenderer from '../components/renderers/table_renderer'; 6 | import ImageRenderer from '../components/renderers/image_renderer'; 7 | import LinkRenderer from '../components/renderers/link_renderer'; 8 | 9 | export default unified().use(reactRenderer, { 10 | sanitize: false, 11 | remarkReactComponents: { 12 | h1: HeadingRenderer(1), 13 | h2: HeadingRenderer(2), 14 | h3: HeadingRenderer(3), 15 | h4: HeadingRenderer(4), 16 | h5: HeadingRenderer(5), 17 | h6: HeadingRenderer(6), 18 | pre: PreRenderer, 19 | table: TableRenderer, 20 | img: ImageRenderer, 21 | a: LinkRenderer 22 | } 23 | }); -------------------------------------------------------------------------------- /src/helpers/routes_helper.js: -------------------------------------------------------------------------------- 1 | import MarkdownFileHelper from './markdown_file_helper'; 2 | 3 | export const getRoutes = ({requireFunc, processor}) => requireFunc.keys().reduce((memo, file) => { 4 | const json = requireFunc(file); 5 | const route = MarkdownFileHelper.getRoute(file); 6 | const tabHeaderIndex = MarkdownFileHelper.getTabHeaderIndex(file); 7 | const pageTitle = MarkdownFileHelper.getPageTitle(file); 8 | const parentTitle = MarkdownFileHelper.getParentTitle(file); 9 | const category = MarkdownFileHelper.getCategory(file); 10 | const text = MarkdownFileHelper.getText(json); 11 | const metadata = MarkdownFileHelper.getMetadata(json); 12 | const pageContent = MarkdownFileHelper.process({processor, json}); 13 | 14 | return { 15 | ...memo, 16 | [route]: { 17 | file, route, pageContent, tabHeaderIndex, pageTitle, parentTitle, category, text, metadata 18 | } 19 | }; 20 | }, {}); 21 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import '@babel/polyfill'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import {AppContainer} from 'react-hot-loader'; 5 | import App from './app'; 6 | import {BrowserRouter as Router} from 'react-router-dom'; 7 | 8 | window.React = React; 9 | window.ReactDOM = ReactDOM; 10 | 11 | const render = Component => ; 12 | 13 | ReactDOM.render(render(App), document.getElementById('root')); 14 | 15 | if (process.env.NODE_ENV === 'development') { 16 | if (module.hot) { 17 | module.hot.accept('./app', () => { 18 | const NextApp = require('./app'); 19 | ReactDOM.render({render(NextApp)}, document.getElementById('root')); 20 | }); 21 | } 22 | } -------------------------------------------------------------------------------- /static/add_circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/cf-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pui-styleguide/be5de22f61cae0d0c40eea1801fe72826b5b913f/static/cf-logo.png -------------------------------------------------------------------------------- /static/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pui-styleguide/be5de22f61cae0d0c40eea1801fe72826b5b913f/static/favicon.ico -------------------------------------------------------------------------------- /static/help.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/such-awesome.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pui-styleguide/be5de22f61cae0d0c40eea1801fe72826b5b913f/static/such-awesome.jpg -------------------------------------------------------------------------------- /stylesheets/app.scss: -------------------------------------------------------------------------------- 1 | @import '~pivotal-ui/css/pui-variables'; 2 | @import 'sidebar'; 3 | @import 'page'; 4 | @import 'code_example'; 5 | @import 'search_bar'; 6 | @import 'search_result'; 7 | 8 | body { 9 | margin: 0; 10 | font-family: $font-family-base; 11 | font-size: $font-size-base; 12 | } 13 | 14 | .grid-show { 15 | margin-bottom: $grid-gutter-width; 16 | text-align: center; 17 | [class*=col]:before { 18 | content: attr(class) '\a' attr(grid-content); 19 | white-space: pre; 20 | display: block; 21 | background-color: $white; 22 | padding: 10px 0; 23 | outline: 1px solid $accent-gray; 24 | } 25 | } 26 | 27 | h1.h1 { 28 | line-height: 40px; 29 | margin-bottom: 24px; 30 | font-weight: 600; 31 | } 32 | 33 | h2.h2 { 34 | margin-bottom: 16px; 35 | } 36 | 37 | .example-form { 38 | .label-row { 39 | outline: 1px solid green; 40 | } 41 | 42 | .field-row { 43 | outline: 1px solid cadetblue; 44 | } 45 | 46 | .help-row { 47 | outline: 1px solid darkred; 48 | } 49 | } 50 | 51 | #content { 52 | padding-left: 240px; 53 | 54 | .policy-link { 55 | &:not(:empty):before { 56 | content: "•"; 57 | margin: 0 8px; 58 | } 59 | 60 | &:first-child:before { 61 | content: ""; 62 | margin-right: 0; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /stylesheets/code_example.scss: -------------------------------------------------------------------------------- 1 | .code-example-title { 2 | p { 3 | margin-top: $base-unit; 4 | margin-bottom: 0; 5 | } 6 | } 7 | 8 | .code-example-button { 9 | &:focus { 10 | box-shadow: 0 0 0 2px transparentize($blue, 0.8); 11 | } 12 | } -------------------------------------------------------------------------------- /stylesheets/page.scss: -------------------------------------------------------------------------------- 1 | .styleguide-page { 2 | .styleguide-import-preview-code { 3 | word-break: normal; 4 | } 5 | 6 | table.md-table { 7 | margin-bottom: 40px; 8 | table-layout: auto; 9 | } 10 | 11 | .md-image { 12 | width: 100%; 13 | } 14 | 15 | .md-heading:first-child { 16 | margin-top: 0 !important; 17 | } 18 | 19 | .md-pre { 20 | background: transparent; 21 | padding: $base-unit; 22 | } 23 | 24 | .styleguide-page-header { 25 | a { 26 | color: $text-color; 27 | 28 | svg { 29 | fill: $gray; 30 | } 31 | } 32 | } 33 | 34 | .styleguide-page-main { 35 | max-width: 960px; 36 | } 37 | 38 | .styleguide-tabs { 39 | border-bottom: none !important; 40 | } 41 | 42 | .styleguide-tab-content { 43 | > .tab-content { 44 | background: transparent; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /stylesheets/search_bar.scss: -------------------------------------------------------------------------------- 1 | .styleguide-search-bar { 2 | position: relative; 3 | 4 | .search-input { 5 | border: none; 6 | background: $white !important; 7 | color: initial !important; 8 | font-size: initial !important; 9 | 10 | &:focus { 11 | border: none; 12 | box-shadow: 0 0 0 2px $accent-teal; 13 | } 14 | } 15 | 16 | .autocomplete { 17 | .autocomplete-list, ul { 18 | margin-top: $base-unit; 19 | } 20 | 21 | .autocomplete-list { 22 | border: none; 23 | border-radius: $base-unit / 4; 24 | max-height: 240px; 25 | } 26 | 27 | .autocomplete-item, .autocomplete-item-no-results { 28 | font-size: 14px; 29 | min-width: 100%; 30 | color: $dark-gray; 31 | opacity: 1; 32 | 33 | &:hover { 34 | background: $black; 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /stylesheets/search_result.scss: -------------------------------------------------------------------------------- 1 | .search-result { 2 | .search-result-category { 3 | font-size: 10px; 4 | line-height: 0.6em; 5 | } 6 | } -------------------------------------------------------------------------------- /stylesheets/sidebar.scss: -------------------------------------------------------------------------------- 1 | @import '~pivotal-ui/css/pui-variables'; 2 | 3 | $sidebar-item-left-padding: $base-unit * 2; 4 | $active-item-border-size: $base-unit / 2; 5 | 6 | .sidebar { 7 | color: $light-gray; 8 | overflow-y: auto; 9 | overflow-x: hidden; 10 | padding-bottom: 40px; 11 | position: fixed; 12 | width: 240px; 13 | height: 100%; 14 | 15 | .autocomplete input { 16 | background-color: $black; 17 | color: $light-gray; 18 | } 19 | } 20 | 21 | .sidebar-header { 22 | padding: $base-unit * 2; 23 | display: flex; 24 | 25 | a { 26 | align-self: center; 27 | } 28 | 29 | .sidebar-icon { 30 | padding: $base-unit; 31 | background-color: $accent-teal; 32 | border-radius: 2px; 33 | height: $base-unit * 6; 34 | width: $base-unit * 6; 35 | 36 | svg { 37 | height: $base-unit * 4; 38 | width: $base-unit * 4; 39 | } 40 | } 41 | 42 | .sidebar-title { 43 | display: inline; 44 | color: $light-gray; 45 | font-size: $font-size-large; 46 | align-self: center; 47 | } 48 | } 49 | 50 | .sidebar-link { 51 | align-self: center; 52 | color: $light-gray; 53 | padding: $base-unit $base-unit $base-unit $sidebar-item-left-padding; 54 | display: block; 55 | cursor: pointer; 56 | text-decoration: none; 57 | 58 | &:hover { 59 | color: $light-gray; 60 | text-decoration: underline; 61 | } 62 | 63 | &.active { 64 | background-color: $black; 65 | border-left: $active-item-border-size solid $accent-teal; 66 | padding-left: $sidebar-item-left-padding - $active-item-border-size; 67 | } 68 | 69 | svg { 70 | fill: $light-gray; 71 | } 72 | } --------------------------------------------------------------------------------