Skip to content

Commit

Permalink
Improve Navbar for smaller screens (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
JorWo authored Aug 10, 2024
1 parent fd9c28b commit 3a420dc
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 168 deletions.
59 changes: 0 additions & 59 deletions ui/src/components/layout/navbar/mobile-navbar.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Role from '@/access/role';

export const NavLinks = [
export const NavbarLinks = [
{
name: 'Admin',
link: '/admin',
Expand Down
21 changes: 21 additions & 0 deletions ui/src/components/layout/navbar/navbar-menu-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const NavbarMenuIcon = ({ open }: { open: boolean }) => (
<div className="flex flex-col justify-center items-center">
<span
data-open={open}
className={`bg-gray-600 block transition-all transform duration-300 ease-out h-0.5 w-5
rounded-lg data-[open=true]:rotate-45 data-[open=true]:translate-y-1 -translate-y-0.5`}
/>
<span
data-open={open}
className={`bg-gray-600 block transition-all transform duration-300 ease-out h-0.5 w-5
rounded-lg my-0.5 data-[open=true]:opacity-0 opacity-100`}
/>
<span
data-open={open}
className={`bg-gray-600 block transition transform duration-300 ease-out h-0.5 w-5
rounded-lg data-[open=true]:-rotate-45 data-[open=true]:-translate-y-1 translate-y-0.5`}
/>
</div>
);

export default NavbarMenuIcon;
39 changes: 39 additions & 0 deletions ui/src/components/layout/navbar/navbar-menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use client';

import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
import User from '@/access/user';
import Link from 'next/link';
import { NavbarLinks } from './navbar-links';
import { useState } from 'react';
import Role from '@/access/role';
import NavbarMenuIcon from './navbar-menu-icon';

const NavbarMenu = ({ currentUser }: { currentUser: User }) => {
const [open, setOpen] = useState(false);
const handleClick = () => {
setOpen(!open);
};

return (
<Sheet open={open}>
<SheetTrigger className="mr-3 lg:hidden" onClick={handleClick} aria-label="Open navigation menu">
<NavbarMenuIcon open={open} aria-hidden="true" />
</SheetTrigger>

<SheetContent className="mt-[3.9rem] text-xl pt-5 lg:hidden" side="top" onClickOutside={handleClick}>
<nav className="container flex flex-col space-y-5 h-1/4">
{NavbarLinks
.filter((navbarLink) =>
currentUser.roles.includes(Role.ADMIN) ||
currentUser.roles.includes(navbarLink.role))
.map((navbarLink) =>
<Link href={navbarLink.link} key={navbarLink.name} className="hover:text-uh-teal">
{navbarLink.name}
</Link>)}
</nav>
</SheetContent>
</Sheet>
);
};

export default NavbarMenu;
21 changes: 11 additions & 10 deletions ui/src/components/layout/navbar/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import Link from 'next/link';
import Image from 'next/image';
import Role from '@/access/role';
import { getCurrentUser } from '@/access/authentication';
import { NavLinks } from './nav-links';
import { NavbarLinks } from './navbar-links';
import LoginButton from './login-button';
import MobileNavbar from './mobile-navbar';
import NavbarMenu from './navbar-menu';
import TimeoutModal from '@/components/modal/timeout-modal';

const Navbar = async () => {
Expand All @@ -24,7 +24,7 @@ const Navbar = async () => {
/>
</Link>
<div className="flex lg:hidden">
<MobileNavbar currentUser={currentUser} />
<NavbarMenu currentUser={currentUser} />
<Link href="/">
<Image
src="/uhgroupings/uh-groupings-logo-large.svg"
Expand All @@ -35,15 +35,16 @@ const Navbar = async () => {
</Link>
</div>
<div className="text-lg text-uh-black my-auto lg:space-x-5">
{NavLinks
.filter((navLink) =>
currentUser.roles.includes(Role.ADMIN) || currentUser.roles.includes(navLink.role))
.map((navLink) =>
{NavbarLinks
.filter((navbarLink) =>
currentUser.roles.includes(Role.ADMIN) ||
currentUser.roles.includes(navbarLink.role))
.map((navbarLink) =>
<Link
href={navLink.link}
key={navLink.name}
href={navbarLink.link}
key={navbarLink.name}
className="hover:text-uh-teal lg:inline hidden">
{navLink.name}
{navbarLink.name}
</Link>)}
<LoginButton currentUser={currentUser} />
</div>
Expand Down
154 changes: 65 additions & 89 deletions ui/src/components/ui/sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,20 @@ import { cn } from '@/components/ui/utils';

const Sheet = SheetPrimitive.Root;

const SheetClose = SheetPrimitive.Close
const SheetClose = SheetPrimitive.Close;

const SheetPortal = SheetPrimitive.Portal
const SheetPortal = SheetPrimitive.Portal;

interface SheetTriggerProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Trigger> {
onClick?: () => void
interface SheetTriggerProps extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Trigger> {
onClick?: () => void;
}
const SheetTrigger = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Trigger>,
SheetTriggerProps
>(({ onClick, className, children, ...props }, ref) => (
<SheetPrimitive.Trigger
className={className}
onClick={onClick}
{...props}
ref={ref}>
{children}
</SheetPrimitive.Trigger>
));
const SheetTrigger = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Trigger>, SheetTriggerProps>(
({ onClick, className, children, ...props }, ref) => (
<SheetPrimitive.Trigger className={className} onClick={onClick} {...props} ref={ref}>
{children}
</SheetPrimitive.Trigger>
)
);
SheetTrigger.displayName = SheetPrimitive.Trigger.displayName;

const SheetOverlay = React.forwardRef<
Expand All @@ -44,11 +38,11 @@ const SheetOverlay = React.forwardRef<
{...props}
ref={ref}
/>
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
));
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;

const sheetVariants = cva(
`fixed z-50 gap-4 bg-white p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in
`fixed z-40 gap-4 bg-white py-6 shadow-lg transition ease-in-out data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500
dark:bg-slate-950`,
{
Expand All @@ -61,80 +55,62 @@ const sheetVariants = cva(
left: `inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left
data-[state=open]:slide-in-from-left sm:max-w-sm`,
right: `inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right
data-[state=open]:slide-in-from-right sm:max-w-sm`,
data-[state=open]:slide-in-from-right sm:max-w-sm`
}
},
defaultVariants: {
side: 'right',
},
side: 'right'
}
}
)
);

interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {
onClickOutside?: () => void,
hasCloseButton?: boolean
VariantProps<typeof sheetVariants> {
onClickOutside?: () => void;
hasCloseButton?: boolean;
}

const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps
>(({ side = 'right', hasCloseButton = false, onClickOutside, className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay className={className} onClick={onClickOutside} />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
onInteractOutside={(e) => {
e.preventDefault();
}}
>
{children}

{hasCloseButton && (
<SheetPrimitive.Close
className={`absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity
const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Content>, SheetContentProps>(
({ side = 'right', hasCloseButton = false, onClickOutside, className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay className={className} onClick={onClickOutside} />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
onInteractOutside={(e) => {
e.preventDefault();
}}
>
{children}

{hasCloseButton && (
<SheetPrimitive.Close
className={`absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity
hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2
disabled:pointer-events-none data-[state=open]:bg-slate-100 dark:ring-offset-slate-950
dark:focus:ring-slate-300 dark:data-[state=open]:bg-slate-800`}>
<X className='h-4 w-4' />
<span className='sr-only'>Close</span>
</SheetPrimitive.Close>
)}
</SheetPrimitive.Content>
</SheetPortal>
))
SheetContent.displayName = SheetPrimitive.Content.displayName

const SheetHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
'flex flex-col space-y-2 text-center sm:text-left',
className
)}
{...props}
/>
)
SheetHeader.displayName = 'SheetHeader'

const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
className
)}
{...props}
/>
)
SheetFooter.displayName = 'SheetFooter'
dark:focus:ring-slate-300 dark:data-[state=open]:bg-slate-800`}
>
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
)}
</SheetPrimitive.Content>
</SheetPortal>
)
);
SheetContent.displayName = SheetPrimitive.Content.displayName;

const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
<div className={cn('flex flex-col space-y-2 text-center sm:text-left', className)} {...props} />
);
SheetHeader.displayName = 'SheetHeader';

const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
<div className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)} {...props} />
);
SheetFooter.displayName = 'SheetFooter';

const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>,
Expand All @@ -145,8 +121,8 @@ const SheetTitle = React.forwardRef<
className={cn('text-lg font-semibold text-slate-950 dark:text-slate-50', className)}
{...props}
/>
))
SheetTitle.displayName = SheetPrimitive.Title.displayName
));
SheetTitle.displayName = SheetPrimitive.Title.displayName;

const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>,
Expand All @@ -157,8 +133,8 @@ const SheetDescription = React.forwardRef<
className={cn('text-sm text-slate-500 dark:text-slate-400', className)}
{...props}
/>
))
SheetDescription.displayName = SheetPrimitive.Description.displayName
));
SheetDescription.displayName = SheetPrimitive.Description.displayName;

export {
Sheet,
Expand All @@ -170,5 +146,5 @@ export {
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}
SheetDescription
};
Loading

0 comments on commit 3a420dc

Please sign in to comment.