preload fonts

This commit is contained in:
m5r 2021-08-25 16:52:24 +08:00
parent 4b54d8e616
commit 6417f5dbcf
15 changed files with 466 additions and 276 deletions

View File

@ -1,3 +1,21 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @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");
}

View File

@ -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<HTMLButtonElement>(null);
const mobileNav = useRef<HTMLElement>(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 (
<header className="absolute w-full z-30">
<div className="max-w-6xl mx-auto px-4 sm:px-6">
<div className="flex items-center justify-between h-20">
{/* Site branding */}
<div className="flex-shrink-0 mr-5">
{/* Logo */}
<Link href="/">
<a className="block">
<svg className="w-8 h-8" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="26%" y1="100%" x2="100%" y2="100%" id="logo_a">
<stop stopColor="#3ABAB4" offset="0%" />
<stop stopColor="#7F9CF5" offset="100%" />
</linearGradient>
<linearGradient x1="26%" y1="100%" x2="100%" y2="100%" id="logo_b">
<stop stopColor="#3ABAB4" offset="0%" />
<stop stopColor="#3ABAB4" stopOpacity="0" offset="100%" />
</linearGradient>
</defs>
<path
d="M32 16h-8a8 8 0 10-16 0H0C0 7.163 7.163 0 16 0s16 7.163 16 16z"
fill="url(#logo_a)"
/>
<path
d="M32 16c0 8.837-7.163 16-16 16S0 24.837 0 16h8a8 8 0 1016 0h8z"
fill="url(#logo_b)"
/>
</svg>
</a>
</Link>
</div>
{/* Desktop navigation */}
<nav className="hidden md:flex md:flex-grow">
{/* Desktop menu links */}
<ul className="flex flex-grow flex-wrap items-center font-medium">
<li>
<Link href="/about">
<a className="text-gray-600 hover:text-gray-900 px-5 py-2 flex items-center transition duration-150 ease-in-out">
About
</a>
</Link>
</li>
<li>
<Link href="/blog">
<a className="text-gray-600 hover:text-gray-900 px-5 py-2 flex items-center transition duration-150 ease-in-out">
Blog
</a>
</Link>
</li>
<li>
<Link href="/testimonials">
<a className="text-gray-600 hover:text-gray-900 px-5 py-2 flex items-center transition duration-150 ease-in-out">
Testimonials
</a>
</Link>
</li>
</ul>
{/* Desktop CTA on the right */}
<ul className="flex justify-end flex-wrap items-center">
<li>
<Link href="/contact">
<a className="btn-sm text-white bg-teal-500 hover:bg-teal-400 ml-6">Request code</a>
</Link>
</li>
</ul>
</nav>
{/* Mobile menu */}
<div className="inline-flex md:hidden">
{/* Hamburger button */}
<button
ref={trigger}
className={`hamburger ${mobileNavOpen && "active"}`}
aria-controls="mobile-nav"
aria-expanded={mobileNavOpen}
onClick={() => setMobileNavOpen(!mobileNavOpen)}
>
<span className="sr-only">Menu</span>
<svg
className="w-6 h-6 fill-current text-gray-900 hover:text-gray-900 transition duration-150 ease-in-out"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<rect y="4" width="24" height="2" rx="1" />
<rect y="11" width="24" height="2" rx="1" />
<rect y="18" width="24" height="2" rx="1" />
</svg>
</button>
{/*Mobile navigation */}
<Transition
show={mobileNavOpen}
as="ul"
className="fixed top-0 h-screen z-20 left-0 w-full max-w-sm -ml-16 overflow-scroll bg-white shadow-lg"
enter="transition ease-out duration-200 transform"
enterFrom="opacity-0 -translate-x-full"
enterTo="opacity-100 translate-x-0"
leave="transition ease-out duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<nav
id="mobile-nav"
ref={mobileNav}
className="fixed top-0 h-screen z-20 left-0 w-full max-w-sm -ml-16 overflow-scroll bg-white shadow-lg no-scrollbar"
>
<div className="py-6 pr-4 pl-20">
{/* Logo */}
<svg className="w-8 h-8" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="26%" y1="100%" x2="100%" y2="100%" id="menulogo_a">
<stop stopColor="#3ABAB4" offset="0%" />
<stop stopColor="#7F9CF5" offset="100%" />
</linearGradient>
<linearGradient x1="26%" y1="100%" x2="100%" y2="100%" id="menulogo_b">
<stop stopColor="#3ABAB4" offset="0%" />
<stop stopColor="#3ABAB4" stopOpacity="0" offset="100%" />
</linearGradient>
</defs>
<path
d="M32 16h-8a8 8 0 10-16 0H0C0 7.163 7.163 0 16 0s16 7.163 16 16z"
fill="url(#menulogo_a)"
/>
<path
d="M32 16c0 8.837-7.163 16-16 16S0 24.837 0 16h8a8 8 0 1016 0h8z"
fill="url(#menulogo_b)"
/>
</svg>
{/* Links */}
<ul>
<li>
<Link href="/about">
<a className="flex text-gray-600 hover:text-gray-900 py-2">About</a>
</Link>
</li>
<li>
<Link href="/blog">
<a className="flex text-gray-600 hover:text-gray-900 py-2">Blog</a>
</Link>
</li>
<li>
<Link href="/testimonials">
<a className="flex text-gray-600 hover:text-gray-900 py-2">
Testimonials
</a>
</Link>
</li>
<li>
<Link href="/contact">
<a className="font-medium w-full inline-flex items-center justify-center border border-transparent px-4 py-2 my-2 rounded text-white bg-teal-500 hover:bg-teal-400 transition duration-150 ease-in-out">
Request code
</a>
</Link>
</li>
</ul>
</div>
</nav>
</Transition>
</div>
</div>
</div>
</header>
);
}
export default Header;

