Mobile layout tweaks

This commit is contained in:
Daniel Pupius
2025-05-05 09:22:41 -07:00
parent 15e6047708
commit fc72e9f65a
11 changed files with 79 additions and 70 deletions

View File

@@ -58,7 +58,7 @@ export const Map: React.FC<MapProps> = ({
const mapContainerClasses = flush
? `w-full h-full overflow-hidden relative ${className}`
: `${className} relative overflow-hidden rounded-lg border border-neutral-700 bg-neutral-800/50`;
: `${className} relative overflow-hidden rounded-xl border border-neutral-700 bg-neutral-800/50`;
if (!apiKeyAvailable) {
return (

View File

@@ -116,14 +116,18 @@ export const Nav: React.FC<NavProps> = ({ connectionStatus }) => {
return (
<>
{/* Mobile header (always visible on mobile) */}
<div className="md:hidden fixed top-0 left-0 right-0 z-20 border-neutral-700 border-b shadow-inner bg-neutral-800/40">
<div className="md:hidden fixed top-0 left-0 right-0 z-20 bg-neutral-800/40">
<div className="flex items-center justify-between p-3">
<div className="flex items-center">
<Link
to="/home"
className="flex items-center"
onClick={() => isMobileView && setIsMobileMenuOpen(false)}
>
<div className="bg-pink-400 rounded-md mr-3 p-1.5 flex items-center justify-center">
<Layers className="h-5 w-5 text-neutral-800" />
</div>
<h1 className="text-xl font-thin tracking-wide text-neutral-100">{SITE_TITLE}</h1>
</div>
</Link>
<Button
variant="ghost"
icon={isMobileMenuOpen ? X : Menu}
@@ -161,12 +165,12 @@ export const Nav: React.FC<NavProps> = ({ connectionStatus }) => {
{/* Desktop sidebar (hidden on mobile) */}
<aside className="hidden md:flex w-64 text-neutral-100 h-screen fixed left-0 top-0 flex-col">
{/* Logo and title section */}
<div className="p-4 flex items-center">
<Link to="/home" className="p-4 flex items-center hover:bg-neutral-800/50 transition-colors">
<div className="bg-pink-400 rounded-md mr-3 p-1.5 flex items-center justify-center">
<Layers className="h-5 w-5 text-neutral-800" />
</div>
<h1 className="text-xl font-thin tracking-wide">{SITE_TITLE}</h1>
</div>
</Link>
<Separator className="mt-1" />

View File

@@ -154,7 +154,7 @@ export const PacketList: React.FC = () => {
return (
<div className="flex flex-col h-full">
<div className="sticky top-0 z-10">
<div className="flex justify-between items-center mb-2">
<div className="flex flex-col md:flex-row space-y-2 md:space-y-0 justify-between md:items-center mb-2">
<div className="flex items-center space-x-3">
{/* Show buffered count when paused */}
{streamPaused && bufferedPackets.length > 0 && (
@@ -240,44 +240,40 @@ export const PacketList: React.FC = () => {
)}
{/* Pagination */}
{totalPages > 1 && (
<>
<Separator className="mx-0 mt-4" />
<div className="flex justify-between items-center text-sm py-2 bg-neutral-800/50 sticky bottom-0">
<div className="text-sm text-neutral-400 px-2">
Page {currentPage} of {totalPages}
</div>
<Separator className="mx-0 mt-4" />
<div className="flex justify-between items-center text-sm sticky bottom-0">
<div className="text-sm text-neutral-400 px-2">
Page {currentPage} of {totalPages}
</div>
<div className="flex items-center space-x-3">
<Button
onClick={() =>
setCurrentPage(currentPage > 1 ? currentPage - 1 : 1)
}
disabled={currentPage === 1}
icon={ChevronLeft}
variant="secondary"
size="md"
>
Previous
</Button>
<div className="flex items-center space-x-3">
<Button
onClick={() =>
setCurrentPage(currentPage > 1 ? currentPage - 1 : 1)
}
disabled={currentPage === 1}
icon={ChevronLeft}
variant="secondary"
size="md"
>
Previous
</Button>
<Button
onClick={() =>
setCurrentPage(
currentPage < totalPages ? currentPage + 1 : totalPages
)
}
disabled={currentPage === totalPages}
icon={ChevronRight}
variant="secondary"
size="md"
>
Next
</Button>
</div>
</div>
</>
)}
<Button
onClick={() =>
setCurrentPage(
currentPage < totalPages ? currentPage + 1 : totalPages
)
}
disabled={currentPage === totalPages}
icon={ChevronRight}
variant="secondary"
size="md"
>
Next
</Button>
</div>
</div>
</div>
</div>
);

View File

@@ -2,7 +2,8 @@ import React from "react";
import { Battery, MapPin, Thermometer, Network, BoomBox } from "lucide-react";
import { Counter } from "../Counter";
import { NodeData } from "../../store/slices/aggregatorSlice";
import { getActivityLevel, getNodeColors, ActivityLevel } from "../../lib/activity";
import { getActivityLevel, getNodeColors } from "../../lib/activity";
import { cn } from "@/lib/cn";
export interface MeshCardProps {
type: "node" | "gateway";
@@ -45,17 +46,6 @@ export const MeshCard: React.FC<MeshCardProps> = ({
const activityLevel = getActivityLevel(lastHeard, type === "gateway");
const colors = getNodeColors(activityLevel, type === "gateway");
// Get card style based on activity
const getCardStyle = () => {
if (activityLevel === ActivityLevel.RECENT) {
return "bg-neutral-800 hover:bg-neutral-700";
} else if (activityLevel === ActivityLevel.ACTIVE) {
return "bg-neutral-800/80 hover:bg-neutral-700/80";
} else {
return "bg-neutral-800/50 hover:bg-neutral-800";
}
};
// Get icon style based on activity
const getIconStyle = () => {
return colors.background + " " + colors.textClass;
@@ -69,10 +59,10 @@ export const MeshCard: React.FC<MeshCardProps> = ({
return (
<div
onClick={handleClick}
className={`flex items-center p-2 rounded-lg ${getCardStyle()} ${onClick ? "cursor-pointer transition-colors" : ""}`}
className={cn('flex items-center p-2 rounded-lg bg-neutral-700/50 hover:bg-neutral-700', {"cursor-pointer transition-colors" : !!onClick})}
>
<div className="mr-2">
<div className={`p-1.5 rounded-full ${getIconStyle()}`}>
<div className={cn('p-1.5 rounded-full', getIconStyle())}>
{getIcon()}
</div>
</div>
@@ -98,7 +88,7 @@ export const MeshCard: React.FC<MeshCardProps> = ({
</div>
<div className="text-xs text-neutral-400 flex items-center">
<span
className={`inline-block w-1.5 h-1.5 rounded-full mr-1 ${getStatusDotStyle()}`}
className={cn('inline-block w-1.5 h-1.5 rounded-full mr-1', getStatusDotStyle())}
></span>
{timeString}
</div>

View File

@@ -609,8 +609,8 @@ function getMarkerIcon(node: MapNode): MarkerIconConfig {
path: google.maps.SymbolPath.CIRCLE,
scale: 12,
fillColor: colors.fill,
fillOpacity: 0.8,
fillOpacity: 1,
strokeColor: colors.stroke,
strokeWeight: 4,
strokeWeight: 2,
};
}

View File

@@ -31,8 +31,6 @@ export const NodeList: React.FC = () => {
navigate({ to: "/node/$nodeId", params: { nodeId: nodeId.toString(16) } });
};
// Instead of early return, we'll handle the empty state in the JSX
return (
<div className="space-y-1">
<div className="flex justify-between items-center mb-2">

View File

@@ -293,10 +293,17 @@ export const MapReportPacket: React.FC<MapReportPacketProps> = ({ packet }) => {
)}
</div>
{/* Position information */}
<div className="grid grid-cols-2 gap-3 mt-3 text-sm">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 mt-3 text-sm">
<KeyValuePair
label="Coordinates"
value={`${center.latitude.toFixed(6)}, ${center.longitude.toFixed(6)}`}
label="Latitude"
value={center.latitude.toFixed(6)}
monospace={true}
inset={true}
/>
<KeyValuePair
label="Longitude"
value={center.longitude.toFixed(6)}
monospace={true}
inset={true}
/>

View File

@@ -35,7 +35,7 @@ export const PositionPacket: React.FC<PositionPacketProps> = ({ packet }) => {
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<KeyValueGrid>
<KeyValueGrid className="grid-cols-2">
<KeyValuePair
label="Latitude"
value={latitude !== undefined ? latitude.toFixed(6) : 'N/A'}

View File

@@ -49,7 +49,7 @@ export const WaypointPacket: React.FC<WaypointPacketProps> = ({ packet }) => {
<div className="text-base text-neutral-300">{waypoint.name}</div>
</div>
)}
<KeyValueGrid>
<KeyValueGrid className="grid-cols-1 sm:grid-cols-2">
{latitude !== undefined && (
<KeyValuePair label="Latitude" value={latitude.toFixed(6)} vertical monospace />
)}

View File

@@ -94,8 +94,22 @@ export const KeyValueGrid: React.FC<{
columns?: number;
className?: string;
}> = ({ children, columns = 2, className }) => {
// Generate the appropriate grid columns class based on the columns prop
let gridColsClass = 'grid-cols-2'; // Default
if (className && className.includes('grid-cols-')) {
// If className already includes a grid-cols class, don't add another one
gridColsClass = '';
} else if (columns === 1) {
gridColsClass = 'grid-cols-1';
} else if (columns === 3) {
gridColsClass = 'grid-cols-3';
} else if (columns === 4) {
gridColsClass = 'grid-cols-4';
}
return (
<div className={cn(`grid grid-cols-${columns} gap-x-6 gap-y-3`, className)}>
<div className={cn(`grid ${gridColsClass} gap-x-6 gap-y-3`, className)}>
{children}
</div>
);

View File

@@ -24,7 +24,7 @@ function MapPage() {
return (
<PageWrapper>
<div className="flex flex-col h-[calc(100vh-4rem)]">
<div className="flex flex-col h-[calc(100vh-7rem)] md:h-[calc(100vh-5rem)]">
<div className="flex-1 flex flex-col">
<NetworkMap
fullHeight
@@ -32,7 +32,7 @@ function MapPage() {
onAutoZoomChange={setAutoZoomEnabled}
/>
<div className="mt-2 bg-neutral-800/50 rounded-lg p-2 text-xs flex items-center justify-between effect-inset">
<div className="mt-2 rounded-lg p-2 text-xs flex items-center justify-between effect-inset">
<div className="flex flex-wrap gap-2">
<div className="flex items-center gap-2">
<span className={`inline-flex items-center px-2 py-0.5 rounded ${getNodeColors(ActivityLevel.RECENT, false).textClass} ${getNodeColors(ActivityLevel.RECENT, false).background}`}>