Skip to content

Commit

Permalink
feat: getToggledStyles() (#363)
Browse files Browse the repository at this point in the history
* feat: getActiveLinkStyles()

* tweaks

* tweak

* getToggledStyles

* tweak
  • Loading branch information
iuioiua authored Jul 13, 2023
1 parent 0e11bcd commit 3359d31
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 17 deletions.
26 changes: 23 additions & 3 deletions components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
// Copyright 2023 the Deno authors. All rights reserved. MIT license.
import {
ACTIVE_LINK_STYLES,
LINK_STYLES,
NAV_STYLES,
SITE_BAR_STYLES,
SITE_NAME,
} from "@/utils/constants.ts";
import { Discord, GitHub } from "./Icons.tsx";
import { getToggledStyles } from "@/utils/display.ts";

export default function Footer() {
export default function Footer(props: { url: URL }) {
return (
<footer
class={`${SITE_BAR_STYLES} flex-col md:flex-row mt-8`}
>
<p>© {SITE_NAME}</p>
<nav class={NAV_STYLES}>
<a href="/stats" class={LINK_STYLES}>Stats</a>
<a href="/blog" class={LINK_STYLES}>Blog</a>
<a
href="/stats"
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
props.url.pathname === "/stats",
)}
>
Stats
</a>
<a
href="/blog"
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
props.url.pathname === "/blog",
)}
>
Blog
</a>
<a
href="https://discord.gg/deno"
target="_blank"
Expand Down
39 changes: 35 additions & 4 deletions components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// Copyright 2023 the Deno authors. All rights reserved. MIT license.
import {
ACTIVE_LINK_STYLES,
BUTTON_STYLES,
LINK_STYLES,
NAV_STYLES,
SITE_BAR_STYLES,
SITE_NAME,
} from "@/utils/constants.ts";
import { stripe } from "@/utils/payments.ts";
import { Bell, CircleFilled } from "./Icons.tsx";
import { getToggledStyles } from "@/utils/display.ts";

export default function Header(
props: { sessionId?: string; hasNotifications: boolean },
props: { sessionId?: string; hasNotifications: boolean; url: URL },
) {
return (
<header class={SITE_BAR_STYLES}>
Expand All @@ -23,13 +26,41 @@ export default function Header(
/>
</a>
<nav class={NAV_STYLES}>
{stripe ? <a href="/pricing" class={LINK_STYLES}>Pricing</a> : null}
{stripe
? (
<a
href="/pricing"
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
props.url.pathname === "/pricing",
)}
>
Pricing
</a>
)
: null}
{props.sessionId
? <a href="/account" class={LINK_STYLES}>Account</a>
? (
<a
href="/account"
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
props.url.pathname === "/account",
)}
>
Account
</a>
)
: <a href="/signin" class={LINK_STYLES}>Sign in</a>}
<a
href="/account/notifications"
class={LINK_STYLES + " relative"}
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
props.url.pathname === "/account/notifications",
) + " relative"}
aria-label="Notifications"
>
<Bell class="w-6 h-6" />
Expand Down
3 changes: 2 additions & 1 deletion routes/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ export default function App(props: AppProps) {
<div class="dark:bg-gray-900">
<div class="flex flex-col min-h-screen mx-auto max-w-7xl w-full dark:text-white">
<Header
url={props.url}
sessionId={props.data?.sessionId}
hasNotifications={props.data?.hasNotifications}
/>
<props.Component />
<Footer />
<Footer url={props.url} />
</div>
</div>
</>
Expand Down
43 changes: 36 additions & 7 deletions routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright 2023 the Deno authors. All rights reserved. MIT license.
import type { Handlers, PageProps } from "$fresh/server.ts";
import { INPUT_STYLES } from "@/utils/constants.ts";
import { calcLastPage, calcPageNum, PAGE_LENGTH } from "@/utils/pagination.ts";
import type { State } from "./_middleware.ts";
import ItemSummary from "@/components/ItemSummary.tsx";
Expand All @@ -15,6 +14,8 @@ import {
type User,
} from "@/utils/db.ts";
import { DAY, WEEK } from "std/datetime/constants.ts";
import { getToggledStyles } from "@/utils/display.ts";
import { ACTIVE_LINK_STYLES, LINK_STYLES } from "@/utils/constants.ts";

interface HomePageData extends State {
itemsUsers: User[];
Expand Down Expand Up @@ -57,21 +58,49 @@ export const handler: Handlers<HomePageData, State> = {
},
};

function TimeSelector() {
function TimeSelector(props: { url: URL }) {
const timeAgo = props.url.searchParams.get("time-ago");
return (
<div class="flex justify-center my-4 gap-2">
<div class="flex justify-center my-4 gap-8">
{/* These links do not preserve current URL queries. E.g. if ?page=2, that'll be removed once one of these links is clicked */}
<a class={INPUT_STYLES} href="/?time-ago=week">Last Week</a>
<a class={INPUT_STYLES} href="/?time-ago=month">Last Month</a>
<a class={INPUT_STYLES} href="/?time-ago=all">All time</a>
<a
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
timeAgo === null || timeAgo === "week",
)}
href="/?time-ago=week"
>
Last Week
</a>
<a
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
timeAgo === "month",
)}
href="/?time-ago=month"
>
Last Month
</a>
<a
class={getToggledStyles(
LINK_STYLES,
ACTIVE_LINK_STYLES,
timeAgo === "all",
)}
href="/?time-ago=all"
>
All time
</a>
</div>
);
}

