Skip to content

Commit

Permalink
feat: implement debounced icon search
Browse files Browse the repository at this point in the history
  • Loading branch information
khanhadi committed Sep 7, 2024
1 parent 840fd89 commit 84c5dea
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 32 deletions.
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ words:
- Upstash
- healthcheck
- timeago
- usehooks
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"tailwind-merge": "^2.5.2",
"timeago.js": "^4.0.2",
"use-resize-observer": "^9.1.0",
"usehooks-ts": "^3.1.0",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
80 changes: 48 additions & 32 deletions src/app/(dashboard)/app/_components/create-module-popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { api } from '@/lib/trpc/react';
import { useRouter } from 'next/navigation';
import { toast } from 'sonner';
import { Textarea } from '@/primitives/textarea';

import { useDebounceValue } from 'usehooks-ts';
interface StepHeadingProps {
title: string;
description: string;
Expand All @@ -46,6 +46,48 @@ const StepHeading = ({ title, description }: StepHeadingProps) => {
);
};

interface IconPickerProps {
iconOnClickHandler: (icon: IconNames) => void;
}

export function IconPicker({ iconOnClickHandler }: IconPickerProps) {
const [iconSearchTerm, setIconSearchTerm] = useDebounceValue('', 200);

return (
<>
<Input
type="text"
placeholder="Search icons..."
onChange={(e) => {
setIconSearchTerm(e.target.value);
}}
/>
<ScrollArea className="mt-2 h-[300px]">
<div className="mt-2 grid grid-cols-6 gap-2">
{iconNames
.filter((icon) =>
iconSearchTerm === ''
? true
: icon.toLowerCase().includes(iconSearchTerm.toLowerCase()),
)
.map((icon) => (
<button
type="button"
key={icon}
className="grid place-items-center rounded-lg p-2 text-foreground transition-colors hover:bg-gray-element"
onClick={() => {
iconOnClickHandler(icon);
}}
>
<Icon name={icon} size={20} strokeWidth={1.5} />
</button>
))}
</div>
</ScrollArea>
</>
);
}

const formSchema = z.object({
name: z.string().min(2),
description: z.string().optional(),
Expand All @@ -58,7 +100,6 @@ const formSchema = z.object({
export function CreateModulePopover() {
const [popoverOpen, setPopoverOpen] = useState(false);
const [step, setStep] = useState<1 | 2 | 3>(1);
const [iconSearchTerm, setIconSearchTerm] = useState('');

const router = useRouter();

Expand Down Expand Up @@ -96,12 +137,6 @@ export function CreateModulePopover() {
});
}

const filteredIcons = iconSearchTerm
? iconNames.filter((icon) =>
icon.toLowerCase().includes(iconSearchTerm.toLowerCase()),
)
: iconNames;

return (
<Popover
open={popoverOpen}
Expand Down Expand Up @@ -293,31 +328,12 @@ export function CreateModulePopover() {
title="Select an icon"
description="You can select an icon for your module to make it easier to identify."
/>
<Input
type="text"
placeholder="Search icons..."
value={iconSearchTerm}
onChange={(e) => {
setIconSearchTerm(e.target.value);
<IconPicker
iconOnClickHandler={(icon) => {
form.setValue('icon', icon);
setStep(1);
}}
></Input>
<ScrollArea className="mt-2 h-[300px]">
<div className="mt-2 grid grid-cols-6 gap-2">
{filteredIcons.map((icon) => (
<button
type="button"
key={icon}
className="grid place-items-center rounded-lg p-2 text-foreground transition-colors hover:bg-gray-element"
onClick={() => {
form.setValue('icon', icon);
setStep(1);
}}
>
<Icon name={icon} size={20} strokeWidth={1.5} />
</button>
))}
</div>
</ScrollArea>
/>
</div>
)}

Expand Down

0 comments on commit 84c5dea

Please sign in to comment.