UI redesign - mobile support and fix black background popups
This commit is contained in:
@@ -24,7 +24,7 @@ export function ConfirmDialog({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 dark:bg-opacity-70 flex items-center justify-center z-[10001]">
|
<div className="fixed inset-0 bg-black/20 dark:bg-black/30 flex items-center justify-center z-[10001]">
|
||||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4 animate-scale-in">
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4 animate-scale-in">
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
<h3 className="text-lg font-bold text-gray-900 dark:text-white mb-2">
|
<h3 className="text-lg font-bold text-gray-900 dark:text-white mb-2">
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import { useUIStore } from '../../stores/uiStore';
|
|||||||
|
|
||||||
interface LayoutProps {
|
interface LayoutProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
onToggleSidebar?: () => void;
|
||||||
|
isSidebarOpen?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Layout({ children }: LayoutProps) {
|
export function Layout({ children, onToggleSidebar, isSidebarOpen }: LayoutProps) {
|
||||||
const { user, logout } = useAuthStore();
|
const { user, logout } = useAuthStore();
|
||||||
const { darkMode, toggleDarkMode, showToast } = useUIStore();
|
const { darkMode, toggleDarkMode, showToast } = useUIStore();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -28,7 +30,26 @@ export function Layout({ children }: LayoutProps) {
|
|||||||
<div className="h-screen flex flex-col bg-gray-50 dark:bg-gray-900 transition-colors">
|
<div className="h-screen flex flex-col bg-gray-50 dark:bg-gray-900 transition-colors">
|
||||||
<header className="bg-blue-600 dark:bg-gray-800 text-white shadow-md">
|
<header className="bg-blue-600 dark:bg-gray-800 text-white shadow-md">
|
||||||
<div className="px-4 py-3 flex items-center justify-between">
|
<div className="px-4 py-3 flex items-center justify-between">
|
||||||
<h1 className="text-xl font-bold">ISP Wiremap</h1>
|
<div className="flex items-center gap-3">
|
||||||
|
{/* Mobile hamburger button */}
|
||||||
|
{onToggleSidebar && (
|
||||||
|
<button
|
||||||
|
onClick={onToggleSidebar}
|
||||||
|
className="md:hidden p-2 hover:bg-blue-700 dark:hover:bg-gray-700 rounded-lg transition-colors"
|
||||||
|
aria-label="Toggle sidebar"
|
||||||
|
>
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
{isSidebarOpen ? (
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||||
|
) : (
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{/* Title - hidden on mobile when hamburger is present */}
|
||||||
|
<h1 className={`text-xl font-bold ${onToggleSidebar ? 'hidden md:block' : ''}`}>ISP Wiremap</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
{user && (
|
{user && (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ export function ShareDialog({ mapId, onClose }: ShareDialogProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-30 dark:bg-opacity-50 flex items-center justify-center transition-colors" style={{ zIndex: 10001 }}>
|
<div className="fixed inset-0 bg-black/20 dark:bg-black/30 flex items-center justify-center transition-colors" style={{ zIndex: 10001 }}>
|
||||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-2xl w-full max-w-2xl max-h-[80vh] overflow-hidden border border-gray-200 dark:border-gray-700 transition-colors animate-scale-in">
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-2xl w-full max-w-2xl max-h-[80vh] overflow-hidden border border-gray-200 dark:border-gray-700 transition-colors animate-scale-in">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center bg-gradient-to-r from-blue-50 to-indigo-50 dark:from-gray-800 dark:to-gray-800">
|
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center bg-gradient-to-r from-blue-50 to-indigo-50 dark:from-gray-800 dark:to-gray-800">
|
||||||
|
|||||||
@@ -34,19 +34,42 @@ export function Dashboard() {
|
|||||||
const [showShareDialog, setShowShareDialog] = useState(false);
|
const [showShareDialog, setShowShareDialog] = useState(false);
|
||||||
const [shareMapId, setShareMapId] = useState<string | null>(null);
|
const [shareMapId, setShareMapId] = useState<string | null>(null);
|
||||||
const [activeLayer, setActiveLayer] = useState<MapLayer>('osm');
|
const [activeLayer, setActiveLayer] = useState<MapLayer>('osm');
|
||||||
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||||
|
|
||||||
const handleShareMap = (mapId: string) => {
|
const handleShareMap = (mapId: string) => {
|
||||||
setShareMapId(mapId);
|
setShareMapId(mapId);
|
||||||
setShowShareDialog(true);
|
setShowShareDialog(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSelectMap = (mapId: string) => {
|
||||||
|
setSelectedMapId(mapId);
|
||||||
|
// Close sidebar on mobile after selecting a map
|
||||||
|
setIsSidebarOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout onToggleSidebar={() => setIsSidebarOpen(!isSidebarOpen)} isSidebarOpen={isSidebarOpen}>
|
||||||
<div className="flex h-full">
|
<div className="flex h-full relative">
|
||||||
|
{/* Mobile overlay */}
|
||||||
|
{isSidebarOpen && (
|
||||||
|
<div
|
||||||
|
className="md:hidden fixed inset-0 bg-black/20 transition-opacity"
|
||||||
|
style={{ zIndex: 9998 }}
|
||||||
|
onClick={() => setIsSidebarOpen(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Left sidebar with map list and toolbar */}
|
{/* Left sidebar with map list and toolbar */}
|
||||||
<div className="flex flex-col bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 transition-colors">
|
<div
|
||||||
|
className={`
|
||||||
|
flex flex-col bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 transition-all duration-300 ease-in-out
|
||||||
|
fixed md:relative h-full w-80
|
||||||
|
${isSidebarOpen ? 'translate-x-0' : '-translate-x-full md:translate-x-0'}
|
||||||
|
`}
|
||||||
|
style={{ zIndex: 9999 }}
|
||||||
|
>
|
||||||
<MapListSidebar
|
<MapListSidebar
|
||||||
onSelectMap={setSelectedMapId}
|
onSelectMap={handleSelectMap}
|
||||||
selectedMapId={selectedMapId}
|
selectedMapId={selectedMapId}
|
||||||
onShareMap={handleShareMap}
|
onShareMap={handleShareMap}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user