leap: fixing nav and mobile issues

This commit is contained in:
Hunter Miller 2021-08-17 14:40:34 -05:00
parent 8c799f9c38
commit 32dda74acf
5 changed files with 52 additions and 60 deletions

View File

@ -34,17 +34,18 @@ export function createPreviousPath(current: string): string {
type LeapProps = {
menu: MenuState;
dropdown: string;
showClose: boolean;
} & HTMLAttributes<HTMLDivElement>;
export const Leap = React.forwardRef(({ menu, dropdown, className }: LeapProps, ref) => {
export const Leap = React.forwardRef(({ menu, dropdown, showClose, className }: LeapProps, ref) => {
const { push } = useHistory();
const match = useRouteMatch<{ query?: string; desk?: string }>(
const match = useRouteMatch<{ menu?: MenuState; query?: string; desk?: string }>(
`/leap/${menu}/:query?/(apps)?/:desk?`
);
const appsMatch = useRouteMatch(`/leap/${menu}/${match?.params.query}/apps`);
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => inputRef.current);
const { rawInput, searchInput, selectedMatch, matches, selection, select } = useLeapStore();
const { rawInput, selectedMatch, matches, selection, select } = useLeapStore();
const toggleSearch = useCallback(() => {
if (selection || menu === 'search') {
@ -54,15 +55,18 @@ export const Leap = React.forwardRef(({ menu, dropdown, className }: LeapProps,
push('/leap/search');
}, [selection, menu]);
const onFocus = useCallback((e: FocusEvent<HTMLInputElement>) => {
// refocusing tab with input focused is false trigger
const windowFocus = e.nativeEvent.currentTarget === document.body;
if (windowFocus) {
return;
}
const onFocus = useCallback(
(e: FocusEvent<HTMLInputElement>) => {
// refocusing tab with input focused is false trigger
const windowFocus = e.nativeEvent.currentTarget === document.body;
if (windowFocus) {
return;
}
toggleSearch();
}, []);
toggleSearch();
},
[toggleSearch]
);
const getMatch = useCallback(
(value: string) => {
@ -212,7 +216,7 @@ export const Leap = React.forwardRef(({ menu, dropdown, className }: LeapProps,
aria-controls={dropdown}
aria-activedescendant={selectedMatch?.display || selectedMatch?.value}
/>
{(selection || searchInput) && (
{showClose && (
<Link
to="/"
className="circle-button w-8 h-8 text-gray-400 bg-gray-100 default-ring"

View File

@ -51,22 +51,32 @@ interface NavProps {
menu?: MenuState;
}
export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
const { push } = useHistory();
const inputRef = useRef<HTMLInputElement>(null);
const navRef = useRef<HTMLDivElement>(null);
const dialogNavRef = useRef<HTMLDivElement>(null);
const [systemMenuOpen, setSystemMenuOpen] = useState(false);
const [dialogContentOpen, setDialogContentOpen] = useState(false);
const { selection, select } = useLeapStore((state) => ({
selectedMatch: state.selectedMatch,
selection: state.selection,
select: state.select
}));
const [systemMenuOpen, setSystemMenuOpen] = useState(false);
const [dialogContentOpen, setDialogContentOpen] = useState(false);
const isOpen = menu !== 'closed';
const menuState = menu || 'closed';
const isOpen = menuState !== 'closed';
const eitherOpen = isOpen || systemMenuOpen;
useEffect(() => {
if (!isOpen) {
select(null);
setDialogContentOpen(false);
} else {
inputRef.current?.focus();
}
}, [selection, isOpen]);
const onOpen = useCallback(
(event: Event) => {
event.preventDefault();
@ -81,14 +91,8 @@ export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
[menu]
);
useEffect(() => {
inputRef.current?.focus();
}, [selection]);
const onDialogClose = useCallback((open: boolean) => {
if (!open) {
select(null);
setDialogContentOpen(false);
push('/');
}
}, []);
@ -112,8 +116,9 @@ export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
</Link>
<Leap
ref={inputRef}
menu={menu}
menu={menuState}
dropdown="leap-items"
showClose={isOpen}
className={!isOpen ? 'bg-gray-100' : ''}
/>
</Portal.Root>

View File

@ -3,25 +3,25 @@
}
.button {
@apply inline-flex items-center justify-center px-4 py-2 font-semibold text-base tracking-tight rounded-lg cursor-pointer;
@apply inline-flex items-center justify-center px-4 py-2 font-semibold text-base tracking-tight rounded-lg cursor-pointer;
}
.dialog-container {
@apply fixed z-40 top-1/2 left-1/2 min-w-80 transform -translate-x-1/2 -translate-y-1/2;
@apply fixed z-40 top-1/2 left-1/2 min-w-80 transform -translate-x-1/2 -translate-y-1/2;
}
.dialog {
@apply relative p-5 sm:p-8 bg-white rounded-3xl;
@apply relative p-5 sm:p-8 bg-white rounded-3xl;
}
.dialog-inner-container {
@apply h-full p-4 md:p-8 space-y-8 overflow-y-auto;
@apply h-full p-4 md:p-8 space-y-8 overflow-y-auto;
}
.dropdown {
@apply min-w-52 p-4 space-y-4 rounded-xl;
@apply min-w-52 p-4 rounded-xl;
}
.spinner {
@apply inline-flex items-center w-6 h-6 animate-spin;
@apply inline-flex items-center w-6 h-6 animate-spin;
}

View File

@ -44,7 +44,7 @@ export const Tile: FunctionComponent<TileProps> = ({ docket, desk }) => {
active={active}
menuColor={menuColor}
lightText={lightText}
className="absolute z-10 top-2.5 right-2.5 sm:top-4 sm:right-4 opacity-0 hover-none:opacity-100 focus:opacity-100 group-hover:opacity-100"
className="absolute z-10 top-2.5 right-2.5 sm:top-4 sm:right-4 opacity-0 hover-none:opacity-100 pointer-coarse:opacity-100 focus:opacity-100 group-hover:opacity-100"
/>
<div className="h4 absolute bottom-4 left-4 lg:bottom-8 lg:left-8">
<h3

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useCallback, useState } from 'react';
import type * as Polymorphic from '@radix-ui/react-polymorphic';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import classNames from 'classnames';
@ -31,7 +31,7 @@ const Item = React.forwardRef(({ children, ...props }, ref) => (
<DropdownMenu.Item
ref={ref}
{...props}
className="block w-full px-4 py-1 leading-none rounded mix-blend-hard-light select-none default-ring ring-gray-600"
className="block w-full px-4 py-3 leading-none rounded mix-blend-hard-light select-none default-ring ring-gray-600"
>
{children}
</DropdownMenu.Item>
@ -47,6 +47,10 @@ export const TileMenu = ({ desk, active, menuColor, lightText, className }: Tile
});
const menuBg = { backgroundColor: menuColor };
const linkOnSelect = useCallback((e: Event) => {
e.preventDefault();
setTimeout(() => setOpen(false), 15);
}, []);
return (
<DropdownMenu.Root open={open} onOpenChange={(isOpen) => setOpen(isOpen)}>
@ -71,50 +75,29 @@ export const TileMenu = ({ desk, active, menuColor, lightText, className }: Tile
sideOffset={4}
onCloseAutoFocus={(e) => e.preventDefault()}
className={classNames(
'dropdown font-semibold',
'dropdown py-2 font-semibold',
lightText ? 'text-gray-100' : 'text-gray-800'
)}
style={menuBg}
>
<DropdownMenu.Group className="space-y-4">
<DropdownMenu.Group>
{/*
TODO: revisit with Liam
<Item as={Link} to={`/leap/search/${provider}/apps/${name.toLowerCase()}`} onSelect={(e) => { e.preventDefault(); setTimeout(() => setOpen(false), 0) }}>App Info</Item>
*/}
<Item
as={Link}
to={`/app/${desk}`}
onSelect={(e) => {
e.preventDefault();
setTimeout(() => setOpen(false), 0);
}}
>
<Item as={Link} to={`/app/${desk}`} onSelect={linkOnSelect}>
App Info
</Item>
</DropdownMenu.Group>
<DropdownMenu.Separator className="-mx-4 my-2 border-t-2 border-solid border-gray-500 mix-blend-soft-light" />
<DropdownMenu.Group className="space-y-4">
<DropdownMenu.Group>
{active && (
<Item
as={Link}
to={`/app/${desk}/suspend`}
onSelect={(e) => {
e.preventDefault();
setTimeout(() => setOpen(false), 0);
}}
>
<Item as={Link} to={`/app/${desk}/suspend`} onSelect={linkOnSelect}>
Suspend App
</Item>
)}
{!active && <Item onSelect={() => mutate()}>Resume App</Item>}
<Item
as={Link}
to={`/app/${desk}/remove`}
onSelect={(e) => {
e.preventDefault();
setTimeout(() => setOpen(false), 0);
}}
>
<Item as={Link} to={`/app/${desk}/remove`} onSelect={linkOnSelect}>
Remove App
</Item>
</DropdownMenu.Group>