Skip to main content
Form blocks provide complete, production-ready forms with built-in validation, error handling, and professional styling.

Demo Form

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

id_prefix
str
Optional prefix for form element IDs to ensure uniqueness when multiple forms exist on the same page. Auto-generated if not provided.
class_name
str
Additional CSS classes to apply to the form container.

Dialog Version Props

trigger
rx.Component
The component that opens the dialog when clicked.

Form Fields

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",
    )

Intro 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

id_prefix
str
Optional prefix for form element IDs. Auto-generated if not provided.
on_submit
EventType
Event handler called when the form is submitted. Receives form data as a dictionary.
class_name
str
Additional CSS classes for the form container.

Dialog Version Props

trigger
rx.Component
Component that triggers the dialog.
on_submit
EventType
Form submission handler.

Form Fields

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",
        ),
    )

Conditional Form Display

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")),
    )

Build docs developers (and LLMs) love