A React component library for creating natural language forms with interactive dropdowns and inputs.
npm install react-nlform # or yarn add react-nlformimport React, { useState } from 'react'; import { NLForm, NLSelect, NLInput } from 'react-nlform'; function App() { const [formData, setFormData] = useState({ foodType: '1', city: '' }); const foodOptions = [ { value: '1', label: 'any food' }, { value: '2', label: 'Italian' }, { value: '3', label: 'Japanese' } ]; const handleSubmit = (e) => { e.preventDefault(); console.log('Form data:', formData); }; return ( <NLForm onSubmit={handleSubmit}> I feel to eat{' '} <NLSelect options={foodOptions} value={formData.foodType} onChange={(value) => setFormData(prev => ({ ...prev, foodType: value }))} /> <br /> in{' '} <NLInput type="text" placeholder="any city" value={formData.city} onChange={(value) => setFormData(prev => ({ ...prev, city: value }))} subline="For example: <em>Los Angeles</em> or <em>New York</em>" /> <div className="nl-submit-wrap"> <button className="nl-submit" type="submit"> Find a restaurant </button> </div> </NLForm> ); }The main container component for natural language forms.
Props:
onSubmit?: (event: FormEvent) => void- Form submission handlerclassName?: string- Custom CSS class (default: 'nl-form')children: ReactNode- Form content
Example:
<NLForm onSubmit={handleSubmit} className="my-form"> {/* Your form content */} </NLForm>Interactive dropdown component for selecting from predefined options.
Props:
options: Option[]- Array of{value: string, label: string}objectsvalue?: string- Currently selected valueonChange: (value: string, label: string) => void- Selection change handlerclassName?: string- Custom CSS class
Example:
const options = [ { value: '1', label: 'Option 1' }, { value: '2', label: 'Option 2' } ]; <NLSelect options={options} value={selectedValue} onChange={(value, label) => { console.log('Selected:', { value, label }); setSelectedValue(value); }} />Interactive text input component with expandable interface.
Props:
type?: string- Input type (default: 'text')value?: string- Current input valueplaceholder?: string- Placeholder textsubline?: string- Helper text below input (supports HTML)onChange: (value: string) => void- Value change handlerclassName?: string- Custom CSS class
Example:
<NLInput type="text" placeholder="Enter your location" value={location} onChange={setLocation} subline="For example: <em>San Francisco</em> or <em>New York</em>" />React NLForm includes a powerful theme system for complete styling control.
Wrap your components with NLThemeProvider to apply custom themes:
import { NLForm, NLSelect, NLInput, NLThemeProvider } from 'react-nlform'; const customTheme = { form: { fontSize: '2.5em', fontFamily: 'Georgia, serif', }, fieldToggle: { color: '#0066cc', borderBottom: '2px solid #0066cc', }, optionsList: { background: '#2c3e50', borderRadius: '8px', boxShadow: '0 4px 12px rgba(0,0,0,0.2)', }, optionItem: { color: '#ecf0f1', padding: '0.75rem 1.5rem', }, submitButton: { background: '#27ae60', borderRadius: '6px', }, }; function App() { return ( <NLThemeProvider theme={customTheme}> <NLForm> {/* Your form components */} </NLForm> </NLThemeProvider> ); }The theme object supports the following properties:
interface NLTheme { form: { fontSize?: string; lineHeight?: string | number; fontFamily?: string; fontWeight?: string | number; width?: string; margin?: string; }; fieldToggle: { color?: string; cursor?: string; borderBottom?: string; textDecoration?: string; padding?: string; background?: string; }; optionsList: { background?: string; border?: string; borderRadius?: string; boxShadow?: string; fontSize?: string; minWidth?: string; zIndex?: number; }; optionItem: { color?: string; padding?: string; cursor?: string; backgroundColor?: string; hoverBackgroundColor?: string; checkedColor?: string; }; input: { width?: string; padding?: string; border?: string; borderRadius?: string; fontSize?: string; color?: string; backgroundColor?: string; }; submitButton: { background?: string; color?: string; padding?: string; fontSize?: string; fontWeight?: string | number; borderRadius?: string; }; // ... and more }Import and extend the default theme:
import { defaultTheme, NLThemeProvider } from 'react-nlform'; const myTheme = { ...defaultTheme, fieldToggle: { ...defaultTheme.fieldToggle, color: '#e74c3c', }, };import React, { useState } from 'react'; import { NLForm, NLSelect, NLInput, NLThemeProvider } from 'react-nlform'; function RestaurantFinder() { const [formData, setFormData] = useState({ foodType: '1', restaurantType: '1', time: '1', city: '' }); const foodOptions = [ { value: '1', label: 'any food' }, { value: '2', label: 'Indian' }, { value: '3', label: 'French' }, { value: '4', label: 'Japanese' }, { value: '5', label: 'Italian' } ]; const restaurantOptions = [ { value: '1', label: 'standard' }, { value: '2', label: 'fancy' }, { value: '3', label: 'casual' }, { value: '4', label: 'romantic' } ]; const timeOptions = [ { value: '1', label: 'anytime' }, { value: '2', label: '7 p.m.' }, { value: '3', label: '8 p.m.' }, { value: '4', label: '9 p.m.' } ]; const customTheme = { form: { fontSize: '3em', fontFamily: 'Arial, sans-serif', }, fieldToggle: { color: '#3498db', borderBottom: '2px solid #3498db', }, optionsList: { background: '#34495e', borderRadius: '8px', }, optionItem: { color: '#ecf0f1', checkedColor: '#f39c12', }, }; const handleSubmit = (e) => { e.preventDefault(); console.log('Restaurant preferences:', formData); // Handle form submission }; return ( <NLThemeProvider theme={customTheme}> <NLForm onSubmit={handleSubmit}> I feel to eat{' '} <NLSelect options={foodOptions} value={formData.foodType} onChange={(value) => setFormData(prev => ({ ...prev, foodType: value }))} /> <br /> in a{' '} <NLSelect options={restaurantOptions} value={formData.restaurantType} onChange={(value) => setFormData(prev => ({ ...prev, restaurantType: value }))} /> {' '}restaurant <br /> at{' '} <NLSelect options={timeOptions} value={formData.time} onChange={(value) => setFormData(prev => ({ ...prev, time: value }))} /> {' '}in{' '} <NLInput type="text" value={formData.city} placeholder="any city" subline="For example: <em>Los Angeles</em> or <em>New York</em>" onChange={(value) => setFormData(prev => ({ ...prev, city: value }))} /> <div className="nl-submit-wrap"> <button className="nl-submit" type="submit"> Find a restaurant </button> </div> </NLForm> </NLThemeProvider> ); }- 🎯 Natural Language Interface - Create forms that read like sentences
- 🎨 Fully Customizable Themes - Complete control over styling with theme provider
- 📱 Mobile Friendly - Touch-optimized interactions
- ♿ Accessible - Keyboard navigation and screen reader support
- 🔧 TypeScript Support - Full type definitions included
- 🪶 Lightweight - Minimal bundle size impact
- âš¡ Easy Integration - Works with any React setup
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
All components and themes are fully typed. Import types as needed:
import { NLTheme, NLFormProps, NLSelectProps, NLInputProps, Option } from 'react-nlform';MIT © Hypercard Limited Liability Co.
Inspired by the original NLForm by Codrops, reimagined for React with modern theming capabilities.
