CodingCode ReviewIntermediate30 minSaves 30 minutes

Build a Headless React Data Table with Compound Components

For React engineers, this prompt guides the creation of a flexible, headless data table using compound components, essential for robust internal admin tools without external UI dependencies.

Develop a headless React data table using the compound component pattern, featuring sorting, pagination, and column visibility. This solution provides a type-safe, performant foundation for internal tools, eliminating reliance on third-party UI libraries while ensuring accessibility and testability.

READY-TO-USE PROMPT

Copy Prompt

prompt.txt
Act as a senior React engineer specializing in robust, maintainable UI components.

Our team requires a highly customizable data table for various internal administration dashboards. We prioritize a headless approach to maintain full control over styling and behavior, and a compound component pattern for API clarity and flexibility. The solution must be production-ready, including considerations for type safety, accessibility, and performance.

Design and implement a headless React data table component using the compound component pattern. The table should support the following core features:

*   **Compound Component Structure:** Implement `Table.Root`, `Table.Header`, `Table.Row`, `Table.Cell`, `Table.ColumnToggle`, and `Table.Pagination`.
*   **Data Handling:** Accept an array of objects as data.
*   **Sorting:** Allow sorting by multiple columns, with visual indicators for current sort order (ascending/descending).
*   **Pagination:** Implement client-side pagination with controls for page navigation and items per page.
*   **Column Visibility:** Provide controls to dynamically show or hide columns.
*   **Headless Logic:** All state management and logic should be exposed via hooks or context, allowing consumers to render their own UI.
*   **TypeScript:** All components, hooks, and types must be fully typed.
*   **Accessibility:** Adhere to WCAG guidelines for data tables, including ARIA attributes where appropriate.
*   **Testing:** Include basic unit tests for core logic (sorting, pagination).
*   **Performance:** Consider large datasets and optimize rendering.

*   Do not use any external UI component libraries (e.g., Material UI, Ant Design, Chakra UI).
*   Focus on functional components and React hooks.
*   Provide a complete, runnable solution.
*   The output must include a file tree, all TSX files, relevant hooks, test files, and dedicated sections for accessibility and performance notes.
*   Assume the data structure will be an array of objects, and column definitions will be provided.

*   `{{data_structure_json}}`: A JSON string representing the array of data objects for the table. Example: `[{"id": 1, "name": "Alice", "age": 30}, {"id": 2, "name": "Bob", "age": 24}]`
*   `{{initial_column_config_json}}`: A JSON string representing the initial column configuration, including `id`, `header`, `accessor` (key to access data), and `sortable` properties. Example: `[{"id": "name", "header": "Name", "accessor": "name", "sortable": true}, {"id": "age", "header": "Age", "accessor": "age", "sortable": true}]`

Provide the complete React solution structured as follows:

1.  **File Tree:** A clear representation of the project structure.
2.  **`Table` Component (TSX):** The main compound component structure.
3.  **Hooks (TSX):** Any custom hooks for state management (e.g., `useTable`, `useSort`, `usePagination`).
4.  **Types (TS):** All necessary TypeScript interfaces and types.
5.  **Example Usage (TSX):** A simple example demonstrating how to use the `Table` component with the provided data.
6.  **Tests (TSX):** Basic unit tests for sorting and pagination logic.
7.  **Accessibility Notes:** A section detailing the accessibility considerations and ARIA attributes used.
8.  **Performance Notes:** A section outlining performance optimizations implemented or considered.

Estimated results

DifficultyIntermediate
Setup time30 min
Time saved30 minutes
Best modelsClaude, ChatGPT, Gemini
Best audienceSoftware Development, Internal Tools

Editor's note

Why this prompt matters

Building custom data tables for internal tools often presents a dilemma: rely on heavy external UI libraries that might not align with an existing design system, or build from scratch, which can be time-consuming. This workflow addresses that challenge directly for React engineers. It focuses on creating a headless data table using the compound component pattern, providing complete control over styling and behavior while maintaining a clear, flexible API. This approach is particularly valuable when consistency across multiple dashboards is critical, and performance for large datasets cannot be compromised. Reach for this workflow when your project demands a tailored data display solution that integrates into your application's specific aesthetic and functional requirements, without the overhead or opinionated styling of third-party components. It's designed for teams who need a solid foundation for their internal administration tools, ensuring maintainability and adaptability as requirements evolve.

Anatomy

Prompt engineering breakdown

Role

senior React engineer specializing in robust, maintainable UI components.

Context

