Tighten Command-K content
This commit is contained in:
parent
3992a426fb
commit
2cdbf43309
@ -54,6 +54,20 @@ export default function CommandKClient({
|
|||||||
}
|
}
|
||||||
}, [queryDebounced, onQueryChange]);
|
}, [queryDebounced, onQueryChange]);
|
||||||
|
|
||||||
|
const sectionTheme: CommandKSection = {
|
||||||
|
heading: 'Theme',
|
||||||
|
items: [{
|
||||||
|
label: 'System',
|
||||||
|
action: () => setTheme('system'),
|
||||||
|
}, {
|
||||||
|
label: 'Light',
|
||||||
|
action: () => setTheme('light'),
|
||||||
|
}, {
|
||||||
|
label: 'Dark',
|
||||||
|
action: () => setTheme('dark'),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Command.Dialog
|
<Command.Dialog
|
||||||
open={open}
|
open={open}
|
||||||
@ -66,64 +80,54 @@ export default function CommandKClient({
|
|||||||
fast
|
fast
|
||||||
>
|
>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="text-sm uppercase text-dim">
|
|
||||||
Search for photos, tags, cameras, and film
|
|
||||||
</div>
|
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Command.Input
|
<Command.Input
|
||||||
onChangeCapture={(e) => setQuery(e.currentTarget.value)}
|
onChangeCapture={(e) => setQuery(e.currentTarget.value)}
|
||||||
className="w-full !min-w-0"
|
className={clsx(
|
||||||
|
'w-full',
|
||||||
|
'placeholder:text-gray-400',
|
||||||
|
'placeholder:dark:text-gray-700',
|
||||||
|
)}
|
||||||
style={{ paddingRight: '2rem' }}
|
style={{ paddingRight: '2rem' }}
|
||||||
|
placeholder="Search photos, views, settings ..."
|
||||||
/>
|
/>
|
||||||
{isLoading &&
|
{isLoading &&
|
||||||
<span className="absolute top-2.5 right-3">
|
<span className="absolute top-2.5 right-3">
|
||||||
<Spinner size={16} />
|
<Spinner size={16} />
|
||||||
</span>}
|
</span>}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<Command.List className="relative max-h-72 overflow-y-scroll">
|
||||||
aria-hidden="true"
|
|
||||||
className={clsx(
|
|
||||||
'absolute bottom-4 inset-x-0 h-6 z-10 pointer-events-none',
|
|
||||||
'bg-gradient-to-t to-transparent',
|
|
||||||
'from-white dark:from-black',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Command.List className="relative max-h-72 pb-4 overflow-y-scroll">
|
|
||||||
<Command.Empty>No results found.</Command.Empty>
|
<Command.Empty>No results found.</Command.Empty>
|
||||||
{[{
|
{sections
|
||||||
heading: 'Theme',
|
.concat(sectionTheme)
|
||||||
items: [{
|
|
||||||
label: 'System',
|
|
||||||
action: () => setTheme('system'),
|
|
||||||
}, {
|
|
||||||
label: 'Light',
|
|
||||||
action: () => setTheme('light'),
|
|
||||||
}, {
|
|
||||||
label: 'Dark',
|
|
||||||
action: () => setTheme('dark'),
|
|
||||||
}],
|
|
||||||
} as CommandKSection]
|
|
||||||
.concat(sections)
|
|
||||||
.filter(({ items }) => items.length > 0)
|
.filter(({ items }) => items.length > 0)
|
||||||
.map(({ heading, items }) =>
|
.map(({ heading, items }) =>
|
||||||
<Command.Group
|
<Command.Group
|
||||||
key={heading}
|
key={heading}
|
||||||
heading={heading}
|
heading={heading}
|
||||||
className="select-none"
|
className={clsx(
|
||||||
|
'uppercase',
|
||||||
|
'select-none',
|
||||||
|
'[&>*:first-child]:py-1.5',
|
||||||
|
'[&>*:first-child]:font-medium',
|
||||||
|
'[&>*:first-child]:text-dim',
|
||||||
|
'[&>*:first-child]:text-xs',
|
||||||
|
'[&>*:first-child]:tracking-wider',
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{items.map(({ label, path, action }) =>
|
{items.map(({ label, path, action }) =>
|
||||||
<Command.Item
|
<Command.Item
|
||||||
key={`${heading}-${label}`}
|
key={`${heading}-${label}`}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'p-1 rounded-md cursor-pointer',
|
'py-1 px-2 rounded-md cursor-pointer',
|
||||||
'data-[selected=true]:bg-gray-100',
|
'data-[selected=true]:bg-gray-100',
|
||||||
'data-[selected=true]:dark:bg-gray-900/75',
|
'data-[selected=true]:dark:bg-gray-900/75',
|
||||||
'data-[active=true]:bg-green-400'
|
'data-[active=true]:bg-green-400'
|
||||||
)}
|
)}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
action?.();
|
action?.();
|
||||||
|
setOpen(false);
|
||||||
if (path) {
|
if (path) {
|
||||||
setOpen(false);
|
|
||||||
router.push(path);
|
router.push(path);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,11 +1,20 @@
|
|||||||
import CommandKClient from '@/components/CommandKClient';
|
import CommandKClient, { CommandKSection } from '@/components/CommandKClient';
|
||||||
import {
|
import {
|
||||||
getUniqueCamerasCached,
|
getUniqueCamerasCached,
|
||||||
getUniqueFilmSimulationsCached,
|
getUniqueFilmSimulationsCached,
|
||||||
getUniqueTagsCached,
|
getUniqueTagsCached,
|
||||||
} from '@/photo/cache';
|
} from '@/photo/cache';
|
||||||
import { pathForCamera, pathForFilmSimulation, pathForTag } from './paths';
|
import {
|
||||||
|
PATH_ADMIN_CONFIGURATION,
|
||||||
|
PATH_ADMIN_PHOTOS,
|
||||||
|
PATH_ADMIN_TAGS,
|
||||||
|
PATH_ADMIN_UPLOADS,
|
||||||
|
pathForCamera,
|
||||||
|
pathForFilmSimulation,
|
||||||
|
pathForTag,
|
||||||
|
} from './paths';
|
||||||
import { formatCameraText } from '@/camera';
|
import { formatCameraText } from '@/camera';
|
||||||
|
import { authCached } from '@/auth/cache';
|
||||||
|
|
||||||
export default async function CommandK() {
|
export default async function CommandK() {
|
||||||
const [
|
const [
|
||||||
@ -18,36 +27,63 @@ export default async function CommandK() {
|
|||||||
getUniqueFilmSimulationsCached().catch(() => []),
|
getUniqueFilmSimulationsCached().catch(() => []),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const session = await authCached().catch(() => null);
|
||||||
|
|
||||||
|
const showAdminPages = Boolean(session?.user?.email);
|
||||||
|
|
||||||
|
const SECTION_TAGS: CommandKSection = {
|
||||||
|
heading: 'Tags',
|
||||||
|
items: tags.map(({ tag }) => ({
|
||||||
|
label: tag,
|
||||||
|
path: pathForTag(tag),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
const SECTION_CAMERAS: CommandKSection = {
|
||||||
|
heading: 'Cameras',
|
||||||
|
items: cameras.map(({ camera }) => ({
|
||||||
|
label: formatCameraText(camera),
|
||||||
|
path: pathForCamera(camera),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
const SECTION_FILM: CommandKSection = {
|
||||||
|
heading: 'Film Simulations',
|
||||||
|
items: filmSimulations.map(({ simulation }) => ({
|
||||||
|
label: simulation,
|
||||||
|
path: pathForFilmSimulation(simulation),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
const SECTION_PAGES: CommandKSection = {
|
||||||
|
heading: 'Pages',
|
||||||
|
items: [{
|
||||||
|
label: 'Home',
|
||||||
|
path: '/',
|
||||||
|
}, {
|
||||||
|
label: 'Grid',
|
||||||
|
path:'/grid',
|
||||||
|
}].concat(showAdminPages ? [{
|
||||||
|
label: 'Admin » Photos',
|
||||||
|
path: PATH_ADMIN_PHOTOS,
|
||||||
|
}, {
|
||||||
|
label: 'Admin » Uploads',
|
||||||
|
path: PATH_ADMIN_UPLOADS,
|
||||||
|
}, {
|
||||||
|
label: 'Admin » Tags',
|
||||||
|
path: PATH_ADMIN_TAGS,
|
||||||
|
}, {
|
||||||
|
label: 'Admin » Config',
|
||||||
|
path: PATH_ADMIN_CONFIGURATION,
|
||||||
|
}] : []),
|
||||||
|
};
|
||||||
|
|
||||||
return <CommandKClient
|
return <CommandKClient
|
||||||
sections={[
|
sections={[
|
||||||
{
|
SECTION_TAGS,
|
||||||
heading: 'Pages',
|
SECTION_CAMERAS,
|
||||||
items: [{
|
SECTION_FILM,
|
||||||
label: 'Home',
|
SECTION_PAGES,
|
||||||
path: '/',
|
|
||||||
}, {
|
|
||||||
label: 'Grid',
|
|
||||||
path:'/grid',
|
|
||||||
}],
|
|
||||||
}, {
|
|
||||||
heading: 'Tags',
|
|
||||||
items: tags.map(({ tag }) => ({
|
|
||||||
label: tag,
|
|
||||||
path: pathForTag(tag),
|
|
||||||
})),
|
|
||||||
}, {
|
|
||||||
heading: 'Cameras',
|
|
||||||
items: cameras.map(({ camera }) => ({
|
|
||||||
label: formatCameraText(camera),
|
|
||||||
path: pathForCamera(camera),
|
|
||||||
})),
|
|
||||||
}, {
|
|
||||||
heading: 'Film Simulations',
|
|
||||||
items: filmSimulations.map(({ simulation }) => ({
|
|
||||||
label: simulation,
|
|
||||||
path: pathForFilmSimulation(simulation),
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user