diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index 48d4f929b6851..4ea7b04ebef6d 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -3,11 +3,18 @@ This guide applies to all development within the Kibana project and is recommended for the development of all Kibana plugins. +- [General](#general) +- [HTML](#html) +- [API endpoints](#api-endpoints) +- [TypeScript/JavaScript](#typeScript/javaScript) +- [SASS files](#sass-files) +- [React](#react) + Besides the content in this style guide, the following style guides may also apply to all development within the Kibana project. Please make sure to also read them: -- [Accessibility style guide](https://elastic.github.io/eui/#/guidelines/accessibility) -- [SASS style guide](https://elastic.github.io/eui/#/guidelines/sass) +- [Accessibility style guide (EUI Docs)](https://elastic.github.io/eui/#/guidelines/accessibility) +- [SASS style guide (EUI Docs)](https://elastic.github.io/eui/#/guidelines/sass) ## General @@ -582,6 +589,39 @@ Do not use setters, they cause more problems than they can solve. [sideeffect]: http://en.wikipedia.org/wiki/Side_effect_(computer_science) +## SASS files + +When writing a new component, create a sibling SASS file of the same name and import directly into the **top** of the JS/TS component file. Doing so ensures the styles are never separated or lost on import and allows for better modularization (smaller individual plugin asset footprint). + +All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & Kibana invisibles (SASS variables, mixins, functions) from the [`globals_[theme].scss` file](src/legacy/ui/public/styles/_globals_v7light.scss). + +While the styles for this component will only be loaded if the component exists on the page, +the styles **will** be global and so it is recommended to use a three letter prefix on your +classes to ensure proper scope. + +**Example:** + +```tsx +// component.tsx + +import './component.scss'; +// All other imports below the SASS import + +export const Component = () => { + return ( +
+ ); +} +``` + +```scss +// component.scss + +.plgComponent { ... } +``` + +Do not use the underscore `_` SASS file naming pattern when importing directly into a javascript file. + ## React The following style guide rules are specific for working with the React framework. diff --git a/docs/developer/getting-started/index.asciidoc b/docs/developer/getting-started/index.asciidoc index ff1623e22f1eb..47c4a52daf303 100644 --- a/docs/developer/getting-started/index.asciidoc +++ b/docs/developer/getting-started/index.asciidoc @@ -29,7 +29,7 @@ you can switch to the correct version when using nvm by running: ---- nvm use ---- - + Install the latest version of https://yarnpkg.com[yarn]. Bootstrap {kib} and install all the dependencies: @@ -93,13 +93,13 @@ yarn es snapshot --license trial `trial` will give you access to all capabilities. -Read about more options for <>, like connecting to a remote host, running from source, -preserving data inbetween runs, running remote cluster, etc. +Read about more options for <>, like connecting to a remote host, running from source, +preserving data inbetween runs, running remote cluster, etc. [float] === Run {kib} -In another terminal window, start up {kib}. Include developer examples by adding an optional `--run-examples` flag. +In another terminal window, start up {kib}. Include developer examples by adding an optional `--run-examples` flag. [source,bash] ---- @@ -125,8 +125,6 @@ cause the {kib} server to reboot. * <> -* <> - * <> * <> @@ -137,8 +135,6 @@ include::sample-data.asciidoc[] include::debugging.asciidoc[] -include::sass.asciidoc[] - include::building-kibana.asciidoc[] include::development-plugin-resources.asciidoc[] \ No newline at end of file diff --git a/docs/developer/getting-started/sass.asciidoc b/docs/developer/getting-started/sass.asciidoc deleted file mode 100644 index 194e001f642e1..0000000000000 --- a/docs/developer/getting-started/sass.asciidoc +++ /dev/null @@ -1,36 +0,0 @@ -[[kibana-sass]] -=== Styling with SASS - -When writing a new component, create a sibling SASS file of the same -name and import directly into the JS/TS component file. Doing so ensures -the styles are never separated or lost on import and allows for better -modularization (smaller individual plugin asset footprint). - -All SASS (.scss) files will automatically build with the -https://elastic.github.io/eui/#/guidelines/sass[EUI] & {kib} invisibles (SASS variables, mixins, functions) from -the {kib-repo}tree/{branch}/src/legacy/ui/public/styles/_globals_v7light.scss[globals_THEME.scss] file. - -*Example:* - -[source,tsx] ----- -// component.tsx - -import './component.scss'; - -export const Component = () => { - return ( -
- ); -} ----- - -[source,scss] ----- -// component.scss - -.plgComponent { ... } ----- - -Do not use the underscore `_` SASS file naming pattern when importing -directly into a javascript file. \ No newline at end of file diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss index 261d6672df93a..a7c8e4dfc6baa 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss @@ -1,6 +1,7 @@ .lnsDataPanelWrapper { flex: 1 0 100%; overflow: hidden; + background-color: lightOrDarkTheme($euiColorLightestShade, $euiColorInk); } .lnsDataPanelWrapper__switchSource { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss index 35c28595a59c0..c2e8d4f6c0049 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss @@ -22,7 +22,7 @@ // Leave out bottom padding so the suggestions scrollbar stays flush to window edge // Leave out left padding so the left sidebar's focus states are visible outside of content bounds // This also means needing to add same amount of margin to page content and suggestion items - padding: $euiSize $euiSize 0 0; + padding: $euiSize $euiSize 0; &:first-child { padding-left: $euiSize; @@ -40,9 +40,10 @@ .lnsFrameLayout__sidebar--right { @include euiScrollBar; - min-width: $lnsPanelMinWidth + $euiSize; + background-color: lightOrDarkTheme($euiColorLightestShade, $euiColorInk); + min-width: $lnsPanelMinWidth + $euiSizeXL; overflow-x: hidden; overflow-y: scroll; - padding-top: $euiSize; + padding: $euiSize 0 $euiSize $euiSize; max-height: 100%; } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss index 924f44a37c459..4e13fd95d1961 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss @@ -2,6 +2,10 @@ margin-bottom: $euiSizeS; } +.lnsLayerPanel__sourceFlexItem { + max-width: calc(100% - #{$euiSize * 3.625}); +} + .lnsLayerPanel__row { background: $euiColorLightestShade; padding: $euiSizeS; @@ -32,5 +36,6 @@ } .lnsLayerPanel__styleEditor { - width: $euiSize * 28; + width: $euiSize * 30; + padding: $euiSizeS; } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx index cc8d97a445016..8d31e1bcc2e6a 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx @@ -40,8 +40,7 @@ export function DimensionPopover({ }} button={trigger} anchorPosition="leftUp" - withTitle - panelPaddingSize="s" + panelPaddingSize="none" > {panel} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 36d5bfd965e26..e51a155a19935 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -103,7 +103,7 @@ export function LayerPanel( {layerDatasource && ( - + - - - + ), }, ]; @@ -194,7 +191,6 @@ export function LayerPanel( }), content: (
- - setIsOpen(!isOpen)} data-test-subj="lns_layer_settings" /> diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss index ae4a7861b1d90..8a44d59ff1c0d 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss @@ -5,15 +5,9 @@ } } -.lnsChartSwitch__triggerButton { - @include euiTitle('xs'); - background-color: $euiColorEmptyShade; - border-color: $euiColorLightShade; -} - .lnsChartSwitch__summaryIcon { margin-right: $euiSizeS; - transform: translateY(-2px); + transform: translateY(-1px); } // Targeting img as this won't target normal EuiIcon's only the custom svgs's diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx index 4c5a44ecc695e..fa87d80e5cf40 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import './chart_switch.scss'; import React, { useState, useMemo } from 'react'; import { EuiIcon, @@ -11,7 +12,6 @@ import { EuiPopoverTitle, EuiKeyPadMenu, EuiKeyPadMenuItem, - EuiButton, } from '@elastic/eui'; import { flatten } from 'lodash'; import { i18n } from '@kbn/i18n'; @@ -19,6 +19,7 @@ import { Visualization, FramePublicAPI, Datasource } from '../../../types'; import { Action } from '../state_management'; import { getSuggestions, switchToSuggestion, Suggestion } from '../suggestion_helpers'; import { trackUiEvent } from '../../../lens_ui_telemetry'; +import { ToolbarButton } from '../../../toolbar_button'; interface VisualizationSelection { visualizationId: string; @@ -72,8 +73,6 @@ function VisualizationSummary(props: Props) { ); } -import './chart_switch.scss'; - export function ChartSwitch(props: Props) { const [flyoutOpen, setFlyoutOpen] = useState(false); @@ -202,16 +201,13 @@ export function ChartSwitch(props: Props) { panelClassName="lnsChartSwitch__popoverPanel" panelPaddingSize="s" button={ - setFlyoutOpen(!flyoutOpen)} data-test-subj="lnsChartSwitchPopover" - iconSide="right" - iconType="arrowDown" - color="text" + fontWeight="bold" > - + } isOpen={flyoutOpen} closePopover={() => setFlyoutOpen(false)} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx index beb6952556067..9f5b6665b31d3 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx @@ -15,6 +15,7 @@ import { EuiText, EuiBetaBadge, EuiButtonEmpty, + EuiLink, } from '@elastic/eui'; import { CoreStart, CoreSetup } from 'kibana/public'; import { @@ -208,18 +209,20 @@ export function InnerWorkspacePanel({ />{' '}

- - - +

+ + + + + +

); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx index 94c0f4083dfee..5e2fe9d7bbc14 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx @@ -6,18 +6,13 @@ import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; -import { - EuiButtonEmpty, - EuiPopover, - EuiPopoverTitle, - EuiSelectable, - EuiButtonEmptyProps, -} from '@elastic/eui'; +import { EuiPopover, EuiPopoverTitle, EuiSelectable } from '@elastic/eui'; import { EuiSelectableProps } from '@elastic/eui/src/components/selectable/selectable'; import { IndexPatternRef } from './types'; import { trackUiEvent } from '../lens_ui_telemetry'; +import { ToolbarButtonProps, ToolbarButton } from '../toolbar_button'; -export type ChangeIndexPatternTriggerProps = EuiButtonEmptyProps & { +export type ChangeIndexPatternTriggerProps = ToolbarButtonProps & { label: string; title?: string; }; @@ -40,29 +35,24 @@ export function ChangeIndexPattern({ const createTrigger = function () { const { label, title, ...rest } = trigger; return ( - setPopoverIsOpen(!isPopoverOpen)} + fullWidth {...rest} > {label} - + ); }; return ( <> setPopoverIsOpen(false)} - className="eui-textTruncate" - anchorClassName="eui-textTruncate" display="block" panelPaddingSize="s" ownFocus diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss index 3e767502fae3b..70fb57ee79ee5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss @@ -7,13 +7,7 @@ .lnsInnerIndexPatternDataPanel__header { display: flex; align-items: center; - height: $euiSize * 3; - margin-top: -$euiSizeS; -} - -.lnsInnerIndexPatternDataPanel__triggerButton { - @include euiTitle('xs'); - line-height: $euiSizeXXL; + margin-bottom: $euiSizeS; } /** diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx index 91c068c2b4fab..6854452fd02a4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx @@ -424,7 +424,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ label: currentIndexPattern.title, title: currentIndexPattern.title, 'data-test-subj': 'indexPattern-switch-link', - className: 'lnsInnerIndexPatternDataPanel__triggerButton', + fontWeight: 'bold', }} indexPatternId={currentIndexPatternId} indexPatternRefs={indexPatternRefs} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss index f619fa55f9ceb..b8986cea48d4e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss @@ -1,7 +1,6 @@ .lnsIndexPatternDimensionEditor { - flex-grow: 1; - line-height: 0; - overflow: hidden; + width: $euiSize * 30; + padding: $euiSizeS; } .lnsIndexPatternDimensionEditor__left, @@ -11,10 +10,7 @@ .lnsIndexPatternDimensionEditor__left { background-color: $euiPageBackgroundColor; -} - -.lnsIndexPatternDimensionEditor__right { - width: $euiSize * 20; + width: $euiSize * 8; } .lnsIndexPatternDimensionEditor__operation > button { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx index 5b84108b99dd9..2fb7382f992e7 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx @@ -299,25 +299,31 @@ export function PopoverEditor(props: PopoverEditorProps) {
{incompatibleSelectedOperationType && selectedColumn && ( - + <> + + + )} {incompatibleSelectedOperationType && !selectedColumn && ( - + <> + + + )} {!incompatibleSelectedOperationType && ParamEditor && ( <> diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx index 1ae10e07b0c24..dac451013826e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx @@ -27,7 +27,8 @@ export function LayerPanel({ state, layerId, onChangeIndexPattern }: IndexPatter label: state.indexPatterns[layer.indexPatternId].title, title: state.indexPatterns[layer.indexPatternId].title, 'data-test-subj': 'lns_layerIndexPatternLabel', - size: 'xs', + size: 's', + fontWeight: 'normal', }} indexPatternId={layer.indexPatternId} indexPatternRefs={state.indexPatternRefs} diff --git a/x-pack/plugins/lens/public/toolbar_button/index.tsx b/x-pack/plugins/lens/public/toolbar_button/index.tsx new file mode 100644 index 0000000000000..ee6489726a0a7 --- /dev/null +++ b/x-pack/plugins/lens/public/toolbar_button/index.tsx @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ToolbarButtonProps, ToolbarButton } from './toolbar_button'; diff --git a/x-pack/plugins/lens/public/toolbar_button/toolbar_button.scss b/x-pack/plugins/lens/public/toolbar_button/toolbar_button.scss new file mode 100644 index 0000000000000..f36fdfdf02aba --- /dev/null +++ b/x-pack/plugins/lens/public/toolbar_button/toolbar_button.scss @@ -0,0 +1,30 @@ +.lnsToolbarButton { + line-height: $euiButtonHeight; // Keeps alignment of text and chart icon + background-color: $euiColorEmptyShade; + border-color: $euiBorderColor; + + // Some toolbar buttons are just icons, but EuiButton comes with margin and min-width that need to be removed + min-width: 0; + + .lnsToolbarButton__text:empty { + margin: 0; + } + + // Toolbar buttons don't look good with centered text when fullWidth + &[class*='fullWidth'] { + text-align: left; + + .lnsToolbarButton__content { + justify-content: space-between; + } + } +} + +.lnsToolbarButton--bold { + font-weight: $euiFontWeightBold; +} + +.lnsToolbarButton--s { + box-shadow: none !important; // sass-lint:disable-line no-important + font-size: $euiFontSizeS; +} diff --git a/x-pack/plugins/lens/public/toolbar_button/toolbar_button.tsx b/x-pack/plugins/lens/public/toolbar_button/toolbar_button.tsx new file mode 100644 index 0000000000000..0a63781818171 --- /dev/null +++ b/x-pack/plugins/lens/public/toolbar_button/toolbar_button.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import './toolbar_button.scss'; +import React from 'react'; +import classNames from 'classnames'; +import { EuiButton, PropsOf, EuiButtonProps } from '@elastic/eui'; + +export type ToolbarButtonProps = PropsOf & { + /** + * Determines prominence + */ + fontWeight?: 'normal' | 'bold'; + /** + * Smaller buttons also remove extra shadow for less prominence + */ + size?: EuiButtonProps['size']; +}; + +export const ToolbarButton: React.FunctionComponent = ({ + children, + className, + fontWeight = 'normal', + size = 'm', + ...rest +}) => { + const classes = classNames( + 'lnsToolbarButton', + [`lnsToolbarButton--${fontWeight}`, `lnsToolbarButton--${size}`], + className + ); + return ( + + {children} + + ); +}; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx index 84ea53fb4dc3d..d22b3ec0a44a6 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +import './xy_config_panel.scss'; import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; import { debounce } from 'lodash'; import { - EuiButtonEmpty, EuiButtonGroup, EuiFlexGroup, EuiFlexItem, @@ -32,8 +32,7 @@ import { State, SeriesType, visualizationTypes, YAxisMode } from './types'; import { isHorizontalChart, isHorizontalSeries, getSeriesColor } from './state_helpers'; import { trackUiEvent } from '../lens_ui_telemetry'; import { fittingFunctionDefinitions } from './fitting_functions'; - -import './xy_config_panel.scss'; +import { ToolbarButton } from '../toolbar_button'; type UnwrapArray = T extends Array ? P : T; @@ -101,17 +100,16 @@ export function XyToolbar(props: VisualizationToolbarProps) { { setOpen(!open); }} > {i18n.translate('xpack.lens.xyChart.settingsLabel', { defaultMessage: 'Settings' })} - + } isOpen={open} closePopover={() => { @@ -119,12 +117,9 @@ export function XyToolbar(props: VisualizationToolbarProps) { }} anchorPosition="downRight" > - ) { }) } > - { - return { - value: id, - dropdownDisplay: ( - <> - {title} - -

{description}

-
- - ), - inputDisplay: title, - }; + props.setState({ ...props.state, fittingFunction: value })} - itemLayoutAlign="top" - hasDividers - /> - + > + { + return { + value: id, + dropdownDisplay: ( + <> + {title} + +

{description}

+
+ + ), + inputDisplay: title, + }; + })} + valueOfSelected={props.state?.fittingFunction || 'None'} + onChange={(value) => props.setState({ ...props.state, fittingFunction: value })} + itemLayoutAlign="top" + hasDividers + /> +
+
@@ -183,12 +185,12 @@ export function DimensionEditor(props: VisualizationDimensionEditorProps) })} > + ); + return ( - + {colorPicker} ) : ( - + colorPicker )} );