Our team requires a highly customizable data table for various internal administration dashboards. We prioritize a headless approach to maintain full control over styling and behavior, and a compound component pattern for API clarity and flexibility. The solution must be production-ready, including considerations for type safety, accessibility, and performance.

Goal

Design and implement a headless React data table component using the compound component pattern with sorting, pagination, and column visibility, no external UI library. Provide a complete, runnable solution including file tree, TSX files, hooks, tests, accessibility, and performance notes.

Constraints

Do not use any external UI component libraries. Focus on functional components and React hooks. Provide a complete, runnable solution. The output must include a file tree, all TSX files, relevant hooks, test files, and dedicated sections for accessibility and performance notes. Assume the data structure will be an array of objects, and column definitions will be provided.

Output format

File Tree, Table Component (TSX), Hooks (TSX), Types (TS), Example Usage (TSX), Tests (TSX), Accessibility Notes, Performance Notes.

Why this structure works

The prompt uses role priming to establish the model's persona as an expert, ensuring the technical depth of the response. Explicit constraints guide the model away from undesired patterns like external UI libraries. Structured output ensures all required components of the solution are present and organized, minimizing omissions and focusing the model on delivering a production-ready code solution with essential documentation.

Pick your version

Prompt variations

BeginnerWorks with any model

For learning basic React component architecture or quickly scaffolding a simple table with core features.

prompt.txt
Act as a React developer. We need a simple data table for an internal tool. It should use a compound component structure to organize its parts.

Create a basic React data table component. It needs a main `Table` component, `TableHeader`, `TableRow`, and `TableCell` for displaying data. The table should accept an array of data objects.

Include basic sorting functionality for one column and simple pagination to show a few items per page.

Use TypeScript for component definitions.

Do not use any UI libraries. Provide a complete code example including the file structure, all component files, and a simple usage example.

Use `{{data_structure_json}}` for the data and `{{initial_column_config_json}}` for column setup.
ProfessionalBest with claude

When a comprehensive, production-ready headless data table with advanced features and documentation is required for a project.

prompt.txt
Act as a senior React engineer specializing in robust, maintainable UI components. Our team needs a highly customizable headless data table for internal dashboards, using a compound component pattern for API clarity. The solution must be production-ready, considering type safety, accessibility, and performance.

Design and implement a headless React data table using compound components: `Table.Root`, `Table.Header`, `Table.Row`, `Table.Cell`, `Table.ColumnToggle`, `Table.Pagination`. It must support data handling from an array of objects, multi-column sorting with visual indicators, client-side pagination, and dynamic column visibility. All state and logic should be exposed via hooks or context.

Ensure the solution is fully typed with TypeScript, adheres to WCAG guidelines (including ARIA), includes basic unit tests for core logic (sorting, pagination), and optimizes rendering for large datasets.

Do not use external UI libraries. Focus on functional components and React hooks. Provide a complete, runnable solution including: a file tree, all TSX files, relevant hooks, types, an example usage, unit tests, and dedicated sections for accessibility and performance notes.

Use `{{data_structure_json}}` for table data and `{{initial_column_config_json}}` for column definitions.
Short VersionBest with chatgpt

For quick prototyping or when you need a concise, high-level request for a feature-rich data table without extensive detail upfront.

prompt.txt
As a senior React engineer, create a headless data table using the compound component pattern (`Table.Root`, `Header`, `Row`, `Cell`, `ColumnToggle`, `Pagination`). Implement multi-column sorting, client-side pagination, and dynamic column visibility. The solution must be fully typed with TypeScript, adhere to WCAG accessibility, include basic unit tests, and optimize for performance with large datasets. No external UI libraries allowed. Provide a complete, runnable solution with file tree, TSX, hooks, types, example, tests, and dedicated accessibility/performance notes. Use `{{data_structure_json}}` and `{{initial_column_config_json}}` for inputs.
EnterpriseBest with gemini

For large-scale projects requiring strict adherence to enterprise standards, comprehensive compliance, and robust maintainability.

prompt.txt
Act as a senior React engineer specializing in robust, maintainable UI components for enterprise applications. Our organization requires a highly customizable headless data table for critical internal administration dashboards. We mandate a headless approach and a compound component pattern for clear API boundaries and long-term flexibility, ensuring production readiness, type safety, accessibility (WCAG 2.1 AA), security, and optimized performance for high-volume data.

Design and implement this headless React data table using `Table.Root`, `Table.Header`, `Table.Row`, `Table.Cell`, `Table.ColumnToggle`, `Table.Pagination`. It must accept an array of objects, support multi-column sorting, secure client-side pagination, and dynamic column visibility. All state/logic must be exposed via well-documented hooks/context for auditing and cross-team integration.

