feat: show tooltip for like button when not logged in
- LikeButton now shows 'Sign in to like' tooltip instead of redirecting - Added interactive LikeButton to tools table (was static display) - All three public list pages (tools, collections, agents) now have like functionality
This commit is contained in:
parent
f7a6df06c5
commit
9f254a5ae8
2 changed files with 40 additions and 21 deletions
|
|
@ -13,6 +13,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { TableVirtuoso } from 'react-virtuoso';
|
import { TableVirtuoso } from 'react-virtuoso';
|
||||||
import { AppHeader } from '~/components/AppHeader';
|
import { AppHeader } from '~/components/AppHeader';
|
||||||
import { CopyButton } from '~/components/CopyButton';
|
import { CopyButton } from '~/components/CopyButton';
|
||||||
|
import { LikeButton } from '~/components/LikeButton';
|
||||||
import {
|
import {
|
||||||
PackageManagerSelector,
|
PackageManagerSelector,
|
||||||
getInstallCommand,
|
getInstallCommand,
|
||||||
|
|
@ -220,10 +221,13 @@ export default function ToolSearchPage(): React.ReactElement {
|
||||||
{formatDownloads(tool.package.npmDownloadsLastMonth)}
|
{formatDownloads(tool.package.npmDownloadsLastMonth)}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3 text-right">
|
<td className="px-4 py-3 text-right">
|
||||||
<span className="inline-flex items-center gap-1 text-sm text-foreground-secondary">
|
<LikeButton
|
||||||
<Icon icon="heart" size="xs" />
|
entityType="tool"
|
||||||
{tool.likeCount ?? 0}
|
entityId={tool.id}
|
||||||
</span>
|
initialCount={tool.likeCount ?? 0}
|
||||||
|
size="sm"
|
||||||
|
showCount={true}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3 text-right">
|
<td className="px-4 py-3 text-right">
|
||||||
<CopyButton text={installCommand} label="Copy" size="xs" />
|
<CopyButton text={installCommand} label="Copy" size="xs" />
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ export function LikeButton({
|
||||||
const [count, setCount] = useState(initialCount);
|
const [count, setCount] = useState(initialCount);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [hasFetched, setHasFetched] = useState(false);
|
const [hasFetched, setHasFetched] = useState(false);
|
||||||
|
const [showTooltip, setShowTooltip] = useState(false);
|
||||||
|
|
||||||
// Fetch initial like status when user is logged in
|
// Fetch initial like status when user is logged in
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -68,8 +69,9 @@ export function LikeButton({
|
||||||
|
|
||||||
const handleClick = useCallback(async () => {
|
const handleClick = useCallback(async () => {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
// Redirect to sign in
|
// Show tooltip instead of redirecting
|
||||||
window.location.href = '/sign-in';
|
setShowTooltip(true);
|
||||||
|
setTimeout(() => setShowTooltip(false), 2000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,21 +113,34 @@ export function LikeButton({
|
||||||
}, [session, liked, count, isLoading, entityType, entityId, onLikeChange]);
|
}, [session, liked, count, isLoading, entityType, entityId, onLikeChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<div className="relative inline-block">
|
||||||
variant={variant}
|
<Button
|
||||||
size={size}
|
variant={variant}
|
||||||
onClick={handleClick}
|
size={size}
|
||||||
disabled={isLoading}
|
onClick={handleClick}
|
||||||
className={className}
|
disabled={isLoading}
|
||||||
aria-label={liked ? `Unlike this ${entityType}` : `Like this ${entityType}`}
|
className={className}
|
||||||
>
|
aria-label={liked ? `Unlike this ${entityType}` : `Like this ${entityType}`}
|
||||||
<Icon
|
>
|
||||||
icon={liked ? 'heartFilled' : 'heart'}
|
<Icon
|
||||||
size="sm"
|
icon={liked ? 'heartFilled' : 'heart'}
|
||||||
className={liked ? 'text-red-500' : ''}
|
size="sm"
|
||||||
/>
|
className={liked ? 'text-red-500' : ''}
|
||||||
{showCount && <span className="ml-1">{count}</span>}
|
/>
|
||||||
</Button>
|
{showCount && <span className="ml-1">{count}</span>}
|
||||||
|
</Button>
|
||||||
|
{showTooltip && (
|
||||||
|
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-3 py-1.5 bg-surface-secondary border border-border rounded-lg shadow-lg text-xs text-foreground whitespace-nowrap z-50 animate-in fade-in slide-in-from-bottom-1 duration-200">
|
||||||
|
<a href="/sign-in" className="text-primary hover:underline">
|
||||||
|
Sign in
|
||||||
|
</a>{' '}
|
||||||
|
to like
|
||||||
|
<div className="absolute top-full left-1/2 -translate-x-1/2 -mt-px">
|
||||||
|
<div className="border-4 border-transparent border-t-border" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue