Skip to content

Commit

Permalink
Improved tooltip (#1674)
Browse files Browse the repository at this point in the history
* Install react-tooltip

* Add new Tooltipo component

* Update Tooltip stories

* Add a global css object for tests

* Replace legacy tooltip with new one

* Use spans as tooltip anchor wrapper

* Replace react-tooltip with rc-tooltip

Co-authored-by: Alessio Biancalana <alessio.biancalana@suse.com>

* Switch Tooltip implementation to rc-tooltip

Co-authored-by: Alessio Biancalana <alessio.biancalana@suse.com>

---------

Co-authored-by: Alessio Biancalana <alessio.biancalana@suse.com>
  • Loading branch information
nelsonkopliku and dottorblaster authored Aug 3, 2023
1 parent 9a00b24 commit 979c45d
Show file tree
Hide file tree
Showing 13 changed files with 480 additions and 110 deletions.
1 change: 1 addition & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* This file is for your main application CSS */
@import './markdown.scss';
@import './tooltip.scss';

@tailwind base;

Expand Down
193 changes: 193 additions & 0 deletions assets/css/tooltip.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/**
Style retrieved here https://stackblitz.com/edit/vitejs-vite-drjjx5?file=src%2Fassets%2Fstyles%2Frc-tooltip.scss
as mentioned in issue https://github.com/react-component/tooltip/issues/445
*/
.rc-tooltip-fade-enter,
.rc-tooltip-fade-leave {
display: block;
}
.rc-tooltip.rc-tooltip-fade-enter,
.rc-tooltip.rc-tooltip-fade-appear {
opacity: 0;
animation-duration: 0.2s;
animation-play-state: paused;
animation-timing-function: linear;
animation-fill-mode: both;
}
.rc-tooltip.rc-tooltip-fade-leave {
animation-duration: 0.2s;
animation-play-state: paused;
animation-timing-function: linear;
animation-fill-mode: both;
}
.rc-tooltip.rc-tooltip-fade-enter.rc-tooltip-fade-enter-active,
.rc-tooltip.rc-tooltip-fade-appear.rc-tooltip-fade-appear-active {
animation-name: rcToolTipFadeIn;
animation-play-state: running;
}
.rc-tooltip.rc-tooltip-fade-leave.rc-tooltip-fade-leave-active {
animation-name: rcToolTipFadeOut;
animation-play-state: running;
}
@keyframes rcToolTipFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes rcToolTipFadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.rc-tooltip {
/**
max-width: 200px;
font-size: 12px;
line-height: 1.5;
*/
@apply block absolute visible opacity-100;

&.rc-tooltip.rc-tooltip-fade-enter,
&.rc-tooltip.rc-tooltip-fade-appear {
animation-duration: 0.2s;
animation-play-state: paused;
animation-timing-function: linear;
animation-fill-mode: both;
@apply opacity-0;
}
&.rc-tooltip.rc-tooltip-fade-leave {
animation-duration: 0.2s;
animation-play-state: paused;
animation-timing-function: linear;
animation-fill-mode: both;
}
&.rc-tooltip.rc-tooltip-fade-enter.rc-tooltip-fade-enter-active,
&.rc-tooltip.rc-tooltip-fade-appear.rc-tooltip-fade-appear-active {
animation-name: rcToolTipFadeIn;
animation-play-state: running;
}
&.rc-tooltip.rc-tooltip-fade-leave.rc-tooltip-fade-leave-active {
animation-name: rcToolTipFadeOut;
animation-play-state: running;
}
}
.rc-tooltip-hidden {
@apply hidden;
}
.rc-tooltip-placement-top,
.rc-tooltip-placement-topLeft,
.rc-tooltip-placement-topRight {
padding: 5px 0 5px 0;
}
.rc-tooltip-placement-right,
.rc-tooltip-placement-rightTop,
.rc-tooltip-placement-rightBottom {
padding: 0 5px 0 5px;
}
.rc-tooltip-placement-bottom,
.rc-tooltip-placement-bottomLeft,
.rc-tooltip-placement-bottomRight {
padding: 5px 0 5px 0;
}
.rc-tooltip-placement-left,
.rc-tooltip-placement-leftTop,
.rc-tooltip-placement-leftBottom {
padding: 0 5px 0 5px;
}

/**
.rc-tooltip-inner is not styled to allow customization from the
.rc-tooltip-inner {
min-height: 34px;
padding: 8px 10px;
border-radius: 6px;
background-color: #373737;
color: #fff;
text-decoration: none;
text-align: center;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.17);
}
*/
.rc-tooltip-arrow {
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-color: transparent;
}
.rc-tooltip-placement-top .rc-tooltip-arrow,
.rc-tooltip-placement-topLeft .rc-tooltip-arrow,
.rc-tooltip-placement-topRight .rc-tooltip-arrow {
bottom: 0;
margin-left: -5px;
border-width: 5px 5px 0;
border-top-color: #373737;
}
.rc-tooltip-placement-top .rc-tooltip-arrow {
left: 50%;
}
.rc-tooltip-placement-topLeft .rc-tooltip-arrow {
left: 15%;
}
.rc-tooltip-placement-topRight .rc-tooltip-arrow {
right: 15%;
}
.rc-tooltip-placement-right .rc-tooltip-arrow,
.rc-tooltip-placement-rightTop .rc-tooltip-arrow,
.rc-tooltip-placement-rightBottom .rc-tooltip-arrow {
left: 4px;
margin-top: -5px;
border-width: 5px 5px 5px 0;
border-right-color: #373737;
}
.rc-tooltip-placement-right .rc-tooltip-arrow {
top: 50%;
}
.rc-tooltip-placement-rightTop .rc-tooltip-arrow {
top: 15%;
margin-top: 0;
}
.rc-tooltip-placement-rightBottom .rc-tooltip-arrow {
bottom: 15%;
}
.rc-tooltip-placement-left .rc-tooltip-arrow,
.rc-tooltip-placement-leftTop .rc-tooltip-arrow,
.rc-tooltip-placement-leftBottom .rc-tooltip-arrow {
right: 4px;
margin-top: -5px;
border-width: 5px 0 5px 5px;
border-left-color: #373737;
}
.rc-tooltip-placement-left .rc-tooltip-arrow {
top: 50%;
}
.rc-tooltip-placement-leftTop .rc-tooltip-arrow {
top: 15%;
margin-top: 0;
}
.rc-tooltip-placement-leftBottom .rc-tooltip-arrow {
bottom: 15%;
}
.rc-tooltip-placement-bottom .rc-tooltip-arrow,
.rc-tooltip-placement-bottomLeft .rc-tooltip-arrow,
.rc-tooltip-placement-bottomRight .rc-tooltip-arrow {
top: 4px;
margin-left: -5px;
border-width: 0 5px 5px;
border-bottom-color: #373737;
}
.rc-tooltip-placement-bottom .rc-tooltip-arrow {
left: 50%;
}
.rc-tooltip-placement-bottomLeft .rc-tooltip-arrow {
left: 15%;
}
.rc-tooltip-placement-bottomRight .rc-tooltip-arrow {
right: 15%;
}
17 changes: 9 additions & 8 deletions assets/js/components/ClusterDetails/ClusterNodeLink.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ function ClusterNodeLink({ hostId, children }) {
return <HostLink hostId={hostId}>{children}</HostLink>;
}
return (
<span className="group flex items-center relative">
<EOS_WARNING_OUTLINED size="base" className="centered fill-yellow-500" />
<span className="ml-1 truncate max-w-[100px]">{children}</span>
<Tooltip
tooltipText="Host currently not registered."
width="w-52 -translate-x-1/3"
/>
</span>
<Tooltip content="Host currently not registered." place="bottom">
<span className="group flex items-center relative">
<EOS_WARNING_OUTLINED
size="base"
className="centered fill-yellow-500"
/>
<span className="ml-1 truncate max-w-[100px]">{children}</span>
</span>
</Tooltip>
);
}

