QueryTab: Design updates (#23906)

* WIP: first stage

* Another take

* argghhh

* Updated

* My brain is mush

* Minor progress

* Progres

* Starting to work

* Fixes

* fixed e2e
pull/23913/head
Torkel Ödegaard 5 years ago committed by GitHub
parent b9a40fc346
commit 49276f2c12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      e2e/suite1/specs/inspect-drawer.spec.ts
  2. 1
      packages/grafana-e2e/src/components/index.ts
  3. 4
      packages/grafana-ui/src/components/Drawer/Drawer.tsx
  4. 2
      packages/grafana-ui/src/components/Modal/getModalStyles.ts
  5. 4
      packages/grafana-ui/src/components/Select/SelectBase.tsx
  6. 2
      packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts
  7. 8
      public/app/core/components/QueryOperationRow/QueryOperationRow.tsx
  8. 10
      public/app/core/components/Select/DataSourcePicker.tsx
  9. 2
      public/app/features/alerting/AlertTab.tsx
  10. 19
      public/app/features/alerting/partials/alert_tab.html
  11. 4
      public/app/features/dashboard/panel_editor/DataSourceOption.tsx
  12. 6
      public/app/features/dashboard/panel_editor/EditorTabBody.tsx
  13. 153
      public/app/features/dashboard/panel_editor/QueriesTab.tsx
  14. 8
      public/app/features/dashboard/panel_editor/QueryEditorRows.tsx
  15. 90
      public/app/features/dashboard/panel_editor/QueryOptions.tsx
  16. 2
      public/sass/_variables.dark.generated.scss
  17. 1
      public/sass/components/_gf-form.scss
  18. 129
      public/sass/components/_panel_editor.scss
  19. 4
      public/sass/components/_query_editor.scss
  20. 5
      public/sass/components/_toolbar.scss

@ -27,7 +27,7 @@ e2e.scenario({
e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST);
e2e.components.QueryEditorToolbarItem.button('Query inspector')
e2e.components.QueryTab.queryInspectorButton()
.should('be.visible')
.click();

@ -77,6 +77,7 @@ export const Components = {
QueryTab: componentFactory({
selectors: {
content: 'Query editor tab content',
queryInspectorButton: 'Query inspector button',
},
}),
AlertTab: componentFactory({

@ -13,7 +13,7 @@ export interface Props {
title?: ReactNode;
/** Subtitle shown below the title */
subtitle?: ReactNode;
/** Should the Drawer be closable by clicking on the mask */
/** Should the Drawer be closable by clicking on the mask, defaults to true */
closeOnMaskClick?: boolean;
/** Render the drawer inside a container on the page */
inline?: boolean;
@ -70,7 +70,7 @@ export const Drawer: FC<Props> = ({
children,
inline = false,
onClose,
closeOnMaskClick = false,
closeOnMaskClick = true,
scrollableContent = false,
title,
subtitle,

@ -3,7 +3,7 @@ import { GrafanaTheme } from '@grafana/data';
import { stylesFactory } from '../../themes';
export const getModalStyles = stylesFactory((theme: GrafanaTheme) => {
const backdropBackground = theme.colors.bg1;
const backdropBackground = theme.colors.bg3;
return {
modal: css`

@ -329,12 +329,12 @@ export function SelectBase<T>({
zIndex: theme.zIndex.dropdown,
}),
//These are required for the menu positioning to function
menu: ({ top, bottom, width, position }: any) => ({
menu: ({ top, bottom, position }: any) => ({
top,
bottom,
width,
position,
marginBottom: !!bottom ? '10px' : '0',
'min-width': '100%',
zIndex: theme.zIndex.dropdown,
}),
container: () => ({

@ -136,7 +136,7 @@ $divider-border-color: $gray-1;
$tight-form-func-bg: $dark-9;
$tight-form-func-highlight-bg: $dark-10;
$modal-backdrop-bg: ${theme.colors.bg1};
$modal-backdrop-bg: ${theme.colors.bg3};
$code-tag-bg: $dark-1;
$code-tag-border: $dark-9;

@ -6,6 +6,7 @@ import { useUpdateEffect } from 'react-use';
interface QueryOperationRowProps {
title?: ((props: { isOpen: boolean }) => React.ReactNode) | React.ReactNode;
headerElement?: React.ReactNode;
actions?:
| ((props: { isOpen: boolean; openRow: () => void; closeRow: () => void }) => React.ReactNode)
| React.ReactNode;
@ -19,6 +20,7 @@ export const QueryOperationRow: React.FC<QueryOperationRowProps> = ({
children,
actions,
title,
headerElement,
onClose,
onOpen,
isOpen,
@ -64,6 +66,7 @@ export const QueryOperationRow: React.FC<QueryOperationRowProps> = ({
>
<Icon name={isContentVisible ? 'angle-down' : 'angle-right'} className={styles.collapseIcon} />
{title && <span className={styles.title}>{titleElement}</span>}
{headerElement}
</div>
{actions && actionsElement}
</HorizontalGroup>
@ -76,7 +79,7 @@ export const QueryOperationRow: React.FC<QueryOperationRowProps> = ({
const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => {
return {
wrapper: css`
margin-bottom: ${theme.spacing.formSpacingBase * 2}px;
margin-bottom: ${theme.spacing.md};
`,
header: css`
padding: 0 ${theme.spacing.sm};
@ -90,6 +93,9 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => {
`,
collapseIcon: css`
color: ${theme.colors.textWeak};
&:hover {
color: ${theme.colors.text};
}
`,
titleWrapper: css`
display: flex;

@ -2,9 +2,8 @@
import React, { PureComponent } from 'react';
// Components
import { LegacyForms } from '@grafana/ui';
import { Select } from '@grafana/ui';
import { SelectableValue, DataSourceSelectItem } from '@grafana/data';
const { Select } = LegacyForms;
export interface Props {
onChange: (ds: DataSourceSelectItem) => void;
@ -66,9 +65,8 @@ export class DataSourcePicker extends PureComponent<Props> {
};
return (
<div className="gf-form-inline">
<Select
className="ds-picker"
className="ds-picker select-container"
isMulti={false}
isClearable={false}
backspaceRemovesValue={false}
@ -78,11 +76,11 @@ export class DataSourcePicker extends PureComponent<Props> {
onBlur={onBlur}
openMenuOnFocus={openMenuOnFocus}
maxMenuHeight={500}
menuPlacement="bottom"
placeholder={placeholder}
noOptionsMessage={() => 'No datasources found'}
noOptionsMessage="No datasources found"
value={value}
/>
</div>
);
}
}

@ -205,7 +205,7 @@ class UnConnectedAlertTab extends PureComponent<Props, State> {
};
return (
<EditorTabBody heading="Alert" toolbarItems={toolbarItems}>
<EditorTabBody toolbarItems={toolbarItems}>
<div aria-label={e2e.components.AlertTab.selectors.content}>
{alert && hasTransformations && (
<Alert

@ -2,8 +2,7 @@
<div class="alert alert-error m-b-2" ng-show="ctrl.error">
<icon name="'exclamation-triangle'"></icon> {{ctrl.error}}
</div>
<div class="panel-options-group">
<div class="panel-options-group__body">
<div class="gf-form-group">
<h4 class="section-heading">Rule</h4>
<div class="gf-form-inline">
@ -30,9 +29,9 @@
placeholder="5m"
/>
<info-popover mode="right-absolute">
If an alert rule has a configured For and the query violates the configured threshold it will first go
from OK to Pending. Going from OK to Pending Grafana will not send any notifications. Once the alert rule
has been firing for more than For duration, it will change to Alerting and send alert notifications.
If an alert rule has a configured For and the query violates the configured threshold it will first go from OK
to Pending. Going from OK to Pending Grafana will not send any notifications. Once the alert rule has been
firing for more than For duration, it will change to Alerting and send alert notifications.
</info-popover>
</div>
</div>
@ -158,12 +157,8 @@
</div>
</div>
</div>
</div>
</div>
<div class="panel-options-group">
<div class="panel-options-group__header">Notifications</div>
<div class="panel-options-group__body">
<h4 class="section-heading">Notifications</h4>
<div class="gf-form-inline">
<div class="gf-form">
<span class="gf-form-label width-8">Send to</span>
@ -214,7 +209,6 @@
</a>
</label>
</div>
<div class="gf-form-group">
<div class="gf-form-inline">
<div class="gf-form">
<input
@ -241,6 +235,3 @@
</div>
</div>
</div>
</div>
</div>
</div>

@ -15,7 +15,9 @@ interface Props {
export const DataSourceOption: FC<Props> = ({ label, placeholder, name, value, onBlur, onChange, tooltipInfo }) => {
return (
<div className="gf-form gf-form--flex-end">
<InlineFormLabel tooltip={tooltipInfo}>{label}</InlineFormLabel>
<InlineFormLabel width={9} tooltip={tooltipInfo}>
{label}
</InlineFormLabel>
<Input
type="text"
className="gf-form-input width-6"

@ -7,7 +7,6 @@ import { e2e } from '@grafana/e2e';
interface Props {
children: JSX.Element;
heading: string;
renderToolbar?: () => JSX.Element;
toolbarItems?: EditorToolbarView[];
scrollTop?: number;
@ -110,16 +109,13 @@ export class EditorTabBody extends PureComponent<Props, State> {
}
render() {
const { children, renderToolbar, heading, toolbarItems, scrollTop, setScrollTop } = this.props;
const { children, renderToolbar, toolbarItems, scrollTop, setScrollTop } = this.props;
const { openView, fadeIn, isOpen } = this.state;
return (
<>
<div className="toolbar">
<div className="toolbar__left">
<div className="toolbar__heading">{heading}</div>
{renderToolbar && renderToolbar()}
</div>
{toolbarItems.map(item => this.renderButton(item))}
</div>
<div className="panel-editor__scroll">

@ -1,10 +1,9 @@
// Libraries
import React, { PureComponent } from 'react';
// Components
import { EditorTabBody, EditorToolbarView } from './EditorTabBody';
import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
import { QueryOptions } from './QueryOptions';
import { PanelOptionsGroup } from '@grafana/ui';
import { CustomScrollbar, stylesFactory, Button, HorizontalGroup, Modal } from '@grafana/ui';
import { getLocationSrv } from '@grafana/runtime';
import { QueryEditorRows } from './QueryEditorRows';
// Services
@ -20,6 +19,7 @@ import { addQuery } from 'app/core/utils/query';
import { Unsubscribable } from 'rxjs';
import { DashboardQueryEditor, isSharedDashboardQuery } from 'app/plugins/datasource/dashboard';
import { expressionDatasource, ExpressionDatasourceID } from 'app/features/expressions/ExpressionDatasource';
import { css } from 'emotion';
import { e2e } from '@grafana/e2e';
interface Props {
@ -35,6 +35,7 @@ interface State {
isAddingMixed: boolean;
scrollTop: number;
data: PanelData;
isHelpOpen: boolean;
}
export class QueriesTab extends PureComponent<Props, State> {
@ -48,6 +49,7 @@ export class QueriesTab extends PureComponent<Props, State> {
helpContent: null,
isPickerOpen: false,
isAddingMixed: false,
isHelpOpen: false,
scrollTop: 0,
data: {
state: LoadingState.NotStarted,
@ -121,6 +123,7 @@ export class QueriesTab extends PureComponent<Props, State> {
openQueryInspector = () => {
const { panel } = this.props;
getLocationSrv().update({
query: { inspect: panel.id, inspectTab: 'query' },
partial: true,
@ -128,7 +131,7 @@ export class QueriesTab extends PureComponent<Props, State> {
};
renderHelp = () => {
return <PluginHelp plugin={this.state.currentDS.meta} type="query_help" />;
return;
};
/**
@ -155,30 +158,45 @@ export class QueriesTab extends PureComponent<Props, State> {
};
onScrollBottom = () => {
this.setState({ scrollTop: this.state.scrollTop + 10000 });
this.setState({ scrollTop: 1000 });
};
renderToolbar = () => {
const { currentDS, isAddingMixed } = this.state;
const showAddButton = !(isAddingMixed || isSharedDashboardQuery(currentDS.name));
renderTopSection(styles: QueriesTabStyls) {
const { panel } = this.props;
const { currentDS, data } = this.state;
return (
<>
<div>
<div className={styles.dataSourceRow}>
<div className={styles.dataSourceRowItem}>
<DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} />
<div className="flex-grow-1" />
{showAddButton && (
<button className="btn navbar-button" onClick={this.onAddQueryClick}>
Add query
</button>
)}
{isAddingMixed && this.renderMixedPicker()}
{config.featureToggles.expressions && (
<button className="btn navbar-button" onClick={this.onAddExpressionClick}>
Add Expression
</button>
)}
</>
</div>
<div className={styles.dataSourceRowItem}>
<Button variant="secondary" icon="info-circle" title="Open data source help" onClick={this.onOpenHelp} />
</div>
<div className={styles.dataSourceRowItem}>
<Button
variant="secondary"
onClick={this.openQueryInspector}
aria-label={e2e.components.QueryTab.selectors.queryInspectorButton}
>
Query inspector
</Button>
</div>
<div className={styles.dataSourceRowItemOptions}>
<QueryOptions panel={panel} datasource={currentDS} data={data} />
</div>
</div>
</div>
);
}
onOpenHelp = () => {
this.setState({ isHelpOpen: true });
};
onCloseHelp = () => {
this.setState({ isHelpOpen: false });
};
renderMixedPicker = () => {
@ -218,7 +236,7 @@ export class QueriesTab extends PureComponent<Props, State> {
this.setState({ scrollTop: target.scrollTop });
};
renderQueryBody = () => {
renderQueries() {
const { panel, dashboard } = this.props;
const { currentDS, data } = this.state;
@ -237,36 +255,83 @@ export class QueriesTab extends PureComponent<Props, State> {
dashboard={dashboard}
data={data}
/>
<PanelOptionsGroup>
<QueryOptions panel={panel} datasource={currentDS} />
</PanelOptionsGroup>
</div>
);
};
}
render() {
const { scrollTop } = this.state;
const queryInspector: EditorToolbarView = {
title: 'Query inspector',
onClick: this.openQueryInspector,
};
renderAddQueryRow(styles: QueriesTabStyls) {
const { currentDS, isAddingMixed } = this.state;
const showAddButton = !(isAddingMixed || isSharedDashboardQuery(currentDS.name));
const dsHelp: EditorToolbarView = {
heading: 'Help',
icon: 'question-circle',
render: this.renderHelp,
};
return (
<HorizontalGroup spacing="md" align="flex-start">
{showAddButton && (
<Button icon="plus" onClick={this.onAddQueryClick} variant="secondary">
Query
</Button>
)}
{isAddingMixed && this.renderMixedPicker()}
{config.featureToggles.expressions && (
<Button icon="plus" onClick={this.onAddExpressionClick} variant="secondary">
Expression
</Button>
)}
</HorizontalGroup>
);
}
render() {
const { scrollTop, isHelpOpen } = this.state;
const styles = getStyles();
return (
<EditorTabBody
heading="Data source"
renderToolbar={this.renderToolbar}
toolbarItems={[queryInspector, dsHelp]}
setScrollTop={this.setScrollTop}
<CustomScrollbar
autoHeightMin="100%"
autoHide={true}
updateAfterMountMs={300}
scrollTop={scrollTop}
setScrollTop={this.setScrollTop}
>
<>{this.renderQueryBody()}</>
</EditorTabBody>
<div className={styles.innerWrapper}>
{this.renderTopSection(styles)}
<div className={styles.queriesWrapper}>{this.renderQueries()}</div>
{this.renderAddQueryRow(styles)}
{isHelpOpen && (
<Modal title="Data source help" isOpen={true} onDismiss={this.onCloseHelp}>
<PluginHelp plugin={this.state.currentDS.meta} type="query_help" />
</Modal>
)}
</div>
</CustomScrollbar>
);
}
}
const getStyles = stylesFactory(() => {
const { theme } = config;
return {
innerWrapper: css`
display: flex;
flex-direction: column;
height: 100%;
padding: ${theme.spacing.md};
`,
dataSourceRow: css`
display: flex;
margin-bottom: ${theme.spacing.md};
`,
dataSourceRowItem: css`
margin-right: ${theme.spacing.inlineFormMargin};
`,
dataSourceRowItemOptions: css`
flex-grow: 1;
`,
queriesWrapper: css`
padding-bottom: 16px;
`,
};
});
type QueriesTabStyls = ReturnType<typeof getStyles>;

@ -73,9 +73,7 @@ export class QueryEditorRows extends PureComponent<Props> {
render() {
const { props } = this;
return (
<div className="query-editor-rows">
{props.queries.map((query, index) => (
return props.queries.map((query, index) => (
<QueryEditorRow
dataSourceValue={query.datasource || props.datasource.value}
key={query.refId}
@ -89,8 +87,6 @@ export class QueryEditorRows extends PureComponent<Props> {
onMoveQuery={this.onMoveQuery}
inMixedMode={props.datasource.meta.mixed}
/>
))}
</div>
);
));
}
}

@ -2,15 +2,25 @@
import React, { PureComponent, ChangeEvent, FocusEvent, ReactText } from 'react';
// Utils
import { rangeUtil, DataSourceSelectItem } from '@grafana/data';
import { rangeUtil, DataSourceSelectItem, PanelData } from '@grafana/data';
// Components
import { EventsWithValidation, LegacyInputStatus, LegacyForms, ValidationEvents, InlineFormLabel } from '@grafana/ui';
import {
EventsWithValidation,
LegacyInputStatus,
LegacyForms,
ValidationEvents,
InlineFormLabel,
stylesFactory,
} from '@grafana/ui';
import { DataSourceOption } from './DataSourceOption';
const { Input, Switch } = LegacyForms;
// Types
import { PanelModel } from '../state';
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
import { config } from 'app/core/config';
import { css } from 'emotion';
const timeRangeValidationEvents: ValidationEvents = {
[EventsWithValidation.onBlur]: [
@ -33,6 +43,7 @@ const emptyToNull = (value: string) => {
interface Props {
panel: PanelModel;
datasource: DataSourceSelectItem;
data: PanelData;
}
interface State {
@ -42,6 +53,7 @@ interface State {
maxDataPoints: string | ReactText;
interval: string;
hideTimeOverride: boolean;
isOpen: boolean;
}
export class QueryOptions extends PureComponent<Props, State> {
@ -95,6 +107,7 @@ export class QueryOptions extends PureComponent<Props, State> {
maxDataPoints: props.panel.maxDataPoints || '',
interval: props.panel.interval || '',
hideTimeOverride: props.panel.hideTimeOverride || false,
isOpen: false,
};
}
@ -180,15 +193,57 @@ export class QueryOptions extends PureComponent<Props, State> {
});
};
onOpenOptions = () => {
this.setState({ isOpen: true });
};
onCloseOptions = () => {
this.setState({ isOpen: false });
};
renderCollapsedText(styles: StylesType): React.ReactNode | undefined {
const { data } = this.props;
const { isOpen, maxDataPoints, interval } = this.state;
if (isOpen) {
return undefined;
}
let mdDesc = maxDataPoints;
if (maxDataPoints === '' && data.request) {
mdDesc = `auto = ${data.request.maxDataPoints}`;
}
let intervalDesc = interval;
if (intervalDesc === '' && data.request) {
intervalDesc = `auto = ${data.request.interval}`;
}
return (
<>
{<div className={styles.collapsedText}>MD = {mdDesc}</div>}
{<div className={styles.collapsedText}>Interval = {intervalDesc}</div>}
</>
);
}
render() {
const { hideTimeOverride } = this.state;
const { relativeTime, timeShift } = this.state;
const { relativeTime, timeShift, isOpen } = this.state;
const styles = getStyles();
return (
<div className="gf-form-inline">
<QueryOperationRow
title="Options"
headerElement={this.renderCollapsedText(styles)}
isOpen={isOpen}
onOpen={this.onOpenOptions}
onClose={this.onCloseOptions}
>
{this.renderOptions()}
<div className="gf-form">
<InlineFormLabel>Relative time</InlineFormLabel>
<InlineFormLabel width={9}>Relative time</InlineFormLabel>
<Input
type="text"
className="width-6"
@ -202,7 +257,7 @@ export class QueryOptions extends PureComponent<Props, State> {
</div>
<div className="gf-form">
<span className="gf-form-label">Time shift</span>
<span className="gf-form-label width-9">Time shift</span>
<Input
type="text"
className="width-6"
@ -216,10 +271,29 @@ export class QueryOptions extends PureComponent<Props, State> {
</div>
{(timeShift || relativeTime) && (
<div className="gf-form-inline">
<Switch label="Hide time info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} />
<Switch
label="Hide time info"
labelClass="width-9"
checked={hideTimeOverride}
onChange={this.onToggleTimeOverride}
/>
</div>
)}
</div>
</QueryOperationRow>
);
}
}
const getStyles = stylesFactory(() => {
const { theme } = config;
return {
collapsedText: css`
margin-left: ${theme.spacing.md};
font-size: ${theme.typography.size.sm};
color: ${theme.colors.textWeak};
`,
};
});
type StylesType = ReturnType<typeof getStyles>;

@ -138,7 +138,7 @@ $divider-border-color: $gray-1;
$tight-form-func-bg: $dark-9;
$tight-form-func-highlight-bg: $dark-10;
$modal-backdrop-bg: #141619;
$modal-backdrop-bg: #2c3235;
$code-tag-bg: $dark-1;
$code-tag-border: $dark-9;

@ -109,6 +109,7 @@ $input-border: 1px solid $input-border-color;
font-size: $font-size-sm;
background-color: $input-label-bg;
height: $input-height;
line-height: $input-height;
margin-right: $space-xs;
border-radius: $input-border-radius;
justify-content: space-between;

@ -1,9 +1,3 @@
.panel-editor-container {
display: flex;
flex-direction: column;
height: 100%;
}
.panel-wrapper {
height: 100%;
position: relative;
@ -16,45 +10,6 @@
}
}
.panel-editor-container__editor {
margin-top: $space-lg;
display: flex;
flex-direction: row;
flex: 1 1 0;
position: relative;
min-height: 0;
}
.panel-editor__right {
display: flex;
flex-direction: column;
flex-grow: 1;
background: $input-bg;
margin: 0 20px 0 84px;
width: calc(100% - 84px);
border-radius: 3px;
box-shadow: $panel-editor-shadow;
min-height: 0;
}
.panel-editor__close {
@include buttonBackground($btn-inverse-bg, $btn-inverse-bg-hl);
position: absolute;
left: 11px;
top: 5px;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
i {
flex-grow: 1;
text-align: center;
font-size: 20px;
}
}
.panel-editor__scroll {
flex-grow: 1;
min-width: 0;
@ -65,7 +20,7 @@
}
.panel-editor__content {
padding: 16px;
padding: 0 16px 16px 16px;
}
.panel-in-fullscreen {
@ -86,88 +41,6 @@
}
}
.panel-editor-container__resizer {
position: relative;
margin-top: -3px;
}
.panel-editor-resizer__handle {
position: relative;
display: block;
background: $vertical-resize-handle-bg;
width: 150px;
margin-left: -75px;
height: 6px;
cursor: ns-resize;
border-radius: 3px;
margin: 0 auto;
&::before {
content: ' ';
position: absolute;
left: 10px;
right: 10px;
top: 2px;
border-top: 2px dotted $vertical-resize-handle-dots;
}
&:hover::before {
border-color: $vertical-resize-handle-dots-hover;
}
}
.panel-editor-tabs {
z-index: 2;
display: flex;
flex-direction: column;
position: absolute;
top: 44px;
left: 20px;
align-items: flex-start;
&::before {
content: '';
display: block;
position: absolute;
top: 10px;
bottom: 10px;
left: 21px;
width: 2px;
background: $panel-editor-tabs-line-color;
}
}
.panel-editor-tabs__item {
margin-bottom: 25px;
position: relative;
z-index: 1;
text-align: center;
&:last-child {
margin-bottom: 0;
}
}
.panel-editor-tabs__link {
display: inline-block;
&.active {
position: relative;
}
.gicon {
height: 44px;
width: 53px;
margin-right: 5px;
transition: transform 0.1s ease 0.1s;
&:hover {
filter: $panel-editor-side-menu-shadow;
transform: scale(1.1);
}
}
}
.ds-picker {
position: relative;
min-width: 200px;

@ -11,10 +11,6 @@
color: $gray-2;
}
.query-editor-rows {
margin: 20px 0;
}
.tight-form-func {
background: $tight-form-func-bg;

@ -2,12 +2,9 @@
display: flex;
align-content: center;
align-items: center;
padding: 3px 20px 3px 20px;
padding: 16px;
position: relative;
flex: 0 0 auto;
background: $toolbar-bg;
border-radius: 3px;
height: 44px;
}
.toolbar__heading {

Loading…
Cancel
Save