diff --git a/apps/studio/components/grid/components/header/HeaderNew.tsx b/apps/studio/components/grid/components/header/HeaderNew.tsx index 16b646bf522..d1bd062b213 100644 --- a/apps/studio/components/grid/components/header/HeaderNew.tsx +++ b/apps/studio/components/grid/components/header/HeaderNew.tsx @@ -30,19 +30,19 @@ import { useTableEditorStateSnapshot } from 'state/table-editor' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { Button, + cn, + copyToClipboard, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Separator, - cn, - copyToClipboard, } from 'ui' import { useInitializeFiltersFromUrl, useSyncFiltersToUrl } from '../../hooks/useFilterLifeCycle' import { ExportDialog } from './ExportDialog' -import { formatRowsForCSV } from './Header.utils' import { FilterPopoverNew } from './filter/FilterPopoverNew' +import { formatRowsForCSV } from './Header.utils' import { SortPopover } from './sort/SortPopover' export type HeaderProps = { @@ -71,7 +71,7 @@ export const HeaderNew = ({ ) : snap.selectedRows.size > 0 ? ( ) : ( - + )}
@@ -84,11 +84,12 @@ export const HeaderNew = ({ const DefaultHeader = ({ tableQueriesEnabled = true, -}: Pick) => { + isRefetching, +}: Pick) => { return ( <> -
- +
+
diff --git a/apps/studio/components/grid/components/header/filter/FilterPopoverNew.tsx b/apps/studio/components/grid/components/header/filter/FilterPopoverNew.tsx index 61374c40a76..b4323dde9d5 100644 --- a/apps/studio/components/grid/components/header/filter/FilterPopoverNew.tsx +++ b/apps/studio/components/grid/components/header/filter/FilterPopoverNew.tsx @@ -2,6 +2,7 @@ import { useTableFilterNew } from 'components/grid/hooks/useTableFilterNew' import type { Filter } from 'components/grid/types' import { useSqlFilterGenerateMutation } from 'data/ai/sql-filter-mutation' import { format } from 'date-fns' +import { Loader2 } from 'lucide-react' import { useCallback, useMemo, useState } from 'react' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { Button, Calendar } from 'ui' @@ -20,6 +21,7 @@ import { columnToFilterProperty } from './FilterPopoverNew.utils' export interface FilterPopoverProps { portal?: boolean + isRefetching?: boolean } // Convert Filter[] to FilterGroup @@ -114,7 +116,7 @@ function serializeFilterProperties( })) } -export const FilterPopoverNew = ({ portal = true }: FilterPopoverProps) => { +export const FilterPopoverNew = ({ isRefetching = false }: FilterPopoverProps) => { const { filters, setFilters } = useTableFilterNew() const snap = useTableEditorTableStateSnapshot() @@ -188,17 +190,24 @@ export const FilterPopoverNew = ({ portal = true }: FilterPopoverProps) => { [generateFilters, serializableFilterProperties, handleFilterChange, setFreeformText] ) + const icon = isRefetching ? ( + + ) : null + return ( - +
+ +
) } diff --git a/packages/ui-patterns/src/FilterBar/FilterBar.tsx b/packages/ui-patterns/src/FilterBar/FilterBar.tsx index 63b8cbb072c..a109ed6c27e 100644 --- a/packages/ui-patterns/src/FilterBar/FilterBar.tsx +++ b/packages/ui-patterns/src/FilterBar/FilterBar.tsx @@ -2,7 +2,9 @@ import { motion } from 'framer-motion' import { Search } from 'lucide-react' +import React from 'react' import { cn } from 'ui' + import { FilterBarRoot, useFilterBar, type FilterBarVariant } from './FilterBarContext' import { FilterGroup } from './FilterGroup' import { FilterBarAction, FilterGroup as FilterGroupType, FilterProperty } from './types' @@ -18,10 +20,11 @@ export type FilterBarProps = { className?: string supportsOperators?: boolean variant?: FilterBarVariant + icon?: React.ReactNode } function FilterBarContent({ className }: { className?: string }) { - const { filters, error, optionsError, isLoading, variant } = useFilterBar() + const { filters, error, optionsError, isLoading, variant, icon: loadingIcon } = useFilterBar() return (
@@ -33,11 +36,21 @@ function FilterBarContent({ className }: { className?: string }) { >
- +
+ +
+ {loadingIcon && ( +
{loadingIcon}
+ )}
diff --git a/packages/ui-patterns/src/FilterBar/FilterBarContext.tsx b/packages/ui-patterns/src/FilterBar/FilterBarContext.tsx index 3209976d6f0..a9bf5c3fdbc 100644 --- a/packages/ui-patterns/src/FilterBar/FilterBarContext.tsx +++ b/packages/ui-patterns/src/FilterBar/FilterBarContext.tsx @@ -1,6 +1,7 @@ 'use client' import React, { createContext, useCallback, useContext, useEffect, useRef } from 'react' + import { ActiveInput, useFilterBarState, useOptionsCache } from './hooks' import { MenuItem } from './menuItems' import { FilterBarAction, FilterGroup, FilterOptionObject, FilterProperty } from './types' @@ -54,6 +55,7 @@ export type FilterBarContextValue = { supportsOperators: boolean variant: FilterBarVariant actions?: FilterBarAction[] + icon?: React.ReactNode // Refs rootRef: React.RefObject @@ -80,6 +82,7 @@ export type FilterBarRootProps = { isLoading?: boolean supportsOperators?: boolean variant?: FilterBarVariant + icon?: React.ReactNode } export type FilterBarVariant = 'default' | 'pill' @@ -95,6 +98,7 @@ export function FilterBarRoot({ isLoading: externalLoading, supportsOperators = false, variant = 'default', + icon, }: FilterBarRootProps) { const rootRef = useRef(null) @@ -306,6 +310,7 @@ export function FilterBarRoot({ supportsOperators, variant, actions, + icon, // Refs rootRef,