diff --git a/apps/www/src/components/datatable-demo.tsx b/apps/www/src/components/datatable-demo.tsx index 482158948..1eccfd3c5 100644 --- a/apps/www/src/components/datatable-demo.tsx +++ b/apps/www/src/components/datatable-demo.tsx @@ -146,4 +146,27 @@ const DataTableVirtualizedDemo = () => { ); }; -export { DataTableDemo, DataTableVirtualizedDemo }; +const DataTableSearchDemo = () => { + const data = useMemo(() => generateData(50), []); + + return ( + + + + + + + ); +}; + +export { DataTableDemo, DataTableSearchDemo, DataTableVirtualizedDemo }; diff --git a/apps/www/src/components/demo/demo.tsx b/apps/www/src/components/demo/demo.tsx index 5db96e688..4d9b8978a 100644 --- a/apps/www/src/components/demo/demo.tsx +++ b/apps/www/src/components/demo/demo.tsx @@ -36,7 +36,11 @@ import dayjs from 'dayjs'; import { Home, Info, Laugh, X } from 'lucide-react'; import NextLink from 'next/link'; import { Suspense } from 'react'; -import { DataTableDemo, DataTableVirtualizedDemo } from '../datatable-demo'; +import { + DataTableDemo, + DataTableSearchDemo, + DataTableVirtualizedDemo +} from '../datatable-demo'; import DataTableSelectionDemo from '../datatable-selection-demo'; import ChipInputDemo from '../inputfield-chip-demo'; import LinearMenuDemo from '../linear-dropdown-demo'; @@ -56,6 +60,7 @@ export default function Demo(props: DemoProps) { OrganizationIcon, SidebarIcon, DataTableDemo, + DataTableSearchDemo, DataTableVirtualizedDemo, ChipInputDemo, DataTableSelectionDemo, diff --git a/apps/www/src/content/docs/components/datatable/demo.ts b/apps/www/src/content/docs/components/datatable/demo.ts index cda0902ae..8d2ab6332 100644 --- a/apps/www/src/content/docs/components/datatable/demo.ts +++ b/apps/www/src/content/docs/components/datatable/demo.ts @@ -49,6 +49,29 @@ export const virtualizedPreview = { ] }; +export const searchPreview = { + type: 'code', + style: { + padding: 0 + }, + previewCode: false, + code: ``, + codePreview: [ + { + label: 'index.tsx', + code: ` + + + + ` + } + ] +}; + export const rowSelectionDemo = { type: 'code', previewCode: false, diff --git a/apps/www/src/content/docs/components/datatable/index.mdx b/apps/www/src/content/docs/components/datatable/index.mdx index 89ffe8833..5944d0e75 100644 --- a/apps/www/src/content/docs/components/datatable/index.mdx +++ b/apps/www/src/content/docs/components/datatable/index.mdx @@ -4,7 +4,7 @@ description: An advanced React table that supports filtering, sorting, and pagin source: packages/raystack/components/datatable --- -import { preview, virtualizedPreview, rowSelectionDemo } from "./demo.ts"; +import { preview, virtualizedPreview, searchPreview, rowSelectionDemo } from "./demo.ts"; @@ -329,6 +329,8 @@ onColumnVisibilityChange={handleColumnVisibilityChange}> The `DataTable.Search` component provides search functionality that automatically integrates with the table query. By default, it is disabled in zero state (when no data and no filters/search applied). + + ```tsx { expect(screen.getByLabelText('Search')).toBeInTheDocument(); }); + + it('clears the search input when the clear button is clicked', async () => { + const user = userEvent.setup(); + render( + + + + + ); + + const input = screen.getByLabelText('Search') as HTMLInputElement; + await user.type(input, 'hello'); + expect(input.value).toBe('hello'); + + await user.click(screen.getByLabelText('Clear search')); + expect(input.value).toBe(''); + }); }); describe('Zero State and Empty State', () => { diff --git a/packages/raystack/components/data-table/components/search.tsx b/packages/raystack/components/data-table/components/search.tsx index a7b909d5d..e91b0e05f 100644 --- a/packages/raystack/components/data-table/components/search.tsx +++ b/packages/raystack/components/data-table/components/search.tsx @@ -54,7 +54,7 @@ export function TableSearch({ diff --git a/packages/raystack/components/data-view-beta/components/search.tsx b/packages/raystack/components/data-view-beta/components/search.tsx index 330692689..546fd57e3 100644 --- a/packages/raystack/components/data-view-beta/components/search.tsx +++ b/packages/raystack/components/data-view-beta/components/search.tsx @@ -54,7 +54,7 @@ export function DataViewSearch({ diff --git a/packages/raystack/components/input/input.module.css b/packages/raystack/components/input/input.module.css index 0624db569..1d50278a8 100644 --- a/packages/raystack/components/input/input.module.css +++ b/packages/raystack/components/input/input.module.css @@ -87,7 +87,6 @@ .input-field:focus { border-color: var(--rs-color-border-accent-emphasis); - background: var(--rs-color-background-base-primary); } .input-field[data-disabled] { diff --git a/packages/raystack/components/search/__tests__/search.test.tsx b/packages/raystack/components/search/__tests__/search.test.tsx index ed9430f00..6321f2fdd 100644 --- a/packages/raystack/components/search/__tests__/search.test.tsx +++ b/packages/raystack/components/search/__tests__/search.test.tsx @@ -85,9 +85,9 @@ describe('Search', () => { expect(screen.getByLabelText('Clear search')).toBeInTheDocument(); }); - it('hides clear button when no value', () => { + it('renders clear button regardless of value (CSS hides it when empty)', () => { render(); - expect(screen.queryByLabelText('Clear search')).not.toBeInTheDocument(); + expect(screen.getByLabelText('Clear search')).toBeInTheDocument(); }); it('calls onClear when clear button clicked', () => { diff --git a/packages/raystack/components/search/search.module.css b/packages/raystack/components/search/search.module.css index ae18df8cd..8925c770b 100644 --- a/packages/raystack/components/search/search.module.css +++ b/packages/raystack/components/search/search.module.css @@ -13,6 +13,10 @@ justify-content: center; } +.container:has(input:placeholder-shown) .clearButtonWrapper { + display: none; +} + .clearButton { color: var(--rs-color-foreground-base-tertiary); } diff --git a/packages/raystack/components/search/search.tsx b/packages/raystack/components/search/search.tsx index 63335eeab..807ca7f1b 100644 --- a/packages/raystack/components/search/search.tsx +++ b/packages/raystack/components/search/search.tsx @@ -24,25 +24,24 @@ export function Search({ variant = 'default', ...props }: SearchProps) { - const trailingIconWithClear = - showClearButton && value ? ( -
- { - e.stopPropagation(); - if (!disabled && onClear) { - onClear(); - } - }} - disabled={disabled} - aria-label='Clear search' - className={styles.clearButton} - > - - -
- ) : undefined; + const trailingIconWithClear = showClearButton ? ( +
+ { + e.stopPropagation(); + if (!disabled && onClear) { + onClear(); + } + }} + disabled={disabled} + aria-label='Clear search' + className={styles.clearButton} + > + + +
+ ) : undefined; return (