feat: keyboard spotlight

This commit is contained in:
diced 2023-03-04 19:57:09 -08:00
parent 463e91c3bd
commit 4428555762
No known key found for this signature in database
GPG key ID: 370BD1BA142842D1
6 changed files with 140 additions and 2 deletions

View file

@ -37,6 +37,7 @@
"@mantine/next": "^6.0.0", "@mantine/next": "^6.0.0",
"@mantine/notifications": "^6.0.0", "@mantine/notifications": "^6.0.0",
"@mantine/prism": "^6.0.0", "@mantine/prism": "^6.0.0",
"@mantine/spotlight": "^6.0.0",
"@prisma/client": "^4.10.1", "@prisma/client": "^4.10.1",
"@prisma/internals": "^4.10.1", "@prisma/internals": "^4.10.1",
"@prisma/migrate": "^4.10.1", "@prisma/migrate": "^4.10.1",

View file

@ -15,9 +15,14 @@ import qogir_dark from 'lib/themes/qogir_dark';
import { createEmotionCache, MantineProvider, MantineThemeOverride, Modal, ScrollArea } from '@mantine/core'; import { createEmotionCache, MantineProvider, MantineThemeOverride, Modal, ScrollArea } from '@mantine/core';
import { useColorScheme } from '@mantine/hooks'; import { useColorScheme } from '@mantine/hooks';
import { ModalsProvider } from '@mantine/modals'; import { ModalsProvider } from '@mantine/modals';
import { SpotlightProvider } from '@mantine/spotlight';
import { Notifications } from '@mantine/notifications'; import { Notifications } from '@mantine/notifications';
import { userSelector } from 'lib/recoil/user'; import { userSelector } from 'lib/recoil/user';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { SearchIcon } from './icons';
import { useRouter } from 'next/router';
import { createSpotlightActions } from 'lib/spotlight';
export const themes = { export const themes = {
system: (colorScheme: 'dark' | 'light') => (colorScheme === 'dark' ? dark_blue : light_blue), system: (colorScheme: 'dark' | 'light') => (colorScheme === 'dark' ? dark_blue : light_blue),
@ -52,6 +57,7 @@ const cache = createEmotionCache({ key: 'zipline' });
export default function ZiplineTheming({ Component, pageProps, ...props }) { export default function ZiplineTheming({ Component, pageProps, ...props }) {
const user = useRecoilValue(userSelector); const user = useRecoilValue(userSelector);
const colorScheme = useColorScheme(); const colorScheme = useColorScheme();
const router = useRouter();
let theme: MantineThemeOverride; let theme: MantineThemeOverride;
@ -141,8 +147,14 @@ export default function ZiplineTheming({ Component, pageProps, ...props }) {
}} }}
> >
<ModalsProvider> <ModalsProvider>
<Notifications position='top-center' style={{ marginTop: -10 }} /> <SpotlightProvider
{props.children ? props.children : <Component {...pageProps} />} searchIcon={<SearchIcon />}
shortcut={['mod + k', '/']}
actions={createSpotlightActions(router)}
>
<Notifications position='top-center' style={{ marginTop: -10 }} />
{props.children ? props.children : <Component {...pageProps} />}
</SpotlightProvider>
</ModalsProvider> </ModalsProvider>
</MantineProvider> </MantineProvider>
); );

View file

@ -0,0 +1,5 @@
import { Search } from 'react-feather';
export default function SearchIcon({ ...props }) {
return <Search size={15} {...props} />;
}

View file

