Skip to content

Commit

Permalink
refactor(web): design
Browse files Browse the repository at this point in the history
  • Loading branch information
krystxf committed Nov 18, 2024
1 parent b0c77ec commit b8e8e37
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 106 deletions.
3 changes: 3 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"@heroicons/react": "^2.1.5",
"@metro-now/constants": "workspace:*",
"@next/mdx": "^14.2.2",
"clsx": "^2.1.1",
"framer-motion": "^11.11.17",
"motion": "^11.11.17",
"next": "14.2.10",
"nextra": "^2.13.4",
"nextra-theme-docs": "^2.13.4",
Expand Down
Binary file added apps/web/public/iphone-mockup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed apps/web/public/metro-now-watch.png
Binary file not shown.
Binary file added apps/web/public/watch-mockup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions apps/web/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
text-wrap: balance;
}
}

html {
scroll-behavior: smooth;
}
2 changes: 1 addition & 1 deletion apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className={notoSans.className}>{children}</body>
<body className={notoSans.className + ""}>{children}</body>
</html>
);
}
11 changes: 9 additions & 2 deletions apps/web/src/app/not-found.module.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
.status_code {
opacity: 0.075;
opacity: 0.1;
font-weight: 900;
color: transparent;
-webkit-text-stroke: 1px black;
font-size: clamp(10vw, 60vw, 100vw);
position: absolute;
pointer-events: none;
}

.status_code_light {
-webkit-text-stroke: 1px black;
}

.status_code_dark {
-webkit-text-stroke: 1px white;
}
37 changes: 32 additions & 5 deletions apps/web/src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Link from "next/link";
import styles from "./not-found.module.css";
import Image from "next/image";
import { MetroNowIcon } from "@/utils/image.utils";
import MetroNowIcon from "../../public/metro-now-icon.png";
import { ChevronRightIcon } from "@heroicons/react/24/solid";
import clsx from "clsx";

