Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions frontend/src/components/info-point.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useEffect, useState } from "react";
import { useState } from "react";

import { CircleQuestionMarkIcon } from "lucide-react";

import { FloatingDrawer } from "@/features/drawer";
import Tooltip, { TooltipSide } from "@/features/system-feedback/tooltip/base";
import usePointerType from "@/lib/hooks/use-pointer-type";

type InfoPointProps = {
/**
Expand Down Expand Up @@ -44,21 +45,13 @@ export default function InfoPoint({
className,
}: InfoPointProps) {
const [drawerOpen, setDrawerOpen] = useState(false);
const [isTouchDevice, setIsTouchDevice] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia("(pointer: coarse)");
setIsTouchDevice(mediaQuery.matches);

const listener = (e: MediaQueryListEvent) => setIsTouchDevice(e.matches);
mediaQuery.addEventListener("change", listener);
return () => mediaQuery.removeEventListener("change", listener);
}, []);
const pointerType = usePointerType();

return (
<>
<Tooltip side={tooltipSide} content={tooltipContent}>
<button
onClick={() => setDrawerOpen(isTouchDevice)}
onClick={() => setDrawerOpen(pointerType === "coarse")}
aria-label={description}
>
<CircleQuestionMarkIcon className={className} />
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/features/event/results/attendees/panel-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CheckIcon, DoorOpenIcon, EraserIcon, Undo2Icon } from "lucide-react";

import ActionButton from "@/features/button/components/action";
import { useResultsContext } from "@/features/event/results/context";
import usePointerType from "@/lib/hooks/use-pointer-type";
import { cn } from "@/lib/utils/classname";

type PanelHeaderProps = {
Expand Down Expand Up @@ -47,6 +48,8 @@ export default function PanelHeader({
currentUser &&
participants.some((p) => p.display_name === currentUser);

const pointerType = usePointerType();

const formatHoveredSlot = () => {
const date = new Date(hoveredSlot!);

Expand Down Expand Up @@ -125,9 +128,13 @@ export default function PanelHeader({
{gridNumParticipants > 0 && (
<span className="text-sm opacity-75">
{isRemoving
? `Select to remove`
? pointerType === "coarse"
? "Tap to remove"
: "Click to remove"
: hoveredSlot === null
? "Hover grid for availability"
? pointerType === "coarse"
? "Tap grid for availability"
: "Hover grid for availability"
: formatHoveredSlot()}
</span>
)}
Expand Down
24 changes: 24 additions & 0 deletions frontend/src/lib/hooks/use-pointer-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use client";

import { useEffect, useState } from "react";

type PointerType = "coarse" | "fine";

export default function usePointerType() {
/**
* This initial null state is used to give the option to render a fallback/placeholder
* before the actual pointer type is determined.
*/
const [pointerType, setPointerType] = useState<PointerType | null>(null);
useEffect(() => {
const mediaQuery = window.matchMedia("(pointer: coarse)");
setPointerType(mediaQuery.matches ? "coarse" : "fine");

const listener = (e: MediaQueryListEvent) =>
setPointerType(e.matches ? "coarse" : "fine");
mediaQuery.addEventListener("change", listener);
return () => mediaQuery.removeEventListener("change", listener);
Comment thread
jzgom067 marked this conversation as resolved.
}, []);

return pointerType;
Comment thread
jzgom067 marked this conversation as resolved.
}
Loading