Tighten Command-K content

This commit is contained in:
Sam Becker 2024-02-19 20:03:22 -06:00
parent 3992a426fb
commit 2cdbf43309
2 changed files with 100 additions and 60 deletions

View File

@ -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);
} }
}} }}

View File

@ -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),
})),
},
]} ]}
/>; />;
} }