Skip to content

Commit b414a59

Browse files
docs: update README for EditableTable component
- Revised the overview to clarify features, removing redundant mentions of column sorting and filtering. - Updated the setup instructions to replace Storybook setup with NuqsAdapter setup for URL state management. - Enhanced the documentation on Medusa Admin setup, emphasizing the need for the NuqsAdapter and providing code examples. - Improved clarity on key features, including column management capabilities. - Removed outdated sections related to Storybook decorators and unnecessary provider details.
1 parent d26c18e commit b414a59

1 file changed

Lines changed: 50 additions & 168 deletions

File tree

  • packages/medusa-forms/src/editable-table

packages/medusa-forms/src/editable-table/README.md

Lines changed: 50 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Overview
44

5-
The `EditableTable` is a powerful, feature-rich React component built for the Medusa2 admin interface that provides inline editing capabilities for tabular data. It combines the flexibility of TanStack Table with real-time validation, auto-save functionality, column sorting, filtering, and URL state persistence to create an efficient data management experience.
5+
The `EditableTable` is a powerful, feature-rich React component built for the Medusa2 admin interface that provides inline editing capabilities for tabular data. It combines the flexibility of TanStack Table with real-time validation, auto-save functionality, and URL state persistence to create an efficient data management experience.
66

77
## Installation & Peer Dependencies
88

@@ -41,173 +41,61 @@ For virtual scrolling support with large datasets:
4141
yarn add @tanstack/react-virtual@^3.10.0
4242
```
4343

44-
## Storybook Setup Requirements
44+
## NuqsAdapter Setup
4545

46-
> **Prerequisites:** Make sure you have installed all [peer dependencies](#installation--peer-dependencies) before setting up Storybook stories.
46+
The `EditableTable` component uses `nuqs` for URL state persistence (search, filters, pagination, sorting). Since Medusa Admin uses React Router v6, you need to wrap your page content with the `NuqsAdapter` from `nuqs/adapters/react-router/v6`.
4747

48-
The `EditableTable` component requires several context providers to function correctly in Storybook (or any standalone environment). Below are the required providers and the errors you'll encounter if they're missing:
48+
> **Note:** The adapter required depends on your React framework. For Medusa Admin (React Router v6), use `nuqs/adapters/react-router/v6`. For other frameworks, see the [official nuqs adapters documentation](https://nuqs.dev/docs/adapters).
4949
50-
### Required Providers
50+
### Medusa Admin Setup
5151

52-
#### 1. NuqsAdapter (URL State Management)
53-
**Package:** `nuqs` (peer dependency)
54-
**Error if missing:**
55-
```
56-
[nuqs] nuqs requires an adapter to work with your framework.
57-
```
58-
59-
**Why needed:** The EditableTable uses `nuqs` for URL state persistence (search, filters, pagination, sorting). In Storybook, which doesn't have a framework router, you need the React adapter.
60-
61-
**Setup:**
62-
```typescript
63-
import { NuqsAdapter } from 'nuqs/adapters/react';
64-
```
52+
In Medusa Admin, add the `NuqsAdapter` at the page level when creating custom pages:
6553

66-
#### 2. QueryClientProvider (React Query)
67-
**Package:** `@tanstack/react-query` (peer dependency)
68-
**Error if missing:**
69-
```
70-
No QueryClient set, use QueryClientProvider to set one
71-
```
72-
73-
**Why needed:** The EditableTable's autocomplete cells and async operations depend on React Query for data fetching and caching.
54+
```tsx
55+
import { NuqsAdapter } from 'nuqs/adapters/react-router/v6';
56+
import { EditableTable } from '@lambdacurry/medusa-forms/editable-table';
57+
import { defineRouteConfig } from '@medusajs/admin-sdk';
58+
import { Buildings } from '@medusajs/icons';
7459

75-
**Setup:**
76-
```typescript
77-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
60+
const MyCustomPage = () => {
61+
return (
62+
<NuqsAdapter>
63+
<EditableTable
64+
data={data}
65+
editableColumns={columns}
66+
getValidateHandler={getValidateHandler}
67+
getSaveHandler={getSaveHandler}
68+
getOptionsHandler={getOptionsHandler}
69+
// ... other props
70+
/>
71+
</NuqsAdapter>
72+
);
73+
};
7874

79-
const queryClient = new QueryClient({
80-
defaultOptions: {
81-
queries: {
82-
retry: false,
83-
staleTime: 1000 * 60 * 5, // 5 minutes
84-
},
85-
},
75+
export const config = defineRouteConfig({
76+
label: 'My Custom Page',
77+
icon: Buildings,
8678
});
87-
```
88-
89-
#### 3. TooltipProvider (Medusa UI)
90-
**Package:** `@medusajs/ui` (peer dependency)
91-
**Error if missing:**
92-
```
93-
`Tooltip` must be used within `TooltipProvider`
94-
```
95-
96-
**Why needed:** The EditableTable uses tooltips for column headers and cell status indicators. Medusa UI's Tooltip component requires a provider.
97-
98-
**Setup:**
99-
```typescript
100-
import { TooltipProvider } from '@medusajs/ui';
101-
```
102-
103-
#### 4. Toaster (Medusa UI - Optional but Recommended)
104-
**Package:** `@medusajs/ui` (peer dependency)
105-
**Why needed:** For displaying toast notifications for validation errors, save confirmations, etc.
10679

107-
**Setup:**
108-
```typescript
109-
import { Toaster } from '@medusajs/ui';
80+
export default MyCustomPage;
11081
```
11182

112-
### Complete Storybook Decorator Example
113-
114-
Here's the complete decorator setup for EditableTable stories with all required imports:
115-
116-
```typescript
117-
// Component imports
118-
import { EditableTable } from '@lambdacurry/medusa-forms/editable-table';
119-
import type { EditableTableColumnDefinition } from '@lambdacurry/medusa-forms/editable-table';
120-
121-
// Provider imports
122-
import { Toaster, TooltipProvider } from '@medusajs/ui';
123-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
124-
import { NuqsAdapter } from 'nuqs/adapters/react';
125-
126-
// Storybook imports
127-
import type { Meta } from '@storybook/react-vite';
128-
129-
// React imports
130-
import { useState } from 'react';
131-
132-
const meta = {
133-
title: 'Your Stories/Editable Table',
134-
component: EditableTable,
135-
decorators: [
136-
(Story) => {
137-
// Initialize React Query client
138-
const queryClient = new QueryClient({
139-
defaultOptions: {
140-
queries: {
141-
retry: false,
142-
staleTime: 1000 * 60 * 5, // 5 minutes
143-
},
144-
},
145-
});
146-
147-
return (
148-
<NuqsAdapter>
149-
<QueryClientProvider client={queryClient}>
150-
<TooltipProvider>
151-
<div className="p-6 bg-ui-bg-subtle min-h-screen">
152-
<Story />
153-
</div>
154-
<Toaster />
155-
</TooltipProvider>
156-
</QueryClientProvider>
157-
</NuqsAdapter>
158-
);
159-
},
160-
],
161-
} satisfies Meta<typeof EditableTable>;
162-
163-
export default meta;
164-
```
165-
166-
**Key Imports Explained:**
167-
- `EditableTable` - Main component from medusa-forms package
168-
- `Toaster`, `TooltipProvider` - From `@medusajs/ui` peer dependency
169-
- `QueryClient`, `QueryClientProvider` - From `@tanstack/react-query` peer dependency
170-
- `NuqsAdapter` - From `nuqs` peer dependency (React adapter for standalone usage)
171-
172-
### Provider Hierarchy
173-
174-
The providers must be nested in this specific order (outermost to innermost):
83+
**Why needed:** The `NuqsAdapter` provides the routing context that `nuqs` requires to synchronize table state (search, filters, pagination, sorting) with the URL query parameters.
17584

85+
**Error if missing:**
17686
```
177-
NuqsAdapter ← URL state management
178-
└─ QueryClientProvider ← React Query context
179-
└─ TooltipProvider ← Medusa UI tooltips
180-
└─ Your Content
181-
└─ Toaster ← Toast notifications (sibling to content)
87+
[nuqs] nuqs requires an adapter to work with your framework.
18288
```
18389

