start making filter user button

This commit is contained in:
Nate Kelley 2025-04-03 16:21:11 -06:00
parent 285f14c24d
commit 55bdd865c1
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
3 changed files with 103 additions and 1 deletions

View File

@ -0,0 +1,18 @@
import type { Meta, StoryObj } from '@storybook/react';
import { FilterDashboardButton } from './FilterDashboardButton';
const meta = {
title: 'Features/Buttons/FilterDashboardButton',
component: FilterDashboardButton,
parameters: {
layout: 'centered'
},
tags: ['autodocs']
} satisfies Meta<typeof FilterDashboardButton>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {}
};

View File

@ -0,0 +1,80 @@
import React, { useMemo, useState } from 'react';
import { Button } from '@/components/ui/buttons';
import { BarsFilter } from '@/components/ui/icons';
import { Dropdown, DropdownItems } from '@/components/ui/dropdown';
import { Input } from '@/components/ui/inputs';
import { MagnifierSparkle } from '@/components/ui/icons';
import { Text } from '@/components/ui/typography';
import { faker } from '@faker-js/faker';
import { cn } from '@/lib/classMerge';
const filterItems = Array.from({ length: 100 }, (_, index) => {
const randomWord = faker.commerce.productAdjective() + ' ' + faker.commerce.productMaterial();
return {
label: randomWord,
value: randomWord + index
};
});
export const FilterDashboardButton: React.FC = React.memo(() => {
const [filterText, setFilterText] = useState('');
const allDropdownItems: DropdownItems = useMemo(() => {
return [
...filterItems.filter((item) => item.label.toLowerCase().includes(filterText.toLowerCase()))
];
}, [filterText]);
const menuHeader = useMemo(() => {
return (
<div className="flex flex-col">
<div className="flex items-center gap-x-2 p-1">
<Input
placeholder="Filters..."
autoFocus
variant={'ghost'}
value={filterText}
onKeyDown={(e) => {
// e.preventDefault();
e.stopPropagation();
}}
onChange={(e) => {
e.preventDefault();
e.stopPropagation();
setFilterText(e.target.value);
}}
/>
</div>
<div className="flex border-t p-1">
<div
className={cn(
'hover:bg-item-select flex w-full cursor-pointer items-center gap-x-1.5 rounded p-1',
filterText && 'bg-item-select'
)}>
<span className="text-icon-color">
<MagnifierSparkle />
</span>
<Text className="whitespace-nowrap" variant="default">
AI Filter
</Text>
{filterText && (
<Text truncate variant="tertiary">
"{filterText}"
</Text>
)}
</div>
</div>
</div>
);
}, [filterText]);
return (
<Dropdown items={allDropdownItems} menuHeader={menuHeader} menuHeaderClassName="p-0!">
<Button variant="ghost" prefix={<BarsFilter />}>
Filter
</Button>
</Dropdown>
);
});
FilterDashboardButton.displayName = 'FilterDashboardButton';

View File

@ -66,6 +66,7 @@ export interface DropdownProps<T = string> extends DropdownMenuProps {
footerClassName?: string;
sideOffset?: number;
disabled?: boolean;
menuHeaderClassName?: string;
}
export interface DropdownContentProps<T = string>
@ -94,6 +95,7 @@ export const DropdownBase = <T,>({
footerContent,
dir,
modal,
menuHeaderClassName,
sideOffset,
footerClassName = '',
showIndex = false,
@ -125,6 +127,7 @@ export const DropdownBase = <T,>({
footerContent={footerContent}
className={contentClassName}
footerClassName={footerClassName}
menuHeaderClassName={menuHeaderClassName}
/>
</DropdownMenuContent>
</DropdownMenu>
@ -142,6 +145,7 @@ export const DropdownContent = <T,>({
emptyStateText = 'No items found',
footerContent,
className,
menuHeaderClassName,
footerClassName,
onSelect
}: DropdownContentProps<T>) => {
@ -213,7 +217,7 @@ export const DropdownContent = <T,>({
<>
{menuHeader && (
<div className="flex flex-col">
<div className="p-1">
<div className={cn('p-1', menuHeaderClassName)}>
<DropdownMenuHeaderSelector
menuHeader={menuHeader}
onChange={handleSearchChange}