@ -42,6 +42,7 @@ import GlobeIcon from './GlobeIcon';
import LockIcon from './LockIcon'; import LockIcon from './LockIcon';
import UnlockIcon from './UnlockIcon'; import UnlockIcon from './UnlockIcon';
import HardDriveIcon from './HardDriveIcon'; import HardDriveIcon from './HardDriveIcon';
import SearchIcon from './SearchIcon';
export { export {
ActivityIcon, ActivityIcon,
@ -88,4 +89,5 @@ export {
LockIcon, LockIcon,
UnlockIcon, UnlockIcon,
HardDriveIcon, HardDriveIcon,
SearchIcon,
}; };

103
src/lib/spotlight.tsx Normal file
View file

@ -0,0 +1,103 @@
import { useClipboard } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications';
import type { SpotlightAction } from '@mantine/spotlight';
import {
FileIcon,
FolderIcon,
HomeIcon,
ActivityIcon,
LinkIcon,
UserIcon,
LogoutIcon,
CopyIcon,
SearchIcon,
} from 'components/icons';
import { NextRouter } from 'next/router';
import { useRecoilValue } from 'recoil';
import { userSelector } from './recoil/user';
export const createSpotlightActions = (router: NextRouter): SpotlightAction[] => {
const user = useRecoilValue(userSelector);
const clipboard = useClipboard();
if (!user) {
return [];
}
const linkTo = (url: string) => {
router.push(url);
};
const actionLink = (
group: string,
title: string,
description: string,
link: string,
icon: any
): SpotlightAction => {
return actionDo(group, title, description, icon, () => linkTo(link));
};
const actionDo = (
group: string,
title: string,
description: string,
icon: any,
action: () => void
): SpotlightAction => {
return {
group,
title,
description,
closeOnTrigger: true,
icon,
onTrigger: action,
};
};
return [
// Navigation
actionLink('Navigation', 'Home', 'Go to the home page', '/dashboard', <HomeIcon />),
actionLink('Navigation', 'Files', 'View your files', '/dashboard/files', <FileIcon />),
actionLink('Navigation', 'URLs', 'View your URLs', '/dashboard/urls', <LinkIcon />),
actionLink('Navigation', 'Folders', 'View your folders', '/dashboard/folders', <FolderIcon />),
actionLink('Navigation', 'Statistics', 'View your statistics', '/dashboard/stats', <ActivityIcon />),
actionLink(
'Navigation',
'Manage Account',
'Manage your account settings',
'/dashboard/manage',
<UserIcon />
),
// Actions
actionLink('Actions', 'Logout', 'Logout of your account', '/auth/logout', <LogoutIcon />),
actionLink('Actions', 'Upload Files', 'Upload files of any kind', '/dashboard/upload/file', <FileIcon />),
actionLink(
'Actions',
'Upload Text',
'Upload code, or any other kind of text file',
'/dashboard/upload/text',
<FileIcon />
),
actionDo('Actions', 'Copy Token', 'Copy your API token to your clipboard', <CopyIcon />, () => {
clipboard.copy(user.token);
showNotification({
title: 'Copied to clipboard',
message: '',
color: 'green',
icon: <CopyIcon />,
});
}),
actionLink(
'Help',
'Documentation',
'View the documentation',
'https://zipline.diced.tech',
<SearchIcon />
),
// the list of actions here is very incomplete, and will be expanded in the future
];
};

View file

@ -1681,6 +1681,20 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/spotlight@npm:^6.0.0":
version: 6.0.0
resolution: "@mantine/spotlight@npm:6.0.0"
dependencies:
"@mantine/utils": 6.0.0
peerDependencies:
"@mantine/core": 6.0.0
"@mantine/hooks": 6.0.0
react: ">=16.8.0"
react-dom: ">=16.8.0"
checksum: d8312be7b422ed70074b39e7fb269827ea864c3eee0eb15c359c469684ea01904c3775b7bd23a2a6c99203c515c22f118e371c7d008a425dbe22d2746b136611
languageName: node
linkType: hard
"@mantine/ssr@npm:6.0.0": "@mantine/ssr@npm:6.0.0":
version: 6.0.0 version: 6.0.0
resolution: "@mantine/ssr@npm:6.0.0" resolution: "@mantine/ssr@npm:6.0.0"
@ -11676,6 +11690,7 @@ __metadata:
"@mantine/next": ^6.0.0 "@mantine/next": ^6.0.0
"@mantine/notifications": ^6.0.0 "@mantine/notifications": ^6.0.0
"@mantine/prism": ^6.0.0 "@mantine/prism": ^6.0.0
"@mantine/spotlight": ^6.0.0
"@prisma/client": ^4.10.1 "@prisma/client": ^4.10.1
"@prisma/internals": ^4.10.1 "@prisma/internals": ^4.10.1
"@prisma/migrate": ^4.10.1 "@prisma/migrate": ^4.10.1