Files
hanzo.ai/components/oss/DualStarButton.tsx

182 lines
5.0 KiB
TypeScript

'use client'
import React, { useState } from 'react'
import { Star, Check, ExternalLink } from 'lucide-react'
import { Text, XStack, YStack } from '@hanzo/ui'
import { useI18n } from '@hanzo/i18n/react'
export interface DualStarButtonProps {
owner: string
repo: string
initialStars?: number
forgeUrl?: string
githubUrl?: string
size?: 'sm' | 'md'
}
export default function DualStarButton({
owner,
repo,
initialStars = 1420,
forgeUrl,
githubUrl,
size = 'md',
}: DualStarButtonProps) {
const { t } = useI18n()
const [starred, setStarred] = useState(false)
const [count, setCount] = useState(initialStars)
const [activeTooltip, setActiveTooltip] = useState(false)
const gh = githubUrl || `https://github.com/${owner}/${repo}`
const forge = forgeUrl || `https://forge.hanzo.ai/${owner}/${repo}`
const handleDualStar = (e: React.MouseEvent) => {
e.preventDefault()
e.stopPropagation()
if (!starred) {
setStarred(true)
setCount((prev) => prev + 1)
setActiveTooltip(true)
setTimeout(() => setActiveTooltip(false), 3000)
// Open GitHub star tab so user stars on GitHub simultaneously
try {
const ghWin = window.open(gh, '_blank', 'noopener,noreferrer')
if (ghWin) ghWin.blur()
window.focus()
} catch (_) {}
// Call Hanzo Forge star API
try {
fetch(`https://forge.hanzo.ai/api/v1/user/starred/${owner}/${repo}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
}).catch(() => {})
} catch (_) {}
} else {
setStarred(false)
setCount((prev) => Math.max(0, prev - 1))
}
}
const isSm = size === 'sm'
return (
<XStack items="center" gap={6} position="relative">
<XStack
render={
<button
type="button"
onClick={handleDualStar}
title={t('Dual-Star on Hanzo Forge and GitHub')}
/>
}
items="center"
gap={6}
px={isSm ? 10 : 13}
py={isSm ? 5 : 7}
rounded={8}
borderWidth={1}
borderColor={starred ? '#39bd7d' : 'var(--border)'}
bg={starred ? 'rgba(57, 189, 125, 0.12)' : 'rgba(255, 255, 255, 0.04)'}
hoverStyle={{
borderColor: starred ? '#56e36d' : 'var(--border-strong)',
bg: starred ? 'rgba(57, 189, 125, 0.2)' : 'rgba(255, 255, 255, 0.08)',
}}
cursor="pointer"
$platform-web={{
borderRadius: '8px',
borderStyle: 'solid',
transition: 'all 0.18s ease-in-out',
boxShadow: starred ? '0 0 12px rgba(57, 189, 125, 0.35)' : undefined,
}}
>
<Star
width={isSm ? 13 : 15}
height={isSm ? 13 : 15}
color={starred ? '#39bd7d' : 'var(--muted-foreground)'}
fill={starred ? '#39bd7d' : 'none'}
/>
<Text
fontSize={isSm ? 11 : 12}
fontWeight="600"
color={starred ? '#39bd7d' : 'var(--foreground)'}
>
{starred ? t('Starred') : t('Star')}
</Text>
<XStack
items="center"
px={6}
py={1}
rounded={4}
bg="rgba(255, 255, 255, 0.06)"
$platform-web={{ borderRadius: '4px' }}
>
<Text
fontFamily="$mono"
fontSize={isSm ? 10 : 11}
fontWeight="600"
color="var(--muted-foreground)"
>
{count.toLocaleString('en-US')}
</Text>
</XStack>
</XStack>
{/* Dual Badge indicating Forge + GitHub sync */}
<XStack
items="center"
gap={4}
px={6}
py={3}
rounded={6}
borderWidth={1}
borderColor="var(--border)"
bg="rgba(0, 0, 0, 0.4)"
$platform-web={{ borderRadius: '6px' }}
>
<Text fontSize={10} fontFamily="$mono" color="#39bd7d" fontWeight="700">
FORGE
</Text>
<Text fontSize={9} color="var(--muted-foreground)">
+
</Text>
<Text fontSize={10} fontFamily="$mono" color="var(--muted-foreground)" fontWeight="600">
GH
</Text>
</XStack>
{/* Instant Notification Tooltip */}
{activeTooltip && (
<YStack
position="absolute"
b="100%"
mb={8}
l="50%"
p={8}
rounded={6}
bg="#101214"
borderWidth={1}
borderColor="#39bd7d"
z={50}
$platform-web={{
borderRadius: '6px',
transform: 'translateX(-50%)',
boxShadow: '0 8px 24px rgba(0,0,0,0.6)',
whiteSpace: 'nowrap',
}}
>
<XStack items="center" gap={6}>
<Check width={12} height={12} color="#39bd7d" />
<Text fontSize={11} fontWeight="600" color="var(--foreground)">
{t('Starred on Hanzo Forge & GitHub!')}
</Text>
</XStack>
</YStack>
)}
</XStack>
)
}