Expand Down
15 changes: 10 additions & 5 deletions assets/js/components/ClusterDetails/ClusterNodeLink.test.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import { screen, render, waitFor, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { renderWithRouter } from '@lib/test-utils';
import ClusterNodeLink from '@components/ClusterDetails/ClusterNodeLink';
Expand All @@ -17,12 +18,16 @@ describe('ClusterNodeLink', () => {
expect(hostLinkElement).toHaveAttribute('href', `/hosts/${id}`);
});

it('renders warning span when hostId is not provided', () => {
it('renders warning span when hostId is not provided', async () => {
const user = userEvent.setup();
const { hostname } = hostFactory.build();

render(<ClusterNodeLink>{hostname}</ClusterNodeLink>);
expect(
screen.getByText('Host currently not registered.')
).toBeInTheDocument();

await act(async () => user.hover(screen.queryByText(hostname)));

await waitFor(() =>
expect(screen.getByText('Host currently not registered.')).toBeVisible()
);
});
});
40 changes: 20 additions & 20 deletions assets/js/components/ClusterDetails/HanaClusterDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,27 @@ function HanaClusterDetails({
Show Results
</Button>

<TriggerChecksExecutionRequest
cssClasses="flex rounded relative ml-0.5 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-gray-400"
clusterId={clusterID}
disabled={startExecutionDisabled}
hosts={hosts.map(({ id }) => id)}
checks={selectedChecks}
onStartExecution={onStartExecution}
<Tooltip
isEnabled={!hasSelectedChecks}
content="Select some Checks first!"
place="bottom"
>
<EOS_PLAY_CIRCLE
className={classNames('inline-block fill-jungle-green-500', {
'fill-slate-500': startExecutionDisabled,
})}
/>{' '}
<span>Start Execution</span>
{!hasSelectedChecks && (
<Tooltip
tooltipText="Select some Checks first!"
width="-translate-x-1/4"
/>
)}
</TriggerChecksExecutionRequest>
<TriggerChecksExecutionRequest
cssClasses="flex rounded relative ml-0.5 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-gray-400"
clusterId={clusterID}
disabled={startExecutionDisabled}
hosts={hosts.map(({ id }) => id)}
checks={selectedChecks}
onStartExecution={onStartExecution}
>
<EOS_PLAY_CIRCLE
className={classNames('inline-block fill-jungle-green-500', {
'fill-slate-500': startExecutionDisabled,
})}
/>{' '}
<span>Start Execution</span>
</TriggerChecksExecutionRequest>
</Tooltip>
</div>
</div>
</div>
Expand Down
23 changes: 12 additions & 11 deletions assets/js/components/HostsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,18 @@ function HostsList() {
const warning = agentVersionWarning(content);
if (warning) {
return (
<Pill
size="xs"
className="bg-yellow-100 text-yellow-800 group flex items-center relative"
>
<EOS_WARNING_OUTLINED
size="base"
className="centered fill-yellow-800"
/>
<span className="ml-1 truncate max-w-[100px]">{content}</span>
<Tooltip tooltipText={warning} width="w-52 -translate-x-1/3" />
</Pill>
<Tooltip className="w-52" content={warning} place="bottom">
<Pill
size="xs"
className="bg-yellow-100 text-yellow-800 group flex items-center relative"
>
<EOS_WARNING_OUTLINED
size="base"
className="centered fill-yellow-800"
/>
<span className="ml-1 truncate max-w-[100px]">{content}</span>
</Pill>
</Tooltip>
);
}
return (
Expand Down
19 changes: 11 additions & 8 deletions assets/js/components/HostsList.test.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { act, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import 'intersection-observer';
import '@testing-library/jest-dom';
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('HostsLists component', () => {
}
);

it('should show a warning state if the agent version is not compatible', () => {
it('should show a warning state if the agent version is not compatible', async () => {
const user = userEvent.setup();

const host1 = hostFactory.build({ agent_version: '1.0.0' });
Expand Down Expand Up @@ -111,12 +111,15 @@ describe('HostsLists component', () => {
host2VersionCell.querySelector("[data-testid='eos-svg-component']")
).toBeNull();

user.hover(host2VersionCell);
expect(
screen.queryByText(
'Agent version 2.0.0 or greater is required for the new checks engine.'
)
).toBeInTheDocument();
await act(async () => user.hover(icon1));

await waitFor(() =>
expect(
screen.queryByText(
'Agent version 2.0.0 or greater is required for the new checks engine.'
)
).toBeVisible()
);
});
});

Expand Down
3 changes: 1 addition & 2 deletions assets/js/components/Pill/Pill.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ export function Truncated() {
export function WithTooltip() {
return (
<Pill className="bg-green-100 text-green-800 relative">
With tooltip!
<Tooltip tooltipText="Oh yeah!" />
<Tooltip content="Oh yeah!">With tooltip!</Tooltip>
</Pill>
);
}
Loading

0 comments on commit 979c45d

Please sign in to comment.