header.tsx (6519B)
1 import React from "react"; 2 import Link from "next/link"; 3 import { useRouter } from "next/router"; 4 import { Container } from "../util/container"; 5 import { useTheme } from "."; 6 import { Icon } from "../util/icon"; 7 import { tinaField } from "tinacms/dist/react"; 8 import { GlobalHeader } from "../../tina/__generated__/types"; 9 10 export const Header = ({ data }: { data: GlobalHeader }) => { 11 const router = useRouter(); 12 const theme = useTheme(); 13 14 const headerColor = { 15 default: 16 "text-black dark:text-white from-gray-50 to-white dark:from-gray-800 dark:to-gray-900", 17 primary: { 18 blue: "text-white from-blue-300 to-blue-500", 19 teal: "text-white from-teal-400 to-teal-500", 20 green: "text-white from-green-400 to-green-500", 21 red: "text-white from-red-400 to-red-500", 22 pink: "text-white from-pink-400 to-pink-500", 23 purple: "text-white from-purple-400 to-purple-500", 24 orange: "text-white from-orange-400 to-orange-500", 25 yellow: "text-white from-yellow-400 to-yellow-500", 26 }, 27 }; 28 29 const headerColorCss = 30 data.color === "primary" 31 ? headerColor.primary[theme.color] 32 : headerColor.default; 33 34 const activeItemClasses = { 35 blue: "border-b-3 border-blue-200 text-blue-700 dark:text-blue-300 font-medium dark:border-blue-700", 36 teal: "border-b-3 border-teal-200 text-teal-700 dark:text-teal-300 font-medium dark:border-teal-700", 37 green: 38 "border-b-3 border-green-200 text-green-700 dark:text-green-300 font-medium dark:border-green-700", 39 red: "border-b-3 border-red-300 text-red-700 dark:text-green-300 font-medium dark:border-red-700", 40 pink: "border-b-3 border-pink-200 text-pink-700 dark:text-pink-300 font-medium dark:border-pink-700", 41 purple: 42 "border-b-3 border-purple-200 text-purple-700 dark:text-purple-300 font-medium dark:border-purple-700", 43 orange: 44 "border-b-3 border-orange-200 text-orange-700 dark:text-orange-300 font-medium dark:border-orange-700", 45 yellow: 46 "border-b-3 border-yellow-300 text-yellow-700 dark:text-yellow-300 font-medium dark:border-yellow-600", 47 }; 48 49 const activeBackgroundClasses = { 50 blue: "text-blue-500", 51 teal: "text-teal-500", 52 green: "text-green-500", 53 red: "text-red-500", 54 pink: "text-pink-500", 55 purple: "text-purple-500", 56 orange: "text-orange-500", 57 yellow: "text-yellow-500", 58 }; 59 const [isClient, setIsClient] = React.useState(false); 60 React.useEffect(() => { 61 setIsClient(true); 62 }, []); 63 64 return ( 65 <div 66 className={`relative overflow-hidden bg-gradient-to-b ${headerColorCss}`} 67 > 68 <Container size="custom" className="py-0 relative z-10 max-w-8xl"> 69 <div className="flex items-center justify-between gap-6"> 70 <h4 className="select-none text-lg font-bold tracking-tight my-4 transition duration-150 ease-out transform"> 71 <Link 72 href="/" 73 className="flex gap-1 items-center whitespace-nowrap tracking-[.002em]" 74 > 75 <Icon 76 tinaField={tinaField(data, "icon")} 77 parentColor={data.color} 78 data={{ 79 name: data.icon.name, 80 color: data.icon.color, 81 style: data.icon.style, 82 }} 83 /> 84 <span data-tina-field={tinaField(data, "name")}>{data.name}</span> 85 </Link> 86 </h4> 87 <ul className="flex gap-6 sm:gap-8 lg:gap-10 tracking-[.002em] -mx-4"> 88 {data.nav && 89 data.nav.map((item, i) => { 90 const activeItem = 91 (item.href === "" 92 ? router.asPath === "/" 93 : router.asPath.includes(item.href)) && isClient; 94 return ( 95 <li 96 key={`${item.label}-${i}`} 97 className={`${ 98 activeItem ? activeItemClasses[theme.color] : "" 99 }`} 100 > 101 <Link 102 data-tina-field={tinaField(item, "label")} 103 href={`/${item.href}`} 104 className={`relative select-none text-base inline-block tracking-wide transition duration-150 ease-out hover:opacity-100 py-8 px-4 ${ 105 activeItem ? `` : `opacity-70` 106 }`} 107 > 108 {item.label} 109 {activeItem && ( 110 <svg 111 className={`absolute bottom-0 left-1/2 w-[180%] h-full -translate-x-1/2 -z-1 opacity-10 dark:opacity-15 ${ 112 activeBackgroundClasses[theme.color] 113 }`} 114 preserveAspectRatio="none" 115 viewBox="0 0 230 230" 116 fill="none" 117 xmlns="http://www.w3.org/2000/svg" 118 > 119 <rect 120 x="230" 121 y="230" 122 width="230" 123 height="230" 124 transform="rotate(-180 230 230)" 125 fill="url(#paint0_radial_1_33)" 126 /> 127 <defs> 128 <radialGradient 129 id="paint0_radial_1_33" 130 cx="0" 131 cy="0" 132 r="1" 133 gradientUnits="userSpaceOnUse" 134 gradientTransform="translate(345 230) rotate(90) scale(230 115)" 135 > 136 <stop stopColor="currentColor" /> 137 <stop 138 offset="1" 139 stopColor="currentColor" 140 stopOpacity="0" 141 /> 142 </radialGradient> 143 </defs> 144 </svg> 145 )} 146 </Link> 147 </li> 148 ); 149 })} 150 </ul> 151 </div> 152 <div 153 className={`absolute h-1 bg-gradient-to-r from-transparent ${ 154 data.color === "primary" ? `via-white` : `via-black dark:via-white` 155 } to-transparent bottom-0 left-4 right-4 -z-1 opacity-5`} 156 /> 157 </Container> 158 </div> 159 ); 160 };