mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
improved tooltips
This commit is contained in:
@@ -4,18 +4,20 @@ courses:
|
|||||||
- path: ./1425/2025-fall-alex/modules/
|
- path: ./1425/2025-fall-alex/modules/
|
||||||
name: "1425"
|
name: "1425"
|
||||||
- path: ./4850_AdvancedFE/2026-spring-alex/modules
|
- path: ./4850_AdvancedFE/2026-spring-alex/modules
|
||||||
name: Adv Frontend Spring
|
name: Adv Frontend
|
||||||
- path: ./1400/2026_spring_alex/modules
|
- path: ./1400/2026_spring_alex/modules
|
||||||
name: "1400"
|
name: "1400"
|
||||||
- path: ./1405/2026_spring_alex
|
- path: ./1405/2026_spring_alex
|
||||||
name: "1405"
|
name: "1405"
|
||||||
- path: ./1810/2026-spring-alex/modules
|
|
||||||
name: Web Intro Spring
|
|
||||||
- path: ./3840_Telemetry/2026_spring_alex
|
- path: ./3840_Telemetry/2026_spring_alex
|
||||||
name: Telem and Ops New
|
name: Telem and Ops
|
||||||
- path: ./4620_Distributed/2026-spring-alex/modules
|
- path: ./4620_Distributed/2026-spring-alex/modules
|
||||||
name: Distributed
|
name: Distributed
|
||||||
- path: ./4620_Distributed/2025Spring/modules/
|
- path: ./4620_Distributed/2025Spring/modules/
|
||||||
name: distributed-old
|
name: distributed-old
|
||||||
- path: ./3840_Telemetry/2025_spring_alex/modules/
|
- path: ./3840_Telemetry/2025_spring_alex/modules/
|
||||||
name: telemetry-old
|
name: telemetry-old
|
||||||
|
- path: ./4850_AdvancedFE/2025-fall-alex/modules/
|
||||||
|
name: adv-frontend-old
|
||||||
|
- path: ./1810/2026-spring-alex/modules/
|
||||||
|
name: Web Intro
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { getLectureForDay } from "@/features/local/utils/lectureUtils";
|
|||||||
import { useLecturesSuspenseQuery } from "@/features/local/lectures/lectureHooks";
|
import { useLecturesSuspenseQuery } from "@/features/local/lectures/lectureHooks";
|
||||||
import ClientOnly from "@/components/ClientOnly";
|
import ClientOnly from "@/components/ClientOnly";
|
||||||
import { Tooltip } from "@/components/Tooltip";
|
import { Tooltip } from "@/components/Tooltip";
|
||||||
import { useRef, useState } from "react";
|
import { useTooltip } from "@/components/useTooltip";
|
||||||
|
|
||||||
export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
|
export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
|
||||||
const { courseName } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
@@ -17,8 +17,7 @@ export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
|
|||||||
const { setIsDragging } = useDragStyleContext();
|
const { setIsDragging } = useDragStyleContext();
|
||||||
const todaysLecture = getLectureForDay(weeks, dayAsDate);
|
const todaysLecture = getLectureForDay(weeks, dayAsDate);
|
||||||
const modal = useModal();
|
const modal = useModal();
|
||||||
const linkRef = useRef<HTMLAnchorElement>(null);
|
const { visible, targetRef, showTooltip, hideTooltip } = useTooltip();
|
||||||
const [tooltipVisible, setTooltipVisible] = useState(false);
|
|
||||||
|
|
||||||
const lectureName = todaysLecture && (todaysLecture.name || "lecture");
|
const lectureName = todaysLecture && (todaysLecture.name || "lecture");
|
||||||
|
|
||||||
@@ -44,9 +43,9 @@ export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
|
|||||||
setIsDragging(true);
|
setIsDragging(true);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
ref={linkRef}
|
ref={targetRef}
|
||||||
onMouseEnter={() => setTooltipVisible(true)}
|
onMouseEnter={showTooltip}
|
||||||
onMouseLeave={() => setTooltipVisible(false)}
|
onMouseLeave={hideTooltip}
|
||||||
>
|
>
|
||||||
{dayAsDate.getDate()} {lectureName}
|
{dayAsDate.getDate()} {lectureName}
|
||||||
</Link>
|
</Link>
|
||||||
@@ -65,8 +64,8 @@ export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
targetRef={linkRef}
|
targetRef={targetRef}
|
||||||
visible={tooltipVisible}
|
visible={visible}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
|
|||||||
@@ -22,6 +22,16 @@ export const BreadCrumbs = () => {
|
|||||||
? decodeURIComponent(pathSegments[3])
|
? decodeURIComponent(pathSegments[3])
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
const lectureDateOnly = lectureDate
|
||||||
|
? (() => {
|
||||||
|
const dateStr = lectureDate.split(" ")[0];
|
||||||
|
const date = new Date(dateStr);
|
||||||
|
const month = date.toLocaleDateString("en-US", { month: "short" });
|
||||||
|
const day = date.getDate();
|
||||||
|
return `${month} ${day}`;
|
||||||
|
})()
|
||||||
|
: null;
|
||||||
|
|
||||||
const sharedBackgroundClassNames = `
|
const sharedBackgroundClassNames = `
|
||||||
group
|
group
|
||||||
hover:bg-blue-900/30
|
hover:bg-blue-900/30
|
||||||
@@ -86,7 +96,7 @@ export const BreadCrumbs = () => {
|
|||||||
shallow={true}
|
shallow={true}
|
||||||
className={sharedLinkClassNames}
|
className={sharedLinkClassNames}
|
||||||
>
|
>
|
||||||
{lectureDate}
|
{lectureDateOnly}
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ export const Tooltip: React.FC<{
|
|||||||
" absolute -translate-x-1/2 " +
|
" absolute -translate-x-1/2 " +
|
||||||
" bg-gray-900 text-slate-200 text-sm " +
|
" bg-gray-900 text-slate-200 text-sm " +
|
||||||
" rounded-md py-1 px-2 " +
|
" rounded-md py-1 px-2 " +
|
||||||
" transition-all duration-400 " +
|
" transition-opacity duration-150 " +
|
||||||
" border border-slate-700 shadow-[0px_0px_10px_5px] shadow-slate-500/20 " +
|
" border border-slate-700 shadow-[0px_0px_10px_5px] shadow-slate-500/20 " +
|
||||||
" max-w-sm max-h-64 overflow-hidden " +
|
" max-w-sm max-h-64 overflow-hidden " +
|
||||||
(visible ? " " : " hidden -z-50 ")
|
(visible ? " opacity-100 " : " opacity-0 pointer-events-none ")
|
||||||
}
|
}
|
||||||
role="tooltip"
|
role="tooltip"
|
||||||
>
|
>
|
||||||
|
|||||||
28
src/components/useTooltip.ts
Normal file
28
src/components/useTooltip.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { useState, useRef, useCallback } from "react";
|
||||||
|
|
||||||
|
export const useTooltip = (delayMs: number = 150) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
const targetRef = useRef<HTMLAnchorElement>(null);
|
||||||
|
|
||||||
|
const showTooltip = useCallback(() => {
|
||||||
|
timeoutRef.current = setTimeout(() => {
|
||||||
|
setVisible(true);
|
||||||
|
}, delayMs);
|
||||||
|
}, [delayMs]);
|
||||||
|
|
||||||
|
const hideTooltip = useCallback(() => {
|
||||||
|
if (timeoutRef.current) {
|
||||||
|
clearTimeout(timeoutRef.current);
|
||||||
|
timeoutRef.current = null;
|
||||||
|
}
|
||||||
|
setVisible(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
visible,
|
||||||
|
targetRef,
|
||||||
|
showTooltip,
|
||||||
|
hideTooltip,
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user