Ensure full TypeScript typing, strict adherence to WCAG 2.1 AA guidelines (with ARIA), comprehensive unit/integration tests, and performance optimizations for large datasets. Compliance with internal code standards and security best practices is paramount.

Do not use external UI libraries. Focus on functional components and React hooks. Provide a complete, auditable solution including: a detailed file tree, all TSX files, documented hooks, types, a production-ready example, a thorough test suite, and dedicated sections for accessibility, performance, and potential security considerations.

Use `{{data_structure_json}}` for table data and `{{initial_column_config_json}}` for initial column configurations.

What you'll get

Expected output

The output would provide a complete, runnable solution structured as follows:

`` src/ ├── components/ │ └── Table/ │ ├── Table.tsx // Table.Root, TableContext provider │ ├── TableHeader.tsx // Table.Header │ ├── TableRow.tsx // Table.Row │ ├── TableCell.tsx // Table.Cell │ ├── TableColumnToggle.tsx // Table.ColumnToggle │ └── TablePagination.tsx // Table.Pagination ├── hooks/ │ └── useTable.ts // Core table logic, state, and actions ├── types/ │ └── table.ts // TypeScript interfaces for data, columns, state ├── utils/ │ └── sort.ts // Sorting utility functions └── App.tsx // Example usage ``

`src/components/Table/Table.tsx`: This file would define the Table.Root component, which establishes the TableContext. It accepts initial data and column configurations, then uses useTable to manage the table's state. The context provides access to sorted data, current page items, column visibility, and state modifiers to all child compound components.

`src/hooks/useTable.ts`: This hook encapsulates the core headless logic. It manages state for sorting (multi-column), pagination (current page, items per page), and column visibility. It exposes computed values like sortedData, paginatedData, and visibleColumns, along with functions to update state, such as setSort, goToPage, setItemsPerPage, and toggleColumnVisibility. All state and functions are strongly typed.

Compound Components (`TableHeader.tsx`, `TableRow.tsx`, `TableCell.tsx`, etc.): Each compound component consumes the TableContext to access relevant state and functions. For instance, Table.Header would render sort indicators based on useTable's sort state and trigger setSort on header clicks. Table.Pagination would use currentPage, totalPages, and goToPage to render controls. These components are primarily concerned with rendering UI based on the logic provided by useTable.

Accessibility Considerations: The solution incorporates WCAG guidelines. Table.Root would use role="table". Table.Header cells would have scope="col" and aria-sort attributes dynamically updated based on the sort state. Interactive elements like pagination buttons and column toggles would have appropriate aria-label attributes and keyboard navigation support.

Performance Optimizations: To handle large datasets, useMemo is applied to expensive computations within useTable, such as sorting and pagination, ensuring these operations only re-run when dependencies change. React.memo is used for individual table cells and rows to prevent unnecessary re-renders when their props haven't changed. For extremely large datasets, a virtualized list library would be noted as a potential future enhancement, but not implemented in the initial output to focus on core headless logic.

Testing Strategy: Unit tests for useTable.ts would cover sorting logic (single, multi-column, direction), pagination calculations (page changes, items per page), and column visibility toggling. Integration tests would verify that compound components correctly interact with the TableContext and trigger the expected state changes in useTable.

Under the hood

Why this prompt works

This prompt functions effectively due to its structured approach and precise instructions. First, establishing the AI's persona as a "senior React engineer specializing in robust, maintainable UI components" immediately sets the expected technical depth and pragmatic tone. This role-playing ensures the generated solution aligns with an experienced developer's perspective on component design and architecture.

Key to its success is the detailed, bulleted feature list. This breaks down the complex task of building a data table into specific, verifiable requirements such as "Compound Component Structure," "Sorting," and "TypeScript." This clear enumeration minimizes ambiguity, directing the model to address all critical aspects comprehensively. Negative constraints, like "Do not use any external UI component libraries," are equally important, preventing the inclusion of unwanted dependencies and ensuring the headless approach is strictly maintained.

The prompt explicitly defines the required output format: a "file tree, all TSX files, relevant hooks, test files, and dedicated sections for accessibility and performance notes." This structured output ensures the generated code is immediately consumable and reviewable. Lastly, the inclusion of specific placeholders for data_structure_json and initial_column_config_json allows for dynamic, type-safe input, making the prompt reusable across various data scenarios without internal modifications.

Model fit

Best AI models for this prompt

Claude

