Skip to content

Commit

Permalink
feat: add a generic Tooltip component (#1643)
Browse files Browse the repository at this point in the history
  • Loading branch information
eh-am authored Oct 27, 2022
1 parent 9a31331 commit e04a9a5
Show file tree
Hide file tree
Showing 17 changed files with 390 additions and 171 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@
"@babel/preset-env": "^7.10.4",
"@babel/preset-react": "^7.12.10",
"@babel/preset-typescript": "7.8.3",
"@emotion/react": "^11.10.4",
"@emotion/styled": "^11.10.4",
"@fortawesome/fontawesome-free": "~5.14.0",
"@fortawesome/fontawesome-svg-core": "~1.2.30",
"@fortawesome/free-brands-svg-icons": "~5.15.1",
Expand All @@ -174,6 +176,7 @@
"@fortawesome/react-fontawesome": "~0.1.11",
"@hookform/resolvers": "^2.9.8",
"@mui/base": "^5.0.0-alpha.98",
"@mui/material": "^5.10.11",
"@react-hook/resize-observer": "^1.2.4",
"@react-hook/window-size": "^3.0.7",
"@reduxjs/toolkit": "^1.6.2",
Expand Down
49 changes: 19 additions & 30 deletions packages/pyroscope-flamegraph/src/SharedQueryInput.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
/* eslint-disable no-unused-expressions */
import React, {
useEffect,
useMemo,
ChangeEvent,
useRef,
useState,
} from 'react';
import React, { useEffect, useMemo, ChangeEvent, useRef } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faLink } from '@fortawesome/free-solid-svg-icons/faLink';
import Input from '@pyroscope/webapp/javascript/ui/Input';
import Tooltip from '@pyroscope/webapp/javascript/ui/Tooltip';
import { Tooltip } from '@pyroscope/webapp/javascript/ui/Tooltip';
import styles from './SharedQueryInput.module.scss';
import type { ProfileHeaderProps, ShowModeType } from './Toolbar';

