Add tooltip to instances of IconButton (#68880)

* refactor: tooltip is required

* refactor: add tooltips

* refactor: add tooltips

* refactor: add tooltips

* refactor: add tooltips

* refactor: add tooltips

* refactor: add tooltips

* refactor: adjust tests

* refactor: apply changes from code review

* refactor: adjust component for e2e test

* refactor: adjust fallback

* refactor: apply changes from code review

* refactor: apply changes from code review

* refactor: set IconButton default as type=button and remove from use cases

* refactor:  remove aria-labels when duplicated and type=button from use cases

* refactor: clean up

* refactor: fix tests

* refactor: fix type errors

* refactor: remove changes in order in order to add them to a separate PR

* refactor: set IconButton default as type=button

* refactor: remove tooltip

* refactor: apply changes requested in review
pull/69763/head
Laura Benz 2 years ago committed by GitHub
parent c826739ee8
commit 24502c4c4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .betterer.results
  2. 10
      packages/grafana-ui/src/components/Card/Card.test.tsx
  3. 2
      packages/grafana-ui/src/components/ContextMenu/ContextMenu.story.tsx
  4. 4
      packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksListItem.tsx
  5. 15
      packages/grafana-ui/src/components/FileDropzone/FileListItem.tsx
  6. 8
      packages/grafana-ui/src/components/IconButton/IconButton.story.tsx
  7. 3
      packages/grafana-ui/src/components/IconButton/IconButton.tsx
  8. 2
      packages/grafana-ui/src/components/Modal/Modal.tsx
  9. 4
      packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx
  10. 2
      packages/grafana-ui/src/components/PanelChrome/PanelChrome.mdx
  11. 2
      packages/grafana-ui/src/components/Select/MultiValue.tsx
  12. 2
      packages/grafana-ui/src/components/TabbedContainer/TabbedContainer.tsx
  13. 2
      packages/grafana-ui/src/components/TagsInput/TagItem.tsx
  14. 3
      packages/grafana-ui/src/components/Toggletip/Toggletip.tsx
  15. 16
      packages/grafana-ui/src/options/builder/stacking.tsx
  16. 1
      public/app/core/components/AppChrome/MegaMenu/NavBarMenu.tsx
  17. 9
      public/app/core/components/CloseButton/CloseButton.tsx
  18. 8
      public/app/core/components/Layers/LayerDragDropList.tsx
  19. 4
      public/app/core/components/OptionsUI/color.tsx
  20. 2
      public/app/core/components/OptionsUI/units.tsx
  21. 3
      public/app/core/components/PasswordField/PasswordField.tsx
  22. 3
      public/app/core/components/QueryOperationRow/QueryOperationRowHeader.tsx
  23. 2
      public/app/features/alerting/unified/RuleViewer.tsx
  24. 2
      public/app/features/alerting/unified/components/AlertLabel.tsx
  25. 4
      public/app/features/alerting/unified/components/DynamicTable.tsx
  26. 4
      public/app/features/alerting/unified/components/expressions/Expression.tsx
  27. 8
      public/app/features/alerting/unified/components/mute-timings/MuteTimingTimeRange.tsx
  28. 8
      public/app/features/alerting/unified/components/mute-timings/MuteTimingsTable.tsx
  29. 7
      public/app/features/alerting/unified/components/notification-policies/EditNotificationPolicyForm.tsx
  30. 2
      public/app/features/alerting/unified/components/silences/MatchersField.tsx
  31. 4
      public/app/features/correlations/Forms/TransformationsEditor.tsx
  32. 7
      public/app/features/dashboard/components/AddLibraryPanelWidget/AddLibraryPanelWidget.tsx
  33. 4
      public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx
  34. 4
      public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsList.tsx
  35. 18
      public/app/features/dashboard/components/DashboardSettings/AnnotationsSettings.test.tsx
  36. 18
      public/app/features/dashboard/components/DashboardSettings/LinksSettings.test.tsx
  37. 6
      public/app/features/dashboard/components/LinksSettings/LinkSettingsList.tsx
  38. 2
      public/app/features/dashboard/components/PanelEditor/DynamicConfigValueEditor.tsx
  39. 2
      public/app/features/dashboard/components/PanelEditor/OverrideCategoryTitle.tsx
  40. 2
      public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx
  41. 2
      public/app/features/dashboard/components/VersionHistory/VersionHistoryHeader.tsx
  42. 2
      public/app/features/dimensions/editors/ThresholdsEditor/ThresholdsEditor.tsx
  43. 16
      public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx
  44. 2
      public/app/features/explore/ExploreQueryInspector.test.tsx
  45. 22
      public/app/features/explore/RichHistory/RichHistoryCard.test.tsx
  46. 10
      public/app/features/explore/RichHistory/RichHistoryCard.tsx
  47. 4
      public/app/features/explore/TraceView/components/common/SearchBarInput.tsx
  48. 4
      public/app/features/logs/components/LogRowMessage.tsx
  49. 1
      public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx
  50. 3
      public/app/features/playlist/PlaylistTableRows.tsx
  51. 2
      public/app/features/search/page/components/ManageActions.tsx
  52. 2
      public/app/features/search/page/components/columns.tsx
  53. 1
      public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx
  54. 7
      public/app/features/support-bundles/SupportBundles.tsx
  55. 1
      public/app/features/transformers/editors/OrganizeFieldsTransformerEditor.tsx
  56. 2
      public/app/features/transformers/extractFields/components/JSONPathEditor.tsx
  57. 4
      public/app/features/variables/editor/VariableEditorListRow.tsx
  58. 2
      public/app/features/variables/inspect/VariableUsagesButton.tsx
  59. 2
      public/app/features/variables/inspect/VariablesUnknownButton.tsx
  60. 6
      public/app/plugins/datasource/elasticsearch/components/QueryEditor/QueryEditorRow.tsx
  61. 2
      public/app/plugins/datasource/loki/querybuilder/components/NestedQuery.tsx
  62. 2
      public/app/plugins/datasource/prometheus/querybuilder/components/NestedQuery.tsx
  63. 36
      public/app/plugins/panel/canvas/editor/element/QuickPositioning.tsx
  64. 8
      public/app/plugins/panel/canvas/editor/inline/InlineEdit.tsx
  65. 6
      public/app/plugins/panel/canvas/editor/layer/TreeNodeTitle.tsx
  66. 2
      public/app/plugins/panel/debug/RenderInfoViewer.tsx
  67. 2
      public/app/plugins/panel/timeseries/LineStyleEditor.tsx
  68. 4
      public/app/plugins/panel/timeseries/TimezonesEditor.tsx
  69. 4
      public/app/plugins/panel/timeseries/plugins/annotations/AnnotationTooltip.tsx
  70. 1
      public/app/plugins/panel/xychart/AutoEditor.tsx
  71. 1
      public/app/plugins/panel/xychart/ManualEditor.tsx

@ -2883,9 +2883,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
],
"public/app/features/playlist/PlaylistTableRows.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
"public/app/features/plugins/admin/components/AppConfigWrapper.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]

