-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6ec37f3
commit e885fb3
Showing
13 changed files
with
421 additions
and
51 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from 'react'; | ||
|
||
const BreakLine: React.FC = () => { | ||
return <hr className="border-kartAI-blue mx-5" />; | ||
}; | ||
|
||
export default BreakLine; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
'use client'; | ||
import { useEffect, useRef, useState } from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import Icons from './Icons'; | ||
import shortcuts from '../data/shortcuts' | ||
|
||
const Dropdown = () => { | ||
const [isOpen, setIsOpen] = useState(false); | ||
const [openedNavbarSection, setOpenedNavbarSection] = useState<number | null>(null); // Track which section is opened | ||
const dropdownRef = useRef<HTMLDivElement>(null); | ||
|
||
const toggleDropdown = () => { | ||
setIsOpen(!isOpen); | ||
}; | ||
|
||
const closeDropdown = () => { | ||
setIsOpen(false); | ||
}; | ||
|
||
const handleClick = (index: number) => { | ||
setOpenedNavbarSection(index === openedNavbarSection ? null : index); // Close if clicked again | ||
}; | ||
|
||
useEffect(() => { | ||
const handleClickOutside = (event: MouseEvent) => { | ||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { | ||
closeDropdown(); | ||
} | ||
}; | ||
// Attach the event listener when the component mounts | ||
document.addEventListener('click', handleClickOutside); | ||
|
||
// Detach the event listener when the component unmounts | ||
return () => { | ||
document.removeEventListener('click', handleClickOutside); | ||
}; | ||
}, []); | ||
|
||
return ( | ||
<> | ||
{isOpen && ReactDOM.createPortal( | ||
<div className="fixed inset-0 bg-black bg-opacity-75 z-10"></div>, | ||
document.body | ||
)} | ||
<div className="px-4 py-2 top-0 relative group text-kartAI-blue flex z-20" ref={dropdownRef}> | ||
<button onClick={toggleDropdown}> | ||
{isOpen ? | ||
<Icons name="Cross" /> : <Icons name="Dropdown" /> | ||
} | ||
</button> | ||
{/* Dropdown content */} | ||
{isOpen && ( | ||
<div className='absolute right-0 mt-11 w-screen bg-white z-30'> | ||
{shortcuts.map((shortcut, index) => { | ||
const isActive = index === openedNavbarSection; | ||
return ( | ||
<div key={index} className="border-b border-gray-200"> | ||
<button | ||
onClick={() => handleClick(index)} | ||
className={`${isActive ? 'font-bold' : ''} tracking-[0.08em] block px-4 py-3 gap-2 text-sm text-black flex flex-row justify-between items-center`} | ||
> | ||
<h3 className='flex whitespace-pre-wrap items-center'>{shortcut.header.toUpperCase()}</h3> | ||
<Icons name={isActive ? 'ArrowUp_sm' : 'ArrowRight_sm'} /> | ||
</button> | ||
{/* Subgroups: reveal when active */} | ||
<div | ||
className={`overflow-hidden transition-[max-height] duration-300 ease-in-out ${isActive ? 'max-h-screen' : 'max-h-0'}`} | ||
> | ||
{isActive && shortcut.subgroups.map((subgroup, subgroupIndex) => ( | ||
<div key={subgroupIndex} className="px-6 py-4"> | ||
<h3 className="text-lg font-bold mb-2">{subgroup.title}</h3> | ||
<div className={`flex flex-wrap flex-col`}> | ||
{subgroup.links.map((link, linkIndex) => ( | ||
<a | ||
key={linkIndex} | ||
href={link.url} | ||
className="block text-sm text-black hover:text-gray-600 py-1 transition-all duration-300 transform hover:scale-105" | ||
> | ||
{link.label} | ||
</a> | ||
))} | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
})} | ||
</div> | ||
)} | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export default Dropdown; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const Footer = () => { | ||
return ( | ||
<footer className="h-12 shadow-inner"> | ||
<div className="h-full flex justify-center items-center"> | ||
<p className="text-gray-500 text-sm">© {new Date().getFullYear()} KartAI</p> | ||
</div> | ||
</footer> | ||
); | ||
}; | ||
|
||
export default Footer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
'use client'; | ||
import React from 'react'; | ||
|
||
interface IconsProps { | ||
name: string; | ||
} | ||
|
||
const Icons: React.FC<IconsProps> = ({ name }) => { | ||
// Define SVG paths for different icons | ||
const iconPaths: Record<string, React.JSX.Element> = { | ||
Dropdown: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="md:size-6 size-8"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> | ||
|
||
</svg>, | ||
Cross: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="md:size-6 size-8"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" /> | ||
</svg>, | ||
Om: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-5"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" /> | ||
</svg>, | ||
Formidling: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-5"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" /> | ||
</svg>, | ||
Arrangementer: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="md:size-6 size-8"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" /> | ||
</svg>, | ||
Utleie: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="md:size-6 size-8"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z" /> | ||
</svg>, | ||
Medlem: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-5"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M18 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0ZM3 19.235v-.11a6.375 6.375 0 0 1 12.75 0v.109A12.318 12.318 0 0 1 9.374 21c-2.331 0-4.512-.645-6.374-1.766Z" /> | ||
</svg>, | ||
Hjem: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-5"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" /> | ||
</svg>, | ||
ArrowRight_sm: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-4"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" /> | ||
</svg>, | ||
ArrowLeft_sm: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-4"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18" /> | ||
</svg>, | ||
ArrowUp_sm: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-4"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" /> | ||
</svg>, | ||
Facebook: | ||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" className='size-10' viewBox="0 0 48 48"> | ||
<path fill="#039be5" d="M24 5A19 19 0 1 0 24 43A19 19 0 1 0 24 5Z"></path><path fill="#fff" d="M26.572,29.036h4.917l0.772-4.995h-5.69v-2.73c0-2.075,0.678-3.915,2.619-3.915h3.119v-4.359c-0.548-0.074-1.707-0.236-3.897-0.236c-4.573,0-7.254,2.415-7.254,7.917v3.323h-4.701v4.995h4.701v13.729C22.089,42.905,23.032,43,24,43c0.875,0,1.729-0.08,2.572-0.194V29.036z"></path> | ||
</svg>, | ||
LinkedIn: | ||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" className='size-11' viewBox="0 0 48 48"> | ||
<path fill="#0288D1" d="M42,37c0,2.762-2.238,5-5,5H11c-2.761,0-5-2.238-5-5V11c0-2.762,2.239-5,5-5h26c2.762,0,5,2.238,5,5V37z"></path><path fill="#FFF" d="M12 19H17V36H12zM14.485 17h-.028C12.965 17 12 15.888 12 14.499 12 13.08 12.995 12 14.514 12c1.521 0 2.458 1.08 2.486 2.499C17 15.887 16.035 17 14.485 17zM36 36h-5v-9.099c0-2.198-1.225-3.698-3.192-3.698-1.501 0-2.313 1.012-2.707 1.99C24.957 25.543 25 26.511 25 27v9h-5V19h5v2.616C25.721 20.5 26.85 19 29.738 19c3.578 0 6.261 2.25 6.261 7.274L36 36 36 36z"></path> | ||
</svg>, | ||
ArrowDown: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-6"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" /> | ||
</svg>, | ||
Pin: | ||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-5"> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /> | ||
<path strokeLinecap="round" strokeLinejoin="round" d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1 1 15 0Z" /> | ||
</svg> | ||
}; | ||
|
||
return ( | ||
<div className="flex items-center justify-center"> | ||
{iconPaths[name]} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Icons; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
'use client'; | ||
|
||
import shortcuts from '../data/shortcuts'; | ||
import { useEffect, useRef, useState } from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import Dropdown from './Dropdown'; | ||
import BreakLine from './Breakline'; | ||
import Icons from './Icons'; | ||
import Link from 'next/link'; | ||
|
||
const Navbar = () => { | ||
const [openedNavbarSection, setOpenedNavbarSection] = useState<number>(-1); | ||
const navbarRef = useRef<HTMLDivElement>(null); // Ref for the entire navbar | ||
|
||
const handleClick = (index: number) => { | ||
if (openedNavbarSection === index) { | ||
setOpenedNavbarSection(-1); // Close if the same section is clicked again | ||
} else { | ||
setOpenedNavbarSection(index); // Open the clicked section | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
const handleClickOutside = (event: MouseEvent) => { | ||
// Check if the click is outside the navbar | ||
if (navbarRef.current && !navbarRef.current.contains(event.target as Node)) { | ||
setOpenedNavbarSection(-1); // Close the opened section | ||
} | ||
}; | ||
|
||
document.addEventListener('click', handleClickOutside); | ||
|
||
// Lock scrolling if a dropdown is open | ||
if (openedNavbarSection !== -1) { | ||
document.body.style.overflow = 'hidden'; | ||
} else { | ||
document.body.style.overflow = ''; | ||
} | ||
|
||
return () => { | ||
document.removeEventListener('click', handleClickOutside); | ||
document.body.style.overflow = ''; // Ensure overflow is reset on cleanup | ||
}; | ||
}, [openedNavbarSection]); // Add openedNavbarSection as a dependency | ||
|
||
return ( | ||
<nav ref={navbarRef} className="py-2 fixed sticky top-0 bottom-auto z-50 font-semibold w-full bg-white shadow-xl"> | ||
{/* Backdrop when a dropdown is open */} | ||
{openedNavbarSection !== -1 && ReactDOM.createPortal( | ||
<div className="fixed inset-0 bg-black bg-opacity-25 z-10" />, | ||
document.body | ||
)} | ||
<div className="flex justify-between items-center w-full"> | ||
<div className="flex items-center pl-4 mb-1 lg:pl-10"> | ||
<Link href={"/"}> | ||
<img | ||
src="/Kartai-logo_white.jpg" // Update with the correct path to your logo if different | ||
alt="KartAI Logo" | ||
className="h-10 pr-2" // Adjust height, width, and margin as needed | ||
/> | ||
</Link> | ||
</div> | ||
<div className="hidden sm:flex justify-end items-center pr-4 lg:pr-10"> | ||
{shortcuts.map((shortcut, index) => { | ||
const isActive = index === openedNavbarSection; | ||
return ( | ||
<div key={index} className="relative"> | ||
<button | ||
onClick={() => handleClick(index)} | ||
className={`relative group px-2 md:px-8 lg:px-5 py-2 text-md flex flex-row gap-2 cursor-hover items-center ${isActive ? 'text-kartAI-blue' : 'text-secondary-black'}`} | ||
style={isActive ? { textDecoration: 'underline', textUnderlineOffset: '6px', textDecorationThickness: '2px' } : {}} | ||
> | ||
<p className="mt-1 whitespace-pre-wrap text-xs xl:text-sm hidden sm:block tracking-[0.15em]"> | ||
{shortcut.header.toUpperCase()} | ||
</p> | ||
</button> | ||
{isActive && ( | ||
<div className="fixed left-0 right-0 pt-4 bg-white shadow-lg z-40 w-screen"> | ||
<BreakLine /> | ||
{/* Dynamically rendering subgroups and links for this section */} | ||
<div className="w-screen-lg flex flex-col mt-4" > | ||
<div className="px-10 md:px-20 pb-10 flex flex-wrap"> | ||
{shortcut.subgroups.map((subgroup, subgroupIndex) => ( | ||
<div key={subgroupIndex} className="w-full md:w-1/2 xl:w-1/3 p-2"> | ||
<h3 className="text-xl font-bold mb-2">{subgroup.title}</h3> | ||
<div className={`flex flex-wrap ${subgroup.links.length > 3 ? '' : 'flex-col'}`}> {/* Adjust flex direction based on number of links */} | ||
{subgroup.links.map((link, linkIndex) => ( | ||
<div key={linkIndex} className={`${subgroup.links.length > 3 ? 'w-1/2' : 'w-full'} p-1`}> {/* Conditional width based on number of links */} | ||
<a | ||
href={link.url} | ||
className="block text-sm text-black hover:text-gray-600 py-1 flex flex-row gap-4" | ||
> | ||
{link.label} | ||
{subgroup.arrow && <Icons name="ArrowRight_sm" />} | ||
</a> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
})} | ||
</div> | ||
<div className="my-1 w-full sm:hidden flex items-center justify-between pl-4 relative text-white"> | ||
<p> | ||
</p> | ||
<Dropdown /> | ||
</div> | ||
</div> | ||
</nav> | ||
); | ||
}; | ||
|
||
export default Navbar; |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.