From 442855576265b19c796236df4b2c434a403a9c0e Mon Sep 17 00:00:00 2001 From: diced Date: Sat, 4 Mar 2023 19:57:09 -0800 Subject: [PATCH] feat: keyboard spotlight --- package.json | 1 + src/components/Theming.tsx | 16 ++++- src/components/icons/SearchIcon.tsx | 5 ++ src/components/icons/index.tsx | 2 + src/lib/spotlight.tsx | 103 ++++++++++++++++++++++++++++ yarn.lock | 15 ++++ 6 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 src/components/icons/SearchIcon.tsx create mode 100644 src/lib/spotlight.tsx diff --git a/package.json b/package.json index 9515466..73a9f03 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@mantine/next": "^6.0.0", "@mantine/notifications": "^6.0.0", "@mantine/prism": "^6.0.0", + "@mantine/spotlight": "^6.0.0", "@prisma/client": "^4.10.1", "@prisma/internals": "^4.10.1", "@prisma/migrate": "^4.10.1", diff --git a/src/components/Theming.tsx b/src/components/Theming.tsx index 6f12236..ae48c58 100644 --- a/src/components/Theming.tsx +++ b/src/components/Theming.tsx @@ -15,9 +15,14 @@ import qogir_dark from 'lib/themes/qogir_dark'; import { createEmotionCache, MantineProvider, MantineThemeOverride, Modal, ScrollArea } from '@mantine/core'; import { useColorScheme } from '@mantine/hooks'; import { ModalsProvider } from '@mantine/modals'; +import { SpotlightProvider } from '@mantine/spotlight'; import { Notifications } from '@mantine/notifications'; import { userSelector } from 'lib/recoil/user'; import { useRecoilValue } from 'recoil'; +import { SearchIcon } from './icons'; + +import { useRouter } from 'next/router'; +import { createSpotlightActions } from 'lib/spotlight'; export const themes = { 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 }) { const user = useRecoilValue(userSelector); const colorScheme = useColorScheme(); + const router = useRouter(); let theme: MantineThemeOverride; @@ -141,8 +147,14 @@ export default function ZiplineTheming({ Component, pageProps, ...props }) { }} > - - {props.children ? props.children : } + } + shortcut={['mod + k', '/']} + actions={createSpotlightActions(router)} + > + + {props.children ? props.children : } + ); diff --git a/src/components/icons/SearchIcon.tsx b/src/components/icons/SearchIcon.tsx new file mode 100644 index 0000000..d90df07 --- /dev/null +++ b/src/components/icons/SearchIcon.tsx @@ -0,0 +1,5 @@ +import { Search } from 'react-feather'; + +export default function SearchIcon({ ...props }) { + return ; +} diff --git a/src/components/icons/index.tsx b/src/components/icons/index.tsx index dec72ed..0f41a40 100644 --- a/src/components/icons/index.tsx +++ b/src/components/icons/index.tsx @@ -42,6 +42,7 @@ import GlobeIcon from './GlobeIcon'; import LockIcon from './LockIcon'; import UnlockIcon from './UnlockIcon'; import HardDriveIcon from './HardDriveIcon'; +import SearchIcon from './SearchIcon'; export { ActivityIcon, @@ -88,4 +89,5 @@ export { LockIcon, UnlockIcon, HardDriveIcon, + SearchIcon, }; diff --git a/src/lib/spotlight.tsx b/src/lib/spotlight.tsx new file mode 100644 index 0000000..900bda5 --- /dev/null +++ b/src/lib/spotlight.tsx @@ -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', ), + actionLink('Navigation', 'Files', 'View your files', '/dashboard/files', ), + actionLink('Navigation', 'URLs', 'View your URLs', '/dashboard/urls', ), + actionLink('Navigation', 'Folders', 'View your folders', '/dashboard/folders', ), + actionLink('Navigation', 'Statistics', 'View your statistics', '/dashboard/stats', ), + actionLink( + 'Navigation', + 'Manage Account', + 'Manage your account settings', + '/dashboard/manage', + + ), + + // Actions + actionLink('Actions', 'Logout', 'Logout of your account', '/auth/logout', ), + actionLink('Actions', 'Upload Files', 'Upload files of any kind', '/dashboard/upload/file', ), + actionLink( + 'Actions', + 'Upload Text', + 'Upload code, or any other kind of text file', + '/dashboard/upload/text', + + ), + actionDo('Actions', 'Copy Token', 'Copy your API token to your clipboard', , () => { + clipboard.copy(user.token); + showNotification({ + title: 'Copied to clipboard', + message: '', + color: 'green', + icon: , + }); + }), + + actionLink( + 'Help', + 'Documentation', + 'View the documentation', + 'https://zipline.diced.tech', + + ), + + // the list of actions here is very incomplete, and will be expanded in the future + ]; +}; diff --git a/yarn.lock b/yarn.lock index 90c28d6..994e808 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1681,6 +1681,20 @@ __metadata: languageName: node 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": version: 6.0.0 resolution: "@mantine/ssr@npm:6.0.0" @@ -11676,6 +11690,7 @@ __metadata: "@mantine/next": ^6.0.0 "@mantine/notifications": ^6.0.0 "@mantine/prism": ^6.0.0 + "@mantine/spotlight": ^6.0.0 "@prisma/client": ^4.10.1 "@prisma/internals": ^4.10.1 "@prisma/migrate": ^4.10.1