diff --git a/app/core/styles/index.css b/app/core/styles/index.css index b5c61c9..d6b6576 100644 --- a/app/core/styles/index.css +++ b/app/core/styles/index.css @@ -1,3 +1,21 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@font-face { + font-family: "Inter var"; + font-weight: 100 900; + font-display: optional; + font-style: normal; + font-named-instance: "Regular"; + src: url("/fonts/inter-roman.var.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter var"; + font-weight: 100 900; + font-display: optional; + font-style: italic; + font-named-instance: "Italic"; + src: url("/fonts/inter-italic.var.woff2") format("woff2"); +} diff --git a/app/landing-page/components/header.tsx b/app/landing-page/components/header.tsx new file mode 100644 index 0000000..c9af055 --- /dev/null +++ b/app/landing-page/components/header.tsx @@ -0,0 +1,209 @@ +import { useState, useRef, useEffect, MouseEventHandler } from "react"; +import { Link } from "blitz"; +import { Menu, Transition } from "@headlessui/react"; + +function Header() { + const [mobileNavOpen, setMobileNavOpen] = useState(false); + + const trigger = useRef(null); + const mobileNav = useRef(null); + + // close the mobile menu on click outside + useEffect(() => { + const clickHandler = ({ target }: MouseEvent) => { + if (!mobileNav.current || !trigger.current) { + return; + } + console.log(mobileNav.current.contains(target as Node)); + if ( + !mobileNavOpen || + mobileNav.current.contains(target as Node) || + trigger.current.contains(target as Node) + ) { + return; + } + setMobileNavOpen(false); + }; + document.addEventListener("click", clickHandler); + return () => document.removeEventListener("click", clickHandler); + }); + + // close the mobile menu if the esc key is pressed + useEffect(() => { + const keyHandler = ({ keyCode }: KeyboardEvent) => { + if (!mobileNavOpen || keyCode !== 27) return; + setMobileNavOpen(false); + }; + document.addEventListener("keydown", keyHandler); + return () => document.removeEventListener("keydown", keyHandler); + }); + + return ( +
+
+
+ {/* Site branding */} +
+ {/* Logo */} + + + + + + + + + + + + + + + + + + +
+ + {/* Desktop navigation */} + + + {/* Mobile menu */} +
+ {/* Hamburger button */} + + + {/*Mobile navigation */} + + + +
+
+
+
+ ); +} + +export default Header; diff --git a/app/landing-page/pages/index.tsx b/app/landing-page/pages/index.tsx new file mode 100644 index 0000000..b1229df --- /dev/null +++ b/app/landing-page/pages/index.tsx @@ -0,0 +1,56 @@ +import { Suspense } from "react"; +import type { BlitzPage } from "blitz"; +import { Head, Link, useMutation, Routes } from "blitz"; + +import BaseLayout from "../../core/layouts/base-layout"; +import logout from "../../auth/mutations/logout"; +import useCurrentUser from "../../core/hooks/use-current-user"; +import Header from "../components/header"; + +import "../styles/index.css"; + +const LandingPage: BlitzPage = () => { + return ( + <> + + Shellphone: Your Personal Cloud Phone + + + + + + +
+
+
+ + ); +}; + +LandingPage.suppressFirstRenderFlicker = true; + +export default LandingPage; diff --git a/app/landing-page/styles/index.css b/app/landing-page/styles/index.css new file mode 100644 index 0000000..e0517e9 --- /dev/null +++ b/app/landing-page/styles/index.css @@ -0,0 +1,31 @@ +@font-face { + font-family: "P22 Mackinac Pro"; + src: url("/fonts/P22MackinacPro-Book.woff2") format("woff2"); + font-weight: 400; + font-style: normal; + font-display: optional; +} + +@font-face { + font-family: "P22 Mackinac Pro"; + src: url("/fonts/P22MackinacPro-Bold.woff2") format("woff2"); + font-weight: 700; + font-style: normal; + font-display: optional; +} + +@font-face { + font-family: "P22 Mackinac Pro"; + src: url("/fonts/P22MackinacPro-ExtraBold.woff2") format("woff2"); + font-weight: 800; + font-style: normal; + font-display: optional; +} + +@font-face { + font-family: "P22 Mackinac Pro"; + src: url("/fonts/P22MackinacPro-Medium.woff2") format("woff2"); + font-weight: 500; + font-style: normal; + font-display: optional; +} diff --git a/app/pages/_document.tsx b/app/pages/_document.tsx index 8217839..ab42f64 100644 --- a/app/pages/_document.tsx +++ b/app/pages/_document.tsx @@ -23,6 +23,21 @@ class MyDocument extends Document { + + +
diff --git a/app/pages/index.tsx b/app/pages/index.tsx deleted file mode 100644 index e6af17c..0000000 --- a/app/pages/index.tsx +++ /dev/null @@ -1,274 +0,0 @@ -import { Suspense } from "react"; -import type { BlitzPage } from "blitz"; -import { Link, useMutation, Routes } from "blitz"; - -import BaseLayout from "../core/layouts/base-layout"; -import logout from "../auth/mutations/logout"; -import useCurrentUser from "../core/hooks/use-current-user"; - -/* - * This file is just for a pleasant getting started page for your new app. - * You can delete everything in here and start from scratch if you like. - */ - -const UserInfo = () => { - const { user } = useCurrentUser(); - const [logoutMutation] = useMutation(logout); - - if (user) { - return ( - <> - -
- User id: {user.id} -
- User role: {user.role} -
- - ); - } else { - return ( - <> - - - Sign Up - - - - - Login - - - - ); - } -}; - -const Home: BlitzPage = () => { - return ( -
-
-
- blitz.js -
-

- Congrats! Your app is ready, including user sign-up and log-in. -

-
- - - -
-

- - To add a new model to your app,
- run the following in your terminal: -
-

-
-					blitz generate all project name:string
-				
-
(And select Yes to run prisma migrate)
-
-

- Then restart the server -

-
-						Ctrl + c
-					
-
-						blitz dev
-					
-

- and go to{" "} - - /projects - -

-
- -
- - - - -
- ); -}; - -Home.suppressFirstRenderFlicker = true; - -Home.getLayout = (page) => {page}; - -export default Home; diff --git a/blitz.config.ts b/blitz.config.ts index 63697b0..727f830 100644 --- a/blitz.config.ts +++ b/blitz.config.ts @@ -6,6 +6,19 @@ import { sessionMiddleware, simpleRolesIsAuthorized } from "blitz"; type Module = Omit & { exports: BlitzConfig }; (module as Module).exports = { + async header() { + return [ + { + source: "/fonts/*.woff2", + headers: [ + { + key: "Cache-Control", + value: "public, max-age=31536000, immutable", + }, + ], + }, + ]; + }, middleware: [ sessionMiddleware({ cookiePrefix: "shellphone", diff --git a/public/fonts/P22MackinacPro-Bold.woff2 b/public/fonts/P22MackinacPro-Bold.woff2 new file mode 100644 index 0000000..db73e53 Binary files /dev/null and b/public/fonts/P22MackinacPro-Bold.woff2 differ diff --git a/public/fonts/P22MackinacPro-Book.woff2 b/public/fonts/P22MackinacPro-Book.woff2 new file mode 100644 index 0000000..86e9a2e Binary files /dev/null and b/public/fonts/P22MackinacPro-Book.woff2 differ diff --git a/public/fonts/P22MackinacPro-ExtraBold.woff2 b/public/fonts/P22MackinacPro-ExtraBold.woff2 new file mode 100644 index 0000000..a64bcb4 Binary files /dev/null and b/public/fonts/P22MackinacPro-ExtraBold.woff2 differ diff --git a/public/fonts/P22MackinacPro-Medium.woff2 b/public/fonts/P22MackinacPro-Medium.woff2 new file mode 100644 index 0000000..d753b55 Binary files /dev/null and b/public/fonts/P22MackinacPro-Medium.woff2 differ diff --git a/public/fonts/inter-italic.var.woff2 b/public/fonts/inter-italic.var.woff2 new file mode 100644 index 0000000..b826d5a Binary files /dev/null and b/public/fonts/inter-italic.var.woff2 differ diff --git a/public/fonts/inter-roman.var.woff2 b/public/fonts/inter-roman.var.woff2 new file mode 100644 index 0000000..6a256a0 Binary files /dev/null and b/public/fonts/inter-roman.var.woff2 differ diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest index c7d10c7..99e858f 100644 --- a/public/manifest.webmanifest +++ b/public/manifest.webmanifest @@ -1,5 +1,5 @@ { - "name": "Shellphone: Your Personal Virtual Phone", + "name": "Shellphone: Your Personal Cloud Phone", "short_name": "Shellphone", "lang": "en-US", "start_url": "/", diff --git a/tailwind.config.js b/tailwind.config.js index c802081..94fe12c 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -6,6 +6,8 @@ module.exports = { extend: { fontFamily: { sans: ["Inter var", ...defaultTheme.fontFamily.sans], + inter: ["Inter var", "sans-serif"], + mackinac: [`"P22 Mackinac Pro"`, "sans-serif"], }, colors: { primary: { @@ -20,10 +22,130 @@ module.exports = { 800: "#39236b", 900: "#1f163f", }, + gray: { + 50: "#FAFAFA", + 100: "#F4F4F5", + 200: "#E4E4E7", + 300: "#D4D4D8", + 400: "#A2A2A8", + 500: "#6E6E76", + 600: "#52525A", + 700: "#3F3F45", + 800: "#2E2E33", + 900: "#1D1D20", + }, + teal: { + 50: "#F4FFFD", + 100: "#E6FFFA", + 200: "#B2F5EA", + 300: "#81E6D9", + 400: "#4FD1C5", + 500: "#3ABAB4", + 600: "#319795", + 700: "#2C7A7B", + 800: "#285E61", + 900: "#234E52", + }, + indigo: { + 50: "#F8FBFF", + 100: "#EBF4FF", + 200: "#C3DAFE", + 300: "#A3BFFA", + 400: "#7F9CF5", + 500: "#667EEA", + 600: "#5A67D8", + 700: "#4C51BF", + 800: "#34399B", + 900: "#1E2156", + }, + purple: { + 50: "#FAF5FF", + 100: "#F3E8FF", + 200: "#E9D8FD", + 300: "#D6BCFA", + 400: "#B794F4", + 500: "#9F7AEA", + 600: "#805AD5", + 700: "#6B46C1", + 800: "#553C9A", + 900: "#44337A", + }, + pink: { + 50: "#FFF5F7", + 100: "#FFEBEF", + 200: "#FED7E2", + 300: "#FBB6CE", + 400: "#F687B3", + 500: "#ED64A6", + 600: "#D53F8C", + 700: "#B83280", + 800: "#97266D", + 900: "#702459", + }, + }, + boxShadow: { + "2xl": "0 25px 50px -12px rgba(0, 0, 0, 0.08)", + }, + outline: { + blue: "2px solid rgba(0, 112, 244, 0.5)", + }, + spacing: { + 128: "32rem", + "9/16": "56.25%", + "3/4": "75%", + "1/1": "100%", + }, + fontSize: { + xs: ["0.75rem", { lineHeight: "1.5" }], + sm: ["0.875rem", { lineHeight: "1.5" }], + base: ["1rem", { lineHeight: "1.5" }], + lg: ["1.125rem", { lineHeight: "1.5" }], + xl: ["1.25rem", { lineHeight: "1.5" }], + "2xl": ["1.63rem", { lineHeight: "1.35" }], + "3xl": ["2.63rem", { lineHeight: "1.24" }], + "4xl": ["3.5rem", { lineHeight: "1.18" }], + "5xl": ["4rem", { lineHeight: "1.16" }], + "6xl": ["5.5rem", { lineHeight: "1.11" }], + }, + inset: { + "1/2": "50%", + full: "100%", + }, + letterSpacing: { + tighter: "-0.02em", + tight: "-0.01em", + normal: "0", + wide: "0.01em", + wider: "0.02em", + widest: "0.4em", + }, + minWidth: { + 10: "2.5rem", + }, + scale: { + 98: ".98", + }, + animation: { + float: "float 5s ease-in-out infinite", + }, + keyframes: { + float: { + "0%, 100%": { transform: "translateY(0)" }, + "50%": { transform: "translateY(-10%)" }, + }, + }, + zIndex: { + "-1": "-1", + "-10": "-10", }, }, }, - variants: {}, + variants: { + extend: { + rotate: ["group-hover"], + translate: ["group-hover"], + }, + }, plugins: [require("@tailwindcss/forms"), require("@tailwindcss/typography")], purge: ["{pages,app}/**/*.{js,ts,jsx,tsx}"], };