Expand Down Expand Up @@ -37,7 +31,6 @@ const SharedQueryInput = ({
sharedQuery,
}: SharedQueryProps) => {
const prevSyncEnabled = usePreviousSyncEnabled(sharedQuery?.syncEnabled);
const [tooltipVisible, toggleTooltip] = useState(false);

const onQueryChange = (e: ChangeEvent<HTMLInputElement>) => {
onHighlightChange(e.target.value);
Expand Down Expand Up @@ -105,30 +98,26 @@ const SharedQueryInput = ({
value={inputValue}
/>
{sharedQuery ? (
<button
className={
sharedQuery.syncEnabled ? styles.syncSelected : styles.sync
<Tooltip
placement="top"
title={
sharedQuery.syncEnabled ? 'Unsync search bars' : 'Sync search bars'
}
onClick={onToggleSync}
onMouseEnter={() => toggleTooltip(true)}
onMouseLeave={() => toggleTooltip(false)}
>
<FontAwesomeIcon
className={`${
sharedQuery.syncEnabled ? styles.checked : styles.icon
}`}
icon={faLink}
/>
<Tooltip
placement="top"
visible={tooltipVisible}
title={
sharedQuery.syncEnabled
? 'Unsync search bars'
: 'Sync search bars'
<button
className={
sharedQuery.syncEnabled ? styles.syncSelected : styles.sync
}
/>
</button>
onClick={onToggleSync}
>
<FontAwesomeIcon
className={`${
sharedQuery.syncEnabled ? styles.checked : styles.icon
}`}
icon={faLink}
/>
</button>
</Tooltip>
) : null}
</div>
);
Expand Down
10 changes: 10 additions & 0 deletions scripts/webpack/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ export function getAlias() {
// this alias maps that dependency to core-js@t3
'core-js/library/fn': 'core-js/stable',
'@webapp': path.resolve(__dirname, '../../webapp/javascript'),

// https://github.com/reactjs/react-transition-group/issues/556#issuecomment-544512681
'dom-helpers/addClass': path.resolve(
__dirname,
'../../node_modules/dom-helpers/class/addClass'
),
'dom-helpers/removeClass': path.resolve(
__dirname,
'../../node_modules/dom-helpers/class/removeClass'
),
};
}

Expand Down
6 changes: 1 addition & 5 deletions scripts/webpack/webpack.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ESBuildMinifyPlugin } from 'esbuild-loader';
import { getAlias, getJsLoader, getStyleLoaders } from './shared';

const packagePath = path.resolve(__dirname, '../../webapp');
const rootPath = path.resolve(__dirname, '../../');

// use a fake hash when running locally
const LOCAL_HASH = 'local';
Expand Down Expand Up @@ -81,11 +82,6 @@ export default {
resolve: {
extensions: ['.ts', '.tsx', '.es6', '.js', '.jsx', '.json', '.svg'],
alias: getAlias(),
modules: [
'node_modules',
path.resolve('webapp'),
path.resolve(packagePath, 'node_modules'),
],
},

stats: {
Expand Down
1 change: 1 addition & 0 deletions stories/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const IconOnly = () => <Button icon={faSyncAlt} />;

export const Primary = () => <Button kind="primary">Primary</Button>;
export const Secondary = () => <Button kind="secondary">Secondary</Button>;
export const Floating = () => <Button kind="float">Floating</Button>;

export const GroupedButtons = () => (
<>
Expand Down
27 changes: 27 additions & 0 deletions stories/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-disable react/jsx-props-no-spreading */
import React from 'react';
import { Tooltip } from '../webapp/javascript/ui/Tooltip';
import { TooltipInfoIcon } from '../webapp/javascript/ui/TooltipInfoIcon';
import { ComponentMeta } from '@storybook/react';
import '../webapp/sass/profile.scss';

export default {
title: 'Components/Tooltip',
component: Tooltip,
} as ComponentMeta<typeof Tooltip>;

export const MyTooltip = () => {
return (
<Tooltip title="I should display be displayed on hover">
<span>hover me</span>
</Tooltip>
);
};

export const TooltipInfo = () => {
return (
<Tooltip title="use me for informational data">
<TooltipInfoIcon />
</Tooltip>
);
};
25 changes: 0 additions & 25 deletions webapp/__tests__/RefreshButton.spec.js

This file was deleted.

29 changes: 0 additions & 29 deletions webapp/__tests__/__snapshots__/RefreshButton.spec.js.snap

This file was deleted.

33 changes: 16 additions & 17 deletions webapp/javascript/components/Settings/APIKeys/APIKeyAddForm.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, { useState } from 'react';
import Button from '@webapp/ui/Button';
import InputField from '@webapp/ui/InputField';
import { TooltipInfoIcon } from '@webapp/ui/TooltipInfoIcon';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import { faCopy } from '@fortawesome/free-solid-svg-icons/faCopy';
import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck';
import { createAPIKey } from '@webapp/redux/reducers/settings';
import { useAppDispatch } from '@webapp/redux/hooks';
import { type APIKey } from '@webapp/models/apikeys';
import Dropdown, { MenuItem } from '@webapp/ui/Dropdown';
import Tooltip from '@webapp/ui/Tooltip';
import { Tooltip } from '@webapp/ui/Tooltip';
import StatusMessage from '@webapp/ui/StatusMessage';
import { addNotification } from '@webapp/redux/reducers/notifications';
import styles from './APIKeyForm.module.css';
Expand All @@ -28,7 +29,6 @@ function APIKeyAddForm() {
ttlSeconds: 360000,
});
const [key, setKey] = useState<string>();
const [isRolesTooltipVisible, setRolesTooltipVisibility] = useState(false);
const dispatch = useAppDispatch();

const handleFormChange = (event: ShamefulAny) => {
Expand Down Expand Up @@ -107,22 +107,21 @@ function APIKeyAddForm() {
<div>
<h4>
Role
<span
className={styles.infoMark}
onMouseEnter={() => setRolesTooltipVisibility(true)}
onMouseLeave={() => setRolesTooltipVisibility(false)}
<Tooltip
title={
<div className={styles.rolesTooltip}>
{[
`Admin: Manage users/API keys`,
`ReadOnly: Used only for visualizations (i.e. Grafana datasource, embedding in a UI)`,
`Agent: Used for "authentication token" in code when auth is enabled`,
].map((r) => (
<div key={r}>{r}</div>
))}
</div>
}
>
<Tooltip
title={
'Admin: Manage users/API keys\n' +
'ReadOnly: Used only for visualizations (i.e. Grafana datasource, embedding in a UI)\n' +
'Agent: Used for "authentication token" in code when auth is enabled\n'
}
visible={isRolesTooltipVisible}
placement="bottom"
className={styles.rolesTooltip}
/>
</span>
<TooltipInfoIcon />
</Tooltip>
</h4>
<Dropdown
onItemClick={(i) => handleRoleChange(i.value)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,7 @@
max-width: 40%;
}

.infoMark {
cursor: pointer;
position: relative;
}

.infoMark::after {
content: 'i';
width: 15px;
height: 15px;
position: absolute;
border: 1px solid var(--ps-neutral-2);
border-radius: 50%;
font-size: 9px;
margin-left: 5px;
top: 3px;
text-align: center;
}

.rolesTooltip {
.rolesTooltip > *:not(:first-child) {
font-weight: normal;
top: calc(100% + 10px);
white-space: pre;
line-height: 24px;
}

.rolesTooltip::before {
right: unset;
left: 40px;
margin-top: 12px;
}
6 changes: 6 additions & 0 deletions webapp/javascript/ui/Button.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ $border-radius: 4px;
}
}

.float {
@extend .default;
border-color: transparent;
background-color: transparent;
}

.danger {
border-color: transparent;
color: var(--ps-neutral-2);
Expand Down
Loading

0 comments on commit e04a9a5

Please sign in to comment.