Skip to content

Commit

Permalink
apply focusable HOC
Browse files Browse the repository at this point in the history
  • Loading branch information
John-Paul-Larkin committed Oct 24, 2024
1 parent a29c6e4 commit 8e76cce
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 103 deletions.
23 changes: 13 additions & 10 deletions app/(editor)/create/[[...paramsArr]]/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Fragment } from "react";
import { type Session } from "next-auth";
import Logo from "@/icons/logo.svg";
import { type PostStatus, status } from "@/utils/post";
import Focusable from "@/components/Focusable/Focusable";

type EditorNavProps = {
session: Session | null;
Expand Down Expand Up @@ -83,16 +84,18 @@ const EditorNav = ({

{session && (
<>
<Link
href="/notifications"
className="focus-style relative rounded-full p-1 text-neutral-500 hover:bg-neutral-100 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-white"
>
<span className="sr-only">View notifications</span>
{hasNotifications && (
<div className="absolute right-0 top-0 h-2 w-2 rounded-full bg-pink-500" />
)}
<BellIcon className="h-5 w-5" aria-hidden="true" />
</Link>
<Focusable>
<Link
href="/notifications"
className="relative rounded-full p-1 text-neutral-500 hover:bg-neutral-100 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-white"
>
<span className="sr-only">View notifications</span>
{hasNotifications && (
<div className="absolute right-0 top-0 h-2 w-2 rounded-full bg-pink-500" />
)}
<BellIcon className="h-5 w-5" aria-hidden="true" />
</Link>
</Focusable>
<Menu as="div" className="relative ml-3">
<div>
<Menu.Button className="flex rounded-full bg-white text-sm focus:outline-none focus:ring-2 focus:ring-pink-500 focus:ring-offset-2">
Expand Down
44 changes: 23 additions & 21 deletions components/ArticleMenu/ArticleMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import copy from "copy-to-clipboard";
import { type Session } from "next-auth";
import { signIn } from "next-auth/react";
import { ReportModal } from "../ReportModal/ReportModal";
import Focusable from "../Focusable/Focusable";

interface CopyToClipboardOption {
label: string;
Expand Down Expand Up @@ -148,27 +149,28 @@ const ArticleMenu = ({
</button>
<span>{data?.likes || 0}</span>
</div>

<button
className="focus-style-rounded rounded-full p-1 hover:bg-neutral-300 dark:hover:bg-neutral-800 lg:mx-auto"
aria-label="bookmark-trigger"
onClick={() => {
if (!session) {
signIn();
}
if (data?.currentUserBookmarked)
return bookmarkPost(postId, false);
bookmarkPost(postId);
}}
>
<BookmarkIcon
className={`w-6 h-6${
data?.currentUserBookmarked
? "fill-blue-400"
: "fill-neutral-400 dark:fill-neutral-600"
}`}
/>
</button>
<Focusable rounded={true}>
<button
className="rounded-full p-1 hover:bg-neutral-300 dark:hover:bg-neutral-800 lg:mx-auto"
aria-label="bookmark-trigger"
onClick={() => {
if (!session) {
signIn();
}
if (data?.currentUserBookmarked)
return bookmarkPost(postId, false);
bookmarkPost(postId);
}}
>
<BookmarkIcon
className={`w-6 h-6${
data?.currentUserBookmarked
? "fill-blue-400"
: "fill-neutral-400 dark:fill-neutral-600"
}`}
/>
</button>
</Focusable>

<Popover className="relative ml-4">
<PopoverButton
Expand Down
47 changes: 25 additions & 22 deletions components/ArticlePreview/ArticlePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { api } from "@/server/trpc/react";
import { signIn, useSession } from "next-auth/react";
import { toast } from "sonner";
import Focusable from "../Focusable/Focusable";

type ButtonOptions = {
label: string;
Expand Down Expand Up @@ -165,29 +166,31 @@ const ArticlePreview: NextPage<Props> = ({
</Link>
<div className="flex gap-x-2">
{showBookmark && (
<button
className="focus-style-rounded rounded-full p-2 hover:bg-neutral-300 dark:hover:bg-neutral-800 lg:mx-auto"
onClick={() => {
if (!session) {
return signIn();
<Focusable rounded={true}>
<button
className="rounded-full p-2 hover:bg-neutral-300 dark:hover:bg-neutral-800 lg:mx-auto"
onClick={() => {
if (!session) {
return signIn();
}
if (bookmarked) {
return bookmarkPost(id, false);
}
bookmarkPost(id);
}}
aria-label={
bookmarked ? "Remove bookmark" : "Bookmark this post"
}
if (bookmarked) {
return bookmarkPost(id, false);
}
bookmarkPost(id);
}}
aria-label={
bookmarked ? "Remove bookmark" : "Bookmark this post"
}
>
<BookmarkIcon
className={`w-6 h-6${
bookmarked
? "fill-blue-400"
: "fill-neutral-400 dark:fill-neutral-600"
}`}
/>
</button>
>
<BookmarkIcon
className={`w-6 h-6${
bookmarked
? "fill-blue-400"
: "fill-neutral-400 dark:fill-neutral-600"
}`}
/>
</button>
</Focusable>
)}
{menuOptions && (
<Menu as="div" className="relative">
Expand Down
6 changes: 4 additions & 2 deletions components/Focusable/Focusable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import React, { cloneElement, ReactElement } from "react";

interface FocusableProps {
children: ReactElement;
rounded?: boolean;
}

const Focusable: React.FC<FocusableProps> = ({ children }) => {
const Focusable: React.FC<FocusableProps> = ({ children, rounded = false }) => {
return cloneElement(children, {
className: `${children.props.className} rounded-md focus:outline-none focus:ring-white focus-visible:ring-2 focus-visible:ring-pink-600 focus-visible:ring-offset-pink-600`,
className: `${children.props.className}
${rounded ? "rounded-full" : "rounded-md"} focus:outline-none focus:ring-white focus-visible:ring-2 focus-visible:ring-pink-600 focus-visible:ring-offset-pink-600`,
});
};

Expand Down
57 changes: 32 additions & 25 deletions components/Nav/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import AnimatedHamburger from "./AnimatedHamburger";
import Logo from "@/icons/logo.svg";
import MobileNav from "./MobileNav";
import { MobileSearch, Search } from "@/components/ui/Search";
import Focusable from "../Focusable/Focusable";

type AlgoliaConfig = {
ALGOLIA_APP_ID: string;
Expand Down Expand Up @@ -83,7 +84,7 @@ const Nav = ({
href={item.href}
target="_blank"
rel="noopener noreferrer"
className="nav-button focus-style p-4"
className="nav-button p-4"
>
{item.name}
</a>
Expand Down Expand Up @@ -135,16 +136,18 @@ const Nav = ({

{session && (
<>
<Link
to="/notifications"
className="focus-style relative flex-shrink-0 rounded-md p-2 text-neutral-500 hover:bg-neutral-200 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-900 dark:hover:text-white"
>
<span className="sr-only">View notifications</span>
{hasNotifications && (
<div className="absolute right-2 top-2 h-2 w-2 animate-pulse rounded-full bg-pink-600" />
)}
<BellIcon className="h-6 w-6" aria-hidden="true" />
</Link>
<Focusable>
<Link
to="/notifications"
className="relative flex-shrink-0 rounded-md p-2 text-neutral-500 hover:bg-neutral-200 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-900 dark:hover:text-white"
>
<span className="sr-only">View notifications</span>
{hasNotifications && (
<div className="absolute right-2 top-2 h-2 w-2 animate-pulse rounded-full bg-pink-600" />
)}
<BellIcon className="h-6 w-6" aria-hidden="true" />
</Link>
</Focusable>
<Menu as="div" className="relative ml-4">
<div>
<MenuButton className="flex rounded-full bg-black text-sm ring-offset-2 focus:outline-none focus:ring-2 focus:ring-pink-600 focus:ring-offset-2 focus:ring-offset-white">
Expand Down Expand Up @@ -204,22 +207,26 @@ const Nav = ({
<MobileSearch algoliaSearchConfig={algoliaSearchConfig} />
<ThemeToggle />
{session && (
<Link
to="/notifications"
className="focus-style relative flex-shrink-0 rounded-md p-2 text-neutral-500 hover:bg-neutral-200 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-900 dark:hover:text-white"
>
<span className="sr-only">View notifications</span>
{hasNotifications && (
<div className="absolute right-1 top-1 h-2 w-2 animate-pulse rounded-full bg-pink-500" />
)}
<BellIcon className="h-6 w-6" aria-hidden="true" />
</Link>
<Focusable>
<Link
to="/notifications"
className="relative flex-shrink-0 rounded-md p-2 text-neutral-500 hover:bg-neutral-200 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-900 dark:hover:text-white"
>
<span className="sr-only">View notifications</span>
{hasNotifications && (
<div className="absolute right-1 top-1 h-2 w-2 animate-pulse rounded-full bg-pink-500" />
)}
<BellIcon className="h-6 w-6" aria-hidden="true" />
</Link>
</Focusable>
)}
{/* Mobile menu button */}
<DisclosureButton className="nav-button focus-style group">
<span className="sr-only">Open main menu</span>
<AnimatedHamburger open={open} />
</DisclosureButton>
<Focusable>
<DisclosureButton className="nav-button group">
<span className="sr-only">Open main menu</span>
<AnimatedHamburger open={open} />
</DisclosureButton>
</Focusable>
</div>
</div>
</div>
Expand Down
25 changes: 14 additions & 11 deletions components/Theme/ThemeToggle/ThemeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import Focusable from "@/components/Focusable/Focusable";
import { MoonIcon, SunIcon } from "@heroicons/react/20/solid";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
Expand All @@ -26,17 +27,19 @@ const ThemeToggle = () => {
};

return (
<button
onClick={toggleTheme}
aria-pressed={resolvedTheme === THEME_MODES.DARK}
className="nav-button focus-style group relative flex-shrink-0 p-4 focus:ring-inset"
type="button"
title="Toggle dark mode"
>
<span className="sr-only">Toggle Dark Mode</span>
<SunIcon className="h-6 w-6 rotate-0 scale-100 text-neutral-500 group-hover:text-yellow-500 group-focus:text-yellow-500 motion-safe:transition-all dark:-rotate-90 dark:scale-0" />
<MoonIcon className="absolute left-1/2 top-1/2 h-6 w-6 -translate-x-1/2 -translate-y-1/2 rotate-90 scale-0 transform text-neutral-400 group-hover:text-white motion-safe:transition-all dark:rotate-0 dark:scale-100" />
</button>
<Focusable>
<button
onClick={toggleTheme}
aria-pressed={resolvedTheme === THEME_MODES.DARK}
className="nav-button group relative flex-shrink-0 p-4 focus:ring-inset"
type="button"
title="Toggle dark mode"
>
<span className="sr-only">Toggle Dark Mode</span>
<SunIcon className="h-6 w-6 rotate-0 scale-100 text-neutral-500 group-hover:text-yellow-500 group-focus:text-yellow-500 motion-safe:transition-all dark:-rotate-90 dark:scale-0" />
<MoonIcon className="absolute left-1/2 top-1/2 h-6 w-6 -translate-x-1/2 -translate-y-1/2 rotate-90 scale-0 transform text-neutral-400 group-hover:text-white motion-safe:transition-all dark:rotate-0 dark:scale-100" />
</button>
</Focusable>
);
};

Expand Down
19 changes: 11 additions & 8 deletions components/ui/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import clsx from "clsx";
import Image from "next/image";
import Focusable from "../Focusable/Focusable";

type Result = {
title: string;
Expand Down Expand Up @@ -540,14 +541,16 @@ export function MobileSearch({

return (
<div className="contents lg:hidden">
<button
type="button"
className="focus-style relative flex-shrink-0 rounded-md p-2 text-neutral-500 hover:bg-neutral-200 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-900 dark:hover:text-white"
aria-label="Search the site"
{...buttonProps}
>
<MagnifyingGlassIcon className="h-6 w-6 stroke-current" />
</button>
<Focusable>
<button
type="button"
className="relative flex-shrink-0 rounded-md p-2 text-neutral-500 hover:bg-neutral-200 hover:text-neutral-600 dark:text-neutral-400 dark:hover:bg-neutral-900 dark:hover:text-white"
aria-label="Search the site"
{...buttonProps}
>
<MagnifyingGlassIcon className="h-6 w-6 stroke-current" />
</button>
</Focusable>
<Suspense fallback={null}>
<SearchDialog
algoliaSearchConfig={algoliaSearchConfig}
Expand Down
4 changes: 0 additions & 4 deletions styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ body {
@apply rounded-md focus:outline-none focus:ring-white focus-visible:ring-2 focus-visible:ring-pink-600 focus-visible:ring-offset-pink-600;
}

.focus-style-rounded {
@apply rounded-full focus:outline-none focus:ring-white focus-visible:ring-2 focus-visible:ring-pink-600 focus-visible:ring-offset-pink-600;
}

.primary-button {
@apply inline-flex justify-center rounded-md bg-gradient-to-r from-orange-400 to-pink-600 px-4 py-2 font-medium text-white shadow-sm hover:from-orange-300 hover:to-pink-500 focus:outline-none focus:ring-2 focus:ring-pink-600 focus:ring-offset-2 focus-visible:ring-2 focus-visible:ring-pink-600 focus-visible:ring-offset-white disabled:border-neutral-300 disabled:from-neutral-500 disabled:to-neutral-700 disabled:text-neutral-300 disabled:hover:text-neutral-300;
}
Expand Down

0 comments on commit 8e76cce

Please sign in to comment.