Header.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. "use client";
  2. import { useState } from "react";
  3. import { Menu, Search, Bell, HelpCircle, X, ArrowLeft } from "lucide-react";
  4. import { ThemeToggle } from "@/components/ThemeToggle";
  5. import { useLayout } from "@/components/LayoutProvider";
  6. import { usePathname, useRouter } from "next/navigation";
  7. import Image from "next/image";
  8. export default function Header() {
  9. const { setMobileMenuOpen } = useLayout();
  10. const [isSearchOpen, setIsSearchOpen] = useState(false);
  11. const pathname = usePathname();
  12. const router = useRouter();
  13. // Only show the back button on pages NOT directly reachable via the sidebar
  14. const sidebarPaths = ['/', '/analysis', '/students', '/settings'];
  15. const showBack = !sidebarPaths.includes(pathname);
  16. return (
  17. <header className="h-20 flex items-center justify-between px-6 lg:px-8 border-b border-outline-variant/30 z-10 bg-background/95 backdrop-blur-sm sticky top-0">
  18. <div className="flex items-center w-full max-w-xl gap-2">
  19. <button
  20. className="lg:hidden mr-2 shrink-0 text-secondary hover:text-on-surface transition-colors"
  21. onClick={() => setMobileMenuOpen(true)}
  22. >
  23. <Menu className="w-6 h-6" />
  24. </button>
  25. {/* Back Button — visible on sub-pages */}
  26. {showBack && (
  27. <button
  28. onClick={() => router.back()}
  29. className="shrink-0 w-9 h-9 rounded-full flex items-center justify-center hover:bg-surface-container-high text-secondary hover:text-on-surface transition-colors cursor-pointer"
  30. title="返回上一页"
  31. >
  32. <ArrowLeft className="w-5 h-5" />
  33. </button>
  34. )}
  35. {/* Mobile Banner */}
  36. <div className="lg:hidden flex-1 flex items-center">
  37. <Image
  38. src="/banner.png"
  39. alt="SEEC Metrics Banner"
  40. width={120}
  41. height={30}
  42. className="object-contain"
  43. priority
  44. />
  45. </div>
  46. {/* Desktop Search (hidden on mobile) */}
  47. <div className="relative w-full hidden lg:block">
  48. <span className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
  49. <Search className="w-5 h-5 text-outline" />
  50. </span>
  51. <input
  52. className="w-full py-2.5 pl-10 pr-4 bg-surface-container-high border-none rounded-full focus:ring-1 focus:ring-primary text-sm placeholder-outline text-on-surface transition-all shadow-inner outline-none focus:outline-none"
  53. placeholder="搜索能力指标、学生名单..."
  54. type="text"
  55. />
  56. </div>
  57. {/* Mobile Search Button */}
  58. <button
  59. className="lg:hidden p-2 text-secondary hover:text-on-surface"
  60. onClick={() => setIsSearchOpen(true)}
  61. >
  62. <Search className="w-5 h-5" />
  63. </button>
  64. </div>
  65. {/* Mobile Expanded Search Overlay */}
  66. {isSearchOpen && (
  67. <div className="absolute inset-y-0 left-0 right-0 bg-background/95 backdrop-blur-sm z-20 flex items-center px-4 lg:hidden">
  68. <div className="relative w-full flex items-center">
  69. <span className="absolute left-3 flex items-center pointer-events-none">
  70. <Search className="w-5 h-5 text-outline" />
  71. </span>
  72. <input
  73. autoFocus
  74. className="w-full py-2 pl-10 pr-10 bg-surface-container-high border-none rounded-full focus:ring-1 focus:ring-primary text-sm placeholder-outline text-on-surface outline-none"
  75. placeholder="搜索能力指标、学生名单..."
  76. type="text"
  77. />
  78. <button
  79. className="absolute right-3 p-1 rounded-full hover:bg-surface-variant text-secondary"
  80. onClick={() => setIsSearchOpen(false)}
  81. >
  82. <X className="w-4 h-4" />
  83. </button>
  84. </div>
  85. </div>
  86. )}
  87. <div className="flex items-center space-x-3">
  88. <ThemeToggle />
  89. <button className="p-2 rounded-full hover:bg-surface-container-high text-secondary hover:text-on-surface transition-colors relative">
  90. <Bell className="w-6 h-6" />
  91. <span className="absolute top-2.5 right-2.5 h-2 w-2 bg-chart-2 rounded-full ring-2 ring-background"></span>
  92. </button>
  93. <button className="p-2 rounded-full hover:bg-surface-container-high text-secondary hover:text-on-surface transition-colors">
  94. <HelpCircle className="w-6 h-6" />
  95. </button>
  96. </div>
  97. </header>
  98. );
  99. }