View File

@ -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 (
<>
<Head>
<title>Shellphone: Your Personal Cloud Phone</title>
<link
rel="preload"
href="/fonts/P22MackinacPro-Book.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
<link
rel="preload"
href="/fonts/P22MackinacPro-Bold.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
<link
rel="preload"
href="/fonts/P22MackinacPro-ExtraBold.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
<link
rel="preload"
href="/fonts/P22MackinacPro-Medium.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
</Head>
<section className="font-inter antialiased bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100 tracking-tight">
<Header />
</section>
</>
);
};
LandingPage.suppressFirstRenderFlicker = true;
export default LandingPage;

View File

@ -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;
}

View File

@ -23,6 +23,21 @@ class MyDocument extends Document {
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="msapplication-starturl" content="/" /> <meta name="msapplication-starturl" content="/" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link
rel="preload"
href="/fonts/inter-roman.var.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
<link
rel="preload"
href="/fonts/inter-italic.var.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
</Head> </Head>
<body> <body>
<Main /> <Main />

View File

@ -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 (
<>
<button
className="button small"
onClick={async () => {
await logoutMutation();
}}
>
Logout
</button>
<div>
User id: <code>{user.id}</code>
<br />
User role: <code>{user.role}</code>
</div>
</>
);
} else {
return (
<>
<Link href={Routes.SignUp()}>
<a className="button small">
<strong>Sign Up</strong>
</a>
</Link>
<Link href={Routes.SignIn()}>
<a className="button small">
<strong>Login</strong>
</a>
</Link>
</>
);
}
};
const Home: BlitzPage = () => {
return (
<div className="container">
<main>
<div className="logo">
<img src="/logo.png" alt="blitz.js" />
</div>
<p>
<strong>Congrats!</strong> Your app is ready, including user sign-up and log-in.
</p>
<div className="buttons" style={{ marginTop: "1rem", marginBottom: "1rem" }}>
<Suspense fallback="Loading...">
<UserInfo />
</Suspense>
</div>
<p>
<strong>
To add a new model to your app, <br />
run the following in your terminal:
</strong>
</p>
<pre>
<code>blitz generate all project name:string</code>
</pre>
<div style={{ marginBottom: "1rem" }}>(And select Yes to run prisma migrate)</div>
<div>
<p>
Then <strong>restart the server</strong>
</p>
<pre>
<code>Ctrl + c</code>
</pre>
<pre>
<code>blitz dev</code>
</pre>
<p>
and go to{" "}
<Link href="/projects">
<a>/projects</a>
</Link>
</p>
</div>
<div className="buttons" style={{ marginTop: "5rem" }}>
<a
className="button"
href="https://blitzjs.com/docs/getting-started?utm_source=blitz-new&utm_medium=app-template&utm_campaign=blitz-new"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
<a
className="button-outline"
href="https://github.com/blitz-js/blitz"
target="_blank"
rel="noopener noreferrer"
>
Github Repo
</a>
<a
className="button-outline"
href="https://discord.blitzjs.com"
target="_blank"
rel="noopener noreferrer"
>
Discord Community
</a>
</div>
</main>
<footer>
<a
href="https://blitzjs.com?utm_source=blitz-new&utm_medium=app-template&utm_campaign=blitz-new"
target="_blank"
rel="noopener noreferrer"
>
Powered by Blitz.js
</a>
</footer>
<style jsx global>{`
@import url("https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@300;700&display=swap");
html,
body {
padding: 0;
margin: 0;
font-family: "Libre Franklin", -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
}
.container {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
main {
padding: 5rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
main p {
font-size: 1.2rem;
}
p {
text-align: center;
}
footer {
width: 100%;
height: 60px;
border-top: 1px solid #eaeaea;
display: flex;
justify-content: center;
align-items: center;
background-color: #45009d;
}
footer a {
display: flex;
justify-content: center;
align-items: center;
}
footer a {
color: #f4f4f4;
text-decoration: none;
}
.logo {
margin-bottom: 2rem;
}
.logo img {
width: 300px;
}
.buttons {
display: grid;
grid-auto-flow: column;
grid-gap: 0.5rem;
}
.button {
font-size: 1rem;
background-color: #6700eb;
padding: 1rem 2rem;
color: #f4f4f4;
text-align: center;
}
.button.small {
padding: 0.5rem 1rem;
}
.button:hover {
background-color: #45009d;
}
.button-outline {
border: 2px solid #6700eb;
padding: 1rem 2rem;
color: #6700eb;
text-align: center;
}
.button-outline:hover {
border-color: #45009d;
color: #45009d;
}
pre {
background: #fafafa;
border-radius: 5px;
padding: 0.75rem;
text-align: center;
}
code {
font-size: 0.9rem;
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace;
}
.grid {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
max-width: 800px;
margin-top: 3rem;
}
@media (max-width: 600px) {
.grid {
width: 100%;
flex-direction: column;
}
}
`}</style>
</div>
);
};
Home.suppressFirstRenderFlicker = true;
Home.getLayout = (page) => <BaseLayout title="Home">{page}</BaseLayout>;
export default Home;

