index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. import React from "react";
  2. import Head from "next/head";
  3. import Link from "next/link";
  4. import { useRouter } from "next/router";
  5. import { FaGithub, FaLinkedin, FaTwitter } from "react-icons/fa";
  6. import {
  7. HiCursorClick,
  8. HiLightningBolt,
  9. HiOutlineDownload,
  10. HiOutlineSearchCircle,
  11. } from "react-icons/hi";
  12. import { TwitterTweetEmbed } from "react-twitter-embed";
  13. import { Button } from "src/components/Button";
  14. import { Producthunt } from "src/components/Producthunt";
  15. import styled from "styled-components";
  16. import pkg from "../../package.json";
  17. const StyledHome = styled.div`
  18. display: flex;
  19. flex-direction: column;
  20. gap: 8em;
  21. font-family: "Roboto", sans-serif;
  22. * {
  23. box-sizing: border-box;
  24. }
  25. @media only screen and (max-width: 768px) {
  26. gap: 3em;
  27. }
  28. `;
  29. const StyledGradientText = styled.span`
  30. background: #ffb76b;
  31. background: linear-gradient(
  32. to right,
  33. #ffb76b 0%,
  34. #ffa73d 30%,
  35. #ff7c00 60%,
  36. #ff7f04 100%
  37. );
  38. background-clip: text;
  39. -webkit-background-clip: text;
  40. -webkit-text-fill-color: transparent;
  41. `;
  42. const StyledNavbar = styled.nav`
  43. display: flex;
  44. justify-content: center;
  45. align-items: center;
  46. width: 100%;
  47. padding: 16px 16px;
  48. gap: 20px;
  49. @media only screen and (max-width: 768px) {
  50. a:first-of-type {
  51. display: none;
  52. }
  53. }
  54. `;
  55. const StyledHeroSection = styled.section`
  56. display: flex;
  57. flex-direction: column;
  58. justify-content: center;
  59. align-items: center;
  60. gap: 1.5em;
  61. min-height: 45vh;
  62. padding: 0 3%;
  63. `;
  64. const StyledNavLink = styled.a`
  65. display: flex;
  66. justify-content: center;
  67. align-items: center;
  68. font-size: 1rem;
  69. cursor: pointer;
  70. transition: color 0.2s;
  71. &:hover {
  72. font-weight: 500;
  73. color: ${({ theme }) => theme.ORANGE};
  74. }
  75. `;
  76. const StyledTitle = styled.h1`
  77. font-size: 5rem;
  78. font-weight: 900;
  79. margin: 0;
  80. @media only screen and (max-width: 768px) {
  81. font-size: 3rem;
  82. }
  83. `;
  84. const StyledSubTitle = styled.h2`
  85. color: #dedede;
  86. text-align: center;
  87. font-size: 2.5rem;
  88. max-width: 40rem;
  89. margin: 0;
  90. @media only screen and (max-width: 768px) {
  91. font-size: 1.5rem;
  92. }
  93. `;
  94. const StyledMinorTitle = styled.p`
  95. color: #b4b4b4;
  96. text-align: center;
  97. font-size: 1.25rem;
  98. margin: 0;
  99. letter-spacing: 1.2px;
  100. @media only screen and (max-width: 992px) {
  101. font-size: 1rem;
  102. }
  103. `;
  104. const StyledButton = styled(Button)`
  105. background: ${({ status }) => !status && "#a13cc2"};
  106. padding: 12px 24px;
  107. div {
  108. font-family: "Roboto", sans-serif;
  109. font-weight: 700;
  110. font-size: 16px;
  111. }
  112. @media only screen and (max-width: 768px) {
  113. &:first-of-type {
  114. pointer-events: none;
  115. div {
  116. content: "Incompatible Device";
  117. }
  118. }
  119. }
  120. `;
  121. const StyledFeaturesSection = styled.section`
  122. display: flex;
  123. max-width: 85%;
  124. margin: 0 auto;
  125. gap: 2rem;
  126. padding: 60px 3%;
  127. @media only screen and (max-width: 768px) {
  128. flex-direction: column;
  129. max-width: 80%;
  130. }
  131. `;
  132. const StyledSectionCard = styled.div`
  133. text-align: center;
  134. flex: 1;
  135. `;
  136. const StyledCardTitle = styled.div`
  137. font-weight: 700;
  138. font-size: 1.5rem;
  139. padding: 1.5rem 0 0.5rem;
  140. letter-spacing: 1px;
  141. `;
  142. const StyledCardIcon = styled.div``;
  143. const StyledCardDescription = styled.p`
  144. color: #e0e0e0;
  145. text-align: left;
  146. line-height: 1.5rem;
  147. font-size: 0.875rem;
  148. `;
  149. const StyledGitHubSection = styled.section`
  150. display: flex;
  151. flex-direction: row;
  152. justify-content: space-between;
  153. max-width: 85%;
  154. margin: 0 auto;
  155. gap: 4rem;
  156. line-height: 1.5;
  157. padding: 60px 3%;
  158. & > div {
  159. width: 100%;
  160. }
  161. @media only screen and (max-width: 768px) {
  162. flex-direction: column-reverse;
  163. max-width: 80%;
  164. }
  165. `;
  166. const StyledSectionArea = styled.div`
  167. display: flex;
  168. flex-direction: column;
  169. gap: 2rem;
  170. width: 40%;
  171. margin-top: 3rem;
  172. h2,
  173. p {
  174. text-align: left;
  175. letter-spacing: unset;
  176. }
  177. @media only screen and (max-width: 768px) {
  178. width: 100%;
  179. h2,
  180. p {
  181. text-align: center;
  182. }
  183. button {
  184. align-self: center;
  185. }
  186. }
  187. `;
  188. const StyledSponsorSection = styled.section`
  189. display: flex;
  190. flex-direction: column;
  191. justify-content: center;
  192. align-items: center;
  193. max-width: 85%;
  194. margin: 0 auto;
  195. gap: 2rem;
  196. line-height: 1.5;
  197. padding: 60px 3%;
  198. @media only screen and (max-width: 768px) {
  199. max-width: 80%;
  200. }
  201. `;
  202. const StyledPreviewSection = styled.section`
  203. display: flex;
  204. flex-direction: row;
  205. justify-content: space-between;
  206. max-width: 85%;
  207. margin: 0 auto;
  208. padding: 0 3%;
  209. @media only screen and (max-width: 768px) {
  210. display: none;
  211. max-width: 80%;
  212. }
  213. `;
  214. const StyledImage = styled.img`
  215. max-width: 100%;
  216. filter: drop-shadow(0px 0px 12px rgba(255, 255, 255, 0.6));
  217. `;
  218. const StyledFooter = styled.footer`
  219. display: flex;
  220. flex-direction: row;
  221. justify-content: space-between;
  222. width: 80%;
  223. margin: 0 auto;
  224. padding: 30px 3%;
  225. border-top: 1px solid #b4b4b4;
  226. opacity: 0.7;
  227. `;
  228. const StyledFooterText = styled.p`
  229. color: #b4b4b4;
  230. `;
  231. const StyledIconLinks = styled.div`
  232. display: flex;
  233. gap: 20px;
  234. ${StyledNavLink} {
  235. color: unset;
  236. }
  237. `;
  238. const StyledHighlightedText = styled.span`
  239. text-decoration: underline;
  240. text-decoration-style: dashed;
  241. text-decoration-color: #eab308;
  242. `;
  243. const StyledProducthuntSection = styled.section`
  244. display: flex;
  245. justify-content: center;
  246. align-items: center;
  247. gap: 3rem;
  248. max-width: 85%;
  249. margin: 0 auto;
  250. padding: 60px 3%;
  251. ${StyledSectionArea} {
  252. margin: 0;
  253. width: 100%;
  254. h2 {
  255. text-align: right;
  256. }
  257. }
  258. @media only screen and (max-width: 768px) {
  259. flex-direction: column;
  260. max-width: 80%;
  261. ${StyledSectionArea} {
  262. h2 {
  263. text-align: center;
  264. }
  265. }
  266. }
  267. `;
  268. const Home: React.FC = () => {
  269. const { push } = useRouter();
  270. const [isMobile, setIsMobile] = React.useState(false);
  271. React.useEffect(() => {
  272. setIsMobile(window.screen.width <= 768);
  273. }, []);
  274. return (
  275. <StyledHome>
  276. <Head>
  277. <title>JSON Visio - Directly onto graphs</title>
  278. </Head>
  279. <StyledNavbar>
  280. <Link href="/editor" passHref>
  281. <StyledNavLink>Editor</StyledNavLink>
  282. </Link>
  283. <Link href="#features" passHref>
  284. <StyledNavLink>Features</StyledNavLink>
  285. </Link>
  286. <Link href="#sponsor" passHref>
  287. <StyledNavLink>Sponsor</StyledNavLink>
  288. </Link>
  289. <StyledNavLink
  290. href="https://github.com/AykutSarac/jsonvisio.com"
  291. target="_blank"
  292. rel="external"
  293. >
  294. GitHub
  295. </StyledNavLink>
  296. </StyledNavbar>
  297. <StyledHeroSection id="main">
  298. <StyledTitle>
  299. <StyledGradientText>JSON</StyledGradientText> Visio
  300. </StyledTitle>
  301. <StyledSubTitle>
  302. Seamlessly visualize your JSON data{" "}
  303. <StyledHighlightedText>instantly</StyledHighlightedText> into graphs.
  304. </StyledSubTitle>
  305. <StyledMinorTitle>Paste - Import - Fetch!</StyledMinorTitle>
  306. <StyledButton onClick={() => push("/editor")} disabled={isMobile}>
  307. {isMobile ? "Incompatible Device" : "GO TO EDITOR"}
  308. </StyledButton>
  309. </StyledHeroSection>
  310. <StyledPreviewSection>
  311. <StyledImage
  312. width="1200"
  313. height="auto"
  314. src="/jsonvisio-screenshot.png"
  315. alt="preview"
  316. loading="lazy"
  317. />
  318. </StyledPreviewSection>
  319. <StyledFeaturesSection id="features">
  320. <StyledSectionCard>
  321. <StyledCardIcon>
  322. <HiCursorClick size={50} color="#3BA55D" />
  323. </StyledCardIcon>
  324. <StyledCardTitle>EASY-TO-USE</StyledCardTitle>
  325. <StyledCardDescription>
  326. Don&apos;t even bother to update your schema to view your JSON into
  327. graphs; directly paste, import or fetch! JSON Visio helps you to
  328. visualize without any additional values and save your time.
  329. </StyledCardDescription>
  330. </StyledSectionCard>
  331. <StyledSectionCard>
  332. <StyledCardIcon>
  333. <HiOutlineSearchCircle size={50} color="#5865F2" />
  334. </StyledCardIcon>
  335. <StyledCardTitle>SEARCH</StyledCardTitle>
  336. <StyledCardDescription>
  337. Have a huge file of values, keys or arrays? Worry no more, type in
  338. the keyword you are looking for into search input and it will take
  339. you to each node with matching result highlighting the line to
  340. understand better!
  341. </StyledCardDescription>
  342. </StyledSectionCard>
  343. <StyledSectionCard>
  344. <StyledCardIcon>
  345. <HiOutlineDownload size={50} color="#DA2877" />
  346. </StyledCardIcon>
  347. <StyledCardTitle>DOWNLOAD</StyledCardTitle>
  348. <StyledCardDescription>
  349. Download the graph to your local machine and use it wherever you
  350. want, to your blogs, website or make it a poster and paste to the
  351. wall. Who wouldn&apos;t want to see a JSON Visio graph onto their
  352. wall, eh?
  353. </StyledCardDescription>
  354. </StyledSectionCard>
  355. <StyledSectionCard>
  356. <StyledCardIcon>
  357. <HiLightningBolt size={50} color="#F5E027" />
  358. </StyledCardIcon>
  359. <StyledCardTitle>LIVE</StyledCardTitle>
  360. <StyledCardDescription>
  361. With Microsoft&apos;s Monaco Editor which is also used by VS Code,
  362. easily edit your JSON and directly view through the graphs. Also
  363. there&apos;s a JSON validator above of it to make sure there is no
  364. type error.
  365. </StyledCardDescription>
  366. </StyledSectionCard>
  367. </StyledFeaturesSection>
  368. <StyledGitHubSection id="github">
  369. <TwitterTweetEmbed
  370. tweetId="1519363257794015233"
  371. options={{
  372. width: "600",
  373. align: "center",
  374. }}
  375. />
  376. <StyledSectionArea>
  377. <StyledSubTitle>Open Source Community</StyledSubTitle>
  378. <StyledMinorTitle>
  379. Join the Open Source Community by suggesting new ideas, support by
  380. contributing; implementing new features, fixing bugs and doing
  381. changes minor to major!
  382. </StyledMinorTitle>
  383. <StyledButton
  384. onClick={() => push("https://github.com/AykutSarac/jsonvisio.com")}
  385. status="SECONDARY"
  386. >
  387. STAR ON GITHUB
  388. </StyledButton>
  389. </StyledSectionArea>
  390. </StyledGitHubSection>
  391. <StyledSponsorSection id="sponsor">
  392. <StyledSubTitle>Sponsors</StyledSubTitle>
  393. <StyledMinorTitle>
  394. Your supports make JSON Visio possible to continue and accessible for
  395. everyone!
  396. </StyledMinorTitle>
  397. <StyledButton
  398. status="SUCCESS"
  399. onClick={() => push("https://www.patreon.com/aykutsarac")}
  400. >
  401. Become A Sponsor!
  402. </StyledButton>
  403. </StyledSponsorSection>
  404. <StyledProducthuntSection>
  405. <StyledSectionArea>
  406. <StyledSubTitle>
  407. Support JSON Visio at
  408. <br />
  409. <StyledHighlightedText>Product Hunt</StyledHighlightedText>
  410. </StyledSubTitle>
  411. </StyledSectionArea>
  412. <Producthunt />
  413. </StyledProducthuntSection>
  414. <StyledFooter>
  415. <StyledFooterText>© 2022 JSON Visio - {pkg.version}</StyledFooterText>
  416. <StyledIconLinks>
  417. <StyledNavLink
  418. href="https://github.com/AykutSarac/jsonvisio.com"
  419. target="_blank"
  420. aria-label="github"
  421. >
  422. <FaGithub size={26} />
  423. </StyledNavLink>
  424. <StyledNavLink
  425. href="https://www.linkedin.com/in/aykutsarac/"
  426. target="_blank"
  427. aria-label="linkedin"
  428. >
  429. <FaLinkedin size={26} />
  430. </StyledNavLink>
  431. <StyledNavLink
  432. href="https://twitter.com/aykutsarach"
  433. target="_blank"
  434. aria-label="twitter"
  435. >
  436. <FaTwitter size={26} />
  437. </StyledNavLink>
  438. </StyledIconLinks>
  439. </StyledFooter>
  440. </StyledHome>
  441. );
  442. };
  443. export default Home;