Claude excels at generating well-structured, idiomatic React code, often producing clean TypeScript and thoughtful component architecture. Its ability to follow complex instructions for compound components and headless logic makes it suitable for this task. However, it may occasionally require minor adjustments for perfect accessibility attribute placement or edge-case test coverage. See the full Claude hub for deeper guidance.

ChatGPT

ChatGPT is proficient in generating functional React components and handling state logic. It can produce a solid initial draft for the data table, including sorting and pagination. While its TypeScript output is generally good, it might need more explicit prompting for advanced type inference or detailed accessibility implementations. Review the generated tests carefully for comprehensive coverage. See the full ChatGPT hub for deeper guidance.

Gemini

Gemini provides strong capabilities for generating React code with a focus on clarity and directness. It can effectively implement the core features like sorting and pagination within a compound component structure. Users might find that Gemini's output benefits from additional refinement regarding performance optimizations for very large datasets or more nuanced accessibility patterns. See the full Gemini hub for deeper guidance.

When to use

  • When a custom design system requires precise control over table presentation.
  • For internal tools where component reusability across multiple dashboards is key.
  • When a lightweight solution is preferred over adding a large UI library dependency.
  • To encapsulate complex table logic (sorting, pagination) for cleaner UI components.
  • When building highly interactive tables that need custom filtering or inline editing.

When not to use

  • For simple, static data displays where basic HTML tables suffice.
  • When rapid prototyping with an existing UI library's table component is acceptable.
  • For projects with extremely tight deadlines and no custom styling requirements.
  • If the team lacks familiarity with advanced React patterns like compound components or custom hooks.

Get more from it

Pro tips

  • 1

    Memoize rendered rows and cells to prevent unnecessary re-renders when data changes, especially with large datasets, optimizing performance.

  • 2

    Consider a dedicated context provider for table state if prop drilling becomes an issue across deeply nested compound components.

  • 3

    Normalize your input data structure to ensure consistent access patterns for sorting and filtering logic, simplifying data manipulation.

  • 4

    Implement a virtualized list or windowing solution for tables with thousands of rows to drastically improve initial render times and scrolling performance.

  • 5

    Carefully manage focus within pagination and column toggle controls to maintain keyboard navigation flow for accessibility users.

  • 6

    Separate presentation logic from data transformation logic in custom hooks for better testability and maintainability of the table's core features.

Don't ship this

Common mistakes

  • Inefficient sorting or pagination logic causes re-renders of the entire dataset on every state change.

    Fix — Apply `useMemo` to the sorted and paginated data arrays to cache results and only recompute when dependencies change.

  • Missing `aria` attributes or incorrect keyboard navigation breaks accessibility for assistive technologies.

    Fix — Systematically add `role`, `aria-sort`, `tabIndex`, and ensure focus management for interactive elements like headers and controls.

  • Not handling `null` or `undefined` values in data accessors, leading to runtime errors during sorting or display.

    Fix — Implement nullish coalescing or optional chaining (`data[accessor] ?? 'N/A'`) when accessing data properties within cells.

  • Over-relying on `useEffect` for all state synchronizations, resulting in complex dependency arrays and potential infinite loops.

    Fix — Prefer `useState` with functional updates or `useReducer` for state transitions to simplify logic and prevent unexpected re-renders.

  • Coupling table logic too tightly with specific data structures, making the component difficult to reuse with different datasets.

    Fix — Design column definitions and accessors to be generic, allowing consumers to map their data fields to the table's internal structure.

People also ask

Frequently asked questions

Q.Can this table handle server-side pagination and sorting?

The provided solution focuses on client-side logic. To support server-side operations, you would modify the usePagination and useSort hooks to dispatch API requests and update state with server-returned data. This involves adapting the data fetching mechanism.

Q.How do I add custom filtering capabilities to this table?

Introduce a new custom hook, useFilter, that processes the data array based on user input (e.g., search queries, dropdowns). Integrate this hook into the Table.Root context, applying filters before sorting and pagination.

Q.Is this approach suitable for tables with tens of thousands of rows?

For extremely large datasets, client-side pagination and sorting can become slow. Consider implementing data virtualization (e.g., react-window, react-virtualized) alongside the headless structure to render only visible rows, improving performance.

Q.What if my table cells require complex, interactive components?

The compound component pattern naturally supports this. You can pass custom render functions or child components directly into Table.Cell, allowing full control over the content and interactivity within each cell.

Q.How can I extend this to support column resizing or reordering?

Column resizing requires tracking mouse events and updating column widths in state, often using a separate context. Reordering involves state management for column order and re-rendering headers and cells based on that order. These are significant additions.

Version 1.0Last reviewed July 20, 2026
Reviewed by PromptInFlow Editorial Team