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
    {hint.message} - +
    )} @@ -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)}> + + ); })} {!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)}> + + ); })} {!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;