mirror of
https://github.com/urbit/shrub.git
synced 2024-11-30 22:15:47 +03:00
grid: tweaking focus styles first pass
This commit is contained in:
parent
5de3919e8c
commit
2ff5a39bf7
2
.gitignore
vendored
2
.gitignore
vendored
@ -78,3 +78,5 @@ pkg/interface/link-webext/web-ext-artifacts
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
.vercel
|
||||
|
13693
pkg/btc-wallet/package-lock.json
generated
13693
pkg/btc-wallet/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -35,8 +35,11 @@ export const AppLink = <T extends DocketWithDesk>({
|
||||
}: AppLinkProps<T>) => {
|
||||
const linkTo = to?.(app);
|
||||
const linkClassnames = classNames(
|
||||
'flex items-center default-ring ring-offset-2 rounded-lg',
|
||||
selected && 'ring-4',
|
||||
'flex items-center default-ring rounded-lg',
|
||||
size === 'default' && 'ring-offset-2',
|
||||
size !== 'xs' && 'p-2',
|
||||
size === 'xs' && 'p-1',
|
||||
selected && 'bg-blue-200',
|
||||
className
|
||||
);
|
||||
const link = (children: ReactNode) =>
|
||||
|
@ -11,7 +11,7 @@ type AppListProps<T extends DocketWithDesk> = {
|
||||
matchAgainst?: MatchItem;
|
||||
onClick?: (e: MouseEvent<HTMLAnchorElement>, app: T) => void;
|
||||
listClass?: string;
|
||||
} & Omit<AppLinkProps<T>, 'app' | 'onClick'>;
|
||||
} & Omit<AppLinkProps, 'app' | 'onClick'>;
|
||||
|
||||
export function appMatches(target: DocketWithDesk, match?: MatchItem): boolean {
|
||||
if (!match) {
|
||||
@ -27,7 +27,7 @@ export const AppList = <T extends DocketWithDesk>({
|
||||
labelledBy,
|
||||
matchAgainst,
|
||||
onClick,
|
||||
listClass = 'space-y-8',
|
||||
listClass,
|
||||
size = 'default',
|
||||
...props
|
||||
}: AppListProps<T>) => {
|
||||
@ -37,9 +37,9 @@ export const AppList = <T extends DocketWithDesk>({
|
||||
return (
|
||||
<ul
|
||||
className={classNames(
|
||||
size === 'default' && 'space-y-8',
|
||||
size === 'small' && 'space-y-4',
|
||||
size === 'xs' && 'space-y-2',
|
||||
size === 'default' && 'space-y-4',
|
||||
size !== 'xs' && '-mx-2',
|
||||
size === 'xs' && '-mx-1',
|
||||
listClass
|
||||
)}
|
||||
aria-labelledby={labelledBy}
|
||||
|
@ -23,8 +23,9 @@ export const ProviderLink = ({
|
||||
<Link
|
||||
to={(to && to(provider)) || `/leap/search/${provider.shipName}/apps`}
|
||||
className={classNames(
|
||||
'flex items-center space-x-3 default-ring ring-offset-2 rounded-lg',
|
||||
selected && 'ring-4',
|
||||
'flex items-center p-2 space-x-3 default-ring rounded-lg',
|
||||
!small && 'ring-offset-2',
|
||||
selected && 'bg-blue-200',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
@ -39,7 +39,7 @@ export const ProviderList = ({
|
||||
|
||||
return (
|
||||
<ul
|
||||
className={classNames(small ? 'space-y-4' : 'space-y-8', listClass)}
|
||||
className={classNames('-mx-2', !small && 'space-y-4', listClass)}
|
||||
aria-labelledby={labelledBy}
|
||||
>
|
||||
{providers.map((p) => (
|
||||
|
@ -1,14 +1,7 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useLeapStore } from './Nav';
|
||||
import React from 'react';
|
||||
import helpAndSupport from '../assets/help-and-support.svg';
|
||||
|
||||
export const Help = () => {
|
||||
const select = useLeapStore((state) => state.select);
|
||||
|
||||
useEffect(() => {
|
||||
select('Help and Support');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center px-4 py-8 md:px-8 md:py-16 space-y-8 md:space-y-16">
|
||||
<img className="w-52 h-auto" src={helpAndSupport} alt="" />
|
||||
|
@ -34,10 +34,10 @@ export function createPreviousPath(current: string): string {
|
||||
type LeapProps = {
|
||||
menu: MenuState;
|
||||
dropdown: string;
|
||||
showClose: boolean;
|
||||
navOpen: boolean;
|
||||
} & HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
export const Leap = React.forwardRef(({ menu, dropdown, showClose, className }: LeapProps, ref) => {
|
||||
export const Leap = React.forwardRef(({ menu, dropdown, navOpen, className }: LeapProps, ref) => {
|
||||
const { push } = useHistory();
|
||||
const match = useRouteMatch<{ menu?: MenuState; query?: string; desk?: string }>(
|
||||
`/leap/${menu}/:query?/(apps)?/:desk?`
|
||||
@ -196,47 +196,51 @@ export const Leap = React.forwardRef(({ menu, dropdown, showClose, className }:
|
||||
);
|
||||
|
||||
return (
|
||||
<form
|
||||
className={classNames(
|
||||
'relative z-50 flex items-center w-full px-2 rounded-full bg-white default-ring focus-within:ring-4',
|
||||
className
|
||||
)}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<label
|
||||
htmlFor="leap"
|
||||
<div className="relative z-50 w-full">
|
||||
<form
|
||||
className={classNames(
|
||||
'inline-block flex-none p-2 h4 text-blue-400',
|
||||
!selection && 'sr-only'
|
||||
'flex items-center h-full w-full px-2 rounded-full bg-white default-ring focus-within:ring-2',
|
||||
navOpen && menu !== 'search' && 'opacity-80',
|
||||
!navOpen ? 'bg-gray-100' : '',
|
||||
className
|
||||
)}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
{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={rawInput}
|
||||
onClick={toggleSearch}
|
||||
onFocus={onFocus}
|
||||
onChange={onChange}
|
||||
onKeyDown={onKeyDown}
|
||||
aria-autocomplete="both"
|
||||
aria-controls={dropdown}
|
||||
aria-activedescendant={selectedMatch?.display || selectedMatch?.value}
|
||||
/>
|
||||
{showClose && (
|
||||
<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 px-2 h4 rounded-full bg-transparent outline-none"
|
||||
value={rawInput}
|
||||
onClick={toggleSearch}
|
||||
onFocus={onFocus}
|
||||
onChange={onChange}
|
||||
onKeyDown={onKeyDown}
|
||||
aria-autocomplete="both"
|
||||
aria-controls={dropdown}
|
||||
aria-activedescendant={selectedMatch?.display || selectedMatch?.value}
|
||||
/>
|
||||
</form>
|
||||
{navOpen && (
|
||||
<Link
|
||||
to="/"
|
||||
className="circle-button w-8 h-8 text-gray-400 bg-gray-100 default-ring"
|
||||
className="absolute top-1/2 right-2 flex-none circle-button w-8 h-8 text-gray-400 bg-gray-100 default-ring -translate-y-1/2"
|
||||
onClick={() => select(null)}
|
||||
>
|
||||
<Cross className="w-3 h-3 fill-current" />
|
||||
<span className="sr-only">Close</span>
|
||||
</Link>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -142,17 +142,12 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
|
||||
<SystemMenu
|
||||
open={systemMenuOpen}
|
||||
setOpen={setSystemMenuOpen}
|
||||
showOverlay={!isOpen}
|
||||
menu={menuState}
|
||||
navOpen={isOpen}
|
||||
className={classNames('relative z-50 flex-none', eitherOpen ? 'bg-white' : 'bg-gray-100')}
|
||||
/>
|
||||
<NotificationsLink isOpen={isOpen} />
|
||||
<Leap
|
||||
ref={inputRef}
|
||||
menu={menuState}
|
||||
dropdown="leap-items"
|
||||
showClose={isOpen}
|
||||
className={classNames('flex-1 max-w-[600px]', !isOpen ? 'bg-gray-100' : '')}
|
||||
/>
|
||||
<NotificationsLink menu={menuState} navOpen={isOpen} />
|
||||
<Leap ref={inputRef} menu={menuState} dropdown="leap-items" navOpen={isOpen} />
|
||||
</Portal.Root>
|
||||
<div
|
||||
ref={navRef}
|
||||
@ -169,7 +164,7 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
|
||||
<DialogContent
|
||||
onOpenAutoFocus={onOpen}
|
||||
onInteractOutside={disableCloseWhenDropdownOpen}
|
||||
className="fixed bottom-0 sm:top-0 scroll-left-50 flex flex-col scroll-full-width max-w-3xl px-4 pb-4 text-gray-400 -translate-x-1/2 outline-none"
|
||||
className="fixed bottom-0 sm:top-0 scroll-left-50 flex flex-col scroll-full-width max-w-3xl px-4 sm:pb-4 text-gray-400 -translate-x-1/2 outline-none"
|
||||
role="combobox"
|
||||
aria-controls="leap-items"
|
||||
aria-owns="leap-items"
|
||||
@ -178,7 +173,7 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
|
||||
<header ref={dialogNavRef} className="my-6 order-last sm:order-none" />
|
||||
<div
|
||||
id="leap-items"
|
||||
className="grid grid-rows-[fit-content(100vh)] bg-white rounded-3xl overflow-hidden default-ring"
|
||||
className="grid grid-rows-[fit-content(100vh)] bg-white rounded-3xl overflow-hidden default-ring focus-visible:ring-2"
|
||||
tabIndex={0}
|
||||
role="listbox"
|
||||
>
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useLeapStore } from './Nav';
|
||||
import { Button } from '../components/Button';
|
||||
import { Notification } from '../state/hark-types';
|
||||
import { BasicNotification } from './notifications/BasicNotification';
|
||||
@ -27,12 +26,12 @@ const Empty = () => (
|
||||
);
|
||||
|
||||
export const Notifications = () => {
|
||||
const select = useLeapStore((s) => s.select);
|
||||
// const select = useLeapStore((s) => s.select);
|
||||
const { notifications, systemNotifications, hasAnyNotifications } = useNotifications();
|
||||
|
||||
useEffect(() => {
|
||||
select('Notifications');
|
||||
}, []);
|
||||
// useEffect(() => {
|
||||
// select('Notifications');
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<div className="grid grid-rows-[auto,1fr] h-full p-4 md:p-8 overflow-hidden">
|
||||
|
@ -4,6 +4,7 @@ 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';
|
||||
|
||||
@ -24,10 +25,11 @@ function getNotificationsState(
|
||||
}
|
||||
|
||||
type NotificationsLinkProps = Omit<LinkProps<HTMLAnchorElement>, 'to'> & {
|
||||
isOpen: boolean;
|
||||
menu: MenuState;
|
||||
navOpen: boolean;
|
||||
};
|
||||
|
||||
export const NotificationsLink = ({ isOpen }: NotificationsLinkProps) => {
|
||||
export const NotificationsLink = ({ navOpen, menu }: NotificationsLinkProps) => {
|
||||
const { notifications, systemNotifications } = useNotifications();
|
||||
const state = getNotificationsState(notifications, systemNotifications);
|
||||
|
||||
@ -35,10 +37,11 @@ export const NotificationsLink = ({ isOpen }: NotificationsLinkProps) => {
|
||||
<Link
|
||||
to="/leap/notifications"
|
||||
className={classNames(
|
||||
'relative z-50 flex-none circle-button h4',
|
||||
isOpen && 'text-opacity-60',
|
||||
state === 'empty' && !isOpen && 'text-gray-400 bg-gray-100',
|
||||
state === 'empty' && isOpen && 'text-gray-400 bg-white',
|
||||
'relative z-50 flex-none circle-button h4 default-ring',
|
||||
navOpen && 'text-opacity-60',
|
||||
navOpen && menu !== 'notifications' && 'opacity-80',
|
||||
state === 'empty' && !navOpen && 'text-gray-400 bg-gray-100',
|
||||
state === 'empty' && navOpen && 'text-gray-400 bg-white',
|
||||
state === 'unread' && 'bg-blue-400 text-white',
|
||||
state === 'attention-needed' && 'text-white bg-orange-500'
|
||||
)}
|
||||
|
@ -4,15 +4,17 @@ import clipboardCopy from 'clipboard-copy';
|
||||
import React, { HTMLAttributes, useCallback, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Adjust } from '../components/icons/Adjust';
|
||||
import { disableDefault } from '../state/util';
|
||||
import { disableDefault, handleDropdownLink } from '../state/util';
|
||||
import { MenuState } from './Nav';
|
||||
|
||||
type SystemMenuProps = HTMLAttributes<HTMLButtonElement> & {
|
||||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
showOverlay?: boolean;
|
||||
menu: MenuState;
|
||||
navOpen: boolean;
|
||||
};
|
||||
|
||||
export const SystemMenu = ({ open, setOpen, className, showOverlay = false }: SystemMenuProps) => {
|
||||
export const SystemMenu = ({ open, setOpen, className, menu, navOpen }: SystemMenuProps) => {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const copyHash = useCallback((event: Event) => {
|
||||
@ -30,7 +32,12 @@ export const SystemMenu = ({ open, setOpen, className, showOverlay = false }: Sy
|
||||
<>
|
||||
<DropdownMenu.Root open={open} onOpenChange={(isOpen) => setOpen(isOpen)}>
|
||||
<DropdownMenu.Trigger
|
||||
className={classNames('circle-button default-ring', open && 'text-gray-300', className)}
|
||||
className={classNames(
|
||||
'circle-button default-ring',
|
||||
open && 'text-gray-300',
|
||||
navOpen && menu !== 'system-preferences' && menu !== 'help-and-support' && 'opacity-80',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<Adjust className="w-6 h-6 fill-current" />
|
||||
<span className="sr-only">System Menu</span>
|
||||
@ -39,17 +46,14 @@ export const SystemMenu = ({ open, setOpen, className, showOverlay = false }: Sy
|
||||
<DropdownMenu.Content
|
||||
onCloseAutoFocus={disableDefault}
|
||||
sideOffset={12}
|
||||
className="dropdown min-w-64 p-6 font-semibold text-gray-500 bg-white"
|
||||
className="dropdown min-w-64 p-4 font-semibold text-gray-500 bg-white"
|
||||
>
|
||||
<DropdownMenu.Group className="space-y-6">
|
||||
<DropdownMenu.Group>
|
||||
<DropdownMenu.Item
|
||||
as={Link}
|
||||
to="/leap/system-preferences"
|
||||
className="flex items-center space-x-2 default-ring ring-offset-2 rounded"
|
||||
onSelect={(e) => {
|
||||
e.preventDefault();
|
||||
setTimeout(() => setOpen(false), 0);
|
||||
}}
|
||||
className="flex items-center p-2 mb-2 space-x-2 focus:bg-blue-200 focus:outline-none rounded"
|
||||
onSelect={handleDropdownLink(setOpen)}
|
||||
>
|
||||
<span className="w-5 h-5 bg-gray-100 rounded-full" />
|
||||
<span className="h4">System Preferences</span>
|
||||
@ -57,19 +61,15 @@ export const SystemMenu = ({ open, setOpen, className, showOverlay = false }: Sy
|
||||
<DropdownMenu.Item
|
||||
as={Link}
|
||||
to="/leap/help-and-support"
|
||||
className="flex items-center space-x-2 default-ring ring-offset-2 rounded"
|
||||
onSelect={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
setTimeout(() => setOpen(false), 0);
|
||||
}}
|
||||
className="flex items-center p-2 mb-2 space-x-2 focus:bg-blue-200 focus:outline-none rounded"
|
||||
onSelect={handleDropdownLink(setOpen)}
|
||||
>
|
||||
<span className="w-5 h-5 bg-gray-100 rounded-full" />
|
||||
<span className="h4">Help and Support</span>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item
|
||||
as="button"
|
||||
className="inline-flex items-center py-2 px-3 h4 text-black bg-gray-100 rounded default-ring"
|
||||
className="inline-flex items-center py-2 px-3 m-2 h4 text-black bg-gray-100 rounded focus:bg-blue-200 focus:outline-none"
|
||||
onSelect={copyHash}
|
||||
>
|
||||
<span className="sr-only">Base Hash</span>
|
||||
@ -82,7 +82,7 @@ export const SystemMenu = ({ open, setOpen, className, showOverlay = false }: Sy
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
|
||||
{showOverlay && open && (
|
||||
{!navOpen && open && (
|
||||
<div className="fixed z-30 right-0 bottom-0 w-screen h-screen bg-black opacity-30" />
|
||||
)}
|
||||
</>
|
||||
|
@ -1,20 +1,14 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { Link, Route, RouteComponentProps, Switch, useRouteMatch } from 'react-router-dom';
|
||||
import classNames from 'classnames';
|
||||
import { useLeapStore } from './Nav';
|
||||
import { NotificationPrefs } from './preferences/NotificationPrefs';
|
||||
import { SystemUpdatePrefs } from './preferences/SystemUpdatePrefs';
|
||||
import notificationsSVG from '../assets/notifications.svg';
|
||||
import systemUpdatesSVG from '../assets/system-updates.svg';
|
||||
|
||||
export const SystemPreferences = ({ match }: RouteComponentProps<{ submenu: string }>) => {
|
||||
const select = useLeapStore((state) => state.select);
|
||||
const subMatch = useRouteMatch<{ submenu: string }>(`${match.url}/:submenu`);
|
||||
|
||||
useEffect(() => {
|
||||
select('System Preferences');
|
||||
}, []);
|
||||
|
||||
const matchSub = useCallback(
|
||||
(target: string) => {
|
||||
if (!subMatch && target === 'notifications') {
|
||||
|
@ -1,16 +1,10 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { Setting } from '../../components/Setting';
|
||||
import { useLeapStore } from '../Nav';
|
||||
import { usePreferencesStore } from './usePreferencesStore';
|
||||
|
||||
export const NotificationPrefs = () => {
|
||||
const select = useLeapStore((s) => s.select);
|
||||
const { doNotDisturb, mentions, toggleDoNotDisturb, toggleMentions } = usePreferencesStore();
|
||||
|
||||
useEffect(() => {
|
||||
select('System Preferences: Notifications');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="h3 mb-7">Notifications</h2>
|
||||
|
@ -4,20 +4,14 @@ import { Setting } from '../../components/Setting';
|
||||
import { ShipName } from '../../components/ShipName';
|
||||
import { Spinner } from '../../components/Spinner';
|
||||
import { useAsyncCall } from '../../logic/useAsyncCall';
|
||||
import { useLeapStore } from '../Nav';
|
||||
import { usePreferencesStore } from './usePreferencesStore';
|
||||
|
||||
export const SystemUpdatePrefs = () => {
|
||||
const select = useLeapStore((s) => s.select);
|
||||
const { otasEnabled, otaSource, toggleOTAs, setOTASource } = usePreferencesStore();
|
||||
const [source, setSource] = useState(otaSource);
|
||||
const sourceDirty = source !== otaSource;
|
||||
const { status: sourceStatus, call: setOTA } = useAsyncCall(setOTASource);
|
||||
|
||||
useEffect(() => {
|
||||
select('System Preferences: Updates');
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setSource(otaSource);
|
||||
}, [otaSource]);
|
||||
|
@ -91,7 +91,7 @@ export const Home = () => {
|
||||
|
||||
return (
|
||||
<div className="h-full p-4 md:p-8 font-semibold leading-tight text-black overflow-y-auto">
|
||||
<h2 id="recent-apps" className="mb-6 h4 text-gray-500">
|
||||
<h2 id="recent-apps" className="mb-4 h4 text-gray-500">
|
||||
Recent Apps
|
||||
</h2>
|
||||
{recentApps.length === 0 && (
|
||||
@ -116,7 +116,7 @@ export const Home = () => {
|
||||
/>
|
||||
)}
|
||||
<hr className="-mx-4 my-6 md:-mx-8 md:my-9" />
|
||||
<h2 id="recent-devs" className="mb-6 h4 text-gray-500">
|
||||
<h2 id="recent-devs" className="mb-4 h4 text-gray-500">
|
||||
Recent Developers
|
||||
</h2>
|
||||
{recentDevs.length === 0 && (
|
||||
|
@ -1,11 +1,5 @@
|
||||
import { DocketHref } from '@urbit/api/docket';
|
||||
|
||||
export function makeKeyFn(key: string) {
|
||||
return (childKeys: string[] = []) => {
|
||||
return [key].concat(childKeys);
|
||||
};
|
||||
}
|
||||
|
||||
export const useMockData = import.meta.env.MODE === 'mock';
|
||||
|
||||
export async function fakeRequest<T>(data: T, time = 300): Promise<T> {
|
||||
@ -24,6 +18,11 @@ export function disableDefault<T extends Event>(e: T): void {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
export function disableDefault<T extends Event>(e: T): void {
|
||||
e.preventDefault();
|
||||
// hack until radix-ui fixes this behavior
|
||||
export function handleDropdownLink(setOpen: (open: boolean) => void): (e: Event) => void {
|
||||
return (e: Event) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
setTimeout(() => setOpen(false), 15);
|
||||
};
|
||||
}
|
||||
|
@ -15,5 +15,5 @@
|
||||
}
|
||||
|
||||
.default-ring {
|
||||
@apply focus:ring-4 ring-blue-400 ring-opacity-80 focus:outline-none;
|
||||
@apply focus-visible:ring-2 ring-blue-400 ring-opacity-80 focus-visible:outline-none;
|
||||
}
|
@ -41,7 +41,7 @@ export const Tile: FunctionComponent<TileProps> = ({ charge, desk }) => {
|
||||
href={active ? link : undefined}
|
||||
target={desk}
|
||||
className={classNames(
|
||||
'group relative font-semibold aspect-w-1 aspect-h-1 rounded-3xl default-ring overflow-hidden',
|
||||
'group relative font-semibold aspect-w-1 aspect-h-1 rounded-3xl default-ring focus-visible:ring-4 overflow-hidden',
|
||||
!active && 'cursor-default'
|
||||
)}
|
||||
style={{ backgroundColor: active ? color || 'purple' : suspendColor }}
|
||||
|
@ -4,7 +4,7 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
||||
import classNames from 'classnames';
|
||||
import { Link } from 'react-router-dom';
|
||||
import useDocketState from '../state/docket';
|
||||
import { disableDefault } from '../state/util';
|
||||
import { disableDefault, handleDropdownLink } from '../state/util';
|
||||
|
||||
export interface TileMenuProps {
|
||||
desk: string;
|
||||
@ -41,10 +41,7 @@ export const TileMenu = ({ desk, active, menuColor, lightText, className }: Tile
|
||||
const [open, setOpen] = useState(false);
|
||||
const toggleDocket = useDocketState((s) => s.toggleDocket);
|
||||
const menuBg = { backgroundColor: menuColor };
|
||||
const linkOnSelect = useCallback((e: Event) => {
|
||||
e.preventDefault();
|
||||
setTimeout(() => setOpen(false), 15);
|
||||
}, []);
|
||||
const linkOnSelect = useCallback(handleDropdownLink(setOpen), []);
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root open={open} onOpenChange={(isOpen) => setOpen(isOpen)}>
|
||||
|
77763
pkg/interface/package-lock.json
generated
77763
pkg/interface/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
4340
pkg/npm/api/package-lock.json
generated
4340
pkg/npm/api/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
6052
pkg/npm/eslint-config/package-lock.json
generated
6052
pkg/npm/eslint-config/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user