Introducing Rich Components: Beyond Text in Conversations

·7 min

Conversations aren't just text. Today we're launching Rich Components—interactive elements that let you embed calendars, forms, payments, and custom React components directly in conversations.


Why Rich Components?


Traditional chatbots are limited to text and simple buttons. But real conversations need more:


Customer: "I'd like to book a table"

Bot (old way): "What date? (type in format MM/DD/YYYY)"

Customer: "08/30/2024"

Bot: "What time? (type in format HH:MM)"

Customer: "7pm"

Bot: "Sorry, 7pm isn't available. Try 6:30pm or 7:30pm"


Frustrating. Now watch this:


Customer: "I'd like to book a table"

Bot (new way): [Shows calendar picker with available dates highlighted]

Customer: [Selects August 30]

Bot: [Shows time slots: 6:30pm, 7:30pm, 8:30pm as clickable buttons]

Customer: [Taps 7:30pm]

Bot: "Perfect! Table for how many?" [Shows number picker: 2, 4, 6, 8]


Much better.


Available Components


1. Calendar Picker


Use cases:

  • Booking appointments
  • Scheduling demos
  • Selecting delivery dates
  • Choosing event dates
  • Example:

    javascript
    {
      type: 'calendar',
      availableDates: ['2024-08-30', '2024-08-31', '2024-09-01'],
      minDate: '2024-08-29',
      maxDate: '2024-12-31',
      onSelect: (date) => handleDateSelection(date)
    }
    

    Features:

  • Highlight available dates
  • Disable unavailable dates
  • Multi-date selection
  • Date range selection
  • Custom styling
  • 2. Form Components


    Use cases:

  • Lead capture
  • Survey responses
  • Address collection
  • Feedback forms
  • Example:

    javascript
    {
      type: 'form',
      fields: [
        { name: 'email', label: 'Email', type: 'email', required: true },
        { name: 'company', label: 'Company', type: 'text' },
        { name: 'size', label: 'Company Size', type: 'select', options: ['1-10', '11-50', '51-200', '200+'] }
      ],
      submitLabel: 'Get Demo',
      onSubmit: (data) => handleFormSubmit(data)
    }
    

    Features:

  • Text, email, number, select, textarea fields
  • Built-in validation
  • Conditional fields
  • Multi-step forms
  • Auto-save drafts
  • 3. Payment Components


    Use cases:

  • Take payments in-conversation
  • Upgrade subscriptions
  • Buy products
  • Pay invoices
  • Example:

    javascript
    {
      type: 'payment',
      amount: 99.00,
      currency: 'USD',
      description: 'Pro Plan - Monthly',
      provider: 'stripe', // or 'paypal'
      onSuccess: (paymentId) => handlePayment(paymentId)
    }
    

    Features:

  • Stripe and PayPal integration
  • Saved payment methods
  • Subscription payments
  • Invoice payments
  • Receipt generation
  • 4. Product Cards


    Use cases:

  • E-commerce product browsing
  • Service selection
  • Plan comparison
  • Feature showcases
  • Example:

    javascript
    {
      type: 'product_card',
      products: [
        {
          id: 'prod_123',
          name: 'Starter Plan',
          image: 'https://...',
          price: '$29/mo',
          features: ['1,000 conversations', 'Email support', 'Basic analytics'],
          primaryAction: { label: 'Choose Plan', action: 'select_starter' }
        }
      ]
    }
    

    Features:

  • Image support
  • Feature lists
  • Pricing display
  • Primary and secondary actions
  • Horizontal scrolling carousel
  • 5. Custom React Components


    Use cases:

  • Anything you can build in React
  • Branded experiences
  • Complex interactions
  • Third-party integrations
  • Example:

    javascript
    {
      type: 'custom',
      component: 'MyCustomBookingFlow',
      props: {
        availableTimes: [...],
        userId: '123',
        onComplete: (booking) => handleBooking(booking)
      }
    }
    

    Your custom component:

    javascript
    export function MyCustomBookingFlow({ availableTimes, userId, onComplete }) {
      // Build whatever you want with React
      return (
        
    {/* Your custom UI here */}
    ); }

    How It Works


    1. Bot Sends Component


    javascript
    async function handleMessage(message) {
      if (message.includes('book a table')) {
        return {
          type: 'message',
          content: "I'd love to help you book a table. What date works for you?",
          components: [
            {
              type: 'calendar',
              availableDates: await getAvailableDates(),
              onSelect: (date) => ({ action: 'date_selected', date })
            }
          ]
        };
      }
    }
    

    2. User Interacts


    The component renders in the conversation:

  • Users see the calendar
  • They select a date
  • Component calls the callback
  • Action sent back to bot
  • 3. Bot Responds


    ``javascript

    if (action === 'date_selected') {

    return {

    type: 'message',

    content: Great! What time on ${formatDate(date)}?,

    components: [

    {

    type: 'button_group',

    buttons: await getAvailableTimes(date)

    }

    ]

    };

    }

    
    
    

    Real-World Examples

    Example 1: Restaurant Booking

    javascript

    // Step 1: Date selection

    bot.send({

    content: "When would you like to dine with us?",

    components: [{

    type: 'calendar',

    availableDates: getNextMonth(),

    onSelect: (date) => ({ action: 'select_time', date })

    }]

    });


    // Step 2: Time selection

    bot.send({

    content: "Available times on Aug 30:",

    components: [{

    type: 'button_group',

    buttons: ['6:30 PM', '7:30 PM', '8:30 PM'],

    onSelect: (time) => ({ action: 'select_party_size', time })

    }]

    });


    // Step 3: Party size

    bot.send({

    content: "Table for how many?",

    components: [{

    type: 'button_group',

    buttons: ['2', '4', '6', '8+'],

    onSelect: (size) => ({ action: 'confirm_booking', size })

    }]

    });


    // Step 4: Confirmation

    bot.send({

    content: "Perfect! Confirming your reservation...",

    components: [{

    type: 'booking_summary',

    date: 'Aug 30',

    time: '7:30 PM',

    party: 4,

    actions: [

    { label: 'Confirm', action: 'book' },

    { label: 'Change', action: 'restart' }

    ]

    }]

    });

    
    
    

    Example 2: E-commerce Shopping

    javascript

    // Browse products

    bot.send({

    content: "Here are our best sellers:",

    components: [{

    type: 'product_carousel',

    products: [

    {

    name: 'Widget Pro',

    image: '...',

    price: '$99',

    rating: 4.5,

    action: 'view_product_123'

    },

    // More products...

    ]

    }]

    });


    // Product details

    bot.send({

    content: "Widget Pro",

    components: [{

    type: 'product_detail',

    images: ['img1.jpg', 'img2.jpg'],

    price: '$99',

    description: '...',

    variants: [

    { name: 'Color', options: ['Black', 'White', 'Blue'] },

    { name: 'Size', options: ['S', 'M', 'L', 'XL'] }

    ],

    primaryAction: { label: 'Add to Cart', action: 'add_to_cart' }

    }]

    });


    // Checkout

    bot.send({

    content: "Ready to checkout?",

    components: [{

    type: 'cart_summary',

    items: [...],

    total: '$99',

    actions: [

    { label: 'Checkout', action: 'checkout' },

    { label: 'Continue Shopping', action: 'browse' }

    ]

    }]

    });


    // Payment

    bot.send({

    content: "Complete your purchase:",

    components: [{

    type: 'payment',

    amount: 99.00,

    currency: 'USD',

    provider: 'stripe'

    }]

    });

    
    
    

    Example 3: Lead Qualification

    javascript

    // Collect info with form

    bot.send({

    content: "Let's get started. Tell us a bit about your needs:",

    components: [{

    type: 'form',

    fields: [

    { name: 'name', label: 'Name', required: true },

    { name: 'email', label: 'Email', type: 'email', required: true },

    { name: 'company', label: 'Company' },

    { name: 'employees', label: 'Company Size', type: 'select', options: ['1-10', '11-50', '51-200', '200+'] },

    { name: 'use_case', label: 'Primary Use Case', type: 'textarea' }

    ],

    submitLabel: 'Continue'

    }]

    });


    // Follow-up based on responses

    if (data.employees === '200+') {

    bot.send({

    content: "Great! Let's schedule a call with our enterprise team.",

    components: [{

    type: 'calendar',

    integration: 'calendly',

    url: 'https://calendly.com/enterprise-demo'

    }]

    });

    } else {

    bot.send({

    content: "Perfect! Here's a quick demo video:",

    components: [{

    type: 'video',

    url: 'https://youtube.com/demo',

    actions: [

    { label: 'Start Free Trial', action: 'sign_up' },

    { label: 'Schedule Demo', action: 'book_demo' }

    ]

    }]

    });

    }

    
    
    

    Technical Details

    Component Rendering

    Rich Components use React for rendering:
    javascript

    // Bot returns component spec

    {

    type: 'calendar',

    availableDates: ['2024-08-30'],

    // ...

    }


    // Widget converts to React component

    availableDates={['2024-08-30']}

    onSelect={handleSelect}

    />

    
    
    

    State Management

    Components maintain their own state:
    javascript

    function CalendarComponent({ availableDates, onSelect }) {

    const [selectedDate, setSelectedDate] = useState(null);


    const handleDateClick = (date) => {

    setSelectedDate(date);

    onSelect(date); // Notify bot

    };


    return ;

    }

    
    
    

    Custom Styling

    Match your brand:
    javascript

    {

    type: 'calendar',

    theme: {

    primaryColor: '#0066cc',

    borderRadius: '8px',

    fontFamily: 'Inter, sans-serif'

    }

    }

    
    
    Or inject custom CSS:
    
    
    javascript

    {

    type: 'custom',

    component: 'MyComponent',

    styles:

    .my-component {

    background: linear-gradient(to right, #667eea, #764ba2);

    }

    }

    
    
    

    Performance

    Fast: Components are lazy-loaded Small: Only load what you use Cached: Shared components cached across conversations Size:
  • Base widget: 45 KB (gzipped)
  • Calendar component: +12 KB
  • Form component: +8 KB
  • Payment component: +18 KB (includes Stripe)
  • Custom components: Your size
  • Pricing

    Rich Components are included in all plans:
  • Free tier: Basic components (buttons, forms, calendar)
  • Pro tier: All components + custom styling
  • Enterprise: Custom components + white-label
  • No additional cost per component. Still outcome-based pricing.

    Get Started

    1. Update your SDK:
    bash

    npm install @ilq/sdk@latest

    
    
    2. Return component in your handler:
    
    javascript

    bot.onMessage(async (message) => {

    return {

    content: "Choose a date:",

    components: [{

    type: 'calendar',

    onSelect: (date) => ({ action: 'date_selected', date })

    }]

    };

    });

    
    
    3. Handle component actions:
    
    javascript

    bot.onAction('date_selected', async ({ date }) => {

    return {

    content: You selected ${date},

    // Next component or final response

    };

    });

    ``


    Full Documentation →


    What's Next


    Coming soon:

  • Video components - embedded video with controls
  • Maps - location selection and display
  • Signature capture - legal documents and agreements
  • Chart components - data visualization in conversations
  • AR components - view products in your space

Questions? Email us at hello@ilq.ai


---


*Rich Components are available now for all ilq.ai customers. Try them today →*