export default function HomePage(props: PageProps<HomePageData>) {
return (
<main class="flex-1 p-4">
<TimeSelector />
<TimeSelector url={props.url} />
{props.data.items.map((item, index) => (
<ItemSummary
item={item}
Expand Down
3 changes: 2 additions & 1 deletion utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export const SITE_BAR_STYLES = "flex justify-between p-4 gap-4";
export const NAV_STYLES =
"flex flex-wrap justify-start gap-x-8 gap-y-4 items-center justify-between h-full";
export const LINK_STYLES =
"text-gray-500 transition duration-300 hover:text-black dark:hover:text-white";
"text-gray-500 transition duration-300 hover:(text-black dark:text-white)";
export const ACTIVE_LINK_STYLES = "!text-black !dark:text-white";
25 changes: 25 additions & 0 deletions utils/display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,28 @@ export function timeAgo(time: number | Date) {
else if (minutes < 24 * 60) return pluralize(~~(minutes / 60), "hour");
else return pluralize(~~(minutes / (24 * 60)), "day");
}

/**
* Dynamically generates styles depending on whether the given condition is truthy.
* This is used to visually highlight a link if it matches the current page.
*
* @example
* ```ts
* import { getToggledStyles } from "@/utils/display.ts";
*
* // Returns "text-gray !text-black"
* const activeLinkStyles = getToggledStyles("text-gray", "!text-black", true);
*
* // Returns "text-gray"
* const inactiveLinkStyles = getToggledStyles("text-gray", "!text-black", false);
* ```
*/
export function getToggledStyles(
baseStyles: string,
toggledStyles: string,
cond: boolean,
) {
let styles = baseStyles;
if (cond) styles += " " + toggledStyles;
return styles;
}
14 changes: 13 additions & 1 deletion utils/display_test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright 2023 the Deno authors. All rights reserved. MIT license.
import { pluralize, timeAgo } from "./display.ts";
import { getToggledStyles, pluralize, timeAgo } from "./display.ts";
import { DAY, HOUR, MINUTE, SECOND } from "std/datetime/constants.ts";
import { assertEquals } from "std/testing/asserts.ts";
import { ACTIVE_LINK_STYLES, LINK_STYLES } from "@/utils/constants.ts";

Deno.test("[display] pluralize()", () => {
assertEquals(pluralize(0, "item"), "0 items");
Expand All @@ -22,3 +23,14 @@ Deno.test("[display] timeAgo()", () => {
assertEquals(timeAgo(Date.now() - DAY - HOUR * 12), "1 day");
assertEquals(timeAgo(Date.now() - DAY * 5), "5 days");
});

Deno.test("[display] getToggledStyles()", () => {
assertEquals(
getToggledStyles(LINK_STYLES, ACTIVE_LINK_STYLES, false),
LINK_STYLES,
);
assertEquals(
getToggledStyles(LINK_STYLES, ACTIVE_LINK_STYLES, true),
LINK_STYLES + " " + ACTIVE_LINK_STYLES,
);
});

0 comments on commit 3359d31

Please sign in to comment.