View File

@ -6,6 +6,19 @@ import { sessionMiddleware, simpleRolesIsAuthorized } from "blitz";
type Module = Omit<NodeModule, "exports"> & { exports: BlitzConfig }; type Module = Omit<NodeModule, "exports"> & { exports: BlitzConfig };
(module as Module).exports = { (module as Module).exports = {
async header() {
return [
{
source: "/fonts/*.woff2",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, immutable",
},
],
},
];
},
middleware: [ middleware: [
sessionMiddleware({ sessionMiddleware({
cookiePrefix: "shellphone", cookiePrefix: "shellphone",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
{ {
"name": "Shellphone: Your Personal Virtual Phone", "name": "Shellphone: Your Personal Cloud Phone",
"short_name": "Shellphone", "short_name": "Shellphone",
"lang": "en-US", "lang": "en-US",
"start_url": "/", "start_url": "/",

View File

@ -6,6 +6,8 @@ module.exports = {
extend: { extend: {
fontFamily: { fontFamily: {
sans: ["Inter var", ...defaultTheme.fontFamily.sans], sans: ["Inter var", ...defaultTheme.fontFamily.sans],
inter: ["Inter var", "sans-serif"],
mackinac: [`"P22 Mackinac Pro"`, "sans-serif"],
}, },
colors: { colors: {
primary: { primary: {
@ -20,10 +22,130 @@ module.exports = {
800: "#39236b", 800: "#39236b",
900: "#1f163f", 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")], plugins: [require("@tailwindcss/forms"), require("@tailwindcss/typography")],
purge: ["{pages,app}/**/*.{js,ts,jsx,tsx}"], purge: ["{pages,app}/**/*.{js,ts,jsx,tsx}"],
}; };