const LINKS = [
{
Expand All @@ -15,15 +16,41 @@ const LINKS = [
},
];

const BackgroundText = () => {
return (
<>
{" "}
<div
className={clsx(
"block dark:hidden",
styles.status_code,
styles.status_code_light,
)}
>
404
</div>
<div
className={clsx(
"hidden dark:block",
styles.status_code,
styles.status_code_dark,
)}
>
404
</div>
</>
);
};

const NotFoundPage = () => {
return (
<div className="flex h-screen w-full flex-col items-center justify-center gap-6 px-4">
<div className={styles.status_code}>404</div>
<div className="flex dark:bg-black h-screen w-full flex-col items-center justify-center gap-6 px-4 dark:text-white overflow-hidden">
<BackgroundText />

<div className="space-y-2 text-center">
<Link
href="/"
className="font-bold text-zinc-800 text-5xl flex items-center gap-2"
className="font-bold text-neutral-800 dark:text-neutral-50 text-5xl flex items-center gap-2"
>
<Image
className="rounded-lg"
Expand All @@ -44,7 +71,7 @@ const NotFoundPage = () => {
<li key={index}>
<Link
href={link.href}
className="flex gap-1 items-center text-zinc-500 hover:text-zinc-950 transition-all"
className="flex gap-1 items-center text-neutral-500 dark:text-neutral-400 dark:hover:text-neutral-100 hover:text-neutral-950 transition-all"
>
<ChevronRightIcon className="h-3" />
{link.text}
Expand Down
224 changes: 134 additions & 90 deletions apps/web/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import { Card } from "@/components/Card";
import Image from "next/image";

Expand All @@ -8,111 +9,154 @@ import {
SOURCE_CODE_URL,
SWAGGER_URL,
} from "@metro-now/constants";
import {
DownloadOnAppStoreLight,
MetroNowIcon,
MetroNowWatch,
} from "@/utils/image.utils";
import DownloadOnAppStoreLight from "../../public/download-on-appstore-light.svg";
import MetroNowIcon from "../../public/metro-now-icon.png";
import MetroNowIphoneMockup from "../../public/iphone-mockup.png";
import MetroNowWatchMockup from "../../public/watch-mockup.png";

import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
import { AppearingText } from "@/components/AppearingText";

const LandingPage = () => {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="flex flex-col gap-2 items-center justify-center text-center">
<h1 className="text-6xl font-bold text-zinc-800 flex gap-2 items-center">
<div className="dark:bg-black px-12 xl:px-24 py-24">
<main className="max-w-screen-lg m-auto">
<div className="flex flex-col gap-2 items-center justify-center text-center">
<h1 className="text-4xl xl:text-6xl font-bold text-zinc-800 flex gap-2 items-center dark:text-slate-50">
<Image
className="rounded-xl"
alt="Icon"
src={MetroNowIcon}
placeholder="blur"
height={56}
priority
/>
Metro&nbsp;Now!
</h1>
<p className="text-slate-800 dark:text-slate-300">
Real-time public transport departures in minimalistic
app
</p>

<Link href={APPSTORE_URL}>
<Image
src={DownloadOnAppStoreLight}
className="mt-4"
alt="Download on App Store"
height={50}
priority
/>
</Link>
</div>
<div className="flex flex-col gap-8 xl:flex-row items-center xl:items-start mt-24">
<div className="xl:w-1/3 xl:mt-24">
<h2 className="font-semibold text-2xl dark:text-slate-200">
Available on iOS
</h2>
<p className="dark:text-slate-400">
<AppearingText text="Public transport departures from the nearest stop" />
</p>
</div>
<Image
className="rounded-xl"
alt="Icon"
src={MetroNowIcon}
placeholder="blur"
height={56}
src={MetroNowIphoneMockup}
className="xl:w-2/3 max-h-[75vh]"
style={{
objectFit: "scale-down",
}}
alt="Apple watch screenshots"
quality={90}
priority
/>
Metro&nbsp;Now!
</h1>
<p className="text-slate-800">
Get a real-time overview of metro departures from the
nearest stop in Prague
</p>
<Link href={APPSTORE_URL}>
</div>

<div className="flex flex-col gap-8 xl:flex-row-reverse items-center xl:items-start mt-24">
<div className="xl:w-1/2 xl:mt-24">
<h2 className="font-semibold text-2xl dark:text-slate-200">
Available on watchOS
</h2>
<p className="dark:text-slate-400">
<AppearingText text="Metro departures from the nearest stop on your wrist" />
</p>
</div>
<Image
src={DownloadOnAppStoreLight}
className="mt-4"
alt="Download on App Store"
height={50}
priority
src={MetroNowWatchMockup}
className="xl:w-1/2 max-h-[50vh]"
style={{
objectFit: "scale-down",
}}
alt="Apple watch screenshots"
quality={90}
/>
</Link>
</div>
<Image
src={MetroNowWatch}
alt="Apple watch screenshots"
height={1200}
placeholder="blur"
quality={90}
priority
/>
<div className="mb-32 gap-4 grid text-center lg:mb-0 lg:w-full lg:max-w-7xl lg:grid-cols-3 lg:text-left">
<Card className="group">
<Link
href={SOURCE_CODE_URL}
className="h-full"
target="_blank"
>
<Card.Title>
Source code
<ArrowTopRightOnSquareIcon className="h-5" />
</Card.Title>
</div>

<Card.Content className="opacity-50">
Every line of code for this project is available on
GitHub.
</Card.Content>
</Link>
</Card>
<div className="mb-32 mt-24 gap-4 grid text-center lg:mb-0 lg:w-full lg:max-w-7xl lg:grid-cols-3 lg:text-left text-slate-950 dark:text-white">
<Card className="group min-h-44">
<Link
href={SOURCE_CODE_URL}
className="h-full"
target="_blank"
>
<Card.Title>
Source code
<ArrowTopRightOnSquareIcon className="h-5" />
</Card.Title>

<Card>
<Link href="/docs" className="group">
<Card.Title>
Documentation <Card.Arrow className="h-5" />
</Card.Title>
</Link>
<Card.Content>
<Card.Content.Link href={SWAGGER_URL} target="_blank">
REST API
<ArrowTopRightOnSquareIcon className="h-3" />
</Card.Content.Link>
<Card.Content className="opacity-50">
Every line of code for this project is available
on GitHub.
</Card.Content>
</Link>
</Card>

<Card.Content.Link href={GRAPHQL_URL} target="_blank">
GrapQL
<ArrowTopRightOnSquareIcon className="h-3" />
</Card.Content.Link>
</Card.Content>
</Card>
<Card className="min-h-44">
<Link href="/docs" className="group">
<Card.Title>
API <Card.Arrow className="h-5" />
</Card.Title>
</Link>
<Card.Content>
<Card.Content.Link
href={SWAGGER_URL}
target="_blank"
>
REST API
<ArrowTopRightOnSquareIcon className="h-3" />
</Card.Content.Link>

<Card>
<Card.Title>Legal</Card.Title>
<Card.Content.Link
href={GRAPHQL_URL}
target="_blank"
>
GrapQL
<ArrowTopRightOnSquareIcon className="h-3" />
</Card.Content.Link>
</Card.Content>
</Card>

<Card.Content>
<Card.Content.Link
href="/docs/privacy-policy"
target="_blank"
>
Privacy policy
<Card.Arrow />
</Card.Content.Link>
<Card className="min-h-44">
<Card.Title>Legal</Card.Title>

<Card.Content.Link
href="/docs/terms-and-conditions"
target="_blank"
>
Terms & conditions
<Card.Arrow />
</Card.Content.Link>
</Card.Content>
</Card>
</div>
</main>
<Card.Content>
<Card.Content.Link
href="/docs/privacy-policy"
target="_blank"
>
Privacy policy
<Card.Arrow />
</Card.Content.Link>

<Card.Content.Link
href="/docs/terms-and-conditions"
target="_blank"
>
Terms & conditions
<Card.Arrow />
</Card.Content.Link>
</Card.Content>
</Card>
</div>
</main>
</div>
);
};

Expand Down
27 changes: 27 additions & 0 deletions apps/web/src/components/AppearingText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { motion } from "framer-motion";

type Props = {
text: string;
};

export const AppearingText = (props: Props) => {
const { text } = props;

return (
<>
{text.split("").map((letter, index) => (
<motion.span
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
duration: 0.01,
delay: index / 100,
}}
key={index}
>
{letter}
</motion.span>
))}
</>
);
};
2 changes: 1 addition & 1 deletion apps/web/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const Card = (props: Props) => {

return (
<div
className={`rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-50 ${className}`}
className={`rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-slate-300 dark:hover:border-slate-700 hover:bg-slate-50 dark:hover:bg-neutral-950 ${className}`}
{...rest}
>
{children}
Expand Down
Loading

1 comment on commit b8e8e37

@vercel
Copy link

@vercel vercel bot commented on b8e8e37 Nov 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.