Skip to content

Commit

Permalink
Finish frontpage and almost finish header
Browse files Browse the repository at this point in the history
  • Loading branch information
Ackuq committed Sep 20, 2023
1 parent 160b371 commit 445f6c1
Show file tree
Hide file tree
Showing 13 changed files with 257 additions and 51 deletions.
13 changes: 13 additions & 0 deletions apps/web/app/global.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
/* For Webkit-based browsers (Chrome, Safari and Opera) */
.scrollbar-hide::-webkit-scrollbar {
display: none;
}

/* For IE, Edge and Firefox */
.scrollbar-hide {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
}
2 changes: 1 addition & 1 deletion apps/web/app/head.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function Head() {
<meta property="og:image" content="/static/images/partiguiden_logo.png" />
<meta
name="theme-color"
content="#1e293b"
content="#f8fafc"
media="(prefers-color-scheme: light)"
/>
<meta
Expand Down
32 changes: 0 additions & 32 deletions apps/web/app/header.tsx

This file was deleted.

6 changes: 3 additions & 3 deletions apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Roboto } from "next/font/google";
import type { PropsWithChildren } from "react";
import Head from "./head";
import Footer from "./footer";
import Header from "./header";
import Header from "@components/header/header";
import { ThemeProvider } from "@components/providers/theme-provider";

