Skip to content

Commit

Permalink
add tooltip and test
Browse files Browse the repository at this point in the history
  • Loading branch information
alissacrane-cb committed Dec 20, 2024
1 parent e68bc09 commit d32c7ef
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 45 deletions.
51 changes: 6 additions & 45 deletions src/buy/components/BuyOnrampItem.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useCallback, useMemo, useState } from 'react';
import { Tooltip } from '@/ui-react/internal/components/Tooltip';
import { useCallback } from 'react';
import { appleSvg } from '../../internal/svg/appleSvg';
import { cardSvg } from '../../internal/svg/cardSvg';
import { coinbaseLogoSvg } from '../../internal/svg/coinbaseLogoSvg';
import { infoSvg } from '../../internal/svg/infoSvg';
import { background, border, cn, color, text } from '../../styles/theme';
import { cn, color, text } from '../../styles/theme';
import { useBuyContext } from './BuyProvider';

type OnrampItemReact = {
Expand All @@ -26,54 +26,13 @@ export function BuyOnrampItem({
onClick,
icon,
}: OnrampItemReact) {
const [isOverlayVisible, setIsOverlayVisible] = useState(false);
const { setIsDropdownOpen } = useBuyContext();

const handleClick = useCallback(() => {
setIsDropdownOpen(false);
onClick();
}, [onClick, setIsDropdownOpen]);

const showOverlay = useCallback(() => {
setIsOverlayVisible(true);
}, []);

const hideOverlay = useCallback(() => {
setIsOverlayVisible(false);
}, []);

// TODO: Remove after figuring out how to hide Apple Pay on desktop
const tooltip = useMemo(() => {
if (name !== 'Apple Pay') {
return null;
}
return (
<>
<div
data-testid="ockBuyApplePayInfo"
className="h-2.5 w-2.5 cursor-pointer object-cover"
onMouseEnter={showOverlay}
onMouseLeave={hideOverlay}
>
{infoSvg}
</div>
{isOverlayVisible && (
<div
className={cn(
'absolute top-0 right-0 flex translate-x-[100%] translate-y-[-140%]',
'whitespace-nowrap p-2',
border.radius,
background.inverse,
text.legal,
)}
>
Only on mobile and Safari
</div>
)}
</>
);
}, [isOverlayVisible, name, showOverlay, hideOverlay]);

return (
<button
className={cn(
Expand All @@ -91,7 +50,9 @@ export function BuyOnrampItem({
<div className="flex flex-col items-start">
<div className="relative flex items-center gap-1">
<div>{name}</div>
{tooltip}
{name === 'Apple Pay' && (
<Tooltip content="Only on mobile and Safari" />
)}
</div>
<div className={cn('text-xs', color.foregroundMuted)}>
{description}
Expand Down
35 changes: 35 additions & 0 deletions src/ui/react/internal/components/Tooltip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { Tooltip } from './Tooltip';

describe('Tooltip', () => {
it('renders the children', () => {
render(<Tooltip content="Test Content" />);
expect(screen.getByTestId('ockBuyApplePayInfo')).toBeInTheDocument();
});

it('shows the content on mouse enter', () => {
render(<Tooltip content="Test Content" />);
const triggerElement = screen.getByTestId('ockBuyApplePayInfo');

fireEvent.mouseEnter(triggerElement);
expect(screen.getByText('Test Content')).toBeInTheDocument();
});

it('hides the content on mouse leave', () => {
render(<Tooltip content="Test Content" />);
const triggerElement = screen.getByTestId('ockBuyApplePayInfo');

fireEvent.mouseEnter(triggerElement);
fireEvent.mouseLeave(triggerElement);

expect(screen.queryByText('Test Content')).not.toBeInTheDocument();
});

it('renders custom children if provided', () => {
const CustomChild = <div>Custom Child</div>;
render(<Tooltip content="Test Content">{CustomChild}</Tooltip>);

expect(screen.getByText('Custom Child')).toBeInTheDocument();
});
});
47 changes: 47 additions & 0 deletions src/ui/react/internal/components/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useCallback, useState } from 'react';
import { background, border, cn, text } from '@/styles/theme';
import { infoSvg } from '@/internal/svg/infoSvg';

type TooltipReact = {
children?: React.ReactNode;
content: React.ReactNode;
};

export function Tooltip({ children = infoSvg, content }: TooltipReact) {
const [isOverlayVisible, setIsOverlayVisible] = useState(false);

const showOverlay = useCallback(() => {
setIsOverlayVisible(true);
}, []);

const hideOverlay = useCallback(() => {
setIsOverlayVisible(false);
}, []);

return (
<>
<div
data-testid="ockBuyApplePayInfo"
className={cn('h-2.5 w-2.5 cursor-pointer object-cover')}
onMouseEnter={showOverlay}
onMouseLeave={hideOverlay}
>
{children}
</div>
{isOverlayVisible && (
<div
className={cn(
'absolute top-0 right-0 flex translate-x-[100%] translate-y-[-100%]',
'whitespace-nowrap p-2',
border.radius,
background.inverse,
text.legal,
border.lineDefault,
)}
>
{content}
</div>
)}
</>
);
}

0 comments on commit d32c7ef

Please sign in to comment.