autobrr/web/src/screens/Base.tsx
stacksmash76 ac988f28f4
feat(web): better tooltips and uniformity (#474)
* - fix: changed all {text,bg}-{teal,indigo}-* color properties to {text,bg}-{blue}-* so there is only one dominant primary color in the UI -- blue
- enhancement: added `cursor: pointer` to the PageButton component (used in pagination)
- enhancement: modified TitleCell to use the new Tooltip component and modified the width selectors to a more sane default value, now instead of scrolling one just has to tap the cell to see it's untruncated value
- enhancement: modified the Tooltip component to use react-popper-tooltip (which in turn uses popper.js) which is a much better alternative, since it uses auto-positioning in case there's not enough space and some things aren't as broken as in the previous version (e.g. there was a problem with forcing the previous tooltip to use a specific width)
- enhancement: added a useMedia hook selector from the react-use repository, which might come in handy in the future for better/easier decoupling of Desktop and Mobile UI/UX patterns via JS (versus CSS-only)
- enhancement: made the mobile navbar more visible and clear. also fixed previous path === "/" bug which was fixed on desktop.
- fix: fixed table headers/footers so they're rounded
- enhancement: made pagination components more compact (buttons and show N result selector)

* changed {ring, border}-indigo-* to ring-blue-*

* build: add yarn.lock

* fix: formatting warnings

* fix: formatting warnings

* fix: more formatting warnings

* fix: more formatting
2022-10-14 21:54:21 +02:00

200 lines
9.2 KiB
TypeScript

import { Fragment } from "react";
import { Link, NavLink, Outlet } from "react-router-dom";
import { Disclosure, Menu, Transition } from "@headlessui/react";
import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/solid";
import { Bars3Icon, ChevronDownIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { AuthContext } from "../utils/Context";
import logo from "../logo.png";
interface NavItem {
name: string;
path: string;
}
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(" ");
}
export default function Base() {
const authContext = AuthContext.useValue();
const nav: Array<NavItem> = [
{ name: "Dashboard", path: "/" },
{ name: "Filters", path: "/filters" },
{ name: "Releases", path: "/releases" },
{ name: "Settings", path: "/settings" },
{ name: "Logs", path: "/logs" }
];
return (
<div className="min-h-screen">
<Disclosure
as="nav"
className="bg-gradient-to-b from-gray-100 dark:from-[#141414]"
>
{({ open }) => (
<>
<div className="max-w-screen-xl mx-auto sm:px-6 lg:px-8">
<div className="border-b border-gray-300 dark:border-gray-700">
<div className="flex items-center justify-between h-16 px-4 sm:px-0">
<div className="flex items-center">
<div className="flex-shrink-0 flex items-center">
<img
className="block lg:hidden h-10 w-auto"
src={logo}
alt="Logo"
/>
<img
className="hidden lg:block h-10 w-auto"
src={logo}
alt="Logo"
/>
</div>
<div className="sm:ml-3 hidden sm:block">
<div className="flex items-baseline space-x-4">
{nav.map((item, itemIdx) =>
<NavLink
key={item.name + itemIdx}
to={item.path}
className={({ isActive }) => classNames(
"hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-2xl text-sm font-medium",
"transition-colors duration-200",
isActive ? "text-black dark:text-gray-50 font-bold" : "text-gray-600 dark:text-gray-500"
)}
end={item.path === "/"}
>
{item.name}
</NavLink>
)}
<a
rel="noopener noreferrer"
target="_blank"
href="https://autobrr.com"
className={classNames(
"text-gray-600 dark:text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-2xl text-sm font-medium",
"transition-colors duration-200 flex items-center justify-center"
)}
>
Docs
<ArrowTopRightOnSquareIcon className="inline ml-1 h-5 w-5" aria-hidden="true" />
</a>
</div>
</div>
</div>
<div className="hidden sm:block">
<div className="ml-4 flex items-center sm:ml-6">
<Menu as="div" className="ml-3 relative">
{({ open }) => (
<>
<Menu.Button
className={classNames(
open ? "bg-gray-200 dark:bg-gray-800" : "",
"text-gray-800 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-800",
"max-w-xs rounded-full flex items-center text-sm px-3 py-2",
"transition-colors duration-200"
)}
>
<span className="hidden text-sm font-medium sm:block">
<span className="sr-only">Open user menu for </span>
{authContext.username}
</span>
<ChevronDownIcon
className="hidden flex-shrink-0 ml-1 h-5 w-5 text-gray-800 dark:text-gray-300 sm:block"
aria-hidden="true"
/>
</Menu.Button>
<Transition
show={open}
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
static
className="origin-top-right absolute right-0 mt-2 w-48 z-10 rounded-md shadow-lg py-1 bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<Menu.Item>
{({ active }) => (
<Link
to="/settings"
className={classNames(
active ? "bg-gray-100 dark:bg-gray-600" : "",
"block px-4 py-2 text-sm text-gray-900 dark:text-gray-200"
)}
>
Settings
</Link>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<Link
to="/logout"
className={classNames(
active ? "bg-gray-100 dark:bg-gray-600" : "",
"block px-4 py-2 text-sm text-gray-900 dark:text-gray-200"
)}
>
Logout
</Link>
)}
</Menu.Item>
</Menu.Items>
</Transition>
</>
)}
</Menu>
</div>
</div>
<div className="-mr-2 flex sm:hidden">
{/* Mobile menu button */}
<Disclosure.Button
className="bg-gray-200 dark:bg-gray-800 inline-flex items-center justify-center p-2 rounded-md text-gray-600 dark:text-gray-400 hover:text-white hover:bg-gray-700">
<span className="sr-only">Open main menu</span>
{open ? (
<XMarkIcon className="block h-6 w-6" aria-hidden="true"/>
) : (
<Bars3Icon className="block h-6 w-6" aria-hidden="true"/>
)}
</Disclosure.Button>
</div>
</div>
</div>
</div>
<Disclosure.Panel className="border-b border-gray-300 dark:border-gray-700 md:hidden">
<div className="px-2 py-3 space-y-1 sm:px-3">
{nav.map((item) =>
<NavLink
key={item.path}
to={item.path}
className={({ isActive }) => classNames(
"shadow-sm border bg-gray-100 border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-white block px-3 py-2 rounded-md text-base",
isActive ? "underline underline-offset-2 decoration-2 decoration-sky-500 font-bold text-black" : "font-medium"
)}
end={item.path === "/"}
>
{item.name}
</NavLink>
)}
<Link
to="/logout"
className="shadow-sm border bg-gray-100 border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-white block px-3 py-2 rounded-md text-base font-medium"
>
Logout
</Link>
</div>
</Disclosure.Panel>
</>
)}
</Disclosure>
<Outlet />
</div>
);
}