mirror of https://github.com/buster-so/buster.git
start making filter user button
This commit is contained in:
parent
285f14c24d
commit
55bdd865c1
|
@ -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: {}
|
||||
};
|
|
@ -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';
|
|
@ -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}
|
||||
|
|
Loading…
Reference in New Issue