mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
* Fix dimension popover layout and color picker “Auto” * Created ToolbarButton * Move disabled help text to tooltip for missing values * Darker side panel backgrounds * Adding to .asciidoc about where to put the SASS import * Moving `SASS` guidelines to STYLEGUIDE.md * Fix keyboard focus of XY settings popover * Fix dark mode
This commit is contained in:
parent
d80ed1f9e9
commit
f74340f6ab
22 changed files with 284 additions and 204 deletions
|
@ -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 (
|
||||
<div className="plgComponent" />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```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.
|
||||
|
|
|
@ -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 <<running-elasticsearch>>, like connecting to a remote host, running from source,
|
||||
preserving data inbetween runs, running remote cluster, etc.
|
||||
Read about more options for <<running-elasticsearch>>, 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.
|
|||
|
||||
* <<kibana-debugging>>
|
||||
|
||||
* <<kibana-sass>>
|
||||
|
||||
* <<building-kibana>>
|
||||
|
||||
* <<development-plugin-resources>>
|
||||
|
@ -137,8 +135,6 @@ include::sample-data.asciidoc[]
|
|||
|
||||
include::debugging.asciidoc[]
|
||||
|
||||
include::sass.asciidoc[]
|
||||
|
||||
include::building-kibana.asciidoc[]
|
||||
|
||||
include::development-plugin-resources.asciidoc[]
|
|
@ -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 (
|
||||
<div className="plgComponent" />
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
[source,scss]
|
||||
----
|
||||
// component.scss
|
||||
|
||||
.plgComponent { ... }
|
||||
----
|
||||
|
||||
Do not use the underscore `_` SASS file naming pattern when importing
|
||||
directly into a javascript file.
|
|
@ -1,6 +1,7 @@
|
|||
.lnsDataPanelWrapper {
|
||||
flex: 1 0 100%;
|
||||
overflow: hidden;
|
||||
background-color: lightOrDarkTheme($euiColorLightestShade, $euiColorInk);
|
||||
}
|
||||
|
||||
.lnsDataPanelWrapper__switchSource {
|
||||
|
|
|
@ -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%;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,7 @@ export function DimensionPopover({
|
|||
}}
|
||||
button={trigger}
|
||||
anchorPosition="leftUp"
|
||||
withTitle
|
||||
panelPaddingSize="s"
|
||||
panelPaddingSize="none"
|
||||
>
|
||||
{panel}
|
||||
</EuiPopover>
|
||||
|
|
|
@ -103,7 +103,7 @@ export function LayerPanel(
|
|||
</EuiFlexItem>
|
||||
|
||||
{layerDatasource && (
|
||||
<EuiFlexItem className="eui-textTruncate">
|
||||
<EuiFlexItem className="lnsLayerPanel__sourceFlexItem">
|
||||
<NativeRenderer
|
||||
render={layerDatasource.renderLayerPanel}
|
||||
nativeProps={{
|
||||
|
@ -170,18 +170,15 @@ export function LayerPanel(
|
|||
defaultMessage: 'Quick functions',
|
||||
}),
|
||||
content: (
|
||||
<>
|
||||
<EuiSpacer size="s" />
|
||||
<NativeRenderer
|
||||
render={props.datasourceMap[datasourceId].renderDimensionEditor}
|
||||
nativeProps={{
|
||||
...layerDatasourceConfigProps,
|
||||
core: props.core,
|
||||
columnId: accessor,
|
||||
filterOperations: group.filterOperations,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
<NativeRenderer
|
||||
render={props.datasourceMap[datasourceId].renderDimensionEditor}
|
||||
nativeProps={{
|
||||
...layerDatasourceConfigProps,
|
||||
core: props.core,
|
||||
columnId: accessor,
|
||||
filterOperations: group.filterOperations,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
@ -194,7 +191,6 @@ export function LayerPanel(
|
|||
}),
|
||||
content: (
|
||||
<div className="lnsLayerPanel__styleEditor">
|
||||
<EuiSpacer size="s" />
|
||||
<NativeRenderer
|
||||
render={activeVisualization.renderDimensionEditor}
|
||||
nativeProps={{
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { EuiPopover, EuiButtonIcon, EuiToolTip } from '@elastic/eui';
|
||||
import { EuiPopover, EuiToolTip } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { NativeRenderer } from '../../../native_renderer';
|
||||
import { Visualization, VisualizationLayerWidgetProps } from '../../../types';
|
||||
import { ToolbarButton } from '../../../toolbar_button';
|
||||
|
||||
export function LayerSettings({
|
||||
layerId,
|
||||
|
@ -25,6 +26,10 @@ export function LayerSettings({
|
|||
return null;
|
||||
}
|
||||
|
||||
const a11yText = i18n.translate('xpack.lens.editLayerSettings', {
|
||||
defaultMessage: 'Edit layer settings',
|
||||
});
|
||||
|
||||
return (
|
||||
<EuiPopover
|
||||
id={`lnsLayerPopover_${layerId}`}
|
||||
|
@ -36,11 +41,11 @@ export function LayerSettings({
|
|||
defaultMessage: 'Edit layer settings',
|
||||
})}
|
||||
>
|
||||
<EuiButtonIcon
|
||||
<ToolbarButton
|
||||
size="s"
|
||||
iconType={activeVisualization.getLayerContextMenuIcon?.(layerConfigProps) || 'gear'}
|
||||
aria-label={i18n.translate('xpack.lens.editLayerSettings', {
|
||||
defaultMessage: 'Edit layer settings',
|
||||
})}
|
||||
aria-label={a11yText}
|
||||
title={a11yText}
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
data-test-subj="lns_layer_settings"
|
||||
/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<boolean>(false);
|
||||
|
||||
|
@ -202,16 +201,13 @@ export function ChartSwitch(props: Props) {
|
|||
panelClassName="lnsChartSwitch__popoverPanel"
|
||||
panelPaddingSize="s"
|
||||
button={
|
||||
<EuiButton
|
||||
className="lnsChartSwitch__triggerButton"
|
||||
<ToolbarButton
|
||||
onClick={() => setFlyoutOpen(!flyoutOpen)}
|
||||
data-test-subj="lnsChartSwitchPopover"
|
||||
iconSide="right"
|
||||
iconType="arrowDown"
|
||||
color="text"
|
||||
fontWeight="bold"
|
||||
>
|
||||
<VisualizationSummary {...props} />
|
||||
</EuiButton>
|
||||
</ToolbarButton>
|
||||
}
|
||||
isOpen={flyoutOpen}
|
||||
closePopover={() => setFlyoutOpen(false)}
|
||||
|
|
|
@ -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({
|
|||
/>{' '}
|
||||
<EuiBetaBadge label="Beta" tooltipContent={tooltipContent} />
|
||||
</p>
|
||||
<EuiButtonEmpty
|
||||
href="https://www.elastic.co/products/kibana/feedback"
|
||||
iconType="popout"
|
||||
iconSide="right"
|
||||
size="xs"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.lens.editorFrame.goToForums"
|
||||
defaultMessage="Make requests and give feedback"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
<p>
|
||||
<small>
|
||||
<EuiLink
|
||||
href="https://www.elastic.co/products/kibana/feedback"
|
||||
target="_blank"
|
||||
external
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.lens.editorFrame.goToForums"
|
||||
defaultMessage="Make requests and give feedback"
|
||||
/>
|
||||
</EuiLink>
|
||||
</small>
|
||||
</p>
|
||||
</EuiText>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -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 (
|
||||
<EuiButtonEmpty
|
||||
className="eui-textTruncate"
|
||||
flush="left"
|
||||
color="text"
|
||||
iconSide="right"
|
||||
iconType="arrowDown"
|
||||
<ToolbarButton
|
||||
title={title}
|
||||
onClick={() => setPopoverIsOpen(!isPopoverOpen)}
|
||||
fullWidth
|
||||
{...rest}
|
||||
>
|
||||
{label}
|
||||
</EuiButtonEmpty>
|
||||
</ToolbarButton>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiPopover
|
||||
style={{ width: '100%' }}
|
||||
button={createTrigger()}
|
||||
isOpen={isPopoverOpen}
|
||||
closePopover={() => setPopoverIsOpen(false)}
|
||||
className="eui-textTruncate"
|
||||
anchorClassName="eui-textTruncate"
|
||||
display="block"
|
||||
panelPaddingSize="s"
|
||||
ownFocus
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -299,25 +299,31 @@ export function PopoverEditor(props: PopoverEditorProps) {
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={true} className="lnsIndexPatternDimensionEditor__right">
|
||||
{incompatibleSelectedOperationType && selectedColumn && (
|
||||
<EuiCallOut
|
||||
data-test-subj="indexPattern-invalid-operation"
|
||||
title={i18n.translate('xpack.lens.indexPattern.invalidOperationLabel', {
|
||||
defaultMessage: 'To use this function, select a different field.',
|
||||
})}
|
||||
color="warning"
|
||||
size="s"
|
||||
iconType="sortUp"
|
||||
/>
|
||||
<>
|
||||
<EuiCallOut
|
||||
data-test-subj="indexPattern-invalid-operation"
|
||||
title={i18n.translate('xpack.lens.indexPattern.invalidOperationLabel', {
|
||||
defaultMessage: 'To use this function, select a different field.',
|
||||
})}
|
||||
color="warning"
|
||||
size="s"
|
||||
iconType="sortUp"
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
)}
|
||||
{incompatibleSelectedOperationType && !selectedColumn && (
|
||||
<EuiCallOut
|
||||
size="s"
|
||||
data-test-subj="indexPattern-fieldless-operation"
|
||||
title={i18n.translate('xpack.lens.indexPattern.fieldlessOperationLabel', {
|
||||
defaultMessage: 'To use this function, select a field.',
|
||||
})}
|
||||
iconType="sortUp"
|
||||
/>
|
||||
<>
|
||||
<EuiCallOut
|
||||
size="s"
|
||||
data-test-subj="indexPattern-fieldless-operation"
|
||||
title={i18n.translate('xpack.lens.indexPattern.fieldlessOperationLabel', {
|
||||
defaultMessage: 'To use this function, select a field.',
|
||||
})}
|
||||
iconType="sortUp"
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
)}
|
||||
{!incompatibleSelectedOperationType && ParamEditor && (
|
||||
<>
|
||||
|
|
|
@ -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}
|
||||
|
|
7
x-pack/plugins/lens/public/toolbar_button/index.tsx
Normal file
7
x-pack/plugins/lens/public/toolbar_button/index.tsx
Normal file
|
@ -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';
|
|
@ -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;
|
||||
}
|
53
x-pack/plugins/lens/public/toolbar_button/toolbar_button.tsx
Normal file
53
x-pack/plugins/lens/public/toolbar_button/toolbar_button.tsx
Normal file
|
@ -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<typeof EuiButton> & {
|
||||
/**
|
||||
* Determines prominence
|
||||
*/
|
||||
fontWeight?: 'normal' | 'bold';
|
||||
/**
|
||||
* Smaller buttons also remove extra shadow for less prominence
|
||||
*/
|
||||
size?: EuiButtonProps['size'];
|
||||
};
|
||||
|
||||
export const ToolbarButton: React.FunctionComponent<ToolbarButtonProps> = ({
|
||||
children,
|
||||
className,
|
||||
fontWeight = 'normal',
|
||||
size = 'm',
|
||||
...rest
|
||||
}) => {
|
||||
const classes = classNames(
|
||||
'lnsToolbarButton',
|
||||
[`lnsToolbarButton--${fontWeight}`, `lnsToolbarButton--${size}`],
|
||||
className
|
||||
);
|
||||
return (
|
||||
<EuiButton
|
||||
className={classes}
|
||||
iconSide="right"
|
||||
iconType="arrowDown"
|
||||
color="text"
|
||||
contentProps={{
|
||||
className: 'lnsToolbarButton__content',
|
||||
}}
|
||||
textProps={{
|
||||
className: 'lnsToolbarButton__text',
|
||||
}}
|
||||
{...rest}
|
||||
size={size}
|
||||
>
|
||||
{children}
|
||||
</EuiButton>
|
||||
);
|
||||
};
|
|
@ -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> = T extends Array<infer P> ? P : T;
|
||||
|
||||
|
@ -101,17 +100,16 @@ export function XyToolbar(props: VisualizationToolbarProps<State>) {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiPopover
|
||||
panelClassName="lnsXyToolbar__popover"
|
||||
ownFocus
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
color="text"
|
||||
iconType="arrowDown"
|
||||
iconSide="right"
|
||||
<ToolbarButton
|
||||
fontWeight="normal"
|
||||
onClick={() => {
|
||||
setOpen(!open);
|
||||
}}
|
||||
>
|
||||
{i18n.translate('xpack.lens.xyChart.settingsLabel', { defaultMessage: 'Settings' })}
|
||||
</EuiButtonEmpty>
|
||||
</ToolbarButton>
|
||||
}
|
||||
isOpen={open}
|
||||
closePopover={() => {
|
||||
|
@ -119,12 +117,9 @@ export function XyToolbar(props: VisualizationToolbarProps<State>) {
|
|||
}}
|
||||
anchorPosition="downRight"
|
||||
>
|
||||
<EuiFormRow
|
||||
display="columnCompressed"
|
||||
label={i18n.translate('xpack.lens.xyChart.fittingLabel', {
|
||||
defaultMessage: 'Fill missing values',
|
||||
})}
|
||||
helpText={
|
||||
<EuiToolTip
|
||||
anchorClassName="eui-displayBlock"
|
||||
content={
|
||||
!hasNonBarSeries &&
|
||||
i18n.translate('xpack.lens.xyChart.fittingDisabledHelpText', {
|
||||
defaultMessage:
|
||||
|
@ -132,29 +127,36 @@ export function XyToolbar(props: VisualizationToolbarProps<State>) {
|
|||
})
|
||||
}
|
||||
>
|
||||
<EuiSuperSelect
|
||||
compressed
|
||||
disabled={!hasNonBarSeries}
|
||||
options={fittingFunctionDefinitions.map(({ id, title, description }) => {
|
||||
return {
|
||||
value: id,
|
||||
dropdownDisplay: (
|
||||
<>
|
||||
<strong>{title}</strong>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<p>{description}</p>
|
||||
</EuiText>
|
||||
</>
|
||||
),
|
||||
inputDisplay: title,
|
||||
};
|
||||
<EuiFormRow
|
||||
display="columnCompressed"
|
||||
label={i18n.translate('xpack.lens.xyChart.fittingLabel', {
|
||||
defaultMessage: 'Fill missing values',
|
||||
})}
|
||||
valueOfSelected={props.state?.fittingFunction || 'None'}
|
||||
onChange={(value) => props.setState({ ...props.state, fittingFunction: value })}
|
||||
itemLayoutAlign="top"
|
||||
hasDividers
|
||||
/>
|
||||
</EuiFormRow>
|
||||
>
|
||||
<EuiSuperSelect
|
||||
compressed
|
||||
disabled={!hasNonBarSeries}
|
||||
options={fittingFunctionDefinitions.map(({ id, title, description }) => {
|
||||
return {
|
||||
value: id,
|
||||
dropdownDisplay: (
|
||||
<>
|
||||
<strong>{title}</strong>
|
||||
<EuiText size="xs" color="subdued">
|
||||
<p>{description}</p>
|
||||
</EuiText>
|
||||
</>
|
||||
),
|
||||
inputDisplay: title,
|
||||
};
|
||||
})}
|
||||
valueOfSelected={props.state?.fittingFunction || 'None'}
|
||||
onChange={(value) => props.setState({ ...props.state, fittingFunction: value })}
|
||||
itemLayoutAlign="top"
|
||||
hasDividers
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiToolTip>
|
||||
</EuiPopover>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -183,12 +185,12 @@ export function DimensionEditor(props: VisualizationDimensionEditorProps<State>)
|
|||
})}
|
||||
>
|
||||
<EuiButtonGroup
|
||||
isFullWidth
|
||||
legend={i18n.translate('xpack.lens.xyChart.axisSide.label', {
|
||||
defaultMessage: 'Axis side',
|
||||
})}
|
||||
name="axisSide"
|
||||
buttonSize="compressed"
|
||||
className="eui-displayInlineBlock"
|
||||
options={[
|
||||
{
|
||||
id: `${idPrefix}auto`,
|
||||
|
@ -241,7 +243,7 @@ const tooltipContent = {
|
|||
}),
|
||||
disabled: i18n.translate('xpack.lens.configPanel.color.tooltip.disabled', {
|
||||
defaultMessage:
|
||||
'Individual series cannot be custom colored when the layer includes a “Break down by“',
|
||||
'Individual series cannot be custom colored when the layer includes a “Break down by.“',
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -286,6 +288,22 @@ const ColorPicker = ({
|
|||
[state, layer, accessor, index]
|
||||
);
|
||||
|
||||
const colorPicker = (
|
||||
<EuiColorPicker
|
||||
compressed
|
||||
isClearable
|
||||
onChange={handleColor}
|
||||
color={disabled ? '' : color}
|
||||
disabled={disabled}
|
||||
placeholder={i18n.translate('xpack.lens.xyChart.seriesColor.auto', {
|
||||
defaultMessage: 'Auto',
|
||||
})}
|
||||
aria-label={i18n.translate('xpack.lens.xyChart.seriesColor.label', {
|
||||
defaultMessage: 'Series color',
|
||||
})}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFormRow
|
||||
display="columnCompressed"
|
||||
|
@ -312,25 +330,10 @@ const ColorPicker = ({
|
|||
delay="long"
|
||||
anchorClassName="eui-displayBlock"
|
||||
>
|
||||
<EuiColorPicker
|
||||
compressed
|
||||
onChange={handleColor}
|
||||
color=""
|
||||
disabled
|
||||
aria-label={i18n.translate('xpack.lens.xyChart.seriesColor.label', {
|
||||
defaultMessage: 'Series color',
|
||||
})}
|
||||
/>
|
||||
{colorPicker}
|
||||
</EuiToolTip>
|
||||
) : (
|
||||
<EuiColorPicker
|
||||
compressed
|
||||
onChange={handleColor}
|
||||
color={color}
|
||||
aria-label={i18n.translate('xpack.lens.xyChart.seriesColor.label', {
|
||||
defaultMessage: 'Series color',
|
||||
})}
|
||||
/>
|
||||
colorPicker
|
||||
)}
|
||||
</EuiFormRow>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue