mirror of https://github.com/buster-so/buster.git
better accessibliity
This commit is contained in:
parent
d6e3ab9a51
commit
b6d7ba91c1
|
@ -32,11 +32,11 @@ export const GlobalSearchModal = () => {
|
|||
selectedAssets,
|
||||
selectedDateRange,
|
||||
}),
|
||||
[selectedAssets]
|
||||
[selectedAssets, selectedDateRange]
|
||||
);
|
||||
|
||||
const assetTypes: AssetType[] | undefined = useMemo(() => {
|
||||
if (selectedAssets) {
|
||||
if (selectedAssets?.length) {
|
||||
return selectedAssets;
|
||||
}
|
||||
if (!hasQuery) {
|
||||
|
|
|
@ -2,7 +2,12 @@ import type { AssetType } from '@buster/server-shared/assets';
|
|||
import React, { useMemo } from 'react';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { DateRangePickerContent } from '@/components/ui/date/DateRangePicker';
|
||||
import { Dropdown, type DropdownProps, type IDropdownItem } from '@/components/ui/dropdown';
|
||||
import {
|
||||
createDropdownItem,
|
||||
Dropdown,
|
||||
type DropdownProps,
|
||||
type IDropdownItem,
|
||||
} from '@/components/ui/dropdown';
|
||||
import BarsFilter from '@/components/ui/icons/NucleoIconOutlined/bars-filter';
|
||||
import Calendar from '@/components/ui/icons/NucleoIconOutlined/calendar';
|
||||
import Grid2 from '@/components/ui/icons/NucleoIconOutlined/grid-2';
|
||||
|
@ -30,41 +35,59 @@ export const GlobalSearchModalFilters = React.memo(
|
|||
value: 'metric_file' satisfies AssetType,
|
||||
selected: selectedAssets?.includes('metric_file'),
|
||||
icon: <ASSET_ICONS.metrics />,
|
||||
onClick: () => setSelectedAssets([...(selectedAssets || []), 'metric_file']),
|
||||
},
|
||||
{
|
||||
label: 'Chats',
|
||||
value: 'chat' satisfies AssetType,
|
||||
icon: <ASSET_ICONS.chats />,
|
||||
onClick: () => setSelectedAssets([...(selectedAssets || []), 'chat']),
|
||||
},
|
||||
{
|
||||
label: 'Reports',
|
||||
value: 'report_file' satisfies AssetType,
|
||||
icon: <ASSET_ICONS.reports />,
|
||||
onClick: () => setSelectedAssets([...(selectedAssets || []), 'report_file']),
|
||||
},
|
||||
{
|
||||
label: 'Dashboards',
|
||||
value: 'dashboard_file',
|
||||
icon: <ASSET_ICONS.dashboards />,
|
||||
onClick: () => setSelectedAssets([...(selectedAssets || []), 'dashboard_file']),
|
||||
},
|
||||
{
|
||||
label: 'Collections',
|
||||
value: 'collection' satisfies AssetType,
|
||||
icon: <ASSET_ICONS.collections />,
|
||||
onClick: () => setSelectedAssets([...(selectedAssets || []), 'collection']),
|
||||
},
|
||||
].map((item) => ({
|
||||
...item,
|
||||
selected: selectedAssets?.includes(item.value as AssetType),
|
||||
onClick: () => {
|
||||
console.log(
|
||||
'onClick',
|
||||
item.value,
|
||||
selectedAssets,
|
||||
selectedAssets?.includes(item.value as AssetType)
|
||||
);
|
||||
if (selectedAssets?.includes(item.value as AssetType)) {
|
||||
setSelectedAssets(selectedAssets.filter((v) => v !== item.value));
|
||||
} else {
|
||||
setSelectedAssets([...(selectedAssets || []), item.value as AssetType]);
|
||||
}
|
||||
},
|
||||
})) as IDropdownItem<AssetType>['items'],
|
||||
};
|
||||
}, [selectedAssets, setSelectedAssets]);
|
||||
|
||||
const DatesDropdownItems: IDropdownItem = useMemo(() => {
|
||||
return {
|
||||
const closeContent = () => {
|
||||
document.dispatchEvent(
|
||||
new KeyboardEvent('keydown', {
|
||||
key: 'Escape',
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return createDropdownItem({
|
||||
label: 'Date range',
|
||||
value: 'date-range',
|
||||
icon: <Calendar />,
|
||||
|
@ -76,15 +99,9 @@ export const GlobalSearchModalFilters = React.memo(
|
|||
disableDateAfter={getNow().add(12, 'hours').toDate()}
|
||||
initialDateFrom={selectedDateRange?.from}
|
||||
initialDateTo={selectedDateRange?.to}
|
||||
cancelButtonText="Clear"
|
||||
showResetButton={false}
|
||||
onUpdate={({ range }) => {
|
||||
document.dispatchEvent(
|
||||
new KeyboardEvent('keydown', {
|
||||
key: 'Escape',
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
})
|
||||
);
|
||||
|
||||
if (range.from == null && range.to == null) {
|
||||
setSelectedDateRange(null);
|
||||
} else {
|
||||
|
@ -93,11 +110,16 @@ export const GlobalSearchModalFilters = React.memo(
|
|||
to: range.to ?? new Date(),
|
||||
});
|
||||
}
|
||||
closeContent();
|
||||
}}
|
||||
onCancel={() => {
|
||||
setSelectedDateRange(null);
|
||||
closeContent();
|
||||
}}
|
||||
/>,
|
||||
],
|
||||
};
|
||||
}, []);
|
||||
});
|
||||
}, [selectedDateRange, setSelectedDateRange]);
|
||||
|
||||
const items: DropdownProps['items'] = [AssetTypeDropdownItems, DatesDropdownItems];
|
||||
|
||||
|
|
|
@ -185,6 +185,8 @@ export interface DateRangePickerContentProps {
|
|||
onUpdate?: (values: { range: DateRange }) => void;
|
||||
/** Callback when Cancel button is clicked */
|
||||
onCancel?: () => void;
|
||||
cancelButtonText?: string;
|
||||
showResetButton?: boolean;
|
||||
}
|
||||
|
||||
export const DateRangePickerContent: FC<DateRangePickerContentProps> = ({
|
||||
|
@ -194,6 +196,8 @@ export const DateRangePickerContent: FC<DateRangePickerContentProps> = ({
|
|||
disableDateAfter,
|
||||
onUpdate,
|
||||
onCancel,
|
||||
cancelButtonText = 'Cancel',
|
||||
showResetButton = false,
|
||||
}) => {
|
||||
const [range, setRange] = useState<DateRange>({
|
||||
from: getDateAdjustedForTimezone(initialDateFrom),
|
||||
|
@ -395,6 +399,7 @@ export const DateRangePickerContent: FC<DateRangePickerContentProps> = ({
|
|||
<div className="flex justify-between gap-2 py-2 px-4 border-t">
|
||||
<Button
|
||||
variant="ghost"
|
||||
className={cn(!showResetButton && 'invisible')}
|
||||
onClick={() => {
|
||||
setRange({
|
||||
from: null,
|
||||
|
@ -412,7 +417,7 @@ export const DateRangePickerContent: FC<DateRangePickerContentProps> = ({
|
|||
}}
|
||||
variant="ghost"
|
||||
>
|
||||
Cancel
|
||||
{cancelButtonText}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
|
|
|
@ -20,11 +20,12 @@ export const SearchInput: React.FC<
|
|||
<div className="flex flex-col gap-y-0">
|
||||
<div className="flex min-h-12 items-center space-x-3 justify-between px-5">
|
||||
<Command.Input
|
||||
className={cn('text-md placeholder:text-gray-light')}
|
||||
className={cn('text-md placeholder:text-gray-light w-full h-full')}
|
||||
value={searchValue}
|
||||
placeholder={placeholder}
|
||||
onValueChange={onChangeValue}
|
||||
autoFocus={debouncedAutoFocus}
|
||||
tabIndex={0}
|
||||
/>
|
||||
{filterContent}
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue