IntegrationWindowLayout.tsx 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { Book, LifeBuoy, X } from 'lucide-react'
  2. import Link from 'next/link'
  3. import { forwardRef, PropsWithChildren, ReactNode } from 'react'
  4. import { cn, LoadingLine } from 'ui'
  5. import { ScaffoldContainer } from '../Scaffold'
  6. import { withAuth } from '@/hooks/misc/withAuth'
  7. import { BASE_PATH } from '@/lib/constants'
  8. export type IntegrationWindowLayoutProps = {
  9. title: string
  10. integrationIcon: ReactNode
  11. loading?: boolean
  12. docsHref?: string
  13. }
  14. const IntegrationWindowLayout = ({
  15. title,
  16. integrationIcon,
  17. children,
  18. loading = false,
  19. docsHref,
  20. }: PropsWithChildren<IntegrationWindowLayoutProps>) => {
  21. return (
  22. <div className="flex w-full flex-col">
  23. <Header title={title} integrationIcon={integrationIcon} />
  24. <LoadingLine loading={loading} />
  25. <main className="overflow-auto flex flex-col h-full bg">{children}</main>
  26. <ScaffoldContainer className="bg-studio flex flex-row gap-6 py-6 border-t">
  27. {docsHref && (
  28. <Link
  29. href={docsHref}
  30. target="_blank"
  31. rel="noopener noreferrer"
  32. className="flex items-center gap-2 text-xs text-foreground-light hover:text"
  33. >
  34. <Book size={16} />
  35. Docs
  36. </Link>
  37. )}
  38. <Link
  39. href={'https://supabase.com/support'}
  40. target="_blank"
  41. rel="noopener noreferrer"
  42. className="flex items-center gap-2 text-xs text-light hover:text"
  43. >
  44. <LifeBuoy size={16} />
  45. Support
  46. </Link>
  47. </ScaffoldContainer>
  48. </div>
  49. )
  50. }
  51. const INTEGRATION_LAYOUT_MAX_WIDTH = '' // 'max-w-[720px]'
  52. export default withAuth(IntegrationWindowLayout)
  53. export const IntegrationWindowLayoutWithoutAuth = IntegrationWindowLayout
  54. export type HeaderProps = {
  55. title: string
  56. integrationIcon: ReactNode
  57. }
  58. const Header = ({ title, integrationIcon }: HeaderProps) => {
  59. return (
  60. <div className="bg">
  61. <ScaffoldContainer className={cn('py-3', INTEGRATION_LAYOUT_MAX_WIDTH)}>
  62. <div className="flex items-center gap-6 w-full">
  63. <div className="flex gap-2 items-center">
  64. <div className="bg-white shadow-sm border rounded-sm p-1 w-8 h-8 flex justify-center items-center">
  65. <img src={`${BASE_PATH}/img/briven-logo.svg`} alt="Briven" className="w-4" />
  66. </div>
  67. <X className="text-border-stronger" strokeWidth={2} size={16} />
  68. {integrationIcon}
  69. </div>
  70. <span className="text-sm" title={title}>
  71. {title}
  72. </span>
  73. </div>
  74. </ScaffoldContainer>
  75. </div>
  76. )
  77. }
  78. const maxWidthClasses = 'mx-auto w-full max-w-[1600px]'
  79. const paddingClasses = 'px-6 lg:px-14 xl:px-28 2xl:px-32'
  80. export const IntegrationScaffoldContainer = forwardRef<
  81. HTMLDivElement,
  82. React.HTMLAttributes<HTMLDivElement>
  83. >(({ className, ...props }, ref) => {
  84. return <div ref={ref} {...props} className={cn(maxWidthClasses, paddingClasses, className)} />
  85. })
  86. IntegrationScaffoldContainer.displayName = 'IntegrationScaffoldContainer'