card-icon.tsx 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { RiCheckLine, RiCloseLine } from '@remixicon/react'
  2. import AppIcon from '@/app/components/base/app-icon'
  3. import cn from '@/utils/classnames'
  4. const iconSizeMap = {
  5. xs: 'w-4 h-4 text-base',
  6. tiny: 'w-6 h-6 text-base',
  7. small: 'w-8 h-8',
  8. medium: 'w-9 h-9',
  9. large: 'w-10 h-10',
  10. }
  11. const Icon = ({
  12. className,
  13. src,
  14. installed = false,
  15. installFailed = false,
  16. size = 'large',
  17. }: {
  18. className?: string
  19. src: string | {
  20. content: string
  21. background: string
  22. }
  23. installed?: boolean
  24. installFailed?: boolean
  25. size?: 'xs' | 'tiny' | 'small' | 'medium' | 'large'
  26. }) => {
  27. const iconClassName = 'flex justify-center items-center gap-2 absolute bottom-[-4px] right-[-4px] w-[18px] h-[18px] rounded-full border-2 border-components-panel-bg'
  28. if (typeof src === 'object') {
  29. return (
  30. <div className={cn('relative', className)}>
  31. <AppIcon
  32. size={size}
  33. iconType={'emoji'}
  34. icon={src.content}
  35. background={src.background}
  36. className='rounded-md'
  37. />
  38. </div>
  39. )
  40. }
  41. return (
  42. <div
  43. className={cn('relative shrink-0 rounded-md bg-contain bg-center bg-no-repeat', iconSizeMap[size], className)}
  44. style={{
  45. backgroundImage: `url(${src})`,
  46. }}
  47. >
  48. {
  49. installed
  50. && <div className={cn(iconClassName, 'bg-state-success-solid')}>
  51. <RiCheckLine className='h-3 w-3 text-text-primary-on-surface' />
  52. </div>
  53. }
  54. {
  55. installFailed
  56. && <div className={cn(iconClassName, 'bg-state-destructive-solid')}>
  57. <RiCloseLine className='h-3 w-3 text-text-primary-on-surface' />
  58. </div>
  59. }
  60. </div>
  61. )
  62. }
  63. export default Icon