mirror of
https://github.com/urbit/shrub.git
synced 2024-12-25 21:12:56 +03:00
leap: portalled menu for less dupe
This commit is contained in:
parent
d89cfc7291
commit
edde5e3ec4
@ -1,4 +1,5 @@
|
|||||||
import { DialogContent } from '@radix-ui/react-dialog';
|
import { DialogContent } from '@radix-ui/react-dialog';
|
||||||
|
import * as Portal from '@radix-ui/react-portal';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React, {
|
import React, {
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
@ -80,8 +81,11 @@ export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
|
|||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
const navRef = useRef<HTMLDivElement>(null);
|
||||||
|
const dialogNavRef = useRef<HTMLDivElement>(null);
|
||||||
const { searchInput, setSearchInput, selection, select } = useNavStore();
|
const { searchInput, setSearchInput, selection, select } = useNavStore();
|
||||||
const [systemMenuOpen, setSystemMenuOpen] = useState(false);
|
const [systemMenuOpen, setSystemMenuOpen] = useState(false);
|
||||||
|
const [delayedOpen, setDelayedOpen] = useState(false);
|
||||||
|
|
||||||
const isOpen = menu !== 'closed';
|
const isOpen = menu !== 'closed';
|
||||||
const eitherOpen = isOpen || systemMenuOpen;
|
const eitherOpen = isOpen || systemMenuOpen;
|
||||||
@ -90,8 +94,11 @@ export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
|
|||||||
(event: Event) => {
|
(event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
setDelayedOpen(true);
|
||||||
if (menu === 'search' && inputRef.current) {
|
if (menu === 'search' && inputRef.current) {
|
||||||
inputRef.current.focus();
|
setTimeout(() => {
|
||||||
|
inputRef.current?.focus();
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[menu]
|
[menu]
|
||||||
@ -119,6 +126,7 @@ export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
|
|||||||
const onDialogClose = useCallback((open: boolean) => {
|
const onDialogClose = useCallback((open: boolean) => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
select(null);
|
select(null);
|
||||||
|
setDelayedOpen(false);
|
||||||
push('/');
|
push('/');
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
@ -156,91 +164,75 @@ export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<menu className="w-full max-w-3xl my-6 px-4 text-gray-400 font-semibold">
|
<>
|
||||||
<div className={classNames('flex space-x-2', isOpen && 'invisible')}>
|
<Portal.Root containerRef={delayedOpen ? dialogNavRef : navRef} className="flex space-x-2">
|
||||||
{!isOpen && (
|
<SystemMenu
|
||||||
<SystemMenu
|
open={systemMenuOpen}
|
||||||
showOverlay
|
setOpen={setSystemMenuOpen}
|
||||||
open={systemMenuOpen}
|
className={classNames('relative z-50 flex-none', eitherOpen ? 'bg-white' : 'bg-gray-100')}
|
||||||
setOpen={setSystemMenuOpen}
|
/>
|
||||||
className={classNames(
|
|
||||||
'relative z-50 flex-none',
|
|
||||||
eitherOpen ? 'bg-white' : 'bg-gray-100'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Link
|
<Link
|
||||||
to="/leap/notifications"
|
to="/leap/notifications"
|
||||||
className="relative z-50 flex-none circle-button bg-blue-400 text-white default-ring"
|
className="relative z-50 flex-none circle-button bg-blue-400 text-white"
|
||||||
>
|
>
|
||||||
3
|
3
|
||||||
</Link>
|
</Link>
|
||||||
<input
|
<form
|
||||||
onClick={toggleSearch}
|
className={classNames(
|
||||||
onFocus={onFocus}
|
'relative z-50 flex items-center w-full px-2 rounded-full bg-white default-ring focus-within:ring-4',
|
||||||
type="text"
|
!isOpen && 'bg-gray-100'
|
||||||
className="relative z-50 rounded-full w-full pl-4 h4 bg-gray-100 default-ring"
|
)}
|
||||||
placeholder="Search Landscape"
|
onSubmit={() => {}}
|
||||||
/>
|
>
|
||||||
</div>
|
<label
|
||||||
|
htmlFor="leap"
|
||||||
|
className={classNames(
|
||||||
|
'inline-block flex-none p-2 h4 text-blue-400',
|
||||||
|
!selection && 'sr-only'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{selection || 'Search Landscape'}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="leap"
|
||||||
|
type="text"
|
||||||
|
ref={inputRef}
|
||||||
|
placeholder={selection ? '' : 'Search Landscape'}
|
||||||
|
className="flex-1 w-full h-full px-2 h4 rounded-full bg-transparent outline-none"
|
||||||
|
value={searchInput}
|
||||||
|
onClick={toggleSearch}
|
||||||
|
onFocus={onFocus}
|
||||||
|
onChange={onChange}
|
||||||
|
role="combobox"
|
||||||
|
aria-controls="leap-items"
|
||||||
|
aria-expanded
|
||||||
|
/>
|
||||||
|
{(selection || searchInput) && (
|
||||||
|
<Link
|
||||||
|
to="/"
|
||||||
|
className="circle-button w-8 h-8 text-gray-400 bg-gray-100 default-ring"
|
||||||
|
onClick={() => select(null)}
|
||||||
|
>
|
||||||
|
<Cross className="w-3 h-3 fill-current" />
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
</Portal.Root>
|
||||||
|
<menu
|
||||||
|
ref={navRef}
|
||||||
|
className={classNames(
|
||||||
|
'w-full max-w-3xl my-6 px-4 text-gray-400 font-semibold',
|
||||||
|
delayedOpen && 'h-12'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<Dialog open={isOpen} onOpenChange={onDialogClose}>
|
<Dialog open={isOpen} onOpenChange={onDialogClose}>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
onOpenAutoFocus={onOpen}
|
onOpenAutoFocus={onOpen}
|
||||||
className="fixed top-0 left-[calc(50%-7.5px)] w-[calc(100%-15px)] max-w-3xl px-4 text-gray-400 -translate-x-1/2 outline-none"
|
className="fixed top-0 left-[calc(50%-7.5px)] w-[calc(100%-15px)] max-w-3xl px-4 text-gray-400 -translate-x-1/2 outline-none"
|
||||||
>
|
>
|
||||||
<div tabIndex={-1} onKeyDown={onDialogKey} role="presentation">
|
<div tabIndex={-1} onKeyDown={onDialogKey} role="presentation">
|
||||||
<header className="flex my-6 space-x-2">
|
<header ref={dialogNavRef} className="my-6" />
|
||||||
<SystemMenu
|
|
||||||
open={systemMenuOpen}
|
|
||||||
setOpen={setSystemMenuOpen}
|
|
||||||
className={classNames(
|
|
||||||
'relative z-50 flex-none',
|
|
||||||
eitherOpen ? 'bg-white' : 'bg-gray-100'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Link
|
|
||||||
to="/leap/notifications"
|
|
||||||
className="relative z-50 flex-none circle-button bg-blue-400 text-white"
|
|
||||||
>
|
|
||||||
3
|
|
||||||
</Link>
|
|
||||||
<div className="relative z-50 flex items-center w-full px-2 rounded-full bg-white default-ring focus-within:ring-4">
|
|
||||||
<label
|
|
||||||
htmlFor="leap"
|
|
||||||
className={classNames(
|
|
||||||
'inline-block flex-none p-2 h4 text-blue-400',
|
|
||||||
!selection && 'sr-only'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{selection || 'Search Landscape'}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="leap"
|
|
||||||
type="text"
|
|
||||||
ref={inputRef}
|
|
||||||
placeholder={selection ? '' : 'Search Landscape'}
|
|
||||||
className="flex-1 w-full h-full px-2 h4 rounded-full bg-transparent outline-none"
|
|
||||||
value={searchInput}
|
|
||||||
onClick={toggleSearch}
|
|
||||||
onFocus={onFocus}
|
|
||||||
onChange={onChange}
|
|
||||||
role="combobox"
|
|
||||||
aria-controls="leap-items"
|
|
||||||
aria-expanded
|
|
||||||
/>
|
|
||||||
{(selection || searchInput) && (
|
|
||||||
<Link
|
|
||||||
to="/"
|
|
||||||
className="circle-button w-8 h-8 text-gray-400 bg-gray-100 default-ring"
|
|
||||||
onClick={() => select(null)}
|
|
||||||
>
|
|
||||||
<Cross className="w-3 h-3 fill-current" />
|
|
||||||
<span className="sr-only">Close</span>
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<div
|
<div
|
||||||
id="leap-items"
|
id="leap-items"
|
||||||
className="grid grid-rows-[fit-content(calc(100vh-7.5rem))] bg-white rounded-3xl overflow-hidden"
|
className="grid grid-rows-[fit-content(calc(100vh-7.5rem))] bg-white rounded-3xl overflow-hidden"
|
||||||
@ -256,6 +248,6 @@ export const Nav: FunctionComponent<NavProps> = ({ menu = 'closed' }) => {
|
|||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</menu>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user