Improved Sidebar styling
This commit is contained in:
parent
f88f783de9
commit
6cd95fa0e4
@ -1,124 +1,128 @@
|
|||||||
import React, { Dispatch, SetStateAction, useEffect, useRef } from "react";
|
import React, { Dispatch, SetStateAction, useEffect, useRef } from "react";
|
||||||
import { TbHexagon } from "react-icons/tb";
|
import { TbHexagon } from "react-icons/tb";
|
||||||
import GeologicalEvent from "@appTypes/Event";
|
import GeologicalEvent from "@appTypes/GeologicalEvent";
|
||||||
import getMagnitudeColor from "@utils/getMagnitudeColour";
|
import getMagnitudeColor from "@utils/getMagnitudeColour";
|
||||||
interface SidebarProps {
|
interface SidebarProps {
|
||||||
logTitle: string;
|
logTitle: string;
|
||||||
logSubtitle: string;
|
logSubtitle: string;
|
||||||
recentsTitle: string;
|
recentsTitle: string;
|
||||||
events: GeologicalEvent[];
|
events: GeologicalEvent[];
|
||||||
selectedEventId: GeologicalEvent["id"];
|
selectedEventId: GeologicalEvent["id"];
|
||||||
setSelectedEventId: Dispatch<SetStateAction<string>>;
|
setSelectedEventId: Dispatch<SetStateAction<string>>;
|
||||||
hoveredEventId: GeologicalEvent["id"];
|
hoveredEventId: GeologicalEvent["id"];
|
||||||
setHoveredEventId: Dispatch<SetStateAction<string>>;
|
setHoveredEventId: Dispatch<SetStateAction<string>>;
|
||||||
button1Name: string;
|
button1Name: string;
|
||||||
button2Name: string;
|
button2Name: string;
|
||||||
onButton2Click?: () => void;
|
onButton2Click?: () => void;
|
||||||
onButton1Click?: () => void;
|
onButton1Click?: () => void;
|
||||||
button1Disabled?: boolean;
|
button1Disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MagnitudeNumber({ magnitude }: { magnitude: number }) {
|
function MagnitudeNumber({ magnitude }: { magnitude: number }) {
|
||||||
const magnitudeStr = magnitude.toFixed(1);
|
const magnitudeStr = magnitude.toFixed(1);
|
||||||
const [whole, decimal] = magnitudeStr.split(".");
|
const [whole, decimal] = magnitudeStr.split(".");
|
||||||
return (
|
return (
|
||||||
<div className="relative" style={{ color: getMagnitudeColor(magnitude) }}>
|
<div className="relative" style={{ color: getMagnitudeColor(magnitude) }}>
|
||||||
<TbHexagon size={40} className="drop-shadow-sm" />
|
<TbHexagon size={40} className="drop-shadow-sm" />
|
||||||
<div className="absolute inset-0 flex items-center justify-center">
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
<div className="flex items-baseline font-mono font-bold tracking-tight">
|
<div className="flex items-baseline font-mono font-bold tracking-tight">
|
||||||
<span className="text-xl -mr-1">{whole}</span>
|
<span className="text-xl -mr-1">{whole}</span>
|
||||||
<span className="text-xs ml-[1.5px] -mr-[2.5px]">.</span>
|
<span className="text-xs ml-[1.5px] -mr-[2.5px]">.</span>
|
||||||
<span className="text-xs -mr-[1px]">{decimal}</span>
|
<span className="text-xs -mr-[1px]">{decimal}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Sidebar({
|
export default function Sidebar({
|
||||||
logTitle,
|
logTitle,
|
||||||
logSubtitle,
|
logSubtitle,
|
||||||
recentsTitle,
|
recentsTitle,
|
||||||
events,
|
events,
|
||||||
selectedEventId,
|
selectedEventId,
|
||||||
setSelectedEventId,
|
setSelectedEventId,
|
||||||
hoveredEventId,
|
hoveredEventId,
|
||||||
setHoveredEventId,
|
setHoveredEventId,
|
||||||
button1Name,
|
button1Name,
|
||||||
button2Name,
|
button2Name,
|
||||||
onButton2Click,
|
onButton2Click,
|
||||||
onButton1Click,
|
onButton1Click,
|
||||||
button1Disabled = false,
|
button1Disabled = false,
|
||||||
}: SidebarProps) {
|
}: SidebarProps) {
|
||||||
const eventsContainerRef = useRef<HTMLDivElement>(null);
|
const eventsContainerRef = useRef<HTMLDivElement>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedEventId && eventsContainerRef.current) {
|
if (selectedEventId && eventsContainerRef.current) {
|
||||||
const selectedEventElement = eventsContainerRef.current.querySelector(`[data-event-id="${selectedEventId}"]`);
|
const selectedEventElement = eventsContainerRef.current.querySelector(`[data-event-id="${selectedEventId}"]`);
|
||||||
if (selectedEventElement) {
|
if (selectedEventElement) {
|
||||||
selectedEventElement.scrollIntoView({
|
selectedEventElement.scrollIntoView({
|
||||||
block: "center",
|
block: "center",
|
||||||
behavior: "smooth",
|
behavior: "smooth",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedEventId]);
|
}, [selectedEventId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full w-80 bg-gradient-to-b from-neutral-100 to-neutral-50 shadow-lg">
|
<div className="flex flex-col h-full w-80 bg-gradient-to-b from-neutral-100 to-neutral-50 shadow-lg">
|
||||||
<div className="py-6 flex flex-col h-full">
|
<div className="py-6 flex flex-col h-full">
|
||||||
<div className="px-6 pb-8 border-b border-neutral-200">
|
<div className="px-6 pb-8 border-b border-neutral-200">
|
||||||
<h2 className="text-2xl font-bold text-neutral-800 mb-2">{logTitle}</h2>
|
<h2 className="text-2xl font-bold text-neutral-800 mb-2">{logTitle}</h2>
|
||||||
<p className="text-sm text-neutral-600 leading-relaxed">{logSubtitle}</p>
|
<p className="text-sm text-neutral-600 leading-relaxed">{logSubtitle}</p>
|
||||||
<button
|
<button
|
||||||
className={`mt-4 w-full py-2 px-4 rounded-lg transition-colors duration-200 font-medium
|
className={`mt-4 w-full py-2 px-4 rounded-lg transition-colors duration-200 font-medium
|
||||||
${button1Disabled
|
${
|
||||||
? "bg-gray-300 text-gray-500 cursor-not-allowed"
|
button1Disabled
|
||||||
: "bg-blue-600 hover:bg-blue-700 text-white"
|
? "bg-gray-300 text-gray-500 cursor-not-allowed"
|
||||||
}`}
|
: "bg-blue-600 hover:bg-blue-700 text-white"
|
||||||
onClick={onButton1Click}
|
}`}
|
||||||
type="button"
|
onClick={onButton1Click}
|
||||||
|
type="button"
|
||||||
tabIndex={button1Disabled ? -1 : 0}
|
tabIndex={button1Disabled ? -1 : 0}
|
||||||
aria-disabled={button1Disabled ? "true" : "false"}
|
aria-disabled={button1Disabled ? "true" : "false"}
|
||||||
>
|
>
|
||||||
{button1Name}
|
{button1Name}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="mt-4 w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg transition-colors duration-200 font-medium"
|
className="mt-4 w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg transition-colors duration-200 font-medium"
|
||||||
onClick={onButton2Click}
|
onClick={onButton2Click}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
{button2Name}
|
{button2Name}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-6 pt-6">
|
<div className="px-6 pt-6">
|
||||||
<h2 className="text-xl font-bold text-neutral-800 mb-4">{recentsTitle}</h2>
|
<h2 className="text-xl font-bold text-neutral-800 mb-4">{recentsTitle}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 px-6 overflow-y-auto" ref={eventsContainerRef}>
|
<div className="flex-1 px-6 overflow-y-auto" ref={eventsContainerRef}>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{events.map((event) => (
|
{events.map((event) => (
|
||||||
<button
|
<button
|
||||||
key={event.id}
|
key={event.id}
|
||||||
data-event-id={event.id}
|
data-event-id={event.id}
|
||||||
className={`w-full border ${hoveredEventId === event.id ? "bg-neutral-100" : "bg-white"} ${
|
className={`w-full border ${
|
||||||
selectedEventId === event.id ? "border-neutral-800" : "border-neutral-200"
|
selectedEventId === event.id
|
||||||
} rounded-lg p-4 flex items-center gap-4 hover:bg-neutral-100 transition-colors duration-150 shadow-sm text-left`}
|
? "border-neutral-500 border-2 shadow-md"
|
||||||
onClick={() => {
|
: hoveredEventId === event.id
|
||||||
setSelectedEventId((prevEventId) => (prevEventId !== event.id ? event.id : ""));
|
? "bg-neutral-100 shadow-sm"
|
||||||
}}
|
: "bg-white border-neutral-200 shadow-sm"
|
||||||
onMouseEnter={() => setHoveredEventId(event.id)}
|
} rounded-lg p-4 flex items-center gap-4 hover:bg-neutral-100 transition-colors duration-150 text-left`}
|
||||||
onMouseLeave={() => setHoveredEventId("")}
|
onClick={() => {
|
||||||
>
|
setSelectedEventId((prevEventId) => (prevEventId !== event.id ? event.id : ""));
|
||||||
<div className="flex-1">
|
}}
|
||||||
<p className="text-sm font-medium text-neutral-800 line-clamp-1">{event.title}</p>
|
onMouseEnter={() => setHoveredEventId(event.id)}
|
||||||
<p className="text-xs text-neutral-500 mt-1 line-clamp-1">{event.text2}</p>
|
onMouseLeave={() => setHoveredEventId("")}
|
||||||
</div>
|
>
|
||||||
{event.magnitude ? <MagnitudeNumber magnitude={event.magnitude} /> : <></>}
|
<div className="flex-1">
|
||||||
</button>
|
<p className="text-sm font-medium text-neutral-800 line-clamp-1">{event.title}</p>
|
||||||
))}
|
<p className="text-xs text-neutral-500 mt-1 line-clamp-1">{event.text2}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{event.magnitude ? <MagnitudeNumber magnitude={event.magnitude} /> : <></>}
|
||||||
</div>
|
</button>
|
||||||
</div>
|
))}
|
||||||
);
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user