BillingChangeBadge.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { AnimatePresence, motion } from 'framer-motion'
  2. import { ChevronRight } from 'lucide-react'
  3. import { Badge, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
  4. import { formatCurrency } from '@/lib/helpers'
  5. interface BillingChangeBadgeProps {
  6. beforePrice?: number
  7. afterPrice?: number
  8. show: boolean | undefined
  9. tooltip?: string
  10. className?: string
  11. free?: boolean
  12. }
  13. export const BillingChangeBadge = ({
  14. beforePrice,
  15. afterPrice,
  16. show,
  17. tooltip,
  18. className,
  19. free,
  20. }: BillingChangeBadgeProps) => {
  21. return (
  22. <AnimatePresence>
  23. {beforePrice !== undefined && afterPrice !== undefined && show && (
  24. <motion.div
  25. initial={{ opacity: 0, x: -4, height: 0 }}
  26. animate={{ opacity: 1, x: 0, height: 'auto' }}
  27. exit={{ opacity: 0, x: -4, height: 0 }}
  28. transition={{ type: 'spring', stiffness: 800, damping: 40, duration: 0.3 }}
  29. >
  30. <Badge
  31. variant="default"
  32. className={cn(
  33. free ? `bg-violet-200 border-violet-900` : 'bg-alternative',
  34. `text-warning`,
  35. className
  36. )}
  37. >
  38. <Tooltip>
  39. <TooltipTrigger asChild>
  40. <div className="flex items-center gap-1">
  41. <span className="text-xs font-mono text-foreground-muted" translate="no">
  42. {formatCurrency(beforePrice)}
  43. </span>
  44. <ChevronRight size={12} strokeWidth={2} className="text-foreground-muted" />
  45. <motion.span
  46. key={afterPrice} // This key will change whenever any form value changes
  47. className={cn(
  48. free ? 'text-violet-1100' : 'text-foreground',
  49. 'text-xs font-mono'
  50. )}
  51. animate={{ scale: [1, 1.1, 1] }}
  52. transition={{ duration: 0.12 }}
  53. translate="no"
  54. >
  55. {`${formatCurrency(afterPrice)}/month`}
  56. </motion.span>
  57. </div>
  58. </TooltipTrigger>
  59. {tooltip !== undefined && <TooltipContent side="bottom">{tooltip}</TooltipContent>}
  60. </Tooltip>
  61. </Badge>
  62. </motion.div>
  63. )}
  64. </AnimatePresence>
  65. )
  66. }