const roboto = Roboto({
Expand All @@ -15,10 +15,10 @@ const roboto = Roboto({

export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="sv">
<html lang="sv" suppressHydrationWarning>
<Head />
<body
className={`${roboto.className} bg-background-light dark:bg-background-dark text-font-light dark:text-font-dark flex min-h-screen flex-col shadow-2xl`}
className={`${roboto.className} bg-background-light dark:bg-background-dark text-font-light dark:text-font-dark flex min-h-screen flex-col shadow-sm`}
>
<ThemeProvider attribute="class">
<Header />
Expand Down
9 changes: 5 additions & 4 deletions apps/web/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const metadata = {

function PageTitleContainer() {
return (
<h2 className="bg-primary-elevated-light dark:bg-primary-elevated-dark mb-4 py-6 text-center text-3xl leading-10 text-white shadow-lg">
<h2 className="bg-primary-elevated-light dark:bg-primary-elevated-dark mb-4 py-6 text-center text-xl font-light leading-10 text-white shadow-sm sm:text-3xl">
Hur vill Sveriges partier förbättra
<br />
<Typed
Expand All @@ -24,6 +24,7 @@ function PageTitleContainer() {
);
}

// TODO: Fetch this from google
const featured = [
{ id: "ekonomi-och-skatter", name: "Ekonomi och Skatter" },
{ id: "lag-och-ratt", name: "Lag och rätt" },
Expand All @@ -37,7 +38,7 @@ export default function IndexPage() {
<PageTitleContainer />
<div className="container grid gap-4">
<BaseCard className="w-full">
<h3 className="pb-4 text-center text-3xl">
<h3 className="pb-4 text-center text-2xl sm:text-3xl">
Vilket parti ska man rösta på?
</h3>
<p>
Expand All @@ -47,15 +48,15 @@ export default function IndexPage() {
</p>
</BaseCard>
<BaseCard>
<h3 className="pb-4 text-center text-3xl">
<h3 className="pb-4 text-center text-2xl sm:text-3xl">
Mest besökta ämnen de senaste 30 dagarna
</h3>
<div className="grid grid-cols-2 gap-6 text-center">
{featured.map((subject) => (
<Link
key={subject.id}
href={`/standpoints/${subject.id}`}
className="bg-background-elevated-light-200 dark:bg-background-elevated-dark-200 rounded py-3 shadow-lg transition-opacity hover:opacity-70"
className="bg-background-elevated-light dark:bg-background-elevated-dark-200 rounded py-3 shadow-md transition-opacity hover:opacity-70"
>
{subject.name}
</Link>
Expand Down
6 changes: 5 additions & 1 deletion apps/web/components/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ type BaseButtonProps = React.PropsWithChildren<
React.ButtonHTMLAttributes<HTMLButtonElement>
>;

export function BaseButton({ children, className, ...props }: BaseButtonProps) {
export function BaseButton({
children,
className = "",
...props
}: BaseButtonProps) {
return (
<button className={`hover:opacity-75 ${className}`} {...props}>
{children}
Expand Down
8 changes: 6 additions & 2 deletions apps/web/components/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ type BaseCardProps = React.PropsWithChildren<
React.HTMLAttributes<HTMLDivElement>
>;

export function BaseCard({ children, className, ...props }: BaseCardProps) {
export function BaseCard({
children,
className = "",
...props
}: BaseCardProps) {
return (
<div
className={`bg-background-elevated-light dark:bg-background-elevated-dark rounded shadow-lg ${className}`}
className={`dark:bg-background-elevated-dark rounded bg-white shadow-md ${className}`}
{...props}
>
<div className="px-4 py-6">{children}</div>
Expand Down
26 changes: 26 additions & 0 deletions apps/web/components/header/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ThemeToggle from "@components/theme-toggle";
import Link from "next/link";
import TabNavigation from "./tab-navigation";

function MainLogo() {
return (
<Link href="/" className="text-font-dark text-3xl font-medium">
Partiguiden
</Link>
);
}

export default function Header() {
return (
<>
<div className="bg-primary-elevated-light dark:bg-background-elevated-dark absolute h-14 w-full sm:h-24"></div>
<header className="bg-primary-elevated-light/75 text-font-dark dark:bg-background-elevated-dark/75 sticky top-0 flex h-14 flex-col shadow-md backdrop-blur-md sm:h-24">
<div className="container flex h-full items-center justify-between">
<MainLogo />
<ThemeToggle />
</div>
<TabNavigation />
</header>
</>
);
}
99 changes: 99 additions & 0 deletions apps/web/components/header/tab-navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"use client";

import { mainNavigation } from "@lib/navigation";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useCallback, useLayoutEffect, useRef, useState } from "react";
import { ArrowRightIcon, ArrowLeftIcon } from "@heroicons/react/24/solid";

const SCROLL_STEP = 300;

export default function TabNavigation() {
const pathname = usePathname();
const [showLeftButton, setShowLeftButton] = useState(false);
const [showRightButton, setShowRightButton] = useState(false);
const navRef = useRef<HTMLElement>(null);

const onScroll = useCallback<React.UIEventHandler<HTMLElement>>((event) => {
if (event.currentTarget.scrollLeft > 0) {
setShowLeftButton(true);
} else if (event.currentTarget.scrollLeft <= 0) {
setShowLeftButton(false);
}

if (
event.currentTarget.scrollWidth - event.currentTarget.scrollLeft <=
event.currentTarget.clientWidth
) {
setShowRightButton(false);
} else {
setShowRightButton(true);
}
}, []);

const handleScrollRight = useCallback<
React.MouseEventHandler<HTMLElement>
>(() => {
navRef.current?.scrollBy({ left: SCROLL_STEP });
}, []);

const handleScrollLeft = useCallback<
React.MouseEventHandler<HTMLElement>
>(() => {
navRef.current?.scrollBy({ left: -SCROLL_STEP });
}, []);

useLayoutEffect(() => {
function resizeHandler() {
if (navRef.current?.clientWidth === navRef.current?.scrollWidth) {
setShowRightButton(false);
} else if (
navRef.current &&
navRef.current?.clientWidth < navRef.current?.scrollWidth
) {
setShowRightButton(true);
}
}

window.addEventListener("resize", resizeHandler);
resizeHandler();
return () => {
window.removeEventListener("resize", resizeHandler);
};
}, []);

return (
<div className="hidden flex-1 items-end sm:flex">
{showLeftButton ? (
<button className="h-14 w-20" onClick={handleScrollLeft}>
<ArrowLeftIcon className="m-auto h-6 w-6" />
</button>
) : (
<div className="h-14 w-20" />
)}
<nav
className="scrollbar-hide flex gap-3 overflow-scroll scroll-smooth text-center"
ref={navRef}
onScroll={onScroll}
>
{mainNavigation.map(({ href, title }) => (
<Link
key={href}
href={href}
aria-current={href === pathname && "page"}
className="aria-current-page:border-b-2 min-w-tab-link border-primary-light dark:border-primary-elevated-light flex-shrink-0 whitespace-nowrap p-4 text-sm uppercase hover:opacity-80"
>
{title}
</Link>
))}
</nav>
{showRightButton ? (
<button className="h-14 w-20" onClick={handleScrollRight}>
<ArrowRightIcon className="m-auto h-6 w-6" />
</button>
) : (
<div className="h-14 w-20" />
)}
</div>
);
}
16 changes: 13 additions & 3 deletions apps/web/components/theme-toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
"use client";

import { useTheme } from "next-themes";
import { SunIcon, MoonIcon } from "@heroicons/react/24/solid";
import { MoonIcon, SunIcon } from "@heroicons/react/24/solid";
import { useEffect, useState } from "react";

export default function ThemeToggle() {
const [mounted, setMounted] = useState(false);
const { setTheme, theme } = useTheme();

useEffect(() => {
setMounted(true);
}, []);

if (!mounted) {
return null;
}

return (
<button
className="hover:cursor-pointer"
Expand All @@ -14,9 +24,9 @@ export default function ThemeToggle() {
}}
>
{theme === "light" ? (
<MoonIcon className="h-6 w-6" />
<MoonIcon className="h-8 w-8" />
) : (
<SunIcon className="h-6 w-6" />
<SunIcon className="h-8 w-8" />
)}
</button>
);
Expand Down
79 changes: 79 additions & 0 deletions apps/web/lib/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
HomeIcon,
PencilSquareIcon,
UserCircleIcon,
ChartBarIcon,
InformationCircleIcon,
DocumentCheckIcon,
ChatBubbleLeftRightIcon,
ScaleIcon,
} from "@heroicons/react/24/solid";

export const routes = {
index: "/",
cookiePolicy: "/cookie-policy",
aboutUs: "/about-us",
polls: "/polls",
votes: "/vote",
vote: "/vote/[id]/[bet]",
decisions: "/decisions",
standpoints: "/standpoints",
standpoint: "/standpoints/[id]",
party: "/party/[party]",
members: "/member",
member: "/member/[id]",
memberStatsYear: "/member-stats/year",
memberStatsPeriod: "/member-stats/period",
document: "/document/[id]",
debates: "/debate",
debate: "/debate/[id]",
};

export const getVoteHref = (id: string, bet: number): string =>
`/vote/${id}/${bet}`;

export const getStandpointHref = (id: number): string => `/standpoints/${id}`;

export const getPartyHref = (party: string): string => `/party/${party}`;

export const getMemberHref = (id: string): string => `/member/${id}`;

export const getDocumentHref = (id: string): string => `/document/${id}`;

export const getDebateHref = (id: string): string => `/debate/${id}`;

export const mainNavigation = [
{ href: routes.index, title: "Hem", Icon: HomeIcon },
{
href: routes.standpoints,
title: "Partiernas Ståndpunkter",
Icon: PencilSquareIcon,
},
// {
// href: routes.party,
// title: "Partierna",
// Icon: UserGroupIcon,
// },
{ href: routes.decisions, title: "Riksdagsbeslut", Icon: DocumentCheckIcon },
{
href: routes.votes,
title: "Voteringar",
Icon: ScaleIcon,
},
{
href: routes.debates,
title: "Debatter",
Icon: ChatBubbleLeftRightIcon,
},
{
href: routes.members,
title: "Ledamöter",
Icon: UserCircleIcon,
},
{
href: routes.polls,
title: "Opinionsundersökningar",
Icon: ChartBarIcon,
},
{ href: routes.aboutUs, title: "Om oss", Icon: InformationCircleIcon },
];
Loading

0 comments on commit 445f6c1

Please sign in to comment.