mirror of
https://github.com/ilyakooo0/urbit.git
synced 2025-01-04 13:19:48 +03:00
nav: fixing dimming and inter nav clicks
This commit is contained in:
parent
f8bfbf1bbb
commit
65b9f229c5
@ -22,7 +22,7 @@ const variants: Record<ButtonVariant, string> = {
|
||||
secondary: 'text-black bg-gray-100',
|
||||
caution: 'text-white bg-orange-400',
|
||||
destructive: 'text-white bg-red-500',
|
||||
'alt-primary': 'text-white bg-blue-400',
|
||||
'alt-primary': 'text-white bg-blue-400 ring-blue-300',
|
||||
'alt-secondary': 'text-blue-400 bg-blue-50'
|
||||
};
|
||||
|
||||
|
@ -35,9 +35,11 @@ type LeapProps = {
|
||||
menu: MenuState;
|
||||
dropdown: string;
|
||||
navOpen: boolean;
|
||||
shouldDim: boolean;
|
||||
} & HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
export const Leap = React.forwardRef(({ menu, dropdown, navOpen, className }: LeapProps, ref) => {
|
||||
export const Leap = React.forwardRef(
|
||||
({ menu, dropdown, navOpen, shouldDim, className }: LeapProps, ref) => {
|
||||
const { push } = useHistory();
|
||||
const match = useRouteMatch<{ menu?: MenuState; query?: string; desk?: string }>(
|
||||
`/leap/${menu}/:query?/(apps)?/:desk?`
|
||||
@ -200,7 +202,7 @@ export const Leap = React.forwardRef(({ menu, dropdown, navOpen, className }: Le
|
||||
<form
|
||||
className={classNames(
|
||||
'flex items-center h-full w-full px-2 rounded-full bg-white default-ring focus-within:ring-2',
|
||||
navOpen && menu !== 'search' && 'opacity-60',
|
||||
shouldDim && 'opacity-60',
|
||||
!navOpen ? 'bg-gray-50' : '',
|
||||
className
|
||||
)}
|
||||
@ -243,4 +245,5 @@ export const Leap = React.forwardRef(({ menu, dropdown, navOpen, className }: Le
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -52,33 +52,6 @@ export type MenuState =
|
||||
| 'help-and-support'
|
||||
| 'system-preferences';
|
||||
|
||||
export function createNextPath(current: string, nextPart?: string): string {
|
||||
let end = nextPart;
|
||||
const parts = current.split('/').reverse();
|
||||
if (parts[1] === 'search') {
|
||||
end = 'apps';
|
||||
}
|
||||
|
||||
if (parts[0] === 'leap') {
|
||||
end = `search/${nextPart}`;
|
||||
}
|
||||
|
||||
return `${current}/${end}`;
|
||||
}
|
||||
|
||||
export function createPreviousPath(current: string): string {
|
||||
const parts = current.split('/');
|
||||
parts.pop();
|
||||
|
||||
if (parts[parts.length - 1] === 'leap') {
|
||||
parts.push('search');
|
||||
}
|
||||
if (parts[parts.length - 2] === 'apps') {
|
||||
parts.pop();
|
||||
}
|
||||
return parts.join('/');
|
||||
}
|
||||
|
||||
interface NavProps {
|
||||
menu?: MenuState;
|
||||
}
|
||||
@ -123,6 +96,15 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const preventClose = useCallback((e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const hasNavAncestor = target.closest('#dialog-nav');
|
||||
|
||||
if (hasNavAncestor) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Using portal so that we can retain the same nav items both in the dialog and in the base header */}
|
||||
@ -132,12 +114,20 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
|
||||
>
|
||||
<SystemMenu
|
||||
open={!!systemMenuOpen}
|
||||
menu={menuState}
|
||||
navOpen={isOpen}
|
||||
shouldDim={isOpen && menu !== 'system-preferences' && menu !== 'help-and-support'}
|
||||
className={classNames('relative z-50 flex-none', eitherOpen ? 'bg-white' : 'bg-gray-50')}
|
||||
/>
|
||||
<NotificationsLink menu={menuState} navOpen={isOpen} />
|
||||
<Leap ref={inputRef} menu={menuState} dropdown="leap-items" navOpen={isOpen} />
|
||||
<NotificationsLink
|
||||
navOpen={isOpen}
|
||||
shouldDim={(isOpen && menu !== 'notifications') || !!systemMenuOpen}
|
||||
/>
|
||||
<Leap
|
||||
ref={inputRef}
|
||||
menu={menuState}
|
||||
dropdown="leap-items"
|
||||
navOpen={isOpen}
|
||||
shouldDim={(isOpen && menu !== 'search') || !!systemMenuOpen}
|
||||
/>
|
||||
</Portal.Root>
|
||||
<div
|
||||
ref={navRef}
|
||||
@ -152,6 +142,7 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
|
||||
/>
|
||||
<Dialog open={isOpen} onOpenChange={onDialogClose}>
|
||||
<DialogContent
|
||||
onInteractOutside={preventClose}
|
||||
onOpenAutoFocus={onOpen}
|
||||
className="fixed bottom-0 sm:top-0 sm:bottom-auto scroll-left-50 flex flex-col scroll-full-width max-w-[882px] px-4 sm:pb-4 text-gray-400 -translate-x-1/2 outline-none"
|
||||
role="combobox"
|
||||
@ -160,6 +151,7 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
<header
|
||||
id="dialog-nav"
|
||||
ref={dialogNavRef}
|
||||
className="max-w-[712px] w-full mx-auto my-6 sm:mb-3 order-last sm:order-none"
|
||||
/>
|
||||
|
@ -4,7 +4,6 @@ import { Link, LinkProps } from 'react-router-dom';
|
||||
import { Bullet } from '../components/icons/Bullet';
|
||||
import { Notification } from '../state/hark-types';
|
||||
import { useNotifications } from '../state/notifications';
|
||||
import { MenuState } from './Nav';
|
||||
|
||||
type NotificationsState = 'empty' | 'unread' | 'attention-needed';
|
||||
|
||||
@ -25,11 +24,11 @@ function getNotificationsState(
|
||||
}
|
||||
|
||||
type NotificationsLinkProps = Omit<LinkProps<HTMLAnchorElement>, 'to'> & {
|
||||
menu: MenuState;
|
||||
navOpen: boolean;
|
||||
shouldDim: boolean;
|
||||
};
|
||||
|
||||
export const NotificationsLink = ({ navOpen, menu }: NotificationsLinkProps) => {
|
||||
export const NotificationsLink = ({ navOpen, shouldDim }: NotificationsLinkProps) => {
|
||||
const { notifications, systemNotifications } = useNotifications();
|
||||
const state = getNotificationsState(notifications, systemNotifications);
|
||||
|
||||
@ -39,7 +38,7 @@ export const NotificationsLink = ({ navOpen, menu }: NotificationsLinkProps) =>
|
||||
className={classNames(
|
||||
'relative z-50 flex-none circle-button h4 default-ring',
|
||||
navOpen && 'text-opacity-60',
|
||||
navOpen && menu !== 'notifications' && 'opacity-60',
|
||||
shouldDim && 'opacity-60',
|
||||
state === 'empty' && !navOpen && 'text-gray-400 bg-gray-50',
|
||||
state === 'empty' && navOpen && 'text-gray-400 bg-white',
|
||||
state === 'unread' && 'bg-blue-400 text-white',
|
||||
|
@ -7,13 +7,11 @@ import { Vat } from '@urbit/api/hood';
|
||||
import { Adjust } from '../components/icons/Adjust';
|
||||
import { useVat } from '../state/kiln';
|
||||
import { disableDefault, handleDropdownLink } from '../state/util';
|
||||
import { MenuState } from './Nav';
|
||||
import { useMedia } from '../logic/useMedia';
|
||||
|
||||
type SystemMenuProps = HTMLAttributes<HTMLButtonElement> & {
|
||||
menu: MenuState;
|
||||
open: boolean;
|
||||
navOpen: boolean;
|
||||
shouldDim: boolean;
|
||||
};
|
||||
|
||||
function getHash(vat: Vat): string {
|
||||
@ -21,7 +19,7 @@ function getHash(vat: Vat): string {
|
||||
return parts[parts.length - 1];
|
||||
}
|
||||
|
||||
export const SystemMenu = ({ className, menu, open, navOpen }: SystemMenuProps) => {
|
||||
export const SystemMenu = ({ className, open, shouldDim }: SystemMenuProps) => {
|
||||
const { push } = useHistory();
|
||||
const [copied, setCopied] = useState(false);
|
||||
const garden = useVat('garden');
|
||||
@ -61,10 +59,7 @@ export const SystemMenu = ({ className, menu, open, navOpen }: SystemMenuProps)
|
||||
className={classNames(
|
||||
'appearance-none circle-button default-ring',
|
||||
open && 'text-gray-300',
|
||||
navOpen &&
|
||||
menu !== 'system-preferences' &&
|
||||
menu !== 'help-and-support' &&
|
||||
'opacity-60',
|
||||
shouldDim && 'opacity-60',
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
@ -53,8 +53,8 @@ export const SystemPreferences = (props: RouteComponentProps<{ submenu: string }
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex h-[600px] max-h-full">
|
||||
<aside className="flex-none min-w-60 border-r-2 border-gray-50">
|
||||
<div className="flex h-full overflow-y-auto">
|
||||
<aside className="flex-none min-w-60">
|
||||
<div className="p-8">
|
||||
<input className="input h4 default-ring bg-gray-50" placeholder="Search Preferences" />
|
||||
</div>
|
||||
@ -84,7 +84,7 @@ export const SystemPreferences = (props: RouteComponentProps<{ submenu: string }
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
<section className="flex-1 p-8 text-black">
|
||||
<section className="flex-1 min-h-[600px] p-8 text-black border-l-2 border-gray-50">
|
||||
<Switch>
|
||||
<Route path={`${match.url}/system-updates`} component={SystemUpdatePrefs} />
|
||||
<Route path={`${match.url}/interface`} component={InterfacePrefs} />
|
||||
|
@ -11,6 +11,10 @@ export const TileInfo = () => {
|
||||
const charge = useCharge(desk);
|
||||
const vat = useVat(desk);
|
||||
|
||||
if (!charge) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open onOpenChange={(open) => !open && push('/')}>
|
||||
<DialogContent>
|
||||
|
Loading…
Reference in New Issue
Block a user