status-with-action.tsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. 'use client'
  2. import { RiAlertFill, RiCheckboxCircleFill, RiErrorWarningFill, RiInformation2Fill } from '@remixicon/react'
  3. import type { FC } from 'react'
  4. import React from 'react'
  5. import cn from '@/utils/classnames'
  6. import Divider from '@/app/components/base/divider'
  7. type Status = 'success' | 'error' | 'warning' | 'info'
  8. type Props = {
  9. type?: Status
  10. description: string
  11. actionText?: string
  12. onAction?: () => void
  13. disabled?: boolean
  14. }
  15. const IconMap = {
  16. success: {
  17. Icon: RiCheckboxCircleFill,
  18. color: 'text-text-success',
  19. },
  20. error: {
  21. Icon: RiErrorWarningFill,
  22. color: 'text-text-destructive',
  23. },
  24. warning: {
  25. Icon: RiAlertFill,
  26. color: 'text-text-warning-secondary',
  27. },
  28. info: {
  29. Icon: RiInformation2Fill,
  30. color: 'text-text-accent',
  31. },
  32. }
  33. const getIcon = (type: Status) => {
  34. return IconMap[type]
  35. }
  36. const StatusAction: FC<Props> = ({
  37. type = 'info',
  38. description,
  39. actionText,
  40. onAction,
  41. disabled,
  42. }) => {
  43. const { Icon, color } = getIcon(type)
  44. return (
  45. <div className='relative flex h-[34px] items-center rounded-lg border border-components-panel-border bg-components-panel-bg-blur pl-2 pr-3 shadow-xs'>
  46. <div className={
  47. `absolute inset-0 rounded-lg opacity-40 ${(type === 'success' && 'bg-[linear-gradient(92deg,rgba(23,178,106,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
  48. || (type === 'warning' && 'bg-[linear-gradient(92deg,rgba(247,144,9,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
  49. || (type === 'error' && 'bg-[linear-gradient(92deg,rgba(240,68,56,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
  50. || (type === 'info' && 'bg-[linear-gradient(92deg,rgba(11,165,236,0.25)_0%,rgba(255,255,255,0.00)_100%)]')
  51. }`}
  52. />
  53. <div className='relative z-10 flex h-full items-center space-x-2'>
  54. <Icon className={cn('h-4 w-4', color)} />
  55. <div className='text-[13px] font-normal text-text-secondary'>{description}</div>
  56. {onAction && (
  57. <>
  58. <Divider type='vertical' className='!h-4' />
  59. <div onClick={onAction} className={cn('cursor-pointer text-[13px] font-semibold text-text-accent', disabled && 'cursor-not-allowed text-text-disabled')}>{actionText}</div>
  60. </>
  61. )}
  62. </div>
  63. </div>
  64. )
  65. }
  66. export default React.memo(StatusAction)