@ -27,7 +27,7 @@ describe('Card', () => {
<Button>Click Me</Button>
</Card.Actions>
<Card.SecondaryActions>
<IconButton name="trash-alt" aria-label="Delete" />
<IconButton name="trash-alt" aria-label="Delete" tooltip="Delete" />
</Card.SecondaryActions>
</Card>
);
@ -42,7 +42,7 @@ describe('Card', () => {
<Button>Click Me</Button>
</Card.Actions>
<Card.SecondaryActions>
<IconButton name="trash-alt" aria-label="Delete" />
<IconButton name="trash-alt" aria-label="Delete" tooltip="Delete" />
</Card.SecondaryActions>
</Card>
);
@ -59,7 +59,7 @@ describe('Card', () => {
<Button disabled>Click Me</Button>
</Card.Actions>
<Card.SecondaryActions>
<IconButton name="trash-alt" aria-label="Delete" disabled />
<IconButton name="trash-alt" aria-label="Delete" tooltip="Delete" disabled />
</Card.SecondaryActions>
</Card>
);
@ -74,7 +74,7 @@ describe('Card', () => {
<Button disabled={false}>Click Me</Button>
</Card.Actions>
<Card.SecondaryActions>
<IconButton name="trash-alt" aria-label="Delete" disabled={false} />
<IconButton name="trash-alt" aria-label="Delete" tooltip="Delete" disabled={false} />
</Card.SecondaryActions>
</Card>
);
@ -93,7 +93,7 @@ describe('Card', () => {
{shouldNotRender && <Button>Delete</Button>}
</Card.Actions>
<Card.SecondaryActions>
{shouldNotRender && <IconButton name="trash-alt" aria-label="Delete" disabled={false} />}
{shouldNotRender && <IconButton name="trash-alt" aria-label="Delete" tooltip="Delete" disabled={false} />}
</Card.SecondaryActions>
</Card>
);

@ -41,7 +41,7 @@ export const Basic: StoryFn<typeof ContextMenu> = (args: ContextMenuProps) => {
export const WithState: StoryFn<typeof WithContextMenu> = (args: WithContextMenuProps) => {
return (
<WithContextMenu {...args}>
{({ openMenu }) => <IconButton name="info-circle" onClick={openMenu} />}
{({ openMenu }) => <IconButton name="info-circle" onClick={openMenu} tooltip="More information" />}
</WithContextMenu>
);
};

@ -35,8 +35,8 @@ export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemP
{hasTitle ? title : 'Data link title not provided'}
</div>
<div className={styles.actionButtons}>
<IconButton name="pen" onClick={onEdit} />
<IconButton name="times" onClick={onRemove} />
<IconButton name="pen" onClick={onEdit} tooltip="Edit data link title" />
<IconButton name="times" onClick={onRemove} tooltip="Remove data link title" />
</div>
</div>
<div

@ -26,24 +26,13 @@ export function FileListItem({ file: customFile, removeFile }: FileListItemProps
return (
<>
<span className={styles.error}>{error.message}</span>
{retryUpload && (
<IconButton
type="button"
aria-label="Retry"
name="sync"
tooltip="Retry"
tooltipPlacement="top"
onClick={retryUpload}
/>
)}
{retryUpload && <IconButton name="sync" tooltip="Retry" tooltipPlacement="top" onClick={retryUpload} />}
{removeFile && (
<IconButton
className={retryUpload ? styles.marginLeft : ''}
type="button"
name="trash-alt"
onClick={() => removeFile(customFile)}
tooltip={REMOVE_FILE}
aria-label={REMOVE_FILE}
/>
)}
</>
@ -69,8 +58,6 @@ export function FileListItem({ file: customFile, removeFile }: FileListItemProps
name="trash-alt"
onClick={() => removeFile(customFile)}
tooltip={REMOVE_FILE}
aria-label={REMOVE_FILE}
type="button"
tooltipPlacement="top"
/>
)

@ -66,7 +66,7 @@ export const ExamplesSizes = () => {
<div className={rowStyle} key={icon}>
{sizes.map((size) => (
<span key={icon + size}>
<IconButton name={icon} size={size} variant={variant} />
<IconButton name={icon} size={size} variant={variant} tooltip="Tooltip example" />
</span>
))}
</div>
@ -81,7 +81,7 @@ export const ExamplesSizes = () => {
<div className={rowStyle} key={icon}>
{sizes.map((size) => (
<span key={icon + size}>
<IconButton name={icon} size={size} disabled />
<IconButton name={icon} size={size} tooltip="Tooltip example" disabled />
</span>
))}
</div>
@ -121,9 +121,9 @@ const RenderBackgroundScenario = ({ background }: ScenarioProps) => {
`}
>
{variants.map((variant) => {
return <IconButton name="times" size="xl" variant={variant} key={variant} />;
return <IconButton name="times" size="xl" variant={variant} key={variant} tooltip="Tooltip example" />;
})}
<IconButton name="times" size="xl" disabled />
<IconButton name="times" size="xl" tooltip="Tooltip example" disabled />
</div>
</VerticalGroup>
</div>

@ -28,7 +28,7 @@ export interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
tooltipPlacement?: TooltipPlacement;
/** Variant to change the color of the Icon */
variant?: IconButtonVariant;
/** Text avilable ony for screenscreen readers. Will use tooltip text as fallback. */
/** Text available only for screen readers. Will use tooltip text as fallback. */
ariaLabel?: string;
}
@ -68,6 +68,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, Props>(
aria-label={ariaLabel || tooltipString}
{...restProps}
className={cx(styles.button, className)}
type="button"
>
<Icon name={name} size={limitedIconSize} className={styles.icon} type={iconType} />
</button>

@ -84,7 +84,7 @@ export function Modal(props: PropsWithChildren<Props>) {
typeof title !== 'string' && title
}
<div className={styles.modalHeaderClose}>
<IconButton aria-label="Close dialog" name="times" size="xl" onClick={onDismiss} />
<IconButton aria-label="Close dialog" name="times" size="xl" onClick={onDismiss} tooltip="Close" />
</div>
</div>
<div className={cx(styles.modalContent, contentClassName)}>{children}</div>

@ -34,8 +34,8 @@ export const Examples = () => {
titleHref=""
parentHref=""
leftItems={[
<IconButton name="share-alt" size="lg" key="share" />,
<IconButton name="favorite" iconType="mono" size="lg" key="favorite" />,
<IconButton name="share-alt" size="lg" key="share" tooltip="Share" />,
<IconButton name="favorite" iconType="mono" size="lg" key="favorite" tooltip="Add to favourites" />,
]}
>
<ToolbarButton icon="panel-add" />

@ -358,7 +358,7 @@ Component used for rendering content wrapped in the same style as grafana panels
variant="secondary"
tooltip="extra content to render"
/>
<IconButton name="sliders-v-alt" variant="secondary" tooltip="extra content2 to render" />
<IconButton name="sliders-v-alt" variant="secondary" tooltip="extra content to render" />
</>
}
actions={

@ -27,5 +27,5 @@ export type MultiValueRemoveProps = {
export const MultiValueRemove = ({ children, innerProps }: React.PropsWithChildren<MultiValueRemoveProps>) => {
const theme = useTheme2();
const styles = getSelectStyles(theme);
return <IconButton {...innerProps} name="times" size="sm" className={styles.multiValueRemove} />;
return <IconButton {...innerProps} name="times" size="sm" className={styles.multiValueRemove} tooltip="Remove" />;
};

@ -72,7 +72,7 @@ export function TabbedContainer(props: TabbedContainerProps) {
icon={t.icon}
/>
))}
<IconButton className={styles.close} onClick={onClose} name="times" title={closeIconTooltip ?? 'Close'} />
<IconButton className={styles.close} onClick={onClose} name="times" tooltip={closeIconTooltip ?? 'Close'} />
</TabsBar>
<CustomScrollbar autoHeightMin="100%">
<TabContent className={styles.tabContent}>{tabs.find((t) => t.value === activeTab)?.content}</TabContent>

@ -29,8 +29,8 @@ export const TagItem = ({ name, disabled, onRemove }: Props) => {
size="lg"
disabled={disabled}
ariaLabel={`Remove "${name}" tag`}
tooltip="Remove tag"
onClick={() => onRemove(name)}
type="button"
className={styles.buttonStyles}
/>
</li>

@ -97,9 +97,8 @@ export const Toggletip = React.memo(
{closeButton && (
<div className={style.headerClose}>
<IconButton
aria-label="Close Toggletip"
tooltip="Close"
name="times"
size="md"
data-testid="toggletip-header-close"
onClick={closeToggletip}
/>

@ -8,15 +8,7 @@ import {
} from '@grafana/data';
import { StackingConfig, StackingMode } from '@grafana/schema';
import {
GraphFieldConfig,
graphFieldOptions,
HorizontalGroup,
IconButton,
Input,
RadioButtonGroup,
Tooltip,
} from '../..';
import { GraphFieldConfig, graphFieldOptions, HorizontalGroup, IconButton, Input, RadioButtonGroup } from '../..';
export const StackingEditor = ({ value, context, onChange, item }: FieldOverrideEditorProps<StackingConfig, any>) => {
return (
@ -35,11 +27,7 @@ export const StackingEditor = ({ value, context, onChange, item }: FieldOverride
<Input
type="text"
placeholder="Group"
suffix={
<Tooltip content="Name of the stacking group" placement="top">
<IconButton name="question-circle" />
</Tooltip>
}
suffix={<IconButton name="question-circle" tooltip="Name of the stacking group" tooltipPlacement="top" />}
defaultValue={value?.group}
onChange={(v) => {
onChange({

@ -67,6 +67,7 @@ export function NavBarMenu({ activeItem, navItems, searchBarHidden, onClose }: P
<Icon name="bars" size="xl" />
<IconButton
aria-label="Close navigation menu"
tooltip="Close menu"
name="times"
onClick={onMenuClose}
size="xl"

@ -13,7 +13,14 @@ type Props = {
export const CloseButton = ({ onClick, 'aria-label': ariaLabel, style }: Props) => {
const styles = useStyles2(getStyles);
return (
<IconButton aria-label={ariaLabel ?? 'Close'} className={styles} name="times" onClick={onClick} style={style} />
<IconButton
aria-label={ariaLabel ?? 'Close'}
className={styles}
name="times"
onClick={onClick}
style={style}
tooltip="Close"
/>
);
};

@ -80,8 +80,8 @@ export const LayerDragDropList = <T extends LayerElement>({
{onDuplicate ? (
<IconButton
name="copy"
title={'Duplicate'}
ariaLabel={'Duplicate button'}
tooltip="Duplicate"
ariaLabel="Duplicate button"
className={style.actionIcon}
onClick={() => onDuplicate(element)}
/>
@ -89,8 +89,8 @@ export const LayerDragDropList = <T extends LayerElement>({
<IconButton
name="trash-alt"
title={'remove'}
ariaLabel={'Remove button'}
tooltip="Remove"
ariaLabel="Remove button"
className={cx(style.actionIcon, style.dragIcon)}
onClick={() => onDelete(element)}
/>

@ -53,7 +53,9 @@ export const ColorValueEditor = ({ value, settings, onChange, details }: Props)
{settings?.placeholder ?? 'Select color'}
</span>
)}
{settings?.isClearable && value && <IconButton name="times" onClick={() => onChange(undefined)} />}
{settings?.isClearable && value && (
<IconButton name="times" onClick={() => onChange(undefined)} tooltip="Clear settings" />
)}
</>
)}
</div>

@ -14,7 +14,7 @@ export function UnitValueEditor({ value, onChange, item }: Props) {
<span className={styles.first}>
<UnitPicker value={value} onChange={onChange} />
</span>
<IconButton ariaLabel="clear unit selection" name="times" onClick={() => onChange(undefined)} />
<IconButton name="times" onClick={() => onChange(undefined)} tooltip="Clear unit selection" />
</div>
);
}

@ -27,14 +27,13 @@ export const PasswordField = React.forwardRef<HTMLInputElement, Props>(
suffix={
<IconButton
name={showPassword ? 'eye-slash' : 'eye'}
type="button"
aria-controls={id}
role="switch"
aria-checked={showPassword}
aria-label="Show password"
onClick={() => {
setShowPassword(!showPassword);
}}
tooltip={showPassword ? 'Hide password' : 'Show password'}
/>
}
/>

@ -37,11 +37,10 @@ export const QueryOperationRowHeader = ({
<div className={styles.column}>
<IconButton
name={isContentVisible ? 'angle-down' : 'angle-right'}
title="toggle collapse and expand"
aria-label="toggle collapse and expand query row"
tooltip={isContentVisible ? 'Collapse query row' : 'Expand query row'}
className={styles.collapseIcon}
onClick={onRowToggle}
type="button"
aria-expanded={isContentVisible}
aria-controls={id}
/>

@ -260,7 +260,7 @@ function GrafanaRuleUID({ rule }: { rule: GrafanaRuleDefinition }) {
return (
<DetailsField label="Rule UID" childrenWrapperClassName={styles.ruleUid}>
{rule.uid} <IconButton name="copy" onClick={copyUID} />
{rule.uid} <IconButton name="copy" onClick={copyUID} tooltip="Copy rule" />
</DetailsField>
);
}

@ -19,7 +19,7 @@ export const AlertLabel = ({ labelKey, value, operator = '=', onRemoveLabel }: P
{labelKey}
{operator}
{value}
{!!onRemoveLabel && <IconButton name="times" size="xs" onClick={onRemoveLabel} />}
{!!onRemoveLabel && <IconButton name="times" size="xs" onClick={onRemoveLabel} tooltip="Remove label" />}
</div>
);
};

@ -124,12 +124,10 @@ export const DynamicTable = <T extends object>({
{isExpandable && (
<div className={cx(styles.cell, styles.expandCell)}>
<IconButton
aria-label={`${isItemExpanded ? 'Collapse' : 'Expand'} row`}
size="md"
tooltip={`${isItemExpanded ? 'Collapse' : 'Expand'} row`}
data-testid="collapse-toggle"
name={isItemExpanded ? 'angle-down' : 'angle-right'}
onClick={() => toggleExpanded(item)}
type="button"
/>
</div>
)}

@ -216,7 +216,7 @@ const Header: FC<HeaderProps> = ({ refId, queryType, onUpdateRefId, onUpdateExpr
* There are 3 edit modes:
*
* 1. "refId": Editing the refId (ie. A -> B)
* 2. "epressionType": Editing the type of the expression (ie. Reduce -> Math)
* 2. "expressionType": Editing the type of the expression (ie. Reduce -> Math)
* 3. "false": This means we're not editing either of those
*/
const [editMode, setEditMode] = useState<'refId' | 'expressionType' | false>(false);
@ -281,11 +281,11 @@ const Header: FC<HeaderProps> = ({ refId, queryType, onUpdateRefId, onUpdateExpr
</Stack>
<Spacer />
<IconButton
type="button"
name="trash-alt"
variant="secondary"
className={styles.mutedIcon}
onClick={onRemoveExpression}
tooltip="Remove expression"
/>
</Stack>
</header>

@ -121,13 +121,13 @@ export const MuteTimingTimeRange = ({ intervalIndex }: Props) => {
</InlineField>
<IconButton
className={styles.deleteTimeRange}
title={'Remove'}
name={'trash-alt'}
type="button"
title="Remove"
name="trash-alt"
onClick={(e) => {
e.preventDefault();
removeTimeRange(index);
}}
tooltip="Remove time range"
/>
</InlineFieldRow>
</div>
@ -139,7 +139,7 @@ export const MuteTimingTimeRange = ({ intervalIndex }: Props) => {
className={styles.addTimeRange}
variant="secondary"
type="button"
icon={'plus'}
icon="plus"
onClick={() => addTimeRange({ start_time: '', end_time: '' })}
>
Add another time range

@ -150,7 +150,7 @@ function useColumns(alertManagerSourceName: string, hideActions = false, setMute
muteName: data.name,
})}
>
<IconButton name="file-alt" title="View mute timing" />
<IconButton name="file-alt" tooltip="View mute timing" />
</Link>
</div>
);
@ -163,13 +163,13 @@ function useColumns(alertManagerSourceName: string, hideActions = false, setMute
muteName: data.name,
})}
>
<IconButton name="edit" title="Edit mute timing" />
<IconButton name="edit" tooltip="Edit mute timing" />
</Link>
</Authorize>
<Authorize actions={[permissions.delete]}>
<IconButton
name={'trash-alt'}
title="Delete mute timing"
name="trash-alt"
tooltip="Delete mute timing"
onClick={() => setMuteTimingName(data.name)}
/>
</Authorize>

@ -137,12 +137,7 @@ export const AmRoutesExpandedForm = ({
placeholder="value"
/>
</Field>
<IconButton
type="button"
tooltip="Remove matcher"
name={'trash-alt'}
onClick={() => remove(index)}
>
<IconButton tooltip="Remove matcher" name={'trash-alt'} onClick={() => remove(index)}>
Remove
</IconButton>
</Stack>

@ -79,7 +79,7 @@ const MatchersField = ({ className }: Props) => {
<IconButton
className={styles.removeButton}
tooltip="Remove matcher"
name={'trash-alt'}
name="trash-alt"
onClick={() => remove(index)}
>
Remove

@ -229,9 +229,8 @@ export const TransformationsEditor = (props: Props) => {
{!readOnly && (
<div className={styles.removeButton}>
<IconButton
type="button"
tooltip="Remove transformation"
name={'trash-alt'}
name="trash-alt"
onClick={() => {
remove(index);
const keptValsCopy: Array<{ expression?: string; mapValue?: string } | undefined> = [
@ -240,7 +239,6 @@ export const TransformationsEditor = (props: Props) => {
keptValsCopy[index] = undefined;
setKeptVals(compact(keptValsCopy));
}}
ariaLabel="Remove transformation"
>
Remove
</IconButton>

@ -47,7 +47,12 @@ export const AddLibraryPanelWidget = ({ panel, dashboard }: Props) => {
<Trans i18nKey="library-panel.add-widget.title">Add panel from panel library</Trans>
</span>
<div className="flex-grow-1" />
<IconButton aria-label="Close 'Add Panel' widget" name="times" onClick={onCancelAddPanel} />
<IconButton
aria-label="Close 'Add Panel' widget"
name="times"
onClick={onCancelAddPanel}
tooltip="Close widget"
/>
</div>
<LibraryPanelsSearch onClick={onAddLibraryPanel} variant={LibraryPanelsSearchVariant.Tight} showPanelFilter />
</div>

@ -213,7 +213,7 @@ const AddPanelWidgetHandle = ({ children, onBack, onCancel, styles }: AddPanelWi
<div className={cx(styles.headerRow, 'grid-drag-handle')}>
{onBack && (
<div className={styles.backButton}>
<IconButton aria-label="Go back" name="arrow-left" onClick={onBack} size="xl" />
<IconButton name="arrow-left" onClick={onBack} size="xl" tooltip="Go back" />
</div>
)}
{!onBack && (
@ -223,7 +223,7 @@ const AddPanelWidgetHandle = ({ children, onBack, onCancel, styles }: AddPanelWi
)}
{children && <span>{children}</span>}
<div className="flex-grow-1" />
<IconButton aria-label="Close 'Add Panel' widget" name="times" onClick={onCancel} />
<IconButton aria-label="Close 'Add Panel' widget" name="times" onClick={onCancel} tooltip="Close widget" />
</div>
);
};

@ -81,11 +81,11 @@ export const AnnotationSettingsList = ({ dashboard, onNew, onEdit }: Props) => {
{dataSourceSrv.getInstanceSettings(annotation.datasource)?.name || annotation.datasource?.uid}
</td>
<td role="gridcell" style={{ width: '1%' }}>
{idx !== 0 && <IconButton name="arrow-up" aria-label="arrow-up" onClick={() => onMove(idx, -1)} />}
{idx !== 0 && <IconButton name="arrow-up" onClick={() => onMove(idx, -1)} tooltip="Move up" />}
</td>
<td role="gridcell" style={{ width: '1%' }}>
{dashboard.annotations.list.length > 1 && idx !== dashboard.annotations.list.length - 1 ? (
<IconButton name="arrow-down" aria-label="arrow-down" onClick={() => onMove(idx, 1)} />
<IconButton name="arrow-down" onClick={() => onMove(idx, 1)} tooltip="Move down" />
) : null}
</td>
<td role="gridcell" style={{ width: '1%' }}>

@ -158,23 +158,23 @@ describe('AnnotationsSettings', () => {
setup(dashboard);
// Check that we have sorting buttons
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'arrow-up' })).not.toBeInTheDocument();
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'arrow-down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'Move up' })).not.toBeInTheDocument();
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'Move down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'arrow-up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'arrow-down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'Move up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'Move down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'arrow-up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'arrow-down' })).not.toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'Move up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'Move down' })).not.toBeInTheDocument();
// Check the original order
expect(within(getTableBodyRows()[0]).queryByText(/annotations & alerts/i)).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByText(/annotation 2/i)).toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByText(/annotation 3/i)).toBeInTheDocument();
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'arrow-down' })[0]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'arrow-down' })[1]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'arrow-up' })[0]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'Move down' })[0]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'Move down' })[1]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'Move up' })[0]);
// Checking if it has changed the sorting accordingly
expect(within(getTableBodyRows()[0]).queryByText(/annotation 3/i)).toBeInTheDocument();

@ -113,23 +113,23 @@ describe('LinksSettings', () => {
setup(dashboard);
// Check that we have sorting buttons
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'arrow-up' })).not.toBeInTheDocument();
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'arrow-down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'Move link up' })).not.toBeInTheDocument();
expect(within(getTableBodyRows()[0]).queryByRole('button', { name: 'Move link down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'arrow-up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'arrow-down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'Move link up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[1]).queryByRole('button', { name: 'Move link down' })).toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'arrow-up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'arrow-down' })).not.toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'Move link up' })).toBeInTheDocument();
expect(within(getTableBodyRows()[2]).queryByRole('button', { name: 'Move link down' })).not.toBeInTheDocument();
// Checking the original order
assertRowHasText(0, links[0].title);
assertRowHasText(1, links[1].title);
assertRowHasText(2, links[2].url);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'arrow-down' })[0]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'arrow-down' })[1]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'arrow-up' })[0]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'Move link down' })[0]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'Move link down' })[1]);
await userEvent.click(within(getTableBody()).getAllByRole('button', { name: 'Move link up' })[0]);
// Checking if it has changed the sorting accordingly
assertRowHasText(0, links[2].url);

@ -75,15 +75,15 @@ export const LinkSettingsList = ({ dashboard, onNew, onEdit }: LinkSettingsListP
</HorizontalGroup>
</td>
<td style={{ width: '1%' }} role="gridcell">
{idx !== 0 && <IconButton name="arrow-up" aria-label="arrow-up" onClick={() => moveLink(idx, -1)} />}
{idx !== 0 && <IconButton name="arrow-up" onClick={() => moveLink(idx, -1)} tooltip="Move link up" />}
</td>
<td style={{ width: '1%' }} role="gridcell">
{links.length > 1 && idx !== links.length - 1 ? (
<IconButton name="arrow-down" aria-label="arrow-down" onClick={() => moveLink(idx, 1)} />
<IconButton name="arrow-down" onClick={() => moveLink(idx, 1)} tooltip="Move link down" />
) : null}
</td>
<td style={{ width: '1%' }} role="gridcell">
<IconButton aria-label="copy" name="copy" onClick={() => duplicateLink(link, idx)} />
<IconButton name="copy" onClick={() => duplicateLink(link, idx)} tooltip="Copy link" />
</td>
<td style={{ width: '1%' }} role="gridcell">
<DeleteButton

@ -66,7 +66,7 @@ export const DynamicConfigValueEditor = ({
</Label>
{!isSystemOverride && (
<div>
<IconButton name="times" onClick={onRemove} />
<IconButton name="times" onClick={onRemove} tooltip="Remove label" />
</div>
)}
</HorizontalGroup>

@ -30,7 +30,7 @@ export const OverrideCategoryTitle = ({
<div>
<HorizontalGroup justify="space-between">
<div>{overrideName}</div>
<IconButton name="trash-alt" onClick={onOverrideRemove} title="Remove override" />
<IconButton name="trash-alt" onClick={onOverrideRemove} tooltip="Remove override" />
</HorizontalGroup>
{!isExpanded && (
<div className={styles.overrideDetails}>

@ -249,6 +249,7 @@ class UnThemedTransformationsEditor extends React.PureComponent<TransformationsE
onClick={() => {
this.setState({ search: '' });
}}
tooltip="Clear search"
/>
</>
);
@ -266,6 +267,7 @@ class UnThemedTransformationsEditor extends React.PureComponent<TransformationsE
onClick={() => {
this.setState({ showPicker: false });
}}
tooltip="Close picker"
/>
);
}

@ -22,7 +22,7 @@ export const VersionHistoryHeader = ({
return (
<h3 className={styles.header}>
<IconButton name="arrow-left" size="xl" onClick={onClick} />
<IconButton name="arrow-left" size="xl" onClick={onClick} tooltip="Reset version" />
<span>
Comparing {baseVersion} <Icon name="arrows-h" /> {newVersion}{' '}
{isNewLatest && <cite className="muted">(Latest)</cite>}

@ -199,10 +199,10 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
}
suffix={
<IconButton
aria-label={`Remove ${ariaLabel}`}
className={styles.trashIcon}
name="trash-alt"
onClick={() => this.onRemoveThreshold(threshold)}
tooltip={`Remove ${ariaLabel}`}
/>
}
/>

@ -220,8 +220,20 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
)}
<td className={styles.textAlignCenter}>
<HorizontalGroup spacing="sm">
<IconButton name="copy" onClick={() => onDuplicate(index)} data-testid="duplicate-value-mapping" />
<IconButton name="trash-alt" onClick={() => onRemove(index)} data-testid="remove-value-mapping" />
<IconButton
name="copy"
onClick={() => onDuplicate(index)}
data-testid="duplicate-value-mapping"
aria-label="Duplicate value mapping"
tooltip="Duplicate"
/>
<IconButton
name="trash-alt"
onClick={() => onRemove(index)}
data-testid="remove-value-mapping"
aria-label="Delete value mapping"
tooltip="Delete"
/>
</HorizontalGroup>
</td>
</tr>

@ -67,7 +67,7 @@ const setup = (propOverrides = {}) => {
describe('ExploreQueryInspector', () => {
it('should render closable drawer component', () => {
setup();
expect(screen.getByTitle(/close query inspector/i)).toBeInTheDocument();
expect(screen.getByLabelText(/close query inspector/i)).toBeInTheDocument();
});
it('should render 4 Tabs if queryResponse has no error', () => {
setup();

@ -384,28 +384,28 @@ describe('RichHistoryCard', () => {
});
it('should have title "Edit comment" at comment icon, if comment present', async () => {
setup({ query: starredQueryWithComment });
const editComment = await screen.findByTitle('Edit comment');
const editComment = await screen.findByLabelText('Edit comment');
const addComment = screen.queryByTitle('Add comment');
expect(editComment).toBeInTheDocument();
expect(addComment).not.toBeInTheDocument();
});
it('should have title "Add comment" at comment icon, if no comment present', async () => {
setup();
const addComment = await screen.findByTitle('Add comment');
const addComment = await screen.findByLabelText('Add comment');
const editComment = await screen.queryByTitle('Edit comment');
expect(addComment).toBeInTheDocument();
expect(editComment).not.toBeInTheDocument();
});
it('should open update comment form when edit comment button clicked', async () => {
setup({ query: starredQueryWithComment });
const editComment = await screen.findByTitle('Edit comment');
const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form');
expect(updateCommentForm).toBeInTheDocument();
});
it('should close update comment form when escape key pressed', async () => {
setup({ query: starredQueryWithComment });
const editComment = await screen.findByTitle('Edit comment');
const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form');
await userEvent.click(updateCommentForm);
@ -417,7 +417,7 @@ describe('RichHistoryCard', () => {
});
it('should close update comment form when enter and shift keys pressed', async () => {
setup({ query: starredQueryWithComment });
const editComment = await screen.findByTitle('Edit comment');
const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form');
await userEvent.click(updateCommentForm);
@ -430,7 +430,7 @@ describe('RichHistoryCard', () => {
});
it('should close update comment form when enter and ctrl keys pressed', async () => {
setup({ query: starredQueryWithComment });
const editComment = await screen.findByTitle('Edit comment');
const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form');
await userEvent.click(updateCommentForm);
@ -443,7 +443,7 @@ describe('RichHistoryCard', () => {
});
it('should not close update comment form when enter key pressed', async () => {
setup({ query: starredQueryWithComment });
const editComment = await screen.findByTitle('Edit comment');
const editComment = await screen.findByLabelText('Edit comment');
await userEvent.click(editComment);
const updateCommentForm = await screen.findByLabelText('Update comment form');
await userEvent.click(updateCommentForm);
@ -459,14 +459,14 @@ describe('RichHistoryCard', () => {
describe('starring', () => {
it('should have title "Star query", if not starred', async () => {
setup();
const starButton = await screen.findByTitle('Star query');
const starButton = await screen.findByLabelText('Star query');
expect(starButton).toBeInTheDocument();
await userEvent.click(starButton);
expect(starRichHistoryMock).toBeCalledWith(starredQueryWithComment.id, true);
});
it('should have title "Unstar query", if not starred', async () => {
setup({ query: starredQueryWithComment });
const unstarButton = await screen.findByTitle('Unstar query');
const unstarButton = await screen.findByLabelText('Unstar query');
expect(unstarButton).toBeInTheDocument();
await userEvent.click(unstarButton);
expect(starRichHistoryMock).toBeCalledWith(starredQueryWithComment.id, false);
@ -476,14 +476,14 @@ describe('RichHistoryCard', () => {
describe('deleting', () => {
it('should delete if not starred', async () => {
setup();
const deleteButton = await screen.findByTitle('Delete query');
const deleteButton = await screen.findByLabelText('Delete query');
expect(deleteButton).toBeInTheDocument();
await userEvent.click(deleteButton);
expect(deleteRichHistoryMock).toBeCalledWith(starredQueryWithComment.id);
});
it('should display modal before deleting if starred', async () => {
setup({ query: starredQueryWithComment });
const deleteButton = await screen.findByTitle('Delete query');
const deleteButton = await screen.findByLabelText('Delete query');
await userEvent.click(deleteButton);
expect(deleteRichHistoryMock).not.toBeCalled();
expect(appEvents.publish).toHaveBeenCalledWith(new ShowConfirmModalEvent(expect.anything()));

@ -304,18 +304,18 @@ export function RichHistoryCard(props: Props) {
<IconButton
name="comment-alt"
onClick={toggleActiveUpdateComment}
title={query.comment?.length > 0 ? 'Edit comment' : 'Add comment'}
tooltip={query.comment?.length > 0 ? 'Edit comment' : 'Add comment'}
/>
<IconButton name="copy" onClick={onCopyQuery} title="Copy query to clipboard" />
<IconButton name="copy" onClick={onCopyQuery} tooltip="Copy query to clipboard" />
{value?.dsInstance && (
<IconButton name="share-alt" onClick={onCreateShortLink} title="Copy shortened link to clipboard" />
<IconButton name="share-alt" onClick={onCreateShortLink} tooltip="Copy shortened link to clipboard" />
)}
<IconButton name="trash-alt" title={'Delete query'} onClick={onDeleteQuery} />
<IconButton name="trash-alt" title="Delete query" tooltip="Delete query" onClick={onDeleteQuery} />
<IconButton
name={query.starred ? 'favorite' : 'star'}
iconType={query.starred ? 'mono' : 'default'}
onClick={onStarrQuery}
title={query.starred ? 'Unstar query' : 'Star query'}
tooltip={query.starred ? 'Unstar query' : 'Star query'}
/>
</div>
);

@ -44,7 +44,9 @@ export default class SearchBarInput extends React.PureComponent<Props> {
const suffix = (
<>
{inputProps.suffix}
{allowClear && value && value.length && <IconButton name="times" onClick={this.clearUiFind} />}
{allowClear && value && value.length && (
<IconButton name="times" onClick={this.clearUiFind} tooltip="Clear input" />
)}
</>
);

@ -103,11 +103,11 @@ export class LogRowMessage extends PureComponent<Props> {
<span className={cx('log-row-menu', styles.rowMenu)} onClick={this.onLogRowClick}>
{shouldShowContextToggle && (
<IconButton
tooltip="Show context"
tooltipPlacement="top"
size="md"
name="gf-show-context"
onClick={this.onShowContextClick}
tooltip="Show context"
tooltipPlacement="top"
/>
)}
<ClipboardButton

@ -64,6 +64,7 @@ export const PanelTypeCard = ({
}}
className={styles.deleteButton}
aria-label="Delete button on panel type card"
tooltip="Delete"
/>
)}
</div>

@ -80,8 +80,7 @@ export const PlaylistTableRows = ({ items, onDelete }: Props) => {
name="times"
size="md"
onClick={() => onDelete(index)}
aria-label={selectors.pages.PlaylistForm.itemDelete}
type="button"
tooltip={selectors.pages.PlaylistForm.itemDelete}
/>
<Icon title="Drag and drop to reorder" name="draggabledots" size="md" />
</div>

@ -44,7 +44,7 @@ export function ManageActions({ items, folder, onChange, clearSelection }: Props
return (
<div className={styles.actionRow} data-testid="manage-actions">
<HorizontalGroup spacing="md" width="auto">
<IconButton name="check-square" onClick={clearSelection} title="Uncheck everything" />
<IconButton name="check-square" onClick={clearSelection} tooltip="Uncheck everything" />
<Button disabled={!canMove} onClick={onMove} icon="exchange-alt" variant="secondary">
Move
</Button>

@ -65,7 +65,7 @@ export const generateColumns = (
if (selection('*', '*')) {
return (
<div className={styles.checkboxHeader}>
<IconButton name="check-square" onClick={clearSelection} />
<IconButton name="check-square" onClick={clearSelection} tooltip="Clear selection" />
</div>
);
}

@ -133,6 +133,7 @@ const ServiceAccountListItem = memo(
size="md"
onClick={() => onRemoveButtonClick(serviceAccount)}
aria-label={`Delete service account ${serviceAccount.name}`}
tooltip="Delete account"
/>
)}
</HorizontalGroup>

@ -93,7 +93,12 @@ const SupportBundlesUnconnected = ({ supportBundles, isLoading, loadBundles, rem
</th>
<th>
{hasDeleteAccess && (
<IconButton onClick={() => removeBundle(bundle.uid)} name="trash-alt" variant="destructive" />
<IconButton
onClick={() => removeBundle(bundle.uid)}
name="trash-alt"
variant="destructive"
tooltip="Remove bundle"
/>
)}
</th>
</tr>

@ -145,6 +145,7 @@ const DraggableFieldName = ({
size="md"
name={visible ? 'eye' : 'eye-slash'}
onClick={() => onToggleVisibility(fieldName, visible)}
tooltip={visible ? 'Disable' : 'Enable'}
/>
<span className={styles.name} title={fieldName}>
{fieldName}

@ -67,7 +67,7 @@ export function JSONPathEditor({ options, onChange }: Props) {
/>
</InlineField>
<InlineField className={cx(style.removeIcon)}>
<IconButton onClick={() => removeJSONPath(key)} name={'trash-alt'} />
<IconButton onClick={() => removeJSONPath(key)} name={'trash-alt'} tooltip="Remove path" />
</InlineField>
</InlineFieldRow>
</li>

@ -94,7 +94,7 @@ export function VariableEditorListRow({
propsOnDuplicate(identifier);
}}
name="copy"
title="Duplicate variable"
tooltip="Duplicate variable"
aria-label={selectors.pages.Dashboard.Settings.Variables.List.tableRowDuplicateButtons(variable.name)}
/>
</td>
@ -107,7 +107,7 @@ export function VariableEditorListRow({
propsOnDelete(identifier);
}}
name="trash-alt"
title="Remove variable"
tooltip="Remove variable"
aria-label={selectors.pages.Dashboard.Settings.Variables.List.tableRowRemoveButtons(variable.name)}
/>
</td>

@ -35,7 +35,7 @@ export const VariableUsagesButton = ({ id, usages, isAdhoc }: Props) => {
showModal();
}}
name="code-branch"
title="Show usages"
tooltip="Show usages"
/>
);
}}

@ -31,7 +31,7 @@ export const VariablesUnknownButton = ({ id, usages }: Props) => {
<IconButton
onClick={() => showModal()}
name="code-branch"
title="Show usages"
tooltip="Show usages"
data-testid="VariablesUnknownButton"
/>
);

@ -33,9 +33,8 @@ export const QueryEditorRow = ({
onClick={onHideClick}
size="sm"
aria-pressed={hidden}
aria-label="hide metric"
className={styles.icon}
type="button"
tooltip="Hide metric"
/>
)}
<IconButton
@ -44,8 +43,7 @@ export const QueryEditorRow = ({
className={styles.icon}
onClick={onRemoveClick || noop}
disabled={!onRemoveClick}
aria-label="remove metric"
type="button"
tooltip="Remove metric"
/>
</span>
</InlineLabel>

@ -72,7 +72,7 @@ export const NestedQuery = React.memo<Props>(
/>
</div>
<FlexItem grow={1} />
<IconButton ariaLabel="Remove nested query" name="times" size="sm" onClick={() => onRemove(index)} />
<IconButton name="times" size="sm" onClick={() => onRemove(index)} tooltip="Remove nested query" />
</div>
<div className={styles.body}>
<EditorRows>

@ -71,7 +71,7 @@ export const NestedQuery = React.memo<Props>((props) => {
/>
</div>
<FlexItem grow={1} />
<IconButton name="times" size="sm" onClick={() => onRemove(index)} />
<IconButton name="times" size="sm" onClick={() => onRemove(index)} tooltip="Remove match" />
</div>
<div className={styles.body}>
<EditorRows>

@ -65,45 +65,45 @@ export const QuickPositioning = ({ onPositionChange, element, settings }: Props)
return (
<div className={styles.buttonGroup}>
<IconButton
name={'horizontal-align-left'}
name="horizontal-align-left"
onClick={() => onQuickPositioningChange(QuickPlacement.Left)}
className={styles.button}
size={'lg'}
tooltip={'Align left'}
size="lg"
tooltip="Align left"
/>
<IconButton
name={'horizontal-align-center'}
name="horizontal-align-center"
onClick={() => onQuickPositioningChange(QuickPlacement.HorizontalCenter)}
className={styles.button}
size={'lg'}
tooltip={'Align horizontal centers'}
size="lg"
tooltip="Align horizontal centers"
/>
<IconButton
name={'horizontal-align-right'}
name="horizontal-align-right"
onClick={() => onQuickPositioningChange(QuickPlacement.Right)}
className={styles.button}
size={'lg'}
tooltip={'Align right'}
size="lg"
tooltip="Align right"
/>
<IconButton
name={'vertical-align-top'}
name="vertical-align-top"
onClick={() => onQuickPositioningChange(QuickPlacement.Top)}
size={'lg'}
tooltip={'Align top'}
size="lg"
tooltip="Align top"
/>
<IconButton
name={'vertical-align-center'}
name="vertical-align-center"
onClick={() => onQuickPositioningChange(QuickPlacement.VerticalCenter)}
className={styles.button}
size={'lg'}
tooltip={'Align vertical centers'}
size="lg"
tooltip="Align vertical centers"
/>
<IconButton
name={'vertical-align-bottom'}
name="vertical-align-bottom"
onClick={() => onQuickPositioningChange(QuickPlacement.Bottom)}
className={styles.button}
size={'lg'}
tooltip={'Align bottom'}
size="lg"
tooltip="Align bottom"
/>
</div>
);

@ -84,7 +84,13 @@ export function InlineEdit({ onClose, id, scene }: Props) {
<strong className={styles.inlineEditorHeader}>
<div className={styles.placeholder} />
<div>Canvas Inline Editor</div>
<IconButton name="times" size="xl" className={styles.inlineEditorClose} onClick={onClose} />
<IconButton
name="times"
size="xl"
className={styles.inlineEditorClose}
onClick={onClose}
tooltip="Close inline editor"
/>
</strong>
<div className={styles.inlineEditorContentWrapper}>
<div className={styles.inlineEditorContent}>

@ -73,15 +73,17 @@ export const TreeNodeTitle = ({ settings, nodeData, setAllowSelection }: Props)
<div className={styles.actionButtonsWrapper}>
<IconButton
name="copy"
title={'Duplicate'}
title="Duplicate"
className={styles.actionIcon}
onClick={() => onDuplicate(element)}
tooltip="Duplicate"
/>
<IconButton
name="trash-alt"
title={'remove'}
title="remove"
className={styles.actionIcon}
onClick={() => onDelete(element)}
tooltip="Remove"
/>
</div>
)}

@ -74,7 +74,7 @@ export class RenderInfoViewer extends Component<Props> {
return (
<div>
<div>
<IconButton name="step-backward" title="reset counters" onClick={this.resetCounters} />
<IconButton name="step-backward" title="reset counters" onClick={this.resetCounters} tooltip="Step back" />
<span>
{showCounters.render && <span>Render: {this.counters.render}&nbsp;</span>}
{showCounters.dataChanged && <span>Data: {this.counters.dataChanged}&nbsp;</span>}

@ -113,7 +113,7 @@ export const LineStyleEditor = ({ value, onChange }: Props) => {
target="_blank"
rel="noreferrer"
>
<IconButton name="question-circle" />
<IconButton name="question-circle" tooltip="Help" />
</a>
</div>
</>

@ -46,9 +46,9 @@ export const TimezonesEditor = ({ value, onChange }: Props) => {
/>
</span>
{idx === value.length - 1 ? (
<IconButton ariaLabel="Add timezone" name="plus" onClick={addTimezone} />
<IconButton name="plus" onClick={addTimezone} tooltip="Add timezone" />
) : (
<IconButton ariaLabel="Remove timezone" name="times" onClick={() => removeTimezone(idx)} />
<IconButton name="times" onClick={() => removeTimezone(idx)} tooltip="Remove timezone" />
)}
</div>
))}

@ -56,8 +56,8 @@ export const AnnotationTooltip = ({
if (canEdit || canDelete) {
editControls = (
<div className={styles.editControls}>
{canEdit && <IconButton name={'pen'} size={'sm'} onClick={onEdit} />}
{canDelete && <IconButton name={'trash-alt'} size={'sm'} onClick={onDelete} />}
{canEdit && <IconButton name={'pen'} size={'sm'} onClick={onEdit} tooltip="Edit" />}
{canDelete && <IconButton name={'trash-alt'} size={'sm'} onClick={onDelete} tooltip="Delete" />}
</div>
);
}

@ -132,6 +132,7 @@ export const AutoEditor = ({
exclude,
});
}}
tooltip={v.value ? 'Disable' : 'Enable'}
/>
{v.label}
</div>

@ -77,6 +77,7 @@ export const ManualEditor = ({
title={'remove'}
className={cx(style.actionIcon)}
onClick={() => onSeriesDelete(index)}
tooltip="Delete series"
/>
</div>
);

Loading…
Cancel
Save