From e0b68e829f7b7d6f1b30ae37e9d5663b727ac6ed Mon Sep 17 00:00:00 2001 From: Xevion Date: Sat, 24 Dec 2022 12:51:07 -0600 Subject: [PATCH] Ref based .active item selector, hoverable device query & usehooks-ts package --- package.json | 1 + src/components/ItemCard.tsx | 14 ++++++++++++-- src/styles/globals.scss | 4 ++-- src/utils/helpers.ts | 9 +++++++++ yarn.lock | 5 +++++ 5 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 src/utils/helpers.ts diff --git a/package.json b/package.json index 9da6afc..1fd6d68 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "react-dom": "18.2.0", "sass": "^1.56.2", "superjson": "1.9.1", + "usehooks-ts": "^2.9.1", "zod": "^3.18.0" }, "devDependencies": { diff --git a/src/components/ItemCard.tsx b/src/components/ItemCard.tsx index 51518fc..aee5ffe 100644 --- a/src/components/ItemCard.tsx +++ b/src/components/ItemCard.tsx @@ -1,6 +1,8 @@ import Image from "next/image"; import {ArrowLongRightIcon} from "@heroicons/react/24/outline"; -import React from "react"; +import React, {useRef} from "react"; +import {useOnClickOutside, useToggle} from "usehooks-ts"; +import {classNames, isHoverable} from "../utils/helpers"; type ItemCardProps = { banner: string; @@ -9,7 +11,15 @@ type ItemCardProps = { } const ItemCard = ({banner, title, description}: ItemCardProps) => { - return
+ const itemRef = useRef(null); + const [active, toggleActive, setActive] = useToggle() + + useOnClickOutside(itemRef, () => { + setActive(false); + }) + + return
{if (!isHoverable()) toggleActive();}} + ref={itemRef} className={classNames("item", active ? "active" : null)}> span { @apply transition-colors delay-300; - &:hover, &:focus-within, &:focus { + &:hover, &.active { @apply text-black bg-white; transition-delay: 0s; } diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts new file mode 100644 index 0000000..1fa978d --- /dev/null +++ b/src/utils/helpers.ts @@ -0,0 +1,9 @@ +export function classNames(...classes: (string | null | undefined)[]) { + return classes.filter(Boolean).join(" "); +} + +const hoverableQuery = window.matchMedia('(hover: hover) and (pointer: fine)'); + +export function isHoverable() { + return hoverableQuery.matches; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 69ed185..168e390 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2171,6 +2171,11 @@ use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== +usehooks-ts@^2.9.1: + version "2.9.1" + resolved "https://registry.yarnpkg.com/usehooks-ts/-/usehooks-ts-2.9.1.tgz#953d3284851ffd097432379e271ce046a8180b37" + integrity sha512-2FAuSIGHlY+apM9FVlj8/oNhd+1y+Uwv5QNkMQz1oSfdHk4PXo1qoCw9I5M7j0vpH8CSWFJwXbVPeYDjLCx9PA== + util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"