Navbar
TailwindCSS
1. Crearea componentei de Navbar
2. Crearea unui fișier cu funcții utilitare pentru librăria de tailwind.

Last updated
TailwindCSS
Primul pas este să adăugăm o bară de navigare în partea de sus a aplicației, care să includă principalele opțiuni:
Navigare către pagina principală și pagina de listare a produselor
Meniu pentru autentificare și delogare
Pentru a simplifica procesul, vom folosi componente predefinite, pe care le vom adapta necesităților aplicației noastre.
În cadrul folderului client, creăm un nou document pe care îl denumim utils și care va conține un fișier numit tailwind.js.
Ce face funcția classNames:
Funcția combină clase CSS într-un singur string
Acceptă orice număr de argumente (...classes)
Elimină valorile false (false, null, undefined, "", etc.)
Unește clasele valide cu spațiu între ele
Utilă pentru clase condiționale în React (ex: isActive && "text-blue-500")

Last updated
// client/components/Navbar.jsx
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
import { Bars3Icon, XMarkIcon, UserCircleIcon } from '@heroicons/react/24/outline'
import { classNames } from '../utils/tailwind'
const navigation = [
{ name: 'Homepage', href: '#', current: true },
{ name: 'Products', href: '#', current: false },
]
export default function Navbar() {
return (
<Disclosure as="nav" className="relative bg-gray-800">
<div className="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
<div className="relative flex h-16 items-center justify-between">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
{/* Mobile menu button*/}
<DisclosureButton className="group relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-white/5 hover:text-white focus:outline-2 focus:-outline-offset-1 focus:outline-indigo-500">
<span className="absolute -inset-0.5" />
<span className="sr-only">Open main menu</span>
<Bars3Icon aria-hidden="true" className="block size-6 group-data-open:hidden" />
<XMarkIcon aria-hidden="true" className="hidden size-6 group-data-open:block" />
</DisclosureButton>
</div>
<div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<div className="flex shrink-0 items-center">
<img
alt="Your Company"
src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=indigo&shade=500"
className="h-8 w-auto"
/>
</div>
<div className="hidden sm:ml-6 sm:block">
<div className="flex space-x-4">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
aria-current={item.current ? 'page' : undefined}
className={classNames(
item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-white/5 hover:text-white',
'rounded-md px-3 py-2 text-sm font-medium',
)}
>
{item.name}
</a>
))}
</div>
</div>
</div>
<div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
{/* Profile dropdown */}
<Menu as="div" className="relative ml-3">
<MenuButton className="relative flex rounded-full focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500">
<span className="absolute -inset-1.5" />
<span className="sr-only">Open user menu</span>
<UserCircleIcon className="size-8 rounded-full bg-gray-800 outline -outline-offset-1 outline-white/10 text-gray-400" />
</MenuButton>
<MenuItems
transition
className="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg outline outline-black/5 transition data-closed:scale-95 data-closed:transform data-closed:opacity-0 data-enter:duration-100 data-enter:ease-out data-leave:duration-75 data-leave:ease-in"
>
<MenuItem>
<a
href="#"
className="block px-4 py-2 text-sm text-gray-700 data-focus:bg-gray-100 data-focus:outline-hidden"
>
Your profile
</a>
</MenuItem>
<MenuItem>
<a
href="#"
className="block px-4 py-2 text-sm text-gray-700 data-focus:bg-gray-100 data-focus:outline-hidden"
>
Settings
</a>
</MenuItem>
<MenuItem>
<a
href="#"
className="block px-4 py-2 text-sm text-gray-700 data-focus:bg-gray-100 data-focus:outline-hidden"
>
Sign out
</a>
</MenuItem>
</MenuItems>
</Menu>
</div>
</div>
</div>
<DisclosurePanel className="sm:hidden">
<div className="space-y-1 px-2 pt-2 pb-3">
{navigation.map((item) => (
<DisclosureButton
key={item.name}
as="a"
href={item.href}
aria-current={item.current ? 'page' : undefined}
className={classNames(
item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-white/5 hover:text-white',
'block rounded-md px-3 py-2 text-base font-medium',
)}
>
{item.name}
</DisclosureButton>
))}
</div>
</DisclosurePanel>
</Disclosure>
)
}
export function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}