├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .node-version ├── .npmrc ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── dist └── framework.css ├── package.json ├── public └── index.html ├── src ├── framework │ ├── components │ │ └── local_nav │ │ │ ├── _index.scss │ │ │ ├── _local_breadcrumbs.scss │ │ │ ├── _local_dropdown.scss │ │ │ ├── _local_menu.scss │ │ │ ├── _local_nav.scss │ │ │ ├── _local_search.scss │ │ │ ├── _local_tabs.scss │ │ │ └── _local_title.scss │ └── framework.scss └── guide │ ├── actions │ ├── action_types.js │ ├── code_viewer │ │ └── code_viewer_actions.js │ └── index.js │ ├── components │ ├── guide_code_viewer │ │ ├── _guide_code_viewer.scss │ │ └── guide_code_viewer.jsx │ ├── guide_example │ │ ├── _guide_example.scss │ │ └── guide_example.jsx │ ├── guide_nav │ │ ├── _guide_nav.scss │ │ └── guide_nav.jsx │ ├── guide_page │ │ ├── _guide_page.scss │ │ └── guide_page.jsx │ ├── guide_page_section │ │ ├── _guide_page_section.scss │ │ └── guide_page_section.jsx │ ├── guide_page_side_nav │ │ ├── _guide_page_side_nav.scss │ │ ├── guide_page_side_nav.jsx │ │ └── guide_page_side_nav_item.jsx │ └── index.js │ ├── index.js │ ├── main.scss │ ├── services │ ├── example │ │ └── createExample.js │ ├── index.js │ ├── js_injector │ │ └── js_injector.js │ ├── routes │ │ └── Routes.js │ └── string │ │ └── slugify.js │ ├── store │ ├── configure_store.js │ └── reducers │ │ └── code_viewer_reducer.js │ ├── variables.scss │ └── views │ ├── _app.scss │ ├── app_container.js │ ├── app_view.jsx │ ├── home │ ├── _home_view.scss │ └── home_view.jsx │ ├── local_nav │ ├── local_nav_breadcrumbs │ │ └── local_nav_breadcrumbs.html │ ├── local_nav_dropdown │ │ └── local_nav_dropdown.html │ ├── local_nav_dropdown_panels │ │ └── local_nav_dropdown_panels.html │ ├── local_nav_example.jsx │ ├── local_nav_menu_item_states │ │ └── local_nav_menu_item_states.html │ ├── local_nav_search │ │ └── local_nav_search.html │ ├── local_nav_search_error │ │ └── local_nav_search_error.html │ ├── local_nav_simple │ │ └── local_nav_simple.html │ └── local_nav_tabs │ │ └── local_nav_tabs.html │ └── not_found │ └── not_found_view.jsx └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | insert_final_newline = false 15 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/kibana-ui-framework/374a97f7de6233c4d6d23d858d04a5ac3bfbb704/.eslintignore -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: '@elastic/kibana' 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log 4 | public/*.js* 5 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 4.4.7 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/kibana-ui-framework/374a97f7de6233c4d6d23d858d04a5ac3bfbb704/CONTRIBUTING.md -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2012–2015 Elasticsearch BV 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kibana UI Framework 2 | 3 | ## The UI Framework has been officially migrated into the [Kibana repo](https://github.com/elastic/kibana/tree/master/src/ui_framework). -------------------------------------------------------------------------------- /dist/framework.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 1. Breadcrumbs are placed in the top-left corner and need to be bumped over 3 | * a bit. 4 | */ 5 | .localBreadcrumbs { 6 | display: flex; 7 | align-items: center; 8 | height: 100%; 9 | padding-left: 10px; 10 | /* 1 */ } 11 | 12 | .localBreadcrumb + .localBreadcrumb { 13 | margin-left: 6px; } 14 | .localBreadcrumb + .localBreadcrumb:before { 15 | content: '/'; 16 | user-select: none; 17 | margin-right: 4px; 18 | color: #5a5a5a; } 19 | .theme-dark .localBreadcrumb + .localBreadcrumb:before { 20 | color: #a5a5a5; } 21 | 22 | .localBreadcrumb:last-child .localBreadcrumb__link { 23 | color: #2d2d2d; 24 | cursor: default; } 25 | .localBreadcrumb:last-child .localBreadcrumb__link:hover { 26 | text-decoration: none; } 27 | .theme-dark .localBreadcrumb:last-child .localBreadcrumb__link { 28 | color: #cecece; } 29 | 30 | .localBreadcrumb__link { 31 | font-size: 14px; 32 | color: #5a5a5a; 33 | text-decoration: none; } 34 | .localBreadcrumb__link:hover { 35 | text-decoration: underline; } 36 | .theme-dark .localBreadcrumb__link { 37 | color: #dedede; } 38 | 39 | .localBreadcrumb__emphasis { 40 | font-weight: 700; } 41 | 42 | .localDropdown { 43 | position: relative; 44 | padding: 10px 10px 14px; 45 | background-color: #f6f6f6; 46 | line-height: 20px; } 47 | .theme-dark .localDropdown { 48 | background-color: #525252; } 49 | 50 | .localDropdownCloseButton { 51 | appearance: none; 52 | background-color: transparent; 53 | padding: 4px; 54 | border: none; 55 | position: absolute; 56 | top: 1px; 57 | right: 5px; 58 | font-size: 16px; 59 | color: #2d2d2d; 60 | cursor: pointer; 61 | opacity: 0.35; } 62 | .localDropdownCloseButton:hover { 63 | opacity: 1; } 64 | .theme-dark .localDropdownCloseButton { 65 | color: #cecece; } 66 | 67 | .localDropdownPanels { 68 | display: flex; } 69 | 70 | .localDropdownPanel { 71 | flex: 1 1 0%; } 72 | 73 | .localDropdownPanel--left { 74 | margin-right: 30px; } 75 | 76 | .localDropdownPanel--right { 77 | margin-left: 30px; } 78 | 79 | .localDropdownTitle { 80 | margin-bottom: 12px; 81 | font-size: 18px; 82 | color: #2d2d2d; } 83 | .theme-dark .localDropdownTitle { 84 | color: #cecece; } 85 | 86 | .localDropdownSection { 87 | margin-bottom: 16px; } 88 | .localDropdownSection:last-child { 89 | margin-bottom: 0; } 90 | 91 | .localDropdownHeader { 92 | display: flex; 93 | align-items: center; 94 | justify-content: space-between; 95 | margin-bottom: 6px; } 96 | 97 | .localDropdownHeader__label { 98 | font-size: 14px; 99 | font-weight: 700; 100 | color: #2d2d2d; } 101 | .theme-dark .localDropdownHeader__label { 102 | color: #cecece; } 103 | 104 | .localDropdownHeader__actions { 105 | display: flex; } 106 | 107 | .localDropdownHeader__action { 108 | color: #328CAA; 109 | font-size: 12px; 110 | text-decoration: none; 111 | cursor: pointer; } 112 | .localDropdownHeader__action + .localDropdownHeader__action { 113 | margin-left: 10px; } 114 | .localDropdownHeader__action:hover, .localDropdownHeader__action:active { 115 | color: #105A73; } 116 | .theme-dark .localDropdownHeader__action { 117 | color: #b7e2ea; } 118 | .theme-dark .localDropdownHeader__action:hover, .theme-dark .localDropdownHeader__action:active { 119 | color: #def2f6; } 120 | 121 | .localDropdownInput { 122 | display: block; 123 | width: 100%; 124 | margin-bottom: 12px; 125 | padding: 5px 15px; 126 | font-size: 14px; 127 | color: #2d2d2d; 128 | background-color: #ffffff; 129 | border: 2px solid #ffffff; 130 | border-radius: 4px; } 131 | .theme-dark .localDropdownInput { 132 | color: #cecece; 133 | background-color: #444444; 134 | border-color: #444444; } 135 | 136 | .localDropdownFormNote { 137 | font-size: 14px; 138 | color: #737373; } 139 | .theme-dark .localDropdownFormNote { 140 | color: #a2a2a2; } 141 | 142 | .localDropdownWarning { 143 | margin-bottom: 16px; 144 | padding: 6px 10px; 145 | font-size: 14px; 146 | color: #2d2d2d; 147 | background-color: #e4e4e4; } 148 | .theme-dark .localDropdownWarning { 149 | color: #cecece; 150 | background-color: #636363; } 151 | 152 | .localDropdownHelpText { 153 | margin-bottom: 16px; 154 | font-size: 14px; 155 | color: #2D2D2D; } 156 | .theme-dark .localDropdownHelpText { 157 | color: #9e9e9e; } 158 | 159 | .localMenu { 160 | display: flex; 161 | align-items: center; 162 | height: 100%; } 163 | 164 | .localMenuItem { 165 | display: flex; 166 | align-items: center; 167 | height: 100%; 168 | padding: 0 10px; 169 | font-size: 14px; 170 | background-color: transparent; 171 | color: #5a5a5a; 172 | border: 0; 173 | cursor: pointer; } 174 | .localMenuItem:hover { 175 | background-color: rgba(0, 0, 0, 0.1); 176 | color: #000000; } 177 | .localMenuItem.localMenuItem-isSelected { 178 | background-color: #f6f6f6; } 179 | .localMenuItem.localMenuItem-isDisabled { 180 | opacity: 0.5; 181 | cursor: default; } 182 | .localMenuItem.localMenuItem-isDisabled:hover { 183 | background-color: transparent; 184 | color: #5a5a5a; } 185 | .theme-dark .localMenuItem { 186 | color: #dedede; } 187 | .theme-dark .localMenuItem:hover { 188 | background-color: #000000; 189 | color: #ffffff; } 190 | .theme-dark .localMenuItem.localMenuItem-isSelected { 191 | background-color: #525252; } 192 | .theme-dark .localMenuItem.localMenuItem-isDisabled:hover { 193 | background-color: transparent; 194 | color: #dedede; } 195 | 196 | .localMenuItem__icon { 197 | margin-right: 5px; 198 | margin-bottom: -1px; } 199 | 200 | /** 201 | * 1. Match height of logo in side bar, but allow it to expand to accommodate 202 | * dropdown. 203 | */ 204 | .localNav { 205 | display: flex; 206 | flex-direction: column; 207 | justify-content: space-between; 208 | min-height: 70px; 209 | /* 1 */ 210 | color: #2d2d2d; 211 | background-color: #e4e4e4; } 212 | .theme-dark .localNav { 213 | color: #cecece; 214 | background-color: #333333; } 215 | 216 | .localNavRow { 217 | display: flex; 218 | align-items: center; 219 | justify-content: space-between; 220 | height: 32px; } 221 | 222 | .localNavRow__section { 223 | height: 100%; } 224 | 225 | .localNavRow--secondary { 226 | height: 38px; 227 | padding: 0 10px; } 228 | 229 | .localSearch { 230 | display: flex; 231 | width: 100%; 232 | height: 30px; } 233 | 234 | .localSearchInput { 235 | flex: 1 1 100%; 236 | padding: 5px 15px; 237 | font-size: 14px; 238 | color: #2d2d2d; 239 | background-color: #ffffff; 240 | border: 2px solid #ffffff; 241 | border-bottom-left-radius: 4px; 242 | border-top-left-radius: 4px; 243 | border-bottom-right-radius: 0; 244 | border-top-right-radius: 0; } 245 | .localSearchInput.localSearchInput-isInvalid { 246 | border-color: #e74C3c; } 247 | .theme-dark .localSearchInput { 248 | color: #cecece; 249 | background-color: #4e4e4e; 250 | border-color: #4e4e4e; } 251 | .theme-dark .localSearchInput.localSearchInput-isInvalid { 252 | border-color: #ff6758; } 253 | 254 | .localSearchButton { 255 | width: 43px; 256 | height: 30px; 257 | font-size: 14px; 258 | color: #ffffff; 259 | background-color: #9c9c9c; 260 | border: 0; 261 | border-bottom-left-radius: 0; 262 | border-top-left-radius: 0; 263 | border-bottom-right-radius: 4px; 264 | border-top-right-radius: 4px; } 265 | .theme-dark .localSearchButton { 266 | color: #ffffff; 267 | background-color: #777777; } 268 | 269 | /** 270 | * 1. We want the bottom border on selected tabs to be flush with the bottom of the container. 271 | */ 272 | .localTabs { 273 | display: flex; 274 | align-items: flex-end; 275 | height: 100%; } 276 | 277 | /** 278 | * 1. Make sure the bottom border is flush with the bottom of the LocalNav. 279 | */ 280 | .localTab { 281 | padding: 5px 0 6px 0; 282 | font-size: 18px; 283 | line-height: 22px; 284 | /* 1 */ 285 | color: #5a5a5a; 286 | border-bottom: 2px solid transparent; 287 | text-decoration: none; 288 | cursor: pointer; } 289 | .localTab:hover, .localTab:active { 290 | color: #000000; } 291 | .theme-dark .localTab:hover, .theme-dark .localTab:active { 292 | color: #ffffff; } 293 | .localTab.localTab-isSelected { 294 | color: #000000; 295 | border-bottom-color: #000000; 296 | cursor: default; } 297 | .theme-dark .localTab.localTab-isSelected { 298 | color: #ffffff; 299 | border-bottom-color: #ffffff; } 300 | .localTab + .localTab { 301 | margin-left: 15px; } 302 | .theme-dark .localTab { 303 | color: #dedede; } 304 | 305 | .localTitle { 306 | display: flex; 307 | align-items: center; 308 | height: 100%; 309 | padding-left: 10px; 310 | font-size: 14px; 311 | font-weight: bold; } 312 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@elastic/kibana-ui-framework", 3 | "version": "0.0.13", 4 | "description": "Kibana UI Framework", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --inline --content-base public/", 8 | "build": "./node_modules/.bin/webpack", 9 | "deploy": "npm run build; gh-pages -d public -r https://github.com/elastic/kibana-ui-framework", 10 | "dist": "./node_modules/node-sass/bin/node-sass ./src/framework/framework.scss ./dist/framework.css", 11 | "preversion": "npm run dist", 12 | "postversion": "npm run deploy" 13 | }, 14 | "dependencies": { 15 | }, 16 | "devDependencies": { 17 | "@elastic/eslint-config-kibana": "0.1.0", 18 | "babel-core": "6.10.4", 19 | "babel-eslint": "4.1.8", 20 | "babel-loader": "6.2.4", 21 | "babel-polyfill": "6.9.1", 22 | "babel-preset-es2015": "6.9.0", 23 | "babel-preset-react": "6.11.1", 24 | "classnames": "2.2.5", 25 | "css-loader": "0.23.1", 26 | "del": "1.2.1", 27 | "eslint": "1.10.3", 28 | "eslint-plugin-jasmine": "1.6.0", 29 | "eslint-plugin-mocha": "1.1.0", 30 | "eslint-plugin-react": "3.16.1", 31 | "expose-loader": "0.7.1", 32 | "gh-pages": "0.11.0", 33 | "highlight.js": "9.0.0", 34 | "history": "2.1.1", 35 | "html-loader": "0.4.3", 36 | "jquery": "3.1.0", 37 | "json-loader": "0.5.4", 38 | "keymirror": "0.1.1", 39 | "node-sass": "3.8.0", 40 | "numeral": "1.5.3", 41 | "raw-loader": "0.5.1", 42 | "react": "15.2.0", 43 | "react-addons-test-utils": "15.2.0", 44 | "react-dom": "15.2.0", 45 | "react-redux": "4.4.5", 46 | "react-router": "2.0.0", 47 | "react-router-redux": "4.0.4", 48 | "redux": "3.0.0", 49 | "redux-thunk": "0.1.0", 50 | "sass-loader": "4.0.0", 51 | "style-loader": "0.13.1", 52 | "webpack": "1.13.1", 53 | "webpack-dev-server": "1.14.1" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_index.scss: -------------------------------------------------------------------------------- 1 | // Normal colors 2 | $localNavTextColor: $textColor; 3 | $localNavBackgroundColor: #e4e4e4; 4 | $localNavButtonTextColor: #5a5a5a; 5 | $localNavButtonTextColor-isHover: #000000; 6 | $localNavButtonBackgroundColor: transparent; 7 | $localNavButtonBackgroundColor-isHover: rgba(#000000, 0.1); 8 | $localNavButtonBackgroundColor-isSelected: #f6f6f6; 9 | $localNavBreadcrumbDelimiterColor: #5a5a5a; 10 | $localSearchBackgroundColor: #ffffff; 11 | $localSearchBorderColor-isInvalid: #e74C3c; 12 | $localDropdownBackgroundColor: $localNavButtonBackgroundColor-isSelected; 13 | $localDropdownFormNoteTextColor: #737373; 14 | $localTabTextColor: $localNavButtonTextColor; 15 | $localTabTextColor-isHover: $localNavButtonTextColor-isHover; 16 | $localTabTextColor-isSelected: $localNavButtonTextColor-isHover; 17 | 18 | // Dark theme colors 19 | $localNavTextColor--darkTheme: $textColor--darkTheme; 20 | $localNavBackgroundColor--darkTheme: #333333; 21 | $localNavButtonTextColor--darkTheme: #dedede; 22 | $localNavButtonTextColor-isHover--darkTheme: #ffffff; 23 | $localNavButtonBackgroundColor-isHover--darkTheme: #000000; 24 | $localNavButtonBackgroundColor-isSelected--darkTheme: #525252; 25 | $localNavBreadcrumbDelimiterColor--darkTheme: #a5a5a5; 26 | $localSearchBackgroundColor--darkTheme: #4e4e4e; 27 | $localSearchBorderColor-isInvalid--darkTheme: #ff6758; 28 | $localDropdownBackgroundColor--darkTheme: $localNavButtonBackgroundColor-isSelected--darkTheme; 29 | $localDropdownFormNoteTextColor--darkTheme: #a2a2a2; 30 | $localDropdownWarningTextColor--darkTheme: $textColor--darkTheme; 31 | $localDropdownWarningBackgroundColor--darkTheme: #636363; 32 | $localTabTextColor--darkTheme: $localNavButtonTextColor--darkTheme; 33 | $localTabTextColor-isHover--darkTheme: $localNavButtonTextColor-isHover--darkTheme; 34 | $localTabTextColor-isSelected--darkTheme: $localNavButtonTextColor-isHover--darkTheme; 35 | 36 | // Spacing 37 | $localNavSideSpacing: 10px; 38 | 39 | // Font size 40 | $localNavFontSizeNormal: 14px; 41 | 42 | @import "local_breadcrumbs"; 43 | @import "local_dropdown"; 44 | @import "local_menu"; 45 | @import "local_nav"; 46 | @import "local_search"; 47 | @import "local_tabs"; 48 | @import "local_title"; 49 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_local_breadcrumbs.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 1. Breadcrumbs are placed in the top-left corner and need to be bumped over 4 | * a bit. 5 | */ 6 | .localBreadcrumbs { 7 | display: flex; 8 | align-items: center; 9 | height: 100%; 10 | padding-left: $localNavSideSpacing; /* 1 */ 11 | } 12 | 13 | .localBreadcrumb { 14 | & + & { 15 | margin-left: 6px; 16 | 17 | &:before { 18 | content: '/'; 19 | user-select: none; 20 | margin-right: 4px; 21 | color: $localNavBreadcrumbDelimiterColor; 22 | 23 | @include darkTheme { 24 | color: $localNavBreadcrumbDelimiterColor--darkTheme; 25 | } 26 | } 27 | } 28 | 29 | &:last-child { 30 | .localBreadcrumb__link { 31 | color: $localNavTextColor; 32 | cursor: default; 33 | 34 | &:hover { 35 | text-decoration: none; 36 | } 37 | 38 | @include darkTheme { 39 | color: $localNavTextColor--darkTheme; 40 | } 41 | } 42 | } 43 | 44 | } 45 | 46 | .localBreadcrumb__link { 47 | font-size: $localNavFontSizeNormal; 48 | color: #5a5a5a; 49 | text-decoration: none; 50 | 51 | &:hover { 52 | text-decoration: underline; 53 | } 54 | 55 | @include darkTheme { 56 | color: $localNavButtonTextColor--darkTheme; 57 | } 58 | } 59 | 60 | .localBreadcrumb__emphasis { 61 | font-weight: 700; 62 | } 63 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_local_dropdown.scss: -------------------------------------------------------------------------------- 1 | 2 | .localDropdown { 3 | position: relative; 4 | padding: 10px $localNavSideSpacing 14px; 5 | background-color: $localDropdownBackgroundColor; 6 | line-height: 20px; 7 | 8 | @include darkTheme { 9 | background-color: $localDropdownBackgroundColor--darkTheme; 10 | } 11 | } 12 | 13 | .localDropdownCloseButton { 14 | appearance: none; 15 | background-color: transparent; 16 | padding: 4px; 17 | border: none; 18 | position: absolute; 19 | top: 1px; 20 | right: 5px; 21 | font-size: 16px; 22 | color: $localNavTextColor; 23 | cursor: pointer; 24 | opacity: 0.35; 25 | 26 | &:hover { 27 | opacity: 1; 28 | } 29 | 30 | @include darkTheme { 31 | color: $localNavTextColor--darkTheme; 32 | } 33 | } 34 | 35 | .localDropdownPanels { 36 | display: flex; 37 | } 38 | 39 | .localDropdownPanel { 40 | flex: 1 1 0%; 41 | } 42 | 43 | .localDropdownPanel--left { 44 | margin-right: 30px; 45 | } 46 | 47 | .localDropdownPanel--right { 48 | margin-left: 30px; 49 | } 50 | 51 | .localDropdownTitle { 52 | margin-bottom: 12px; 53 | font-size: 18px; 54 | color: $localNavTextColor; 55 | 56 | @include darkTheme { 57 | color: $localNavTextColor--darkTheme; 58 | } 59 | } 60 | 61 | .localDropdownSection { 62 | margin-bottom: 16px; 63 | 64 | &:last-child { 65 | margin-bottom: 0; 66 | } 67 | } 68 | 69 | .localDropdownHeader { 70 | display: flex; 71 | align-items: center; 72 | justify-content: space-between; 73 | margin-bottom: 6px; 74 | } 75 | 76 | .localDropdownHeader__label { 77 | font-size: 14px; 78 | font-weight: 700; 79 | color: $localNavTextColor; 80 | 81 | @include darkTheme { 82 | color: $localNavTextColor--darkTheme; 83 | } 84 | } 85 | 86 | .localDropdownHeader__actions { 87 | display: flex; 88 | } 89 | 90 | .localDropdownHeader__action { 91 | color: $linkColor; 92 | font-size: 12px; 93 | text-decoration: none; 94 | cursor: pointer; 95 | 96 | & + & { 97 | margin-left: 10px; 98 | } 99 | 100 | &:hover, 101 | &:active { 102 | color: $linkColor-isHover; 103 | } 104 | 105 | @include darkTheme { 106 | color: $linkColor--darkTheme; 107 | 108 | &:hover, 109 | &:active { 110 | color: $linkColor-isHover--darkTheme; 111 | } 112 | } 113 | } 114 | 115 | .localDropdownInput { 116 | display: block; 117 | width: 100%; 118 | margin-bottom: 12px; 119 | padding: 5px 15px; 120 | font-size: 14px; 121 | color: $inputTextColor; 122 | background-color: $inputBackgroundColor; 123 | border: 2px solid $inputBorderColor; 124 | border-radius: 4px; 125 | 126 | @include darkTheme { 127 | color: $inputTextColor--darkTheme; 128 | background-color: $inputBackgroundColor--darkTheme; 129 | border-color: $inputBorderColor--darkTheme; 130 | } 131 | } 132 | 133 | .localDropdownFormNote { 134 | font-size: 14px; 135 | color: $localDropdownFormNoteTextColor; 136 | 137 | @include darkTheme { 138 | color: $localDropdownFormNoteTextColor--darkTheme; 139 | } 140 | } 141 | 142 | .localDropdownWarning { 143 | margin-bottom: 16px; 144 | padding: 6px 10px; 145 | font-size: 14px; 146 | color: $textColor; 147 | background-color: $localNavBackgroundColor; 148 | 149 | @include darkTheme { 150 | color: $localDropdownWarningTextColor--darkTheme; 151 | background-color: $localDropdownWarningBackgroundColor--darkTheme; 152 | } 153 | } 154 | 155 | .localDropdownHelpText { 156 | margin-bottom: 16px; 157 | font-size: 14px; 158 | color: #2D2D2D; 159 | 160 | @include darkTheme { 161 | color: #9e9e9e; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_local_menu.scss: -------------------------------------------------------------------------------- 1 | 2 | .localMenu { 3 | display: flex; 4 | align-items: center; 5 | height: 100%; 6 | } 7 | 8 | .localMenuItem { 9 | display: flex; 10 | align-items: center; 11 | height: 100%; 12 | padding: 0 $localNavSideSpacing; 13 | font-size: $localNavFontSizeNormal; 14 | background-color: $localNavButtonBackgroundColor; 15 | color: $localNavButtonTextColor; 16 | border: 0; 17 | cursor: pointer; 18 | 19 | &:hover { 20 | background-color: $localNavButtonBackgroundColor-isHover; 21 | color: $localNavButtonTextColor-isHover; 22 | } 23 | 24 | &.localMenuItem-isSelected { 25 | background-color: $localNavButtonBackgroundColor-isSelected; 26 | } 27 | 28 | &.localMenuItem-isDisabled { 29 | opacity: 0.5; 30 | cursor: default; 31 | 32 | &:hover { 33 | background-color: $localNavButtonBackgroundColor; 34 | color: $localNavButtonTextColor; 35 | } 36 | } 37 | 38 | @include darkTheme { 39 | color: $localNavButtonTextColor--darkTheme; 40 | 41 | &:hover { 42 | background-color: $localNavButtonBackgroundColor-isHover--darkTheme; 43 | color: $localNavButtonTextColor-isHover--darkTheme; 44 | } 45 | 46 | &.localMenuItem-isSelected { 47 | background-color: $localNavButtonBackgroundColor-isSelected--darkTheme; 48 | } 49 | 50 | &.localMenuItem-isDisabled { 51 | &:hover { 52 | background-color: transparent; 53 | color: $localNavButtonTextColor--darkTheme; 54 | } 55 | } 56 | } 57 | } 58 | 59 | .localMenuItem__icon { 60 | margin-right: 5px; 61 | margin-bottom: -1px; 62 | } 63 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_local_nav.scss: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 1. Match height of logo in side bar, but allow it to expand to accommodate 4 | * dropdown. 5 | */ 6 | .localNav { 7 | display: flex; 8 | flex-direction: column; 9 | justify-content: space-between; 10 | min-height: 70px; /* 1 */ 11 | color: $localNavTextColor; 12 | background-color: $localNavBackgroundColor; 13 | 14 | @include darkTheme { 15 | color: $localNavTextColor--darkTheme; 16 | background-color: $localNavBackgroundColor--darkTheme; 17 | } 18 | } 19 | 20 | .localNavRow { 21 | display: flex; 22 | align-items: center; 23 | justify-content: space-between; 24 | height: 32px; 25 | } 26 | 27 | .localNavRow__section { 28 | height: 100%; 29 | } 30 | 31 | .localNavRow--secondary { 32 | height: 38px; 33 | padding: 0 $localNavSideSpacing; 34 | } 35 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_local_search.scss: -------------------------------------------------------------------------------- 1 | 2 | $localSearchHeight: 30px; 3 | 4 | .localSearch { 5 | display: flex; 6 | width: 100%; 7 | height: $localSearchHeight; 8 | } 9 | 10 | .localSearchInput { 11 | flex: 1 1 100%; 12 | padding: 5px 15px; 13 | font-size: $localNavFontSizeNormal; 14 | color: $localNavTextColor; 15 | background-color: $localSearchBackgroundColor; 16 | border: 2px solid $localSearchBackgroundColor; 17 | border-bottom-left-radius: 4px; 18 | border-top-left-radius: 4px; 19 | border-bottom-right-radius: 0; 20 | border-top-right-radius: 0; 21 | 22 | &.localSearchInput-isInvalid { 23 | border-color: $localSearchBorderColor-isInvalid; 24 | } 25 | 26 | @include darkTheme { 27 | color: $localNavTextColor--darkTheme; 28 | background-color: $localSearchBackgroundColor--darkTheme; 29 | border-color: $localSearchBackgroundColor--darkTheme; 30 | 31 | &.localSearchInput-isInvalid { 32 | border-color: $localSearchBorderColor-isInvalid--darkTheme; 33 | } 34 | } 35 | } 36 | 37 | .localSearchButton { 38 | width: 43px; 39 | height: $localSearchHeight; 40 | font-size: $localNavFontSizeNormal; 41 | color: $buttonTextColor; 42 | background-color: $buttonBackgroundColor; 43 | border: 0; 44 | border-bottom-left-radius: 0; 45 | border-top-left-radius: 0; 46 | border-bottom-right-radius: 4px; 47 | border-top-right-radius: 4px; 48 | 49 | @include darkTheme { 50 | color: $buttonTextColor--darkTheme; 51 | background-color: $buttonBackgroundColor--darkTheme; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_local_tabs.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 1. We want the bottom border on selected tabs to be flush with the bottom of the container. 3 | */ 4 | .localTabs { 5 | display: flex; 6 | align-items: flex-end; // 1 7 | height: 100%; 8 | } 9 | 10 | /** 11 | * 1. Make sure the bottom border is flush with the bottom of the LocalNav. 12 | */ 13 | .localTab { 14 | padding: 5px 0 6px 0; 15 | font-size: 18px; 16 | line-height: 22px; /* 1 */ 17 | color: $localTabTextColor; 18 | border-bottom: 2px solid transparent; 19 | text-decoration: none; 20 | cursor: pointer; 21 | 22 | &:hover, 23 | &:active { 24 | color: $localTabTextColor-isHover; 25 | 26 | @include darkTheme { 27 | color: $localTabTextColor-isHover--darkTheme; 28 | } 29 | } 30 | 31 | &.localTab-isSelected { 32 | color: $localTabTextColor-isSelected; 33 | border-bottom-color: $localTabTextColor-isSelected; 34 | cursor: default; 35 | 36 | @include darkTheme { 37 | color: $localTabTextColor-isSelected--darkTheme; 38 | border-bottom-color: $localTabTextColor-isSelected--darkTheme; 39 | } 40 | } 41 | 42 | & + & { 43 | margin-left: 15px; 44 | } 45 | 46 | @include darkTheme { 47 | color: $localTabTextColor--darkTheme; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/framework/components/local_nav/_local_title.scss: -------------------------------------------------------------------------------- 1 | .localTitle { 2 | display: flex; 3 | align-items: center; 4 | height: 100%; 5 | padding-left: $localNavSideSpacing; 6 | font-size: $localNavFontSizeNormal; 7 | font-weight: bold; 8 | } 9 | -------------------------------------------------------------------------------- /src/framework/framework.scss: -------------------------------------------------------------------------------- 1 | // Normal colors 2 | $textColor: #2d2d2d; 3 | $buttonTextColor: #ffffff; 4 | $buttonBackgroundColor: #9c9c9c; 5 | $linkColor: #328CAA; 6 | $linkColor-isHover: #105A73; 7 | $inputTextColor: $textColor; 8 | $inputBackgroundColor: #ffffff; 9 | $inputBorderColor: $inputBackgroundColor; 10 | 11 | // Dark theme colors 12 | $textColor--darkTheme: #cecece; 13 | $buttonTextColor--darkTheme: #ffffff; 14 | $buttonBackgroundColor--darkTheme: #777777; 15 | $linkColor--darkTheme: #b7e2ea; 16 | $linkColor-isHover--darkTheme: #def2f6; 17 | $inputTextColor--darkTheme: $textColor--darkTheme; 18 | $inputBackgroundColor--darkTheme: #444444; 19 | $inputBorderColor--darkTheme: $inputBackgroundColor--darkTheme; 20 | 21 | @mixin darkTheme() { 22 | .theme-dark & { 23 | @content; 24 | } 25 | } 26 | 27 | @import "components/local_nav/index"; 28 | -------------------------------------------------------------------------------- /src/guide/actions/action_types.js: -------------------------------------------------------------------------------- 1 | 2 | import keyMirror from 'keymirror'; 3 | 4 | export default keyMirror({ 5 | 6 | // Source code viewer actions 7 | OPEN_CODE_VIEWER: null, 8 | UPDATE_CODE_VIEWER: null, 9 | CLOSE_CODE_VIEWER: null, 10 | REGISTER_CODE: null, 11 | UNREGISTER_CODE: null, 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /src/guide/actions/code_viewer/code_viewer_actions.js: -------------------------------------------------------------------------------- 1 | 2 | import ActionTypes from '../action_types'; 3 | 4 | export default { 5 | 6 | openCodeViewer: slug => ({ 7 | type: ActionTypes.OPEN_CODE_VIEWER, 8 | slug, 9 | }), 10 | 11 | updateCodeViewer: slug => ({ 12 | type: ActionTypes.UPDATE_CODE_VIEWER, 13 | slug, 14 | }), 15 | 16 | closeCodeViewer: () => ({ 17 | type: ActionTypes.CLOSE_CODE_VIEWER, 18 | }), 19 | 20 | registerCode: code => ({ 21 | type: ActionTypes.REGISTER_CODE, 22 | code, 23 | }), 24 | 25 | unregisterCode: code => ({ 26 | type: ActionTypes.UNREGISTER_CODE, 27 | code 28 | }), 29 | 30 | }; 31 | -------------------------------------------------------------------------------- /src/guide/actions/index.js: -------------------------------------------------------------------------------- 1 | 2 | export { 3 | default as CodeViewerActions, 4 | } from './code_viewer/code_viewer_actions'; 5 | -------------------------------------------------------------------------------- /src/guide/components/guide_code_viewer/_guide_code_viewer.scss: -------------------------------------------------------------------------------- 1 | 2 | .guideCodeViewer { 3 | position: fixed; 4 | top: $guideNavHeight; 5 | right: 0; 6 | bottom: 0; 7 | width: $guideCodeViewerWidth; 8 | padding: 40px 20px 40px 0; 9 | background-color: white; 10 | transform: translateX($guideCodeViewerWidth); 11 | transition: transform $guideCodeViewerTransition; 12 | overflow: auto; 13 | 14 | @include scrollbar; 15 | 16 | @include whenNarrowerThan($normalBreakpoint) { 17 | width: $guideCodeViewerSmallWidth; 18 | } 19 | 20 | &.is-code-viewer-open { 21 | transform: translateX(0); 22 | } 23 | } 24 | 25 | .guideCodeViewer__header { 26 | padding-bottom: 10px; 27 | line-height: $guideLineHeight; 28 | border-bottom: 1px solid #d6d6d6; 29 | font-size: 18px; 30 | font-weight: 700; 31 | margin-bottom: 10px; 32 | } 33 | 34 | .guideCodeViewer__closeButton { 35 | position: absolute; 36 | top: 5px; 37 | right: 5px; 38 | cursor: pointer; 39 | padding: 10px; 40 | border-radius: 3px; 41 | color: #6b7490; 42 | 43 | &:hover { 44 | color: #2b52cc; 45 | } 46 | } 47 | 48 | 49 | .guideCodeViewer__title { 50 | padding-bottom: 6px; 51 | border-bottom: 1px solid #d6d6d6; 52 | line-height: $guideLineHeight; 53 | font-size: 14px; 54 | } 55 | 56 | .guideCodeViewer__content { 57 | margin: 0 0 16px; 58 | } 59 | 60 | // HLJS 61 | 62 | .hljs { 63 | display: block; 64 | padding: 15px 20px; 65 | color: #637c84; 66 | font-size: 14px; 67 | line-height: 1.3; 68 | font-family: 'Ubuntu Mono', monospace; 69 | } 70 | 71 | .hljs-keyword { 72 | color: #b58900; 73 | } 74 | 75 | .hljs-function { 76 | .hljs-keyword { 77 | color: #268bd2; 78 | } 79 | 80 | .hljs-title { 81 | color: #7441c6; 82 | } 83 | } 84 | 85 | .hljs-built_in { 86 | color: #268bd2; 87 | } 88 | 89 | .hljs-string { 90 | color: #36958e; 91 | } 92 | 93 | .hljs-comment { 94 | color: #9d9d9d; 95 | } 96 | 97 | .hljs-number, 98 | .hljs-literal { 99 | color: #d84a7e; 100 | } 101 | 102 | .hljs-tag { 103 | .hljs-name { 104 | color: #63a35c; 105 | } 106 | 107 | .hljs-attr { 108 | color: #795da3; 109 | } 110 | 111 | .hljs-string { 112 | color: #df5000; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/guide/components/guide_code_viewer/guide_code_viewer.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | PropTypes, 5 | } from 'react'; 6 | 7 | import classNames from 'classnames'; 8 | import hljs from 'highlight.js'; 9 | 10 | export default class GuideCodeViewer extends Component { 11 | 12 | constructor(props) { 13 | super(props); 14 | } 15 | 16 | componentDidUpdate() { 17 | if (this.refs.html) { 18 | hljs.highlightBlock(this.refs.html); 19 | } 20 | 21 | if (this.refs.javascript) { 22 | hljs.highlightBlock(this.refs.javascript); 23 | } 24 | } 25 | 26 | renderSection(title, content, codeClass) { 27 | if (content) { 28 | return ( 29 |
30 |
31 | {title} 32 |
33 |
34 |             
38 |               {content}
39 |             
40 |           
41 |
42 | ); 43 | } 44 | } 45 | 46 | render() { 47 | const classes = classNames('guideCodeViewer', { 48 | 'is-code-viewer-open': this.props.isOpen, 49 | }); 50 | 51 | return ( 52 |
53 |
54 | {this.props.title} 55 |
56 | 57 |
61 | 62 | {this.renderSection('HTML', this.props.html, 'html')} 63 | {this.renderSection('JavaScript', this.props.js, 'javascript')} 64 |
65 | ); 66 | } 67 | 68 | } 69 | 70 | GuideCodeViewer.propTypes = { 71 | isOpen: PropTypes.bool, 72 | onClose: PropTypes.func, 73 | title: PropTypes.string, 74 | html: PropTypes.string, 75 | js: PropTypes.string, 76 | }; 77 | -------------------------------------------------------------------------------- /src/guide/components/guide_example/_guide_example.scss: -------------------------------------------------------------------------------- 1 | .guideExample { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/guide/components/guide_example/guide_example.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | PropTypes, 5 | } from 'react'; 6 | 7 | import { 8 | Slugify, 9 | } from '../../services'; 10 | 11 | import { 12 | GuidePage, 13 | GuidePageSection, 14 | } from '../'; 15 | 16 | export default class GuideExample extends Component { 17 | 18 | constructor(props, sections) { 19 | super(props); 20 | 21 | this.sections = sections.map(section => Object.assign({}, section, { 22 | slug: Slugify.one(section.title), 23 | })); 24 | } 25 | 26 | componentWillMount() { 27 | this.sections.forEach(section => { 28 | this.context.registerCode(section); 29 | }); 30 | } 31 | 32 | componentWillUnmount() { 33 | this.sections.forEach(section => { 34 | this.context.unregisterCode(section); 35 | }); 36 | } 37 | 38 | renderSections() { 39 | return this.sections.map((section, index) => ( 40 | 47 | {section.description} 48 | 49 | )); 50 | } 51 | 52 | render() { 53 | return ( 54 | 57 | {this.renderSections()} 58 | 59 | ); 60 | } 61 | 62 | } 63 | 64 | GuideExample.contextTypes = { 65 | registerCode: PropTypes.func, 66 | unregisterCode: PropTypes.func, 67 | }; 68 | 69 | GuideExample.propTypes = { 70 | route: PropTypes.object.isRequired, 71 | sections: PropTypes.arrayOf(React.PropTypes.shape({ 72 | title: React.PropTypes.string.isRequired, 73 | description: React.PropTypes.any, 74 | html: React.PropTypes.string.isRequired, 75 | js: React.PropTypes.string, 76 | })), 77 | }; 78 | -------------------------------------------------------------------------------- /src/guide/components/guide_nav/_guide_nav.scss: -------------------------------------------------------------------------------- 1 | .guideNav { 2 | position: fixed; 3 | z-index: 1; 4 | top: 0; 5 | left: 0; 6 | right: 0; 7 | height: $guideNavHeight; 8 | padding: 0 20px; 9 | background-color: #e8488b; 10 | color: #ffffff; 11 | box-shadow: 12 | inset 0 -20px 18px rgba(#5a1029, 0.2), 13 | inset 0 -5px 4px rgba(#5a1029, 0.3); 14 | transition: height 0.3s ease; 15 | overflow: hidden; 16 | 17 | &.is-guide-nav-open { 18 | height: 100%; 19 | } 20 | } 21 | 22 | .guideNav__header { 23 | display: flex; 24 | align-items: center; 25 | height: 60px; 26 | } 27 | 28 | .guideNav__menu { 29 | cursor: pointer; 30 | margin-right: 10px; 31 | padding: 10px; 32 | border-radius: 3px; 33 | 34 | &.is-menu-button-pinned, 35 | &:hover { 36 | background-color: rgba(black, 0.15); 37 | } 38 | 39 | &:active { 40 | background-color: rgba(black, 0.2); 41 | box-shadow: inset 0 2px 8px rgba(black, 0.2); 42 | } 43 | } 44 | 45 | .guideNav__title { 46 | color: white; 47 | text-decoration: none; 48 | font-size: 18px; 49 | } 50 | 51 | .guideNav__version { 52 | margin-left: 10px; 53 | font-weight: 300; 54 | font-size: 14px; 55 | } 56 | 57 | .guideNavItem { 58 | color: white; 59 | text-decoration: none; 60 | font-size: 20px; 61 | padding: 10px; 62 | border-radius: 3px; 63 | 64 | &:hover { 65 | background-color: rgba(black, 0.15); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/guide/components/guide_nav/guide_nav.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | PropTypes, 4 | } from 'react'; 5 | 6 | import { 7 | Link, 8 | } from 'react-router'; 9 | 10 | import classNames from 'classnames'; 11 | 12 | const GuideNav = props => { 13 | const classes = classNames('guideNav', { 14 | 'is-guide-nav-open': props.isNavOpen, 15 | }); 16 | 17 | const buttonClasses = classNames('guideNav__menu fa fa-bars', { 18 | 'is-menu-button-pinned': props.isNavOpen, 19 | }); 20 | 21 | const navItems = props.items.map((item, index) => { 22 | return ( 23 | 29 | {item.name} 30 | 31 | ); 32 | }); 33 | 34 | return ( 35 |
36 |
37 |
41 | 46 | Kibana UI Framework {props.version} 47 | 48 |
49 | 50 |
51 | {navItems} 52 |
53 |
54 | ); 55 | }; 56 | 57 | GuideNav.propTypes = { 58 | isNavOpen: PropTypes.bool, 59 | onToggleNav: PropTypes.func, 60 | onClickNavItem: PropTypes.func, 61 | version: PropTypes.string, 62 | items: PropTypes.array, 63 | }; 64 | 65 | export default GuideNav; 66 | -------------------------------------------------------------------------------- /src/guide/components/guide_page/_guide_page.scss: -------------------------------------------------------------------------------- 1 | 2 | @import "../../variables"; 3 | 4 | .guidePage { 5 | display: flex; 6 | } 7 | 8 | .guidePageBody { 9 | flex: 1 1 auto; 10 | padding: 0 80px 0 80px + $guideSideNavWidth; 11 | 12 | @include whenNarrowerThan($normalBreakpoint) { 13 | padding: 0 20px 0 $guideSideNavSmallWidth; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/guide/components/guide_page/guide_page.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | PropTypes, 5 | } from 'react'; 6 | 7 | import { 8 | Slugify, 9 | } from '../../services'; 10 | 11 | import { 12 | GuidePageSideNav, 13 | GuidePageSideNavItem, 14 | } from '../'; 15 | 16 | export default class GuidePage extends Component { 17 | 18 | constructor(props) { 19 | super(props); 20 | 21 | this.onClickLink = this.onClickLink.bind(this); 22 | } 23 | 24 | onClickLink(slug) { 25 | // Scroll to element. 26 | $('html, body').animate({ 27 | scrollTop: $(`#${slug}`).offset().top - 100 28 | }, 250); 29 | 30 | // Load in code viewer. 31 | this.context.updateCodeViewer(slug); 32 | } 33 | 34 | renderSideNavMenu() { 35 | // Traverse children and build side nav from it. 36 | return this.props.children.map((section, index) => { 37 | return ( 38 | 43 | {section.props.title} 44 | 45 | ); 46 | }); 47 | } 48 | 49 | render() { 50 | return ( 51 |
52 | 53 | {this.renderSideNavMenu()} 54 | 55 | 56 |
57 | {this.props.children} 58 |
59 |
60 | ); 61 | } 62 | 63 | } 64 | 65 | GuidePage.contextTypes = { 66 | updateCodeViewer: PropTypes.func, 67 | }; 68 | 69 | GuidePage.propTypes = { 70 | children: PropTypes.any, 71 | title: PropTypes.string, 72 | }; 73 | -------------------------------------------------------------------------------- /src/guide/components/guide_page_section/_guide_page_section.scss: -------------------------------------------------------------------------------- 1 | 2 | @import "../../variables"; 3 | 4 | .guidePageSection { 5 | margin-bottom: 40px; 6 | } 7 | 8 | .guidePageSection__header { 9 | display: flex; 10 | justify-content: space-between; 11 | align-items: center; 12 | padding-bottom: 10px; 13 | line-height: $guideLineHeight; 14 | border-bottom: 1px solid #d6d6d6; 15 | } 16 | 17 | .guidePageSection__title { 18 | font-size: 18px; 19 | font-weight: 700; 20 | } 21 | 22 | .guidePageSection__sourceButton { 23 | line-height: 10px; 24 | padding: 4px 10px; 25 | background-color: #19a8e0; 26 | color: white; 27 | border-radius: 3px; 28 | cursor: pointer; 29 | 30 | &:hover { 31 | box-shadow: 32 | inset 0 1px 0 rgba(#95e1ff, 1), 33 | 0 2px 4px rgba(black, 0.2); 34 | } 35 | 36 | &:active { 37 | box-shadow: 38 | inset 0 20px 20px rgba(black, 0.1), 39 | inset 0 2px 8px rgba(black, 0.2); 40 | } 41 | } 42 | 43 | .guidePageSection__description { 44 | font-size: 14px; 45 | line-height: 21px; 46 | } 47 | 48 | .guidePageSection__example { 49 | & + & { 50 | margin-top: 20px; 51 | } 52 | } 53 | 54 | .guidePageSection__example--standalone { 55 | margin-top: 10px; 56 | } 57 | -------------------------------------------------------------------------------- /src/guide/components/guide_page_section/guide_page_section.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | PropTypes, 5 | } from 'react'; 6 | 7 | import classNames from 'classnames'; 8 | 9 | import { 10 | JsInjector, 11 | } from '../../services'; 12 | 13 | export default class GuidePageSection extends Component { 14 | 15 | constructor(props) { 16 | super(props); 17 | 18 | this.onClickSource = this.onClickSource.bind(this); 19 | } 20 | 21 | componentDidMount() { 22 | // NOTE: This will cause a race condition if a GuidePage adds and removes 23 | // GuidePageSection instances during its lifetime (e.g. if a user is allowed 24 | // to click "add" and "delete" buttons to add and remove GuidePageSections). 25 | // 26 | // In such a race condition, we could end up with GuidePageSections with 27 | // identical id values. 28 | // 29 | // As long as all GuidePageSection instances are added when a GuidePage 30 | // is instantiated, and then they're all removed when a GuidePage is 31 | // removed, we won't encounter this race condition. 32 | if (this.props.js) { 33 | this.scriptId = `${GuidePageSection.SCRIPT_ID}${GuidePageSection.count}`; 34 | GuidePageSection.count++; 35 | // JS injection must occur _after_ the component has been mounted, so 36 | // the component DOM is available for the JS to manipulate. 37 | JsInjector.inject(this.props.js, this.scriptId); 38 | } 39 | 40 | function trimChildren(node) { 41 | if (node.children.length > 0) { 42 | [...node.children].forEach(trimChildren); 43 | return; 44 | } 45 | node.textContent = node.textContent.trim(); 46 | } 47 | 48 | trimChildren(this.refs.html); 49 | trimChildren(this.refs.htmlDarkTheme); 50 | } 51 | 52 | componentWillUnmount() { 53 | JsInjector.remove(this.scriptId); 54 | GuidePageSection.count--; 55 | } 56 | 57 | onClickSource() { 58 | this.context.openCodeViewer(this.props.slug); 59 | } 60 | 61 | render() { 62 | let description; 63 | 64 | if (this.props.children) { 65 | description = ( 66 |
67 | {this.props.children} 68 |
69 | ); 70 | } 71 | 72 | const exampleClasses = classNames('guidePageSection__example', { 73 | 'guidePageSection__example--standalone': !this.props.children, 74 | }); 75 | 76 | return ( 77 |
81 |
82 |
83 | {this.props.title} 84 |
85 |
89 |
90 | 91 | {description} 92 | 93 |
98 | 99 |
104 |
105 | ); 106 | } 107 | 108 | } 109 | 110 | GuidePageSection.count = 0; 111 | GuidePageSection.SCRIPT_ID = 'EXAMPLE_SCRIPT'; 112 | 113 | GuidePageSection.contextTypes = { 114 | openCodeViewer: PropTypes.func, 115 | }; 116 | 117 | GuidePageSection.propTypes = { 118 | title: PropTypes.string, 119 | slug: PropTypes.string, 120 | html: PropTypes.string, 121 | js: PropTypes.string, 122 | children: PropTypes.any, 123 | }; 124 | -------------------------------------------------------------------------------- /src/guide/components/guide_page_side_nav/_guide_page_side_nav.scss: -------------------------------------------------------------------------------- 1 | 2 | .guidePageSideNav { 3 | position: fixed; 4 | top: 100px; 5 | left: 0; 6 | bottom: 0; 7 | width: $guideSideNavWidth; 8 | padding: 0 20px 30px 80px; 9 | overflow: auto; 10 | 11 | @include scrollbar; 12 | 13 | @include whenNarrowerThan($normalBreakpoint) { 14 | padding: 0 20px 30px 20px; 15 | width: $guideSideNavSmallWidth; 16 | } 17 | } 18 | 19 | .guidePageSideNav__title { 20 | padding-bottom: 10px; 21 | margin-bottom: 10px; 22 | font-size: 22px; 23 | line-height: $guideLineHeight; 24 | border-bottom: 1px solid #d6d6d6; 25 | opacity: 0.8; 26 | } 27 | 28 | .guidePageSideNavMenu { 29 | line-height: $guideLineHeight; 30 | } 31 | 32 | .guidePageSideNavMenu__item { 33 | & + & { 34 | margin-top: 6px; 35 | } 36 | } 37 | 38 | .guidePageSideNavMenu__itemLink { 39 | cursor: pointer; 40 | color: #6b7490; 41 | text-decoration: none; 42 | 43 | &:hover { 44 | color: #2b52cc; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/guide/components/guide_page_side_nav/guide_page_side_nav.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | PropTypes, 5 | } from 'react'; 6 | 7 | export default class GuidePageSideNav extends Component { 8 | 9 | constructor(props) { 10 | super(props); 11 | } 12 | 13 | render() { 14 | return ( 15 |
16 |
17 | {this.props.title} 18 |
19 | 20 |
21 | {this.props.children} 22 |
23 |
24 | ); 25 | } 26 | 27 | } 28 | 29 | GuidePageSideNav.propTypes = { 30 | title: PropTypes.string, 31 | children: PropTypes.any, 32 | }; 33 | -------------------------------------------------------------------------------- /src/guide/components/guide_page_side_nav/guide_page_side_nav_item.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | PropTypes, 5 | } from 'react'; 6 | 7 | export default class GuidePageSideNavItem extends Component { 8 | 9 | constructor(props) { 10 | super(props); 11 | 12 | this.onClick = this.onClick.bind(this); 13 | } 14 | 15 | onClick() { 16 | this.props.onClick(this.props.slug); 17 | } 18 | 19 | render() { 20 | return ( 21 |
22 |
26 | {this.props.children} 27 |
28 |
29 | ); 30 | } 31 | 32 | } 33 | 34 | GuidePageSideNavItem.propTypes = { 35 | slug: PropTypes.string, 36 | children: PropTypes.any, 37 | onClick: PropTypes.func, 38 | }; 39 | -------------------------------------------------------------------------------- /src/guide/components/index.js: -------------------------------------------------------------------------------- 1 | 2 | export * from './guide_code_viewer/guide_code_viewer.jsx'; 3 | export { default as GuideCodeViewer } from './guide_code_viewer/guide_code_viewer.jsx'; 4 | 5 | export * from './guide_example/guide_example.jsx'; 6 | export { default as GuideExample } from './guide_example/guide_example.jsx'; 7 | 8 | export * from './guide_nav/guide_nav.jsx'; 9 | export { default as GuideNav } from './guide_nav/guide_nav.jsx'; 10 | 11 | export * from './guide_page/guide_page.jsx'; 12 | export { default as GuidePage } from './guide_page/guide_page.jsx'; 13 | 14 | export * from './guide_page_section/guide_page_section.jsx'; 15 | export { default as GuidePageSection } from './guide_page_section/guide_page_section.jsx'; 16 | 17 | export * from './guide_page_side_nav/guide_page_side_nav.jsx'; 18 | export { default as GuidePageSideNav } from './guide_page_side_nav/guide_page_side_nav.jsx'; 19 | 20 | export * from './guide_page_side_nav/guide_page_side_nav_item.jsx'; 21 | export { default as GuidePageSideNavItem } from './guide_page_side_nav/guide_page_side_nav_item.jsx'; 22 | -------------------------------------------------------------------------------- /src/guide/index.js: -------------------------------------------------------------------------------- 1 | require('./main.scss'); 2 | 3 | import 'babel-polyfill'; 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | import { Provider } from 'react-redux'; 7 | import { 8 | Router, 9 | useRouterHistory, 10 | } from 'react-router'; 11 | import { syncHistoryWithStore } from 'react-router-redux'; 12 | import createHashHistory from 'history/lib/createHashHistory'; 13 | 14 | // Store. 15 | import configureStore from './store/configure_store'; 16 | 17 | // Guide views. 18 | import AppContainer from './views/app_container'; 19 | import HomeView from './views/home/home_view.jsx'; 20 | import NotFoundView from './views/not_found/not_found_view.jsx'; 21 | 22 | import { 23 | Routes, 24 | } from './services'; 25 | 26 | const store = configureStore(); 27 | const browserHistory = useRouterHistory(createHashHistory)({ 28 | queryKey: false, 29 | }); 30 | const history = syncHistoryWithStore(browserHistory, store); 31 | 32 | const childRoutes = Routes.getAppRoutes(); 33 | childRoutes.push({ 34 | path: '*', 35 | component: NotFoundView, 36 | name: 'Page Not Found', 37 | }); 38 | 39 | const routes = [{ 40 | path: '/', 41 | component: AppContainer, 42 | indexRoute: { 43 | component: HomeView, 44 | source: 'views/home/HomeView.jsx', 45 | }, 46 | childRoutes, 47 | }]; 48 | 49 | // Update document title with route name. 50 | const onRouteEnter = route => { 51 | const leafRoute = route.routes[route.routes.length - 1]; 52 | document.title = leafRoute.name ? 53 | `Kibana UI Framework - ${leafRoute.name}` : 54 | 'Kibana UI Framework'; 55 | }; 56 | 57 | const syncTitleWithRoutes = routesList => { 58 | if (!routesList) return; 59 | routesList.forEach(route => { 60 | route.onEnter = onRouteEnter; // eslint-disable-line no-param-reassign 61 | if (route.indexRoute) { 62 | // Index routes have a weird relationship with their "parent" routes, 63 | // so it seems we need to give their own onEnter hooks. 64 | route.indexRoute.onEnter = onRouteEnter; // eslint-disable-line no-param-reassign 65 | } 66 | syncTitleWithRoutes(route.childRoutes); 67 | }); 68 | }; 69 | 70 | syncTitleWithRoutes(routes); 71 | 72 | ReactDOM.render( 73 | 74 | 78 | , 79 | document.getElementById('guide') 80 | ); 81 | -------------------------------------------------------------------------------- /src/guide/main.scss: -------------------------------------------------------------------------------- 1 | 2 | @import "../framework/framework"; 3 | @import "./views/app"; 4 | @import "./components/guide_code_viewer/guide_code_viewer"; 5 | @import "./components/guide_nav/guide_nav"; 6 | @import "./components/guide_page/guide_page"; 7 | @import "./components/guide_page_section/guide_page_section"; 8 | @import "./components/guide_page_side_nav/guide_page_side_nav"; 9 | 10 | * { 11 | box-sizing: border-box; 12 | } 13 | 14 | html, 15 | body { 16 | height: 100%; 17 | } 18 | 19 | /** 20 | * 1. Insane line-height makes it easier to notice when components are relying 21 | * on styles inherited from body. 22 | */ 23 | body { 24 | font-family: 'Lato', 'Helvetica Neue', sans-serif; 25 | background: #ffffff; 26 | line-height: 40px; /* 1 */ 27 | margin: 0; 28 | } 29 | -------------------------------------------------------------------------------- /src/guide/services/example/createExample.js: -------------------------------------------------------------------------------- 1 | 2 | import { 3 | GuideExample, 4 | } from '../../components'; 5 | 6 | export default function creatExample(examples) { 7 | class Example extends GuideExample { 8 | constructor(props) { 9 | super(props, examples); 10 | } 11 | } 12 | 13 | Example.propTypes = Object.assign({}, GuideExample.propTypes); 14 | 15 | return Example; 16 | } 17 | -------------------------------------------------------------------------------- /src/guide/services/index.js: -------------------------------------------------------------------------------- 1 | 2 | export * from './example/createExample'; 3 | export { default as createExample } from './example/createExample'; 4 | 5 | export * from './js_injector/js_injector'; 6 | export { default as JsInjector } from './js_injector/js_injector'; 7 | 8 | export * from './routes/routes'; 9 | export { default as Routes } from './routes/routes'; 10 | 11 | export * from './string/slugify'; 12 | export { default as Slugify } from './string/slugify'; 13 | -------------------------------------------------------------------------------- /src/guide/services/js_injector/js_injector.js: -------------------------------------------------------------------------------- 1 | 2 | import $ from 'jquery'; 3 | 4 | const ID_ATTRIBUTE = 'injected-js-tag-id'; 5 | 6 | export default { 7 | 8 | inject(js, id) { 9 | if (id) { 10 | $(`[${ID_ATTRIBUTE}=${id}]`).remove(); 11 | } 12 | 13 | const script = $(``); 14 | $('body').append(script); 15 | }, 16 | 17 | remove(id) { 18 | $(`[${ID_ATTRIBUTE}=${id}]`).remove(); 19 | }, 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /src/guide/services/routes/Routes.js: -------------------------------------------------------------------------------- 1 | 2 | import Slugify from '../string/slugify'; 3 | 4 | import LocalNavExample 5 | from '../../views/local_nav/local_nav_example.jsx'; 6 | 7 | // Component route names should match the component name exactly. 8 | const components = [{ 9 | name: 'LocalNav', 10 | component: LocalNavExample, 11 | }]; 12 | 13 | export default { 14 | components: Slugify.each(components, 'name', 'path'), 15 | getAppRoutes: function getAppRoutes() { 16 | const list = this.components; 17 | return list.slice(0); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /src/guide/services/string/slugify.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * Lowercases input and replaces spaces with hyphens: 5 | * e.g. 'GridView Example' -> 'gridview-example' 6 | */ 7 | function one(str) { 8 | const parts = str 9 | .toLowerCase() 10 | .replace(/[-]+/g, ' ') 11 | .replace(/[^\w^\s]+/g, '') 12 | .replace(/ +/g, ' ').split(' '); 13 | return parts.join('-'); 14 | } 15 | 16 | function each(items, src, dest) { 17 | return items.map(item => { 18 | const _item = item; 19 | _item[dest] = one(_item[src]); 20 | return _item; 21 | }); 22 | } 23 | 24 | export default { 25 | one, 26 | each, 27 | }; 28 | -------------------------------------------------------------------------------- /src/guide/store/configure_store.js: -------------------------------------------------------------------------------- 1 | import { 2 | applyMiddleware, 3 | createStore, 4 | compose, 5 | } from 'redux'; 6 | import thunk from 'redux-thunk'; 7 | import { browserHistory } from 'react-router'; 8 | import { 9 | routerMiddleware, 10 | routerReducer, 11 | } from 'react-router-redux'; 12 | 13 | import codeViewerReducer from './reducers/code_viewer_reducer'; 14 | 15 | /** 16 | * @param {Object} initialState An object defining the application's initial 17 | * state. 18 | */ 19 | export default function configureStore(initialState) { 20 | function rootReducer(state = {}, action) { 21 | return { 22 | routing: routerReducer(state.routing, action), 23 | codeViewer: codeViewerReducer(state.codeViewer, action), 24 | }; 25 | } 26 | 27 | const finalStore = compose( 28 | applyMiddleware( 29 | thunk, 30 | routerMiddleware(browserHistory) 31 | ) 32 | )(createStore)(rootReducer, initialState); 33 | 34 | return finalStore; 35 | } 36 | -------------------------------------------------------------------------------- /src/guide/store/reducers/code_viewer_reducer.js: -------------------------------------------------------------------------------- 1 | 2 | import ActionTypes from '../../actions/action_types'; 3 | 4 | const defaultState = { 5 | isOpen: false, 6 | codesBySlug: {}, 7 | code: undefined, 8 | }; 9 | 10 | export default function codeViewerReducer(state = defaultState, action) { 11 | switch (action.type) { 12 | case ActionTypes.OPEN_CODE_VIEWER: { 13 | const newCode = state.codesBySlug[action.slug]; 14 | 15 | if (state.code === newCode) { 16 | // If we are opening the existing code, then close the viewer. 17 | return Object.assign({}, state, { 18 | isOpen: false, 19 | code: undefined, 20 | }); 21 | } 22 | 23 | return Object.assign({}, state, { 24 | isOpen: true, 25 | code: newCode, 26 | }); 27 | } 28 | 29 | case ActionTypes.UPDATE_CODE_VIEWER: { 30 | if (state.isOpen) { 31 | return Object.assign({}, state, { 32 | code: state.codesBySlug[action.slug], 33 | }); 34 | } 35 | return state; 36 | } 37 | 38 | case ActionTypes.CLOSE_CODE_VIEWER: { 39 | return Object.assign({}, state, { 40 | isOpen: false, 41 | code: undefined, 42 | }); 43 | } 44 | 45 | case ActionTypes.REGISTER_CODE: { 46 | const codesBySlug = Object.assign({}, state.codesBySlug, { 47 | [action.code.slug]: action.code, 48 | }); 49 | 50 | return Object.assign({}, state, { 51 | codesBySlug 52 | }); 53 | } 54 | 55 | case ActionTypes.UNREGISTER_CODE: { 56 | const codesBySlug = Object.assign({}, state.codesBySlug); 57 | delete codesBySlug[action.code.slug]; 58 | 59 | return Object.assign({}, state, { 60 | codesBySlug 61 | }); 62 | } 63 | 64 | default: 65 | break; 66 | } 67 | 68 | return state; 69 | } 70 | -------------------------------------------------------------------------------- /src/guide/variables.scss: -------------------------------------------------------------------------------- 1 | 2 | $guideLineHeight: 24px; 3 | $guideNavHeight: 60px; 4 | $guideSideNavWidth: 400px; 5 | $guideSideNavSmallWidth: 220px; 6 | $guideCodeViewerWidth: 700px; 7 | $guideCodeViewerSmallWidth: 580px; 8 | $guideCodeViewerTransition: 0.2s ease; 9 | 10 | $normalBreakpoint: 1900px; 11 | 12 | @mixin whenNarrowerThan($browserWidth) { 13 | @media only screen and (max-width: #{$browserWidth}) { 14 | @content; 15 | } 16 | } 17 | 18 | @mixin whenWiderThan($browserWidth) { 19 | @media only screen and (min-width: #{$browserWidth}) { 20 | @content; 21 | } 22 | } 23 | 24 | @mixin scrollbar($color: rgba(#454D58, 0.4)) { 25 | &::-webkit-scrollbar { 26 | width: 16px; 27 | height: 16px; 28 | } 29 | 30 | &::-webkit-scrollbar-thumb { 31 | background-color: $color; 32 | border: 6px solid transparent; 33 | background-clip: content-box; 34 | } 35 | 36 | &::-webkit-scrollbar-track { 37 | background-color: transparent; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/guide/views/_app.scss: -------------------------------------------------------------------------------- 1 | 2 | @import "../variables"; 3 | @import "./home/home_view"; 4 | 5 | .guide { 6 | display: flex; 7 | height: 100%; 8 | } 9 | 10 | .guideContent { 11 | flex: 1 1 auto; 12 | padding-top: 100px; 13 | transition: padding-right $guideCodeViewerTransition; 14 | 15 | &.is-code-viewer-open { 16 | padding-right: $guideCodeViewerWidth; 17 | 18 | @include whenNarrowerThan($normalBreakpoint) { 19 | padding-right: $guideCodeViewerSmallWidth; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/guide/views/app_container.js: -------------------------------------------------------------------------------- 1 | 2 | import { bindActionCreators } from 'redux'; 3 | import { connect } from 'react-redux'; 4 | import AppView from './app_view.jsx'; 5 | 6 | import { 7 | CodeViewerActions, 8 | } from '../actions'; 9 | 10 | function mapStateToProps(state, ownProps) { 11 | return { 12 | routes: ownProps.routes, 13 | isCodeViewerOpen: state.codeViewer.isOpen, 14 | code: state.codeViewer.code, 15 | }; 16 | } 17 | 18 | function mapDispatchToProps(dispatch) { 19 | const actions = { 20 | openCodeViewer: CodeViewerActions.openCodeViewer, 21 | updateCodeViewer: CodeViewerActions.updateCodeViewer, 22 | closeCodeViewer: CodeViewerActions.closeCodeViewer, 23 | registerCode: CodeViewerActions.registerCode, 24 | unregisterCode: CodeViewerActions.unregisterCode, 25 | }; 26 | 27 | return bindActionCreators(actions, dispatch); 28 | } 29 | 30 | export default connect(mapStateToProps, mapDispatchToProps)(AppView); 31 | -------------------------------------------------------------------------------- /src/guide/views/app_view.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | PropTypes, 5 | } from 'react'; 6 | 7 | import classNames from 'classnames'; 8 | 9 | import { 10 | Routes, 11 | } from '../services'; 12 | 13 | import { 14 | GuideCodeViewer, 15 | GuideNav, 16 | } from '../components'; 17 | 18 | // Inject version into header. 19 | const pkg = require('json!../../../package.json'); 20 | 21 | export default class AppView extends Component { 22 | 23 | constructor(props) { 24 | super(props); 25 | 26 | this.state = { 27 | isNavOpen: false, 28 | }; 29 | 30 | this.onClickNavItem = this.onClickNavItem.bind(this); 31 | this.onToggleNav = this.onToggleNav.bind(this); 32 | this.onCloseCodeViewer = this.onCloseCodeViewer.bind(this); 33 | } 34 | 35 | getChildContext() { 36 | return { 37 | openCodeViewer: this.props.openCodeViewer, 38 | updateCodeViewer: this.props.updateCodeViewer, 39 | registerCode: this.props.registerCode, 40 | unregisterCode: this.props.unregisterCode, 41 | }; 42 | } 43 | 44 | onClickNavItem() { 45 | this.setState({ 46 | isNavOpen: false, 47 | }); 48 | } 49 | 50 | onCloseCodeViewer() { 51 | this.props.closeCodeViewer(); 52 | } 53 | 54 | onToggleNav() { 55 | this.setState({ 56 | isNavOpen: !this.state.isNavOpen, 57 | }) 58 | } 59 | 60 | render() { 61 | const contentClasses = classNames('guideContent', { 62 | 'is-code-viewer-open': this.props.isCodeViewerOpen, 63 | }); 64 | 65 | return ( 66 |
67 | 74 | 75 |
76 | {this.props.children} 77 |
78 | 79 | 86 |
87 | ); 88 | } 89 | 90 | } 91 | 92 | AppView.childContextTypes = { 93 | openCodeViewer: PropTypes.func, 94 | updateCodeViewer: PropTypes.func, 95 | registerCode: PropTypes.func, 96 | unregisterCode: PropTypes.func, 97 | }; 98 | 99 | AppView.propTypes = { 100 | children: PropTypes.any, 101 | routes: PropTypes.array.isRequired, 102 | openCodeViewer: PropTypes.func, 103 | updateCodeViewer: PropTypes.func, 104 | closeCodeViewer: PropTypes.func, 105 | registerCode: PropTypes.func, 106 | unregisterCode: PropTypes.func, 107 | isCodeViewerOpen: PropTypes.bool, 108 | code: PropTypes.object, 109 | }; 110 | 111 | AppView.defaultProps = { 112 | code: {}, 113 | }; 114 | -------------------------------------------------------------------------------- /src/guide/views/home/_home_view.scss: -------------------------------------------------------------------------------- 1 | 2 | @import "../../variables"; 3 | 4 | .guideHome { 5 | display: flex; 6 | justify-content: center; 7 | } 8 | 9 | .guideHome__panel { 10 | width: 100%; 11 | max-width: 600px; 12 | max-height: 500px; 13 | padding: 60px; 14 | margin-bottom: 20px; 15 | border-radius: 3px; 16 | background-color: #e8e8e8; 17 | line-height: $guideLineHeight; 18 | } 19 | 20 | .guideHome__panelTitle { 21 | font-weight: 700; 22 | font-size: 22px; 23 | margin-bottom: 20px; 24 | } 25 | 26 | .guideHome__panelText { 27 | font-size: 18px; 28 | } 29 | -------------------------------------------------------------------------------- /src/guide/views/home/home_view.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | } from 'react'; 5 | 6 | export default class HomeView extends Component { 7 | 8 | constructor(props) { 9 | super(props); 10 | } 11 | 12 | render() { 13 | return ( 14 |
15 |
16 |
17 | Welcome to the Kibana UI Framework 18 |
19 | 20 |
21 | Get started by clicking the menu button in the top left corner of the screen. 22 |
23 |
24 |
25 | ); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_breadcrumbs/local_nav_breadcrumbs.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 11 | 12 | 17 |
18 |
19 | 20 |
21 |
22 |
23 | New 24 |
25 | 26 |
27 | Save 28 |
29 | 30 |
31 | Open 32 |
33 | 34 | 38 |
39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_dropdown/local_nav_dropdown.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 11 | 12 | 17 |
18 |
19 | 20 |
21 |
22 |
23 | New 24 |
25 | 26 |
27 | Save 28 |
29 | 30 |
31 | Open 32 |
33 | 34 | 38 |
39 |
40 |
41 | 42 |
43 | 44 | 47 | 48 | 49 |
Dropdown title
50 | 51 | 52 |
53 | Here's some help text to explain the purpose of the dropdown. 54 |
55 | 56 | 57 |
58 | Here's some warning text in case the user has something misconfigured. 59 |
60 | 61 |
62 | 63 |
64 |
65 | Header for a section of content 66 |
67 |
68 | 69 | 70 | 75 |
76 | 77 |
78 | 79 |
80 |
81 | Header for another section of content 82 |
83 | 97 |
98 | 99 | 100 | 106 | 107 | 108 |
109 | Here are some notes to explain the purpose of this section of the dropdown. 110 |
111 |
112 |
113 | 114 |
115 |
116 | 122 | 125 |
126 |
127 |
128 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_dropdown_panels/local_nav_dropdown_panels.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 11 | 12 | 17 |
18 |
19 | 20 |
21 |
22 |
23 | New 24 |
25 | 26 |
27 | Save 28 |
29 | 30 |
31 | Open 32 |
33 | 34 | 38 |
39 |
40 |
41 | 42 |
43 | 44 | 47 | 48 |
49 | 50 |
51 | 52 |
Left panel
53 | 54 | 55 |
56 | Here's some help text to explain the purpose of the dropdown. 57 |
58 |
59 | 60 | 61 |
62 | 63 |
Right panel
64 | 65 | 66 |
67 | Here's some help text to explain the purpose of the dropdown. 68 |
69 |
70 |
71 |
72 | 73 |
74 |
75 | 81 | 84 |
85 |
86 |
87 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_example.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React from 'react'; 3 | 4 | import { 5 | createExample, 6 | } from '../../services'; 7 | 8 | export default createExample([{ 9 | title: 'Simple', 10 | description: ( 11 |

Here's a simple LocalNav with a Title in the top left corner and Menu in the top right.

12 | ), 13 | html: require('./local_nav_simple/local_nav_simple.html'), 14 | }, { 15 | title: 'Breadcrumbs', 16 | description: ( 17 |

You can replace the Title with Breadcrumbs.

18 | ), 19 | html: require('./local_nav_breadcrumbs/local_nav_breadcrumbs.html'), 20 | }, { 21 | title: 'Search', 22 | description: ( 23 |

You can add a Search component for filtering results.

24 | ), 25 | html: require('./local_nav_search/local_nav_search.html'), 26 | }, { 27 | title: 'Invalid Search', 28 | html: require('./local_nav_search_error/local_nav_search_error.html'), 29 | }, { 30 | title: 'Selected and disabled Menu Item states', 31 | description: ( 32 |
33 |

When the user selects a Menu Item, additional content can be displayed inside of a Dropdown.

34 |

Menu Items can also be disabled, in which case they become non-interactive.

35 |
36 | ), 37 | html: require('./local_nav_menu_item_states/local_nav_menu_item_states.html'), 38 | }, { 39 | title: 'Dropdown', 40 | description: ( 41 |

Selecting a Menu Item will commonly result in an open Dropdown.

42 | ), 43 | html: require('./local_nav_dropdown/local_nav_dropdown.html'), 44 | }, { 45 | title: 'Dropdown panels', 46 | description: ( 47 |

You can split the Dropdown into side-by-side Panels.

48 | ), 49 | html: require('./local_nav_dropdown_panels/local_nav_dropdown_panels.html'), 50 | }, { 51 | title: 'Tabs', 52 | description: ( 53 |

You can display Tabs for navigating local content.

54 | ), 55 | html: require('./local_nav_tabs/local_nav_tabs.html'), 56 | }]); 57 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_menu_item_states/local_nav_menu_item_states.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 11 | 12 | 17 |
18 |
19 | 20 |
21 |
22 |
23 | New 24 |
25 | 26 |
27 | Save 28 |
29 | 30 |
31 | Open 32 |
33 | 34 | 38 |
39 |
40 |
41 | 42 |
43 |
44 | 50 | 53 |
54 |
55 |
56 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_search/local_nav_search.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 11 | 12 | 17 |
18 |
19 | 20 |
21 |
22 | 25 | 26 | 29 | 30 | 33 | 34 | 38 |
39 |
40 |
41 | 42 |
43 |
44 | 50 | 53 |
54 |
55 |
56 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_search_error/local_nav_search_error.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 11 | 12 | 17 |
18 |
19 | 20 |
21 |
22 | 25 | 26 | 29 | 30 | 33 | 34 | 38 |
39 |
40 |
41 | 42 |
43 |
44 | 50 | 53 |
54 |
55 |
56 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_simple/local_nav_simple.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | Untitled Document 7 |
8 |
9 | 10 |
11 |
12 |
13 | New 14 |
15 | 16 |
17 | Save 18 |
19 | 20 |
21 | Open 22 |
23 | 24 | 28 |
29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /src/guide/views/local_nav/local_nav_tabs/local_nav_tabs.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 | 11 | 12 | 17 |
18 |
19 | 20 |
21 |
22 | 25 | 26 | 29 | 30 | 33 | 34 | 38 |
39 |
40 |
41 | 42 | 57 |
58 | -------------------------------------------------------------------------------- /src/guide/views/not_found/not_found_view.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { 3 | Component, 4 | } from 'react'; 5 | 6 | export default class NotFoundView extends Component { 7 | 8 | constructor(props) { 9 | super(props); 10 | } 11 | 12 | render() { 13 | return ( 14 |
15 |

Page not found.

16 |
17 | ); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = { 4 | devtool: 'source-map', 5 | 6 | entry: { 7 | guide: './src/guide/index.js' 8 | }, 9 | 10 | output: { 11 | path: path.resolve(__dirname, 'public'), 12 | filename: 'bundle.js' 13 | }, 14 | 15 | resolve: { 16 | root: [ 17 | path.resolve(__dirname, 'src') 18 | ] 19 | }, 20 | 21 | module: { 22 | loaders: [{ 23 | test: /\.jsx?$/, 24 | loader: 'babel', 25 | query: { 26 | presets: ['es2015', 'react'] 27 | }, 28 | exclude: /node_modules/ 29 | }, { 30 | test: /\.scss$/, 31 | loaders: ['style', 'css', 'sass'], 32 | exclude: /node_modules/ 33 | }, { 34 | test: /\.html$/, 35 | loader: 'html', 36 | exclude: /node_modules/ 37 | }, { 38 | test: require.resolve('jquery'), 39 | loader: 'expose?jQuery!expose?$' 40 | }] 41 | } 42 | }; 43 | --------------------------------------------------------------------------------