feat(waybar): tooltips
This commit is contained in:
@@ -22,11 +22,11 @@ const AppRoot = () => {
|
||||
<main className="h-screen w-screen overflow-hidden bg-[url(/wallpaper.jpg)] bg-cover">
|
||||
{loggedIn ? (
|
||||
<div className="h-full flex-col">
|
||||
<div className="px-2 py-2">
|
||||
<div className="relative z-10 px-2 py-2">
|
||||
<Waybar />
|
||||
</div>
|
||||
|
||||
<div className="flex h-[calc(100%-50px)] w-full flex-col">
|
||||
<div className="relative flex h-[calc(100%-50px)] w-full flex-col">
|
||||
<Kitty className="w-full flex-1 pb-1 pl-2 pr-2 pt-1">
|
||||
<Nvim />
|
||||
</Kitty>
|
||||
|
||||
@@ -36,7 +36,7 @@ export const Music = () => {
|
||||
if (!audio.current) return;
|
||||
|
||||
setMetadata(m);
|
||||
audio.current.volume = 0.01;
|
||||
audio.current.volume = 0.5;
|
||||
});
|
||||
}, [metadata]);
|
||||
|
||||
|
||||
@@ -1,19 +1,57 @@
|
||||
import { type ReactNode } from "react";
|
||||
import { useState, type ReactNode, type MouseEvent, useRef } from "react";
|
||||
import { cn } from "~/utils/react";
|
||||
|
||||
export const WaybarWidget = (props: {
|
||||
className?: string;
|
||||
tooltip?: string;
|
||||
tooltip?: ReactNode;
|
||||
interactable?: boolean;
|
||||
children: ReactNode | Array<ReactNode>;
|
||||
}) => (
|
||||
children: ReactNode;
|
||||
}) => {
|
||||
const [tooltipPosition, setTooltipPosition] = useState<{
|
||||
x: number;
|
||||
y: number;
|
||||
}>();
|
||||
const [tooltipVisible, setTooltipVisible] = useState(false);
|
||||
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
setTooltipVisible(true);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
const handleMouveMove = (e: MouseEvent) => {
|
||||
if (!tooltipVisible) {
|
||||
setTooltipPosition({ x: e.clientX, y: e.clientY });
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
clearTimeout(timeoutRef.current);
|
||||
timeoutRef.current = undefined;
|
||||
setTooltipVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"py-[6.5px] font-bold text-[#2b2b2c]",
|
||||
"relative py-[6.5px] font-bold text-[#2b2b2c] opacity-90",
|
||||
props.className,
|
||||
props.interactable && "cursor-pointer",
|
||||
)}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseMove={handleMouveMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
{props.children}
|
||||
{props.tooltip && tooltipPosition && tooltipVisible && (
|
||||
<div
|
||||
className="fixed z-20 -translate-x-1/2 whitespace-pre-line rounded-[10px] border-2 border-[#11111b] bg-[#e7e7ec] px-3 py-3 font-extrabold text-[#2b2b2c]"
|
||||
style={{ top: tooltipPosition.y + 20, left: tooltipPosition.x }}
|
||||
>
|
||||
{props.tooltip}
|
||||
</div>
|
||||
);
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,11 +7,10 @@ export const WaybarWidgetGroup = (props: {
|
||||
}) => (
|
||||
<div
|
||||
className={cn(
|
||||
`flex flex-row justify-between rounded-[10px] bg-[#e6e7ec] opacity-80`,
|
||||
`flex flex-row justify-between rounded-[10px] bg-[#e6e7ec] bg-opacity-80`,
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
// gap-5 px-3 py-[6.5px]
|
||||
|
||||
@@ -19,8 +19,26 @@ export const WaybarBatteryWidget = (props: { frequency: number }) => {
|
||||
return () => clearInterval(interval);
|
||||
});
|
||||
|
||||
const tooltip =
|
||||
battery === 100
|
||||
? "Full"
|
||||
: battery >= 70
|
||||
? "Almost full"
|
||||
: battery >= 50
|
||||
? "Halfway down, but still doing great. I wonder what happens if the battery reaches 0"
|
||||
: battery >= 25
|
||||
? "Uh maybe you should consider charging me ?"
|
||||
: battery >= 15
|
||||
? "It's really reaching low level now"
|
||||
: battery >= 5
|
||||
? "Are you ignoring my messages ??"
|
||||
: "I warned you";
|
||||
|
||||
return (
|
||||
<WaybarWidget className="pl-[0.625rem] pr-3 text-[#1d7715]">
|
||||
<WaybarWidget
|
||||
className="pl-[0.625rem] pr-3 text-[#1d7715]"
|
||||
tooltip={tooltip}
|
||||
>
|
||||
{lerpIcon(ICONS, battery, 100)} {battery}%
|
||||
</WaybarWidget>
|
||||
);
|
||||
|
||||
@@ -16,8 +16,23 @@ export const WaybarBrightnessWidget = () => {
|
||||
setBrightness(newBrightness);
|
||||
};
|
||||
|
||||
const tooltip =
|
||||
brightness === 100
|
||||
? "Full"
|
||||
: brightness >= 70
|
||||
? "Almost full"
|
||||
: brightness >= 50
|
||||
? "Halfway down, but still doing great. I wonder what happens if the brightness reaches 0"
|
||||
: brightness >= 25
|
||||
? "Uh maybe you should consider charging me ?"
|
||||
: brightness >= 15
|
||||
? "It's really reaching low level now"
|
||||
: brightness >= 5
|
||||
? "Are you ignoring my messages ??"
|
||||
: "I warned you";
|
||||
|
||||
return (
|
||||
<WaybarWidget className="pl-3 pr-[0.625rem]">
|
||||
<WaybarWidget className="pl-3 pr-[0.625rem]" tooltip={tooltip}>
|
||||
<span onWheel={handleScroll}>
|
||||
{lerpIcon(ICONS, brightness, 100)} {brightness}%
|
||||
</span>
|
||||
|
||||
@@ -1,31 +1,51 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { WaybarWidget } from "../WaybarWidget";
|
||||
|
||||
// 1 is really active, but often changes, 19-30%
|
||||
// 2 are middly active, 8-11%
|
||||
// other cores are low, 1-7%
|
||||
import { clamp, randomMinMax } from "~/utils/math";
|
||||
|
||||
export const WaybarCPUWidget = (props: {
|
||||
cores: number;
|
||||
min: number;
|
||||
max: number;
|
||||
variation: number;
|
||||
frequency: number;
|
||||
}) => {
|
||||
const [usage, setUsage] = useState(new Array<number>(props.cores).fill(0));
|
||||
const [usage, setUsage] = useState(
|
||||
new Array<number>(props.cores)
|
||||
.fill(0)
|
||||
.map((_) => randomMinMax(props.min, props.max)),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
usage[0] += 1;
|
||||
const variation = randomMinMax(-props.variation, props.variation + 1);
|
||||
const index = randomMinMax(0, usage.length);
|
||||
usage[index] = clamp(usage[index] + variation, props.min, props.max);
|
||||
|
||||
setUsage([...usage]);
|
||||
}, props.frequency);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [usage, props.frequency]);
|
||||
}, [usage, props.variation, props.min, props.max, props.frequency]);
|
||||
|
||||
const totalUsage = Math.round(
|
||||
usage.reduce((acc, v) => acc + v, 0) / usage.length,
|
||||
);
|
||||
|
||||
return (
|
||||
<WaybarWidget className="pl-3 pr-[0.625rem]"> {totalUsage}%</WaybarWidget>
|
||||
<WaybarWidget
|
||||
className="pl-3 pr-[0.625rem]"
|
||||
tooltip={
|
||||
<ul>
|
||||
<li>Total: {totalUsage}%</li>
|
||||
{usage.map((value, i) => (
|
||||
<li>
|
||||
Core{i}: {value}%
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
{totalUsage}%
|
||||
</WaybarWidget>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,5 +12,14 @@ export const WaybarDiskWidget = (props: {
|
||||
props.current + randomMinMax(-props.variation, props.variation + 1);
|
||||
const usage = Math.round((value / props.capacity) * 100);
|
||||
|
||||
return <WaybarWidget className="pl-[0.625rem] pr-3"> {usage}%</WaybarWidget>;
|
||||
return (
|
||||
<WaybarWidget
|
||||
className="pl-[0.625rem] pr-3"
|
||||
tooltip={`SSD - ${value.toFixed(1)}GB used out of ${
|
||||
props.capacity
|
||||
}GiB on / (${usage}%)`}
|
||||
>
|
||||
{usage}%
|
||||
</WaybarWidget>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,8 +19,19 @@ export const WaybarMicrophoneWidget = () => {
|
||||
|
||||
const icon = muted ? "" : "";
|
||||
|
||||
const tooltip =
|
||||
volume === 0 || muted
|
||||
? "Don't worry I'm not listening to you"
|
||||
: volume === 100
|
||||
? "Broadcasting loud and clear!"
|
||||
: volume >= 50
|
||||
? "Your voice sounds really great!"
|
||||
: volume >= 20
|
||||
? "I can still hear you, just a bit quieter"
|
||||
: "I can barely hear you anymore :(";
|
||||
|
||||
return (
|
||||
<WaybarWidget className="pl-[0.625rem] pr-3" interactable>
|
||||
<WaybarWidget className="pl-[0.625rem] pr-3" interactable tooltip={tooltip}>
|
||||
<span
|
||||
className="text-[#ad6bfd]"
|
||||
onWheel={handleWheel}
|
||||
|
||||
@@ -24,7 +24,16 @@ export const WaybarRAMWidget = (props: {
|
||||
return () => clearInterval(interval);
|
||||
});
|
||||
|
||||
const used = (usage / 100) * props.capacity;
|
||||
|
||||
// TODO: tooltip
|
||||
// Memory - (capacity * usage).1f GB used
|
||||
return <WaybarWidget className="px-[0.625rem]"> {usage}%</WaybarWidget>;
|
||||
return (
|
||||
<WaybarWidget
|
||||
className="px-[0.625rem]"
|
||||
tooltip={`Memory - ${used.toFixed(1)}GB used`}
|
||||
>
|
||||
{usage}%
|
||||
</WaybarWidget>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,7 +22,10 @@ export const WaybarTemperatureWidget = (props: {
|
||||
});
|
||||
|
||||
return (
|
||||
<WaybarWidget className="pl-3 pr-[0.625rem]">
|
||||
<WaybarWidget
|
||||
className="pl-3 pr-[0.625rem]"
|
||||
tooltip="All good until I start playing btd6"
|
||||
>
|
||||
{temperature}°C
|
||||
</WaybarWidget>
|
||||
);
|
||||
|
||||
@@ -23,8 +23,17 @@ export const WaybarVolumeWidget = () => {
|
||||
|
||||
const icon = muted ? "" : lerpIcon(ICONS, volume, 100);
|
||||
|
||||
const toolip =
|
||||
volume === 0 || muted
|
||||
? "You don't like the music? :("
|
||||
: volume === 100
|
||||
? "Always maximum volume when it's Hysta"
|
||||
: volume >= 50
|
||||
? "Turning up the vibes !"
|
||||
: "Enjoying music at a moderate level";
|
||||
|
||||
return (
|
||||
<WaybarWidget className="px-[0.625rem]" interactable>
|
||||
<WaybarWidget className="px-[0.625rem]" interactable tooltip={toolip}>
|
||||
<span
|
||||
className="text-[#407cdd]"
|
||||
onWheel={handleWheel}
|
||||
|
||||
@@ -26,7 +26,13 @@ export const Waybar = () => {
|
||||
</WaybarWidgetGroup>
|
||||
|
||||
<WaybarWidgetGroup>
|
||||
<WaybarCPUWidget variation={2} frequency={1000} cores={10} />
|
||||
<WaybarCPUWidget
|
||||
variation={1}
|
||||
frequency={1250}
|
||||
cores={10}
|
||||
min={8}
|
||||
max={16}
|
||||
/>
|
||||
<WaybarRAMWidget
|
||||
variation={1}
|
||||
frequency={3000}
|
||||
|
||||
Reference in New Issue
Block a user