tp-react-elements
tp-react-elements
A comprehensive React form library built with Material-UI and React Hook Form, designed for enterprise applications.
What's New
Quick-glance log of notable fixes and changes. Newest entries first. Each entry should also be reflected in the affected component's Storybook docs (
*.stories.tsx→meta.parameters.docs.description) so consumers see the same explanation in both places.
SingleSelectSearchApi— The selected-valueTooltipis now suppressed viaopen={false}(controlled-closed) instead of relying on the Popper modifier fix. Background: the tooltip previously rendered pinned to the viewport's top-left corner (0,0) instead of near the input when the field sat inside anoverflow: hiddenancestor (e.g. a table cell inmaterial-react-table/GenericPaginatedGrid). Disabling Popper'shidemodifier and usingrootBoundary: 'viewport'verifiably fixed this in Storybook (MUI v7), but the same build still mis-anchored when consumed live in apps pinned to MUI v6 (below our@mui/material >=7.3.1peer requirement) — MUI v6's Popper/Tooltip runtime ignores the modifier configuration. Rather than ship a tooltip that only behaves correctly on some MUI majors, we now suppress it at the prop level:open={false}forces MUI'sTooltipinto fully-controlled mode so it never opens. TheTooltipelement (and its modifier config) is retained (not removed) — flippingopenback to the default is a one-line change once the anchoring fix is confirmed across all supported MUI majors. See the "Tooltip inside a clipped container" story inSingleSelectSearchApi.stories.tsxand the component's JSDoc for details.
Features
- Seamless Integration - Built on React Hook Form for performance and flexibility
- Material Design - Consistent with Material-UI design system
- Robust Validation - Integrated with Yup for schema validation
- Accessibility First - WCAG compliant with proper ARIA attributes
- TypeScript Ready - Full type safety and IntelliSense support
- Rich Documentation - Comprehensive docs with Storybook
- Well Tested - Extensive test coverage with React Testing Library
Requirements
- Node.js: v18.17+ or v20.11+ (LTS recommended)
- React: v18.x or v19.x
- TypeScript: v5.x (recommended)
Supported Versions
| Package | Supported Versions |
|---|---|
| React | >=18 <20 |
| React DOM | >=18 <20 |
| React Hook Form | 7.x |
| Material-UI | 7.x |
| Material-UI Icons | 7.x |
| Emotion React | 11.14.x |
| Emotion Styled | 11.14.x |
Installation
This library uses peer dependencies to avoid version conflicts and reduce bundle size. You need to install the required dependencies separately.
Quick Install (Recommended)
Install the library, then install only the core peer dependencies. Optional features (Rich Text, Session Timeout) can be added separately.
npm install tp-react-elements
# installs only core peers (no rich text, no idle timer)
npx install-tp-form-deps
# if you need Rich Text Editor
npx install-tp-form-deps --with-richtext
# or install optional peers manually
npm install jodit@^4.6.2 jodit-react@^5.2.19Optimized Imports
To reduce bundle size, you can import only the components you need using subpath imports:
// Import a specific component (top-level component folders only)
import { ModalField } from 'tp-react-elements/components/ModalField';
// Import Form module shortcuts
import { RenderForm } from 'tp-react-elements/form';
// Import utilities
import * as Utils from 'tp-react-elements/utils';See our Subpath Imports Guide for detailed instructions on optimizing your imports.
Manual Installation
Step 1: Install Required Dependencies (Core)
npm install react@^19.1.1 react-dom@^19.1.1 \
react-hook-form@^7.62.0 \
@mui/material@^7.3.1 @mui/icons-material@^7.3.1 \
@emotion/react@^11.14.0 @emotion/styled@^11.14.1 \
@mui/x-date-pickers@^8.10.2 \
@hookform/error-message@^2.0.1 @hookform/resolvers@^5.2.1 \
date-fns@^4.1.0 dayjs@^1.11.13 \
yup@^1.7.0 \
crypto-js@^4.2.0 file-saver@^2.0.5 xlsx-js-style@^1.2.0Step 2: Optional Dependencies
# Rich Text Editor (optional)
npm install jodit@^4.6.2 jodit-react@^5.2.19
# Session timeout (optional)
npm install react-idle-timer@^5.7.2Step 3: Install the Library
npm install tp-react-elementsQuick Start
import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import { Input } from "tp-react-elements";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
const schema = yup.object({
email: yup.string().email().required(),
password: yup.string().min(8).required(),
});
function LoginForm() {
const { control, handleSubmit } = useForm({
resolver: yupResolver(schema),
});
const onSubmit = (data) => {
console.log(data);
};
return (
<ThemeProvider theme={createTheme()}>
<CssBaseline />
<form onSubmit={handleSubmit(onSubmit)}>
<Input
name="email"
control={control}
label="Email Address"
type="email"
required
fullWidth
/>
<Input
name="password"
control={control}
label="Password"
type="password"
required
fullWidth
/>
<button type="submit">Sign In</button>
</form>
</ThemeProvider>
);
}Components
The library provides a comprehensive set of form components that integrate seamlessly with React Hook Form and Material-UI:
- Input - Text input fields with various types (text, email, password, etc.)
- Select - Single and multi-select dropdowns with autocomplete
- DatePicker - Calendar-based date selection
- TimePicker - Time selection with various formats
- FileUpload - File upload with preview and validation
- RichTextEditor - WYSIWYG editor for formatted text
- Checkbox - Single and group checkbox components
- RadioGroup - Radio button selection groups
- Switch - Toggle switches for boolean values
- Form - Container component with built-in validation
- GenericPaginatedGrid - Server-paginated data grid with dynamic filter chips (see Storybook Docs → Paginated Grid)
Refer to our Storybook documentation for detailed API documentation and examples.
Paginated grid (Storybook)
npm run storybook- Docs → Paginated Grid — API reference plus four copy-paste examples (embedded panel, wrapped headers, typography, invoice filters)
- Components → PaginatedGrid → Sample Grids — mock grids (no API): header wrap, compact layout, viewport fill, multi-select with Apply button, month picker
- Components → PaginatedGrid → Example Grid — invoice grid demo using mock data (no API)
Global Search: every GenericPaginatedGrid includes a built-in search icon in the top-right toolbar — collapsed by default (set showGlobalSearchByDefault={true} to start expanded). Click the icon to expand a free-text search that filters across all visible columns of the current batch. See Docs → Paginated Grid → Global search.
Excel export: the Export button downloads an .xlsx file with the header row styled in headerBgColor (bold white text) and columns auto-sized to fit content. Requires xlsx-js-style as a peer dependency.
Element IDs: every interactive element (toolbar buttons, filter chips, pagination controls) receives a stable id attribute. Pass gridId="invoice" (or omit to default to exportFilename) and all elements follow the pattern {gridId}_refresh_icon, {gridId}_dateRange_chip, {gridId}_next_page_icon, etc. See Docs → Paginated Grid — Element IDs in Storybook for the full reference table.
Example — compact embedded grid with smaller fonts:
<GenericPaginatedGrid
tableHeight="calc(100vh - 240px)"
autoFillViewport={false}
uiDensity="compact"
headerBgColor="#f5f5f5"
headerMaxHeight={64}
headerFontSize={11}
bodyFontSize={10}
{...gridProps}
/>Example — wrapped header “Department / Business Unit”:
<GenericPaginatedGrid
headerBgColor="#e8eaf6"
headerMinHeight="48px"
headerMaxHeight="96px"
headerFontSize={12}
bodyFontSize={12}
layoutMode="grid"
{...gridProps}
/>Full examples: Storybook Docs → Paginated Grid → Examples.
Best Practices for Code Structure and Organization
Component Organization
Feature-Based Organization: Group related components together in feature-based directories for better organization.
src/ features/ text-inputs/ date-pickers/ selects/ file-uploads/Component Documentation: Add JSDoc comments to all components and functions, describing their purpose, props, and usage examples.
Component Factories: Implement factory patterns for similar components to reduce code duplication.
// Example of a component factory const createFormField = (FieldComponent) => { return ({ name, control, label, ...props }) => ( <Controller name={name} control={control} render={({ field, fieldState }) => ( <FieldComponent {...field} label={label} error={!!fieldState.error} helperText={fieldState.error?.message} {...props} /> )} /> ); };Barrel Exports: Use barrel files (index.ts) to simplify imports for consumers.
Naming Conventions: Adopt consistent naming conventions across the codebase (PascalCase for components, camelCase for utilities).
Performance Optimization
Component Memoization: Use React.memo for complex components to prevent unnecessary re-renders.
const MemoizedFormField = React.memo(FormField, (prevProps, nextProps) => { return prevProps.value === nextProps.value && prevProps.error === nextProps.error; });Code Splitting: Implement dynamic imports for larger components to reduce initial load time.
// Use dynamic imports for complex components const RichTextEditor = React.lazy(() => import('./RichTextEditor'));Tree-Shaking Friendly Exports: Ensure all exports are compatible with tree-shaking.
Debounced Validation: Implement debounced validation for fields with expensive validation operations.
const debouncedValidate = useCallback( debounce((value) => validateField(value), 300), [] );Virtual Rendering: For components that render large lists, implement virtualization to improve performance.
Context Optimization: Split context providers to minimize re-renders when state changes.
// Split form context into smaller, focused contexts const FormValuesContext = createContext({}); const FormErrorsContext = createContext({});
Documentation and Usability
Interactive Examples: Enhance Storybook documentation with interactive examples for common use cases.
Component Playground: Create an online playground for experimenting with components in real-time.
Migration Guides: Provide comprehensive migration guides for major version updates.
Enhanced Type Definitions: Improve TypeScript definitions with descriptive comments and examples.
/** * Props for the Input component * @example * <Input * name="email" * control={control} * label="Email Address" * required * /> */ export interface InputProps { /** Field name in the form */ name: string; /** Form control from useForm hook */ control: Control<any>; // ... other props }Theme Customization Guide: Document how to customize the theme to match brand guidelines.
Accessibility Documentation: Add specific documentation about accessibility features and how to maintain accessibility when customizing components.
Performance Best Practices: Document performance considerations for using the library in large applications.
For Library Developers
If you're contributing to this library or setting up for development:
Development Setup
# Clone the repository
git clone https://github.com/your-office/form-elements.git
cd form-elements
# Install all dependencies (including devDependencies)
npm install
# Start development server
npm run dev
# Run tests
npm test
# Build the library
npm run buildDependency Structure
peerDependencies: Required by library consumers, must be installed separatelydevDependencies: Required for development, testing, and building the librarydependencies: Empty (following library best practices)
Why Peer Dependencies?
- Avoid Version Conflicts: Prevents multiple versions of React, MUI, etc.
- Smaller Bundle Size: No duplicate packages in consumer projects
- Version Control: Users control which versions they use
- Industry Standard: Same pattern used by MUI, React Hook Form, etc.
Reducing “Wide” Peer Dependencies
- Make non-core peers optional: Rich text (
jodit,jodit-react) and session timeout (react-idle-timer) are optional and not installed by default viainstall-tp-form-deps. - Feature subpackages (advanced): Move heavy features into dedicated entry points (e.g.,
tp-react-elements/richtext) with their own peer sets. - Thin wrappers (advanced): Provide adapters that lazy-load optional features so apps that don’t use them never import those packages.
- Clear installer flags: Use
--with-richtextand--with-idle(or--all) to explicitly include optional peers only when needed.
License
MIT