184-
### Troubleshooting
185-
186-
| Error Message | Missing Provider | Package | Solution |
187-
|---------------|------------------|---------|----------|
188-
| `nuqs requires an adapter` | `NuqsAdapter` | `nuqs` | Wrap in `<NuqsAdapter>` from `nuqs/adapters/react` |
189-
| `No QueryClient set` | `QueryClientProvider` | `@tanstack/react-query` | Wrap in `<QueryClientProvider client={queryClient}>` |
190-
| `Tooltip must be used within TooltipProvider` | `TooltipProvider` | `@medusajs/ui` | Wrap in `<TooltipProvider>` from `@medusajs/ui` |
191-
| Toast notifications not appearing | `Toaster` | `@medusajs/ui` | Add `<Toaster />` component from `@medusajs/ui` |
192-
| Icons not rendering | `@medusajs/icons` | `@medusajs/icons` | Ensure peer dependency is installed |
193-
| Table functionality broken | `@tanstack/react-table` | `@tanstack/react-table` | Ensure peer dependency is installed |
194-
195-
### Production Usage
196-
197-
In a production Medusa Admin application, these providers are typically already set up at the app level:
198-
- Next.js or React Router provides the routing context for `nuqs`
199-
- React Query is configured globally
200-
- Medusa UI providers are included in the app shell
201-
202-
You only need to configure these providers explicitly in isolated environments like Storybook or standalone demos.
90+
For other frameworks or standalone usage, refer to the [official nuqs adapters documentation](https://nuqs.dev/docs/adapters).
20391

20492
## Key Features
20593

20694
- **Inline Editing**: Edit data directly in table cells without navigation
20795
- **Real-time Validation**: Immediate feedback with Zod schema validation
20896
- **Auto-save**: Debounced saving with visual status indicators
20997
- **URL State Persistence**: Table state (search, sort, pagination) persists in URL
210-
- **Column Management**: Sorting and filtering
98+
- **Column Management**: Sorting, filtering, pinning, and resizing
21199
- **Loading States**: Built-in skeleton loading with customizable row/column counts
212100
- **Tooltip Support**: Column headers can display helpful tooltips
213101
- **Pagination**: Configurable pagination with customizable page sizes
@@ -347,8 +235,7 @@ export const MyEditableTable = () => {
347235
showControls={true}
348236
showPagination={true}
349237
enableGlobalFilter={true}
350-
enableSorting={true} // Enable sorting (click headers)
351-
enableColumnFilters={true} // Enable column filters
238+
enableSorting={true}
352239
enablePagination={true}
353240
tableId="my-table" // Optional: for URL state persistence
354241
/>
@@ -366,7 +253,6 @@ export const MyEditableTable = () => {
366253
type: 'text',
367254
placeholder: 'Enter title',
368255
required: true,
369-
enableSorting: true, // Click header to sort
370256
}
371257
```
372258

@@ -382,7 +268,6 @@ export const MyEditableTable = () => {
382268
max: 999999,
383269
step: 1,
384270
},
385-
enableSorting: true, // Click header to sort
386271
}
387272
```
388273

@@ -1183,8 +1068,10 @@ interface EditableTableProps<T extends Record<string, unknown>> {
11831068
// Table Features
11841069
enableGlobalFilter?: boolean; // Enable global search
11851070
enableColumnFilters?: boolean; // Enable column-specific filters
1186-
enableSorting?: boolean; // Enable column sorting (click headers to sort)
1071+
enableSorting?: boolean; // Enable column sorting
11871072
enablePagination?: boolean; // Enable pagination
1073+
enableColumnPinning?: boolean; // Enable column pinning
1074+
enableColumnVisibility?: boolean; // Enable column show/hide
11881075
enableRowSelection?: boolean; // Enable row selection
11891076

11901077
// Event Handlers
@@ -1218,8 +1105,10 @@ interface EditableTableColumnDefinition<T> {
12181105
maxWidth?: number; // Maximum column width
12191106

12201107
// Features
1221-
enableSorting?: boolean; // Enable sorting for this column (click header to sort)
1108+
enableSorting?: boolean; // Enable sorting for this column
12221109
enableFiltering?: boolean; // Enable filtering for this column
1110+
enableHiding?: boolean; // Allow hiding this column
1111+
isPinnable?: boolean; // Allow pinning this column
12231112

12241113
// Dependencies and validation
12251114
dependsOn?: string[]; // Fields this column depends on
@@ -1541,23 +1430,16 @@ describe('Cell Save', () => {
15411430
// Basic column filtering is available
15421431
<EditableTable
15431432
enableColumnFilters={true}
1544-
// Future: Advanced filter types (date ranges, number ranges, etc.)
1545-
/>
1546-
```
1547-
1548-
4. **Column Sorting** (✅ Implemented)
1549-
```tsx
1550-
// Click column headers to sort (ascending → descending → unsorted)
1551-
<EditableTable
1552-
enableSorting={true}
1553-
editableColumns={[
1554-
{ name: 'Name', key: 'name', type: 'text', enableSorting: true },
1555-
{ name: 'Price', key: 'price', type: 'number', enableSorting: true },
1556-
]}
1433+
// Future: Advanced filter types
1434+
filterTypes={{
1435+
status: 'select',
1436+
date: 'dateRange',
1437+
price: 'numberRange',
1438+
}}
15571439
/>
15581440
```
15591441

1560-
5. **Column Tooltips** (✅ Implemented)
1442+
4. **Column Tooltips** (✅ Implemented)
15611443
```tsx
15621444
// Tooltip support for column headers is now available
15631445
<EditableTable
@@ -1566,8 +1448,8 @@ describe('Cell Save', () => {
15661448
}}
15671449
/>
15681450
```
1569-
1570-
6. **Pagination** (✅ Implemented)
1451+
1452+
5. **Pagination** (✅ Implemented)
15711453
```tsx
15721454
// Full pagination system with customizable page sizes
15731455
<EditableTable

0 commit comments

Comments
 (0)