+
Showing 5 of {value.length} rows
)}
diff --git a/packages/layout/src/SidebarNav.tsx b/packages/layout/src/SidebarNav.tsx
index 7a83d7fb2..70b0051b4 100644
--- a/packages/layout/src/SidebarNav.tsx
+++ b/packages/layout/src/SidebarNav.tsx
@@ -36,7 +36,7 @@ export function SidebarNav({ items, title = "Application", className, collapsibl
{items.map((item) => (
-
+
{item.icon && }
{item.title}
diff --git a/packages/plugin-grid/src/ObjectGrid.tsx b/packages/plugin-grid/src/ObjectGrid.tsx
index c02e41a82..43615bb0c 100644
--- a/packages/plugin-grid/src/ObjectGrid.tsx
+++ b/packages/plugin-grid/src/ObjectGrid.tsx
@@ -708,8 +708,8 @@ export const ObjectGrid: React.FC = ({
}
return (
-
-
Loading grid...
+
+
Loading grid...
);
}
@@ -909,7 +909,7 @@ export const ObjectGrid: React.FC = ({
return 'bg-indigo-100 text-indigo-800 border-indigo-300';
if (v.includes('prospecting') || v.includes('new') || v.includes('open'))
return 'bg-purple-100 text-purple-800 border-purple-300';
- return 'bg-gray-100 text-gray-800 border-gray-300';
+ return 'bg-muted text-muted-foreground border-border';
};
// Left border color for card accent based on stage
diff --git a/packages/plugin-grid/src/VirtualGrid.tsx b/packages/plugin-grid/src/VirtualGrid.tsx
index bbefc8f2d..603a51d18 100644
--- a/packages/plugin-grid/src/VirtualGrid.tsx
+++ b/packages/plugin-grid/src/VirtualGrid.tsx
@@ -84,7 +84,7 @@ export const VirtualGrid: React.FC = ({
{/* Header */}
col.width || '1fr')
@@ -94,7 +94,7 @@ export const VirtualGrid: React.FC
= ({
{columns.map((column, index) => (
= ({
return fields;
}, [objectDef, schema.fields, schema.filterableFields]);
- const [searchExpanded, setSearchExpanded] = React.useState(false);
-
// Quick filter toggle handler
const toggleQuickFilter = React.useCallback((id: string) => {
setActiveQuickFilters(prev => {
@@ -1012,7 +1010,7 @@ export const ListView: React.FC
= ({
{/* Airtable-style Toolbar — Row 2: Tool buttons */}
-
+
{/* Hide Fields */}
{toolbarFlags.showHideFields && (
@@ -1021,7 +1019,7 @@ export const ListView: React.FC = ({
variant="ghost"
size="sm"
className={cn(
- "h-7 px-2 text-muted-foreground hover:text-primary text-xs",
+ "h-7 px-2 text-muted-foreground hover:text-primary text-xs transition-colors duration-150",
hiddenFields.size > 0 && "text-primary"
)}
>
@@ -1080,8 +1078,8 @@ export const ListView: React.FC = ({
variant="ghost"
size="sm"
className={cn(
- "h-7 px-2 text-muted-foreground hover:text-primary text-xs",
- hasFilters && "text-primary"
+ "h-7 px-2 text-muted-foreground hover:text-primary text-xs transition-colors duration-150",
+ hasFilters && "bg-primary/10 border border-primary/20 text-primary"
)}
>
@@ -1119,8 +1117,8 @@ export const ListView: React.FC = ({
variant="ghost"
size="sm"
className={cn(
- "h-7 px-2 text-muted-foreground hover:text-primary text-xs",
- groupingConfig && "text-primary"
+ "h-7 px-2 text-muted-foreground hover:text-primary text-xs transition-colors duration-150",
+ groupingConfig && "bg-primary/10 border border-primary/20 text-primary"
)}
>
@@ -1179,8 +1177,8 @@ export const ListView: React.FC = ({
variant="ghost"
size="sm"
className={cn(
- "h-7 px-2 text-muted-foreground hover:text-primary text-xs",
- currentSort.length > 0 && "text-primary"
+ "h-7 px-2 text-muted-foreground hover:text-primary text-xs transition-colors duration-150",
+ currentSort.length > 0 && "bg-primary/10 border border-primary/20 text-primary"
)}
>
@@ -1218,8 +1216,8 @@ export const ListView: React.FC = ({
variant="ghost"
size="sm"
className={cn(
- "h-7 px-2 text-muted-foreground hover:text-primary text-xs",
- rowColorConfig && "text-primary"
+ "h-7 px-2 text-muted-foreground hover:text-primary text-xs transition-colors duration-150",
+ rowColorConfig && "bg-primary/10 border border-primary/20 text-primary"
)}
>
@@ -1283,7 +1281,7 @@ export const ListView: React.FC = ({
@@ -1474,7 +1456,7 @@ export const ListView: React.FC
= ({
props.onAddRecord?.()}
>
diff --git a/packages/plugin-list/src/__tests__/ListView.test.tsx b/packages/plugin-list/src/__tests__/ListView.test.tsx
index 8dcdcc238..fb85babd4 100644
--- a/packages/plugin-list/src/__tests__/ListView.test.tsx
+++ b/packages/plugin-list/src/__tests__/ListView.test.tsx
@@ -66,7 +66,7 @@ describe('ListView', () => {
expect(container).toBeTruthy();
});
- it('should render search button', () => {
+ it('should render search input', () => {
const schema: ListViewSchema = {
type: 'list-view',
objectName: 'contacts',
@@ -75,8 +75,8 @@ describe('ListView', () => {
};
renderWithProvider();
- const searchButton = screen.getByRole('button', { name: /search/i });
- expect(searchButton).toBeInTheDocument();
+ const searchInput = screen.getByPlaceholderText(/search/i);
+ expect(searchInput).toBeInTheDocument();
});
it('should expand search and call onSearchChange when search input changes', () => {
@@ -90,11 +90,7 @@ describe('ListView', () => {
renderWithProvider();
- // Click search button to expand
- const searchButton = screen.getByRole('button', { name: /search/i });
- fireEvent.click(searchButton);
-
- const searchInput = screen.getByPlaceholderText(/find/i);
+ const searchInput = screen.getByPlaceholderText(/search/i);
fireEvent.change(searchInput, { target: { value: 'test' } });
expect(onSearchChange).toHaveBeenCalledWith('test');
});
@@ -201,17 +197,13 @@ describe('ListView', () => {
renderWithProvider();
- // Click search button to expand search input
- const searchButton = screen.getByRole('button', { name: /search/i });
- fireEvent.click(searchButton);
-
- const searchInput = screen.getByPlaceholderText(/find/i) as HTMLInputElement;
+ const searchInput = screen.getByPlaceholderText(/search/i) as HTMLInputElement;
// Type in search
fireEvent.change(searchInput, { target: { value: 'test' } });
expect(searchInput.value).toBe('test');
- // Find and click clear button (the X button inside the expanded search)
+ // Find and click clear button (the X button inside the search area)
const buttons = screen.getAllByRole('button');
const clearButton = buttons.find(btn =>
btn.querySelector('svg') !== null && searchInput.value !== ''
@@ -603,7 +595,7 @@ describe('ListView', () => {
// Toolbar Toggle Visibility
// ============================
describe('Toolbar Toggle Visibility', () => {
- it('should hide Search button when showSearch is false', () => {
+ it('should hide Search input when showSearch is false', () => {
const schema: ListViewSchema = {
type: 'list-view',
objectName: 'contacts',
@@ -613,10 +605,10 @@ describe('ListView', () => {
};
renderWithProvider();
- expect(screen.queryByRole('button', { name: /search/i })).not.toBeInTheDocument();
+ expect(screen.queryByPlaceholderText(/search/i)).not.toBeInTheDocument();
});
- it('should show Search button when showSearch is true', () => {
+ it('should show Search input when showSearch is true', () => {
const schema: ListViewSchema = {
type: 'list-view',
objectName: 'contacts',
@@ -626,10 +618,10 @@ describe('ListView', () => {
};
renderWithProvider();
- expect(screen.getByRole('button', { name: /search/i })).toBeInTheDocument();
+ expect(screen.getByPlaceholderText(/search/i)).toBeInTheDocument();
});
- it('should show Search button when showSearch is undefined (default)', () => {
+ it('should show Search input when showSearch is undefined (default)', () => {
const schema: ListViewSchema = {
type: 'list-view',
objectName: 'contacts',
@@ -638,7 +630,7 @@ describe('ListView', () => {
};
renderWithProvider();
- expect(screen.getByRole('button', { name: /search/i })).toBeInTheDocument();
+ expect(screen.getByPlaceholderText(/search/i)).toBeInTheDocument();
});
it('should hide Filter button when showFilters is false', () => {
@@ -1222,7 +1214,7 @@ describe('ListView', () => {
};
renderWithProvider();
- expect(screen.queryByRole('button', { name: /search/i })).not.toBeInTheDocument();
+ expect(screen.queryByPlaceholderText(/search/i)).not.toBeInTheDocument();
});
it('should hide Sort when userActions.sort is false', () => {
@@ -1274,7 +1266,7 @@ describe('ListView', () => {
};
renderWithProvider();
- expect(screen.getByRole('button', { name: /search/i })).toBeInTheDocument();
+ expect(screen.getByPlaceholderText(/search/i)).toBeInTheDocument();
expect(screen.getByRole('button', { name: /^sort$/i })).toBeInTheDocument();
expect(screen.getByRole('button', { name: /filter/i })).toBeInTheDocument();
expect(screen.getByTitle(/density/i)).toBeInTheDocument();
@@ -1291,7 +1283,7 @@ describe('ListView', () => {
};
renderWithProvider();
- expect(screen.queryByRole('button', { name: /search/i })).not.toBeInTheDocument();
+ expect(screen.queryByPlaceholderText(/search/i)).not.toBeInTheDocument();
});
});
@@ -1456,11 +1448,8 @@ describe('ListView', () => {
renderWithProvider();
- // Click search button to expand
- const searchButton = screen.getByRole('button', { name: /search/i });
- fireEvent.click(searchButton);
-
- const searchInput = screen.getByPlaceholderText(/find/i);
+ // Search input is always visible inline
+ const searchInput = screen.getByPlaceholderText(/search/i);
fireEvent.change(searchInput, { target: { value: 'alice' } });
// Wait for debounced fetch
diff --git a/packages/plugin-list/src/components/TabBar.tsx b/packages/plugin-list/src/components/TabBar.tsx
index efc224ac5..4cbbe291c 100644
--- a/packages/plugin-list/src/components/TabBar.tsx
+++ b/packages/plugin-list/src/components/TabBar.tsx
@@ -87,7 +87,7 @@ export const TabBar: React.FC = ({
return (
@@ -97,9 +97,14 @@ export const TabBar: React.FC
= ({
return (
= ({ schema }) => {
}
return (
-
+
);
@@ -62,7 +62,7 @@ export const ReportRenderer: React.FC
= ({ schema }) => {
{/* Render Data Grid Section */}
{data && data.length > 0 && (
-
+
{(() => {
const GridComponent = showGrid ? (ComponentRegistry.get('aggrid') || ComponentRegistry.get('table')) : null;
return GridComponent ? (
@@ -78,7 +78,7 @@ export const ReportRenderer: React.FC
= ({ schema }) => {
// Simple Fallback Table if Grid plugin missing
-
+
{columns?.map((col: any) => (
| {col.headerName || col.label || col.field} |
@@ -87,7 +87,7 @@ export const ReportRenderer: React.FC = ({ schema }) => {
{data.map((row: any, i: number) => (
-
+
{columns?.map((col: any) => (
| {row[col.field]} |
))}
diff --git a/packages/runner/src/LayoutRenderer.tsx b/packages/runner/src/LayoutRenderer.tsx
index 37f52b30c..01684b9f3 100644
--- a/packages/runner/src/LayoutRenderer.tsx
+++ b/packages/runner/src/LayoutRenderer.tsx
@@ -150,7 +150,7 @@ export const LayoutRenderer = ({ app, children, currentPath, onNavigate }: Layou
const LogoIcon = app.logo && !app.logo.includes('/') && !app.logo.includes('.') ? getIcon(app.logo) : null;
return (
-
+
{/* Sidebar - Only if configured */}
{layout === 'sidebar' && (