diff --git a/.eslintrc b/.eslintrc
index a68cff5244c..8ecb52df151 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -72,7 +72,6 @@
// rules marked "off" are those left in the recommended preset we need to fix
// we should remove the corresponding line and fix them one by one
// any marked "error" contain specific overrides we'll need to keep
- "jsx-a11y/anchor-is-valid": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/interactive-supports-focus": "off",
"jsx-a11y/label-has-associated-control": "off",
diff --git a/packages/grafana-ui/src/components/Button/Button.tsx b/packages/grafana-ui/src/components/Button/Button.tsx
index 4813543f9c6..ae3a9032956 100644
--- a/packages/grafana-ui/src/components/Button/Button.tsx
+++ b/packages/grafana-ui/src/components/Button/Button.tsx
@@ -302,3 +302,12 @@ export function getPropertiesForVariant(theme: GrafanaTheme2, variant: ButtonVar
return getButtonVariantStyles(theme, theme.colors.primary, fill);
}
}
+
+export const clearButtonStyles = (theme: GrafanaTheme2) => {
+ return css`
+ background: transparent;
+ color: ${theme.colors.text.primary};
+ border: none;
+ padding: 0;
+ `;
+};
diff --git a/packages/grafana-ui/src/components/Segment/Segment.story.tsx b/packages/grafana-ui/src/components/Segment/Segment.story.tsx
index 7b0b43dd127..16a0514ef65 100644
--- a/packages/grafana-ui/src/components/Segment/Segment.story.tsx
+++ b/packages/grafana-ui/src/components/Segment/Segment.story.tsx
@@ -7,9 +7,9 @@ import { Segment, Icon, SegmentSection } from '@grafana/ui';
import { SegmentSyncProps } from './Segment';
const AddButton = (
-
+
-
+
);
const toOption = (value: any) => ({ label: value, value: value });
diff --git a/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx b/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx
index dc2eade4b0d..2e813675000 100644
--- a/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx
+++ b/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx
@@ -9,9 +9,9 @@ import { SegmentAsync, Icon, SegmentSection } from '@grafana/ui';
import { SegmentAsyncProps } from './SegmentAsync';
const AddButton = (
-
+
-
+
);
const toOption = (value: any) => ({ label: value, value: value });
diff --git a/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx b/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx
index 9e14cf25818..68958c0e6cd 100644
--- a/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx
+++ b/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx
@@ -87,14 +87,15 @@ export const InputWithAutoFocus = () => {
{inputComponents.map((InputComponent: any, i: number) => (
))}
- {
setInputComponents([...inputComponents, InputComponent]);
}}
>
-
+
);
};
diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts
index 5846e35d78a..9b6d3dd00e5 100644
--- a/packages/grafana-ui/src/components/index.ts
+++ b/packages/grafana-ui/src/components/index.ts
@@ -191,7 +191,7 @@ export { RangeSlider } from './Slider/RangeSlider';
export { Form } from './Forms/Form';
export { sharedInputStyle } from './Forms/commonStyles';
export { InputControl } from './InputControl';
-export { Button, LinkButton, type ButtonVariant, ButtonGroup, type ButtonProps } from './Button';
+export { Button, LinkButton, type ButtonVariant, ButtonGroup, type ButtonProps, clearButtonStyles } from './Button';
export { ToolbarButton, ToolbarButtonRow } from './ToolbarButton';
export { ValuePicker } from './ValuePicker/ValuePicker';
export { fieldMatchersUI } from './MatchersUI/fieldMatchersUI';
diff --git a/packages/jaeger-ui-components/src/TracePageHeader/TracePageHeader.tsx b/packages/jaeger-ui-components/src/TracePageHeader/TracePageHeader.tsx
index dd476a85046..5c78064d18f 100644
--- a/packages/jaeger-ui-components/src/TracePageHeader/TracePageHeader.tsx
+++ b/packages/jaeger-ui-components/src/TracePageHeader/TracePageHeader.tsx
@@ -83,6 +83,10 @@ const getStyles = (theme: GrafanaTheme2) => {
&:hover small {
text-decoration: none;
}
+ /* Adapt styles when changing from a element into button */
+ background: transparent;
+ text-align: left;
+ border: none;
`,
TracePageHeaderDetailToggle: css`
label: TracePageHeaderDetailToggle;
@@ -236,7 +240,8 @@ export default function TracePageHeader(props: TracePageHeaderEmbedProps) {
{links && links.length > 0 &&
}
{canCollapse ? (
-
{title}
-
+
) : (
title
)}
diff --git a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanBarRow.tsx b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanBarRow.tsx
index 8d6ee2d9808..890395aaaeb 100644
--- a/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanBarRow.tsx
+++ b/packages/jaeger-ui-components/src/TraceTimelineViewer/SpanBarRow.tsx
@@ -240,6 +240,9 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
&:hover > small {
color: ${autoColor(theme, '#000')};
}
+ text-align: left;
+ background: transparent;
+ border: none;
`,
nameDetailExpanded: css`
label: nameDetailExpanded;
@@ -437,7 +440,8 @@ export class UnthemedSpanBarRow extends React.PureComponent
{
addHoverIndentGuideId={addHoverIndentGuideId}
removeHoverIndentGuideId={removeHoverIndentGuideId}
/>
- {
{rpc ? rpc.operationName : operationName}
{this.getSpanBarLabel(span, spanBarOptions, label)}
-
+
{createSpanLink &&
(() => {
const links = createSpanLink(span);
diff --git a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx
index e708b68423d..de1e29cc8ed 100644
--- a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx
+++ b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx
@@ -76,8 +76,9 @@ export class DashboardRow extends React.Component {
return (
-
@@ -86,7 +87,7 @@ export class DashboardRow extends React.Component {
({count} {panels})
-
+
{canEdit && (
{
repeat={this.props.panel.repeat}
onUpdate={this.onUpdate}
/>
-
+
+
)}
{this.props.panel.collapsed === true && (
diff --git a/public/app/features/dashboard/components/RowOptions/RowOptionsButton.tsx b/public/app/features/dashboard/components/RowOptions/RowOptionsButton.tsx
index 7d90e64a3ba..67d653849b4 100644
--- a/public/app/features/dashboard/components/RowOptions/RowOptionsButton.tsx
+++ b/public/app/features/dashboard/components/RowOptions/RowOptionsButton.tsx
@@ -21,16 +21,16 @@ export const RowOptionsButton: FC
= ({ repeat, title, onU
{({ showModal, hideModal }) => {
return (
- {
showModal(RowOptionsModal, { title, repeat, onDismiss: hideModal, onUpdate: onUpdateChange(hideModal) });
}}
>
-
+
);
}}
diff --git a/public/app/features/variables/adhoc/picker/AdHocFilterKey.tsx b/public/app/features/variables/adhoc/picker/AdHocFilterKey.tsx
index bbc0da18bd3..da71333bce2 100644
--- a/public/app/features/variables/adhoc/picker/AdHocFilterKey.tsx
+++ b/public/app/features/variables/adhoc/picker/AdHocFilterKey.tsx
@@ -52,9 +52,9 @@ export const REMOVE_FILTER_KEY = '-- remove filter --';
const REMOVE_VALUE = { label: REMOVE_FILTER_KEY, value: REMOVE_FILTER_KEY };
const plusSegment: ReactElement = (
-
+
-
+
);
const fetchFilterKeys = async (
diff --git a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx
index 244e0d461d5..942cdedd0e6 100644
--- a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx
+++ b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx
@@ -16,7 +16,7 @@ import { VariableOption, VariableWithMultiSupport, VariableWithOptions } from '.
import { toKeyedVariableIdentifier } from '../../utils';
import { VariableInput } from '../shared/VariableInput';
import { VariableLink } from '../shared/VariableLink';
-import { VariableOptions } from '../shared/VariableOptions';
+import VariableOptions from '../shared/VariableOptions';
import { NavigationKey, VariablePickerProps } from '../types';
import { commitChangesToVariable, filterOrSearchOptions, navigateOptions, openOptions } from './actions';
diff --git a/public/app/features/variables/pickers/shared/VariableOptions.tsx b/public/app/features/variables/pickers/shared/VariableOptions.tsx
index 3a4e96e05fc..078abb753cf 100644
--- a/public/app/features/variables/pickers/shared/VariableOptions.tsx
+++ b/public/app/features/variables/pickers/shared/VariableOptions.tsx
@@ -1,12 +1,13 @@
import { css, cx } from '@emotion/css';
+import classNames from 'classnames';
import React, { PureComponent } from 'react';
import { selectors } from '@grafana/e2e-selectors';
-import { Tooltip } from '@grafana/ui';
+import { Tooltip, Themeable2, withTheme2, clearButtonStyles } from '@grafana/ui';
import { VariableOption } from '../../types';
-export interface Props extends React.HTMLProps {
+export interface Props extends React.HTMLProps, Themeable2 {
multi: boolean;
values: VariableOption[];
selectedValues: VariableOption[];
@@ -19,19 +20,19 @@ export interface Props extends React.HTMLProps {
id: string;
}
-export class VariableOptions extends PureComponent {
- onToggle = (option: VariableOption) => (event: React.MouseEvent) => {
+class VariableOptions extends PureComponent {
+ onToggle = (option: VariableOption) => (event: React.MouseEvent) => {
const clearOthers = event.shiftKey || event.ctrlKey || event.metaKey;
this.handleEvent(event);
this.props.onToggle(option, clearOthers);
};
- onToggleAll = (event: React.MouseEvent) => {
+ onToggleAll = (event: React.MouseEvent) => {
this.handleEvent(event);
this.props.onToggleAll();
};
- handleEvent(event: React.MouseEvent) {
+ handleEvent(event: React.MouseEvent) {
event.preventDefault();
event.stopPropagation();
}
@@ -57,24 +58,30 @@ export class VariableOptions extends PureComponent {
}
renderOption(option: VariableOption, index: number) {
- const { highlightIndex } = this.props;
+ const { highlightIndex, theme } = this.props;
const selectClass = option.selected ? 'variable-option pointer selected' : 'variable-option pointer';
const highlightClass = index === highlightIndex ? `${selectClass} highlighted` : selectClass;
return (
-
+
+
);
}
renderMultiToggle() {
- const { multi, selectedValues } = this.props;
+ const { multi, selectedValues, theme } = this.props;
if (!multi) {
return null;
@@ -82,12 +89,12 @@ export class VariableOptions extends PureComponent {
return (
- 1
? 'variable-options-column-header many-selected'
: 'variable-options-column-header'
- }`}
+ } ${noStyledButton} ${clearButtonStyles(theme)}`}
role="checkbox"
aria-checked={selectedValues.length > 1 ? 'mixed' : 'false'}
onClick={this.onToggleAll}
@@ -96,7 +103,7 @@ export class VariableOptions extends PureComponent {
>
Selected ({selectedValues.length})
-
+
);
}
@@ -108,3 +115,10 @@ const listStyles = cx(
list-style-type: none;
`
);
+
+const noStyledButton = css`
+ width: 100%;
+ text-align: left;
+`;
+
+export default withTheme2(VariableOptions);
diff --git a/public/app/plugins/datasource/cloudwatch/components/LogsQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/LogsQueryEditor.tsx
index 6d5ae523662..dca3678399d 100644
--- a/public/app/plugins/datasource/cloudwatch/components/LogsQueryEditor.tsx
+++ b/public/app/plugins/datasource/cloudwatch/components/LogsQueryEditor.tsx
@@ -10,7 +10,7 @@ import { CloudWatchDatasource } from '../datasource';
import { CloudWatchJsonData, CloudWatchLogsQuery, CloudWatchQuery } from '../types';
import CloudWatchLink from './CloudWatchLink';
-import { CloudWatchLogsQueryField } from './LogsQueryField';
+import CloudWatchLogsQueryField from './LogsQueryField';
type Props = QueryEditorProps & {
query: CloudWatchLogsQuery;
diff --git a/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx b/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx
index 425c7851d22..099b153f8bf 100644
--- a/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx
+++ b/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx
@@ -6,7 +6,7 @@ import { act } from 'react-dom/test-utils';
import { ExploreId } from '../../../../types';
import { setupMockedDataSource } from '../__mocks__/CloudWatchDataSource';
-import { CloudWatchLogsQueryField } from './LogsQueryField';
+import CloudWatchLogsQueryField from './LogsQueryField';
jest
.spyOn(_, 'debounce')
diff --git a/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.tsx b/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.tsx
index 6e871cc0225..cdbb29a4cc4 100644
--- a/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.tsx
+++ b/public/app/plugins/datasource/cloudwatch/components/LogsQueryField.tsx
@@ -1,11 +1,21 @@
-import { css } from '@emotion/css';
+import { css, cx } from '@emotion/css';
import { LanguageMap, languages as prismLanguages } from 'prismjs';
import React, { ReactNode } from 'react';
import { Node, Plugin } from 'slate';
import { Editor } from 'slate-react';
import { AbsoluteTimeRange, QueryEditorProps } from '@grafana/data';
-import { BracesPlugin, LegacyForms, QueryField, SlatePrism, TypeaheadInput, TypeaheadOutput } from '@grafana/ui';
+import {
+ BracesPlugin,
+ LegacyForms,
+ QueryField,
+ SlatePrism,
+ TypeaheadInput,
+ TypeaheadOutput,
+ Themeable2,
+ withTheme2,
+ clearButtonStyles,
+} from '@grafana/ui';
import { ExploreId } from 'app/types';
// Utils & Services
// dom also includes Element polyfills
@@ -20,7 +30,8 @@ import { LogGroupSelector } from './LogGroupSelector';
import QueryHeader from './QueryHeader';
export interface CloudWatchLogsQueryFieldProps
- extends QueryEditorProps {
+ extends QueryEditorProps,
+ Themeable2 {
absoluteRange: AbsoluteTimeRange;
onLabelsRefresh?: () => void;
ExtraFieldElement?: ReactNode;
@@ -32,6 +43,10 @@ const rowGap = css`
gap: 3px;
`;
+const addPaddingToButton = css`
+ padding: 1px 4px;
+`;
+
interface State {
hint:
| {
@@ -44,7 +59,7 @@ interface State {
| undefined;
}
-export class CloudWatchLogsQueryField extends React.PureComponent {
+class CloudWatchLogsQueryField extends React.PureComponent {
state: State = {
hint: undefined,
};
@@ -112,7 +127,7 @@ export class CloudWatchLogsQueryField extends React.PureComponent
)}
@@ -182,3 +201,5 @@ export class CloudWatchLogsQueryField extends React.PureComponent>>();
const [keyIsLoading, updKeyIsLoading] = useState();
@@ -121,20 +123,25 @@ export function FilterSection({
return (
{fil.tagk} = {fil.type}({fil.filter}), groupBy = {'' + fil.groupBy}
- editFilter(fil, idx)}>
+
- removeFilter(idx)} data-testid={testIds.remove}>
+
+
+
);
})}
{!addFilterMode && (
)}
@@ -224,10 +231,12 @@ export function FilterSection({
)}
diff --git a/public/app/plugins/datasource/opentsdb/components/TagSection.tsx b/public/app/plugins/datasource/opentsdb/components/TagSection.tsx
index 563cdbe8764..4cfa34ad876 100644
--- a/public/app/plugins/datasource/opentsdb/components/TagSection.tsx
+++ b/public/app/plugins/datasource/opentsdb/components/TagSection.tsx
@@ -2,7 +2,7 @@ import { has, size } from 'lodash';
import React, { useCallback, useState } from 'react';
import { SelectableValue, toOption } from '@grafana/data';
-import { Select, InlineFormLabel, Icon } from '@grafana/ui';
+import { Select, InlineFormLabel, Icon, clearButtonStyles, useStyles2 } from '@grafana/ui';
import { OpenTsdbQuery } from '../types';
@@ -23,6 +23,8 @@ export function TagSection({
suggestTagValues,
tsdbVersion,
}: TagSectionProps) {
+ const buttonStyles = useStyles2(clearButtonStyles);
+
const [tagKeys, updTagKeys] = useState>>();
const [keyIsLoading, updKeyIsLoading] = useState();
@@ -119,20 +121,25 @@ export function TagSection({
return (
{tagKey}={tagValue}
- editTag(tagKey, tagValue)}>
+
- removeTag(tagKey)} data-testid={testIds.remove}>
+
+
+
);
})}
{!addTagMode && (
)}
@@ -195,10 +202,12 @@ export function TagSection({
)}
diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx
index f9edcc95f48..e8ebe60700b 100644
--- a/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx
+++ b/public/app/plugins/datasource/prometheus/components/PromQueryField.tsx
@@ -1,3 +1,4 @@
+import { cx } from '@emotion/css';
import { LanguageMap, languages as prismLanguages } from 'prismjs';
import React, { ReactNode } from 'react';
import { Plugin } from 'slate';
@@ -13,6 +14,9 @@ import {
SuggestionsState,
TypeaheadInput,
TypeaheadOutput,
+ Themeable2,
+ withTheme2,
+ clearButtonStyles,
} from '@grafana/ui';
import { LocalStorageValueProvider } from 'app/core/components/LocalStorageValueProvider';
import {
@@ -74,7 +78,7 @@ export function willApplySuggestion(suggestion: string, { typeaheadContext, type
return suggestion;
}
-interface PromQueryFieldProps extends QueryEditorProps {
+interface PromQueryFieldProps extends QueryEditorProps, Themeable2 {
ExtraFieldElement?: ReactNode;
'data-testid'?: string;
}
@@ -277,6 +281,7 @@ class PromQueryField extends React.PureComponent
{hint.label}{' '}
{hint.fix ? (
-
+
+
) : null}
@@ -348,4 +357,4 @@ class PromQueryField extends React.PureComponent = ({ card }) => {
const styles = getStyles(theme, card.done);
return (
- ) => handleTutorialClick(event, card)}>
+ ) => handleTutorialClick(event, card)}
+ >
{card.type}
{card.done ? 'complete' : card.heading}
@@ -36,7 +42,6 @@ const handleTutorialClick = (event: MouseEvent
, card: Tutoria
if (!isSet) {
store.set(card.key, true);
}
- window.open(`${card.href}?utm_source=grafana_gettingstarted`, '_blank');
};
const getStyles = stylesFactory((theme: GrafanaTheme, complete: boolean) => {
diff --git a/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx b/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx
index f64d00fc59b..e34c5e093b7 100644
--- a/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx
+++ b/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx
@@ -150,7 +150,8 @@ class LegendSeriesLabel extends PureComponent,
-
{label}
- ,
+ ,
];
}
}
diff --git a/public/sass/components/_panel_graph.scss b/public/sass/components/_panel_graph.scss
index 2362c8364a9..521efac9ed4 100644
--- a/public/sass/components/_panel_graph.scss
+++ b/public/sass/components/_panel_graph.scss
@@ -60,6 +60,11 @@
}
}
+.graph-legend-alias {
+ background: transparent;
+ border: none;
+}
+
.graph-legend-content {
position: relative;
}
diff --git a/public/sass/components/_row.scss b/public/sass/components/_row.scss
index b5e04fa07c8..8dc1b234d21 100644
--- a/public/sass/components/_row.scss
+++ b/public/sass/components/_row.scss
@@ -40,6 +40,8 @@
font-size: $font-size-h5;
font-weight: $font-weight-semi-bold;
color: $text-color;
+ background: transparent;
+ border: none;
.fa {
color: $text-muted;
@@ -54,9 +56,11 @@
opacity: 0;
transition: 200ms opacity ease-in 200ms;
- a {
+ button {
color: $text-color-weak;
padding-left: $spacer;
+ background: transparent;
+ border: none;
&:hover {
color: $link-hover-color;