Hero.jsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import clsx from 'clsx';
  2. import Image from 'next/image';
  3. import Highlight, { defaultProps } from 'prism-react-renderer';
  4. import { Fragment } from 'react';
  5. import { Button } from '@/components/Button';
  6. import { HeroBackground } from '@/components/HeroBackground';
  7. import blurCyanImage from '@/images/blur-cyan.png';
  8. import blurIndigoImage from '@/images/blur-indigo.png';
  9. const codeLanguage = 'rust'
  10. const code = `pub struct Metadata {
  11. pub key: Key,
  12. pub update_authority: Pubkey,
  13. pub mint: Pubkey,
  14. pub data: Data,
  15. pub primary_sale_happened: bool,
  16. pub is_mutable: bool,
  17. // ...
  18. }`
  19. const tabs = [
  20. { name: 'metadata.rs', isActive: true },
  21. { name: 'offchain-metadata.json', isActive: false },
  22. ]
  23. function TrafficLightsIcon(props) {
  24. return (
  25. <svg aria-hidden="true" viewBox="0 0 42 10" fill="none" {...props}>
  26. <circle cx="5" cy="5" r="4.5" />
  27. <circle cx="21" cy="5" r="4.5" />
  28. <circle cx="37" cy="5" r="4.5" />
  29. </svg>
  30. )
  31. }
  32. export function Hero({ page }) {
  33. return (
  34. <div className="overflow-hidden bg-slate-900 dark:-mb-32 dark:mt-[-7rem] dark:pb-32 dark:pt-[7rem] dark:lg:mt-[-7.25rem] dark:lg:pt-[7.25rem]">
  35. <div className="py-16 sm:px-2 lg:relative lg:px-0 lg:py-20">
  36. <div className="mx-auto grid max-w-2xl grid-cols-1 items-center gap-x-8 gap-y-16 px-4 lg:max-w-8xl lg:grid-cols-2 lg:px-8 xl:gap-x-16 xl:px-12">
  37. <div className="relative z-10 md:text-center lg:text-left">
  38. <Image
  39. className="absolute bottom-full right-full -mb-56 -mr-72 opacity-50"
  40. src={blurCyanImage}
  41. alt=""
  42. width={530}
  43. height={530}
  44. unoptimized
  45. priority
  46. />
  47. <div className="relative">
  48. <p className="inline bg-gradient-to-r from-indigo-200 via-sky-400 to-indigo-200 bg-clip-text font-display text-5xl tracking-tight text-transparent">
  49. {page.product.name}
  50. </p>
  51. <p className="mt-3 text-2xl tracking-tight text-slate-400">
  52. Sunt anim in quis sit sit.
  53. </p>
  54. <div className="mt-8 flex gap-4 md:justify-center lg:justify-start">
  55. <Button href="/">Get started</Button>
  56. <Button href="/" variant="secondary">
  57. View on GitHub
  58. </Button>
  59. </div>
  60. </div>
  61. </div>
  62. <div className="relative lg:static xl:pl-10">
  63. <div className="absolute inset-x-[-50vw] -bottom-48 -top-32 [mask-image:linear-gradient(transparent,white,white)] dark:[mask-image:linear-gradient(transparent,white,transparent)] lg:-bottom-32 lg:-top-32 lg:left-[calc(50%+14rem)] lg:right-0 lg:[mask-image:none] lg:dark:[mask-image:linear-gradient(white,white,transparent)]">
  64. <HeroBackground className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 lg:left-0 lg:translate-x-0 lg:translate-y-[-60%]" />
  65. </div>
  66. <div className="relative">
  67. <Image
  68. className="absolute -right-64 -top-64"
  69. src={blurCyanImage}
  70. alt=""
  71. width={530}
  72. height={530}
  73. unoptimized
  74. priority
  75. />
  76. <Image
  77. className="absolute -bottom-40 -right-44"
  78. src={blurIndigoImage}
  79. alt=""
  80. width={567}
  81. height={567}
  82. unoptimized
  83. priority
  84. />
  85. <div className="absolute inset-0 rounded-2xl bg-gradient-to-tr from-sky-300 via-sky-300/70 to-blue-300 opacity-10 blur-lg" />
  86. <div className="absolute inset-0 rounded-2xl bg-gradient-to-tr from-sky-300 via-sky-300/70 to-blue-300 opacity-10" />
  87. <div className="relative rounded-2xl bg-[#0A101F]/80 ring-1 ring-white/10 backdrop-blur">
  88. <div className="absolute -top-px left-20 right-11 h-px bg-gradient-to-r from-sky-300/0 via-sky-300/70 to-sky-300/0" />
  89. <div className="absolute -bottom-px left-11 right-20 h-px bg-gradient-to-r from-blue-400/0 via-blue-400 to-blue-400/0" />
  90. <div className="pl-4 pt-4">
  91. <TrafficLightsIcon className="h-2.5 w-auto stroke-slate-500/30" />
  92. <div className="mt-4 flex space-x-2 text-xs">
  93. {tabs.map((tab) => (
  94. <div
  95. key={tab.name}
  96. className={clsx(
  97. 'flex h-6 rounded-full',
  98. tab.isActive
  99. ? 'bg-gradient-to-r from-sky-400/30 via-sky-400 to-sky-400/30 p-px font-medium text-sky-300'
  100. : 'text-slate-500'
  101. )}
  102. >
  103. <div
  104. className={clsx(
  105. 'flex items-center rounded-full px-2.5',
  106. tab.isActive && 'bg-slate-800'
  107. )}
  108. >
  109. {tab.name}
  110. </div>
  111. </div>
  112. ))}
  113. </div>
  114. <div className="mt-6 flex items-start px-1 text-sm">
  115. <div
  116. aria-hidden="true"
  117. className="select-none border-r border-slate-300/5 pr-4 font-mono text-slate-600"
  118. >
  119. {Array.from({
  120. length: code.split('\n').length,
  121. }).map((_, index) => (
  122. <Fragment key={index}>
  123. {(index + 1).toString().padStart(2, '0')}
  124. <br />
  125. </Fragment>
  126. ))}
  127. </div>
  128. <Highlight
  129. {...defaultProps}
  130. code={code}
  131. language={codeLanguage}
  132. theme={undefined}
  133. >
  134. {({
  135. className,
  136. style,
  137. tokens,
  138. getLineProps,
  139. getTokenProps,
  140. }) => (
  141. <pre
  142. className={clsx(
  143. className,
  144. 'flex overflow-x-auto pb-6'
  145. )}
  146. style={style}
  147. >
  148. <code className="px-4">
  149. {tokens.map((line, lineIndex) => (
  150. <div key={lineIndex} {...getLineProps({ line })}>
  151. {line.map((token, tokenIndex) => (
  152. <span
  153. key={tokenIndex}
  154. {...getTokenProps({ token })}
  155. />
  156. ))}
  157. </div>
  158. ))}
  159. </code>
  160. </pre>
  161. )}
  162. </Highlight>
  163. </div>
  164. </div>
  165. </div>
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. </div>
  171. )
  172. }