Form blocks provide complete, production-ready forms with built-in validation, error handling, and professional styling.
A comprehensive demo request form designed for enterprise sales. Validates company emails, collects detailed user information, and can integrate with PostHog and Slack.
Basic Usage
import reflex as rx
from reflex_ui.blocks.demo_form import demo_form, demo_form_dialog
import reflex_ui as ui
# As a dialog
def demo_dialog_example():
return demo_form_dialog(
trigger=ui.button("Book a Demo"),
)
# As a standalone form
def demo_form_example():
return demo_form()
Features
- Email Validation: Rejects personal email providers (Gmail, Yahoo, etc.)
- Required Fields: First name, last name, business email, job title, company name
- Additional Context: Custom text area for project details
- Dropdowns: Employee count, referral source, technical level
- Error Display: Real-time validation feedback
- Auto-submit: Closes dialog on successful submission
Props
Optional prefix for form element IDs to ensure uniqueness when multiple forms exist on the same page. Auto-generated if not provided.
Additional CSS classes to apply to the form container.
Dialog Version Props
The component that opens the dialog when clicked.
The demo form includes these fields:
# Personal Information
- first_name (required)
- last_name (required)
- email (required, validated for company domain)
# Company Information
- job_title (required)
- company_name (required)
- number_of_employees (required dropdown)
# Project Details
- internal_tools (required textarea)
- how_did_you_hear_about_us (required dropdown)
- technical_level (required dropdown)
Email Validation
The form validates that users provide a company email address:
from reflex_ui.blocks.demo_form import check_if_company_email
# Validates email is not from personal providers
check_if_company_email("[email protected]") # True
check_if_company_email("[email protected]") # False
Customization Example
import reflex as rx
from reflex_ui.blocks.demo_form import demo_form_dialog
import reflex_ui as ui
def custom_demo_form():
return demo_form_dialog(
trigger=ui.button(
"Schedule Enterprise Demo",
size="lg",
variant="primary",
),
id_prefix="enterprise",
class_name="enterprise-form",
)
A user onboarding form for collecting initial user information during free trial signups or account creation.
Basic Usage
import reflex as rx
from reflex_ui.blocks.intro_form import intro_form, intro_form_dialog
import reflex_ui as ui
class FormState(rx.State):
async def handle_submit(self, form_data: dict):
# Process form submission
print(f"User: {form_data['email']}")
# As a dialog
def intro_dialog_example():
return intro_form_dialog(
trigger=ui.button("Get Started"),
on_submit=FormState.handle_submit,
)
# As a standalone form
def intro_form_example():
return intro_form(
on_submit=FormState.handle_submit,
)
Features
- Email Validation: Rejects personal email providers
- Phone Number Field: Collects contact information
- Company Details: Job title and company name
- Project Context: What users plan to build
- User Profiling: Employee count, referral source, technical level
- Loading State: Shows loading indicator during submission
- Custom Submission: Hook into form submission with
on_submit
Props
Optional prefix for form element IDs. Auto-generated if not provided.
Event handler called when the form is submitted. Receives form data as a dictionary.
Additional CSS classes for the form container.
Dialog Version Props
Component that triggers the dialog.
The intro form includes:
# Personal Information
- first_name (required)
- last_name (required)
- email (required, validated)
- phone_number (required)
# Company Information
- job_title (required)
- company_name (required)
- number_of_employees (required dropdown)
# Project Details
- internal_tools (required textarea)
- how_did_you_hear_about_us (required dropdown)
- technical_level (required dropdown)
Handling Submission
import reflex as rx
from reflex_ui.blocks.intro_form import intro_form_dialog
import reflex_ui as ui
class OnboardingState(rx.State):
is_processing: bool = False
async def process_signup(self, form_data: dict):
self.is_processing = True
# Extract form data
email = form_data.get("email")
first_name = form_data.get("first_name")
company = form_data.get("company_name")
# Process signup (e.g., create account, send email)
# await create_user_account(email, first_name, company)
self.is_processing = False
return rx.redirect("/dashboard")
def signup_page():
return intro_form_dialog(
trigger=ui.button("Start Free Trial"),
on_submit=OnboardingState.process_signup,
)
Client State
Both forms use client state for managing UI state:
# Demo form client state
from reflex_ui.blocks.demo_form import (
demo_form_open_cs, # Dialog open state
demo_form_error_message, # Validation error message
)
# Intro form client state
from reflex_ui.blocks.intro_form import (
intro_form_open_cs, # Dialog open state
intro_form_error_message, # Validation error message
is_submitting_intro_form_cs, # Submission loading state
)
Common Patterns
Multiple Forms on One Page
Use id_prefix to avoid ID conflicts:
def multi_form_page():
return rx.vstack(
demo_form_dialog(
trigger=ui.button("Enterprise Demo"),
id_prefix="enterprise",
),
intro_form_dialog(
trigger=ui.button("Free Trial"),
id_prefix="trial",
),
)
class FormState(rx.State):
show_enterprise_form: bool = False
def conditional_forms():
return rx.cond(
FormState.show_enterprise_form,
demo_form_dialog(trigger=ui.button("Enterprise")),
intro_form_dialog(trigger=ui.button("Free Trial")),
)