├── .eslintignore
├── CONTRIBUTING.md
├── .node-version
├── .npmrc
├── .eslintrc
├── .babelrc
├── .gitignore
├── src
├── guide
│ ├── components
│ │ ├── guide_example
│ │ │ ├── _guide_example.scss
│ │ │ └── guide_example.jsx
│ │ ├── guide_page
│ │ │ ├── _guide_page.scss
│ │ │ └── guide_page.jsx
│ │ ├── guide_page_side_nav
│ │ │ ├── guide_page_side_nav.jsx
│ │ │ ├── guide_page_side_nav_item.jsx
│ │ │ └── _guide_page_side_nav.scss
│ │ ├── index.js
│ │ ├── guide_page_section
│ │ │ ├── _guide_page_section.scss
│ │ │ └── guide_page_section.jsx
│ │ ├── guide_nav
│ │ │ ├── _guide_nav.scss
│ │ │ └── guide_nav.jsx
│ │ └── guide_code_viewer
│ │ │ ├── guide_code_viewer.jsx
│ │ │ └── _guide_code_viewer.scss
│ ├── actions
│ │ ├── index.js
│ │ ├── action_types.js
│ │ └── code_viewer
│ │ │ └── code_viewer_actions.js
│ ├── views
│ │ ├── not_found
│ │ │ └── not_found_view.jsx
│ │ ├── _app.scss
│ │ ├── home
│ │ │ ├── _home_view.scss
│ │ │ └── home_view.jsx
│ │ ├── local_nav
│ │ │ ├── local_nav_simple
│ │ │ │ └── local_nav_simple.html
│ │ │ ├── local_nav_breadcrumbs
│ │ │ │ └── local_nav_breadcrumbs.html
│ │ │ ├── local_nav_search
│ │ │ │ └── local_nav_search.html
│ │ │ ├── local_nav_tabs
│ │ │ │ └── local_nav_tabs.html
│ │ │ ├── local_nav_search_error
│ │ │ │ └── local_nav_search_error.html
│ │ │ ├── local_nav_menu_item_states
│ │ │ │ └── local_nav_menu_item_states.html
│ │ │ ├── local_nav_example.jsx
│ │ │ ├── local_nav_dropdown_panels
│ │ │ │ └── local_nav_dropdown_panels.html
│ │ │ └── local_nav_dropdown
│ │ │ │ └── local_nav_dropdown.html
│ │ ├── app_container.js
│ │ └── app_view.jsx
│ ├── services
│ │ ├── example
│ │ │ └── createExample.js
│ │ ├── index.js
│ │ ├── js_injector
│ │ │ └── js_injector.js
│ │ ├── routes
│ │ │ └── Routes.js
│ │ └── string
│ │ │ └── slugify.js
│ ├── main.scss
│ ├── store
│ │ ├── configure_store.js
│ │ └── reducers
│ │ │ └── code_viewer_reducer.js
│ ├── variables.scss
│ └── index.js
└── framework
│ ├── components
│ └── local_nav
│ │ ├── _local_title.scss
│ │ ├── _local_nav.scss
│ │ ├── _local_tabs.scss
│ │ ├── _local_breadcrumbs.scss
│ │ ├── _local_search.scss
│ │ ├── _local_menu.scss
│ │ ├── _index.scss
│ │ └── _local_dropdown.scss
│ └── framework.scss
├── README.md
├── .editorconfig
├── LICENSE.md
├── public
└── index.html
├── webpack.config.js
├── package.json
└── dist
└── framework.css
/.eslintignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | 4.4.7
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | save-exact=true
2 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | ---
2 | extends: '@elastic/kibana'
3 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | *.log
4 | public/*.js*
5 |
--------------------------------------------------------------------------------
/src/guide/components/guide_example/_guide_example.scss:
--------------------------------------------------------------------------------
1 | .guideExample {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/src/guide/actions/index.js:
--------------------------------------------------------------------------------
1 |
2 | export {
3 | default as CodeViewerActions,
4 | } from './code_viewer/code_viewer_actions';
5 |
--------------------------------------------------------------------------------
/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).
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/views/local_nav/local_nav_simple/local_nav_simple.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Untitled Document
7 |
8 |
9 |
10 |
11 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/views/local_nav/local_nav_breadcrumbs/local_nav_breadcrumbs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/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/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_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/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/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/guide/views/local_nav/local_nav_search/local_nav_search.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
39 |
40 |
41 |
42 |
43 |
44 |
50 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/guide/views/local_nav/local_nav_tabs/local_nav_tabs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
39 |
40 |
41 |
42 |
57 |
58 |
--------------------------------------------------------------------------------
/src/guide/views/local_nav/local_nav_search_error/local_nav_search_error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
39 |
40 |
41 |
42 |
43 |
44 |
50 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/guide/views/local_nav/local_nav_menu_item_states/local_nav_menu_item_states.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
39 |
40 |
41 |
42 |
43 |
44 |
50 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/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.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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/views/local_nav/local_nav_dropdown_panels/local_nav_dropdown_panels.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
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/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/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/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/views/local_nav/local_nav_dropdown/local_nav_dropdown.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
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 |
68 |
69 |
70 |
75 |
76 |
77 |
78 |
79 |
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------