Skip to content

AI Sections

AI Sections is an embeddable component that displays predefined questions visitors can click to instantly trigger conversations with the Rose widget. It helps guide visitors toward relevant topics and increases engagement.

Overview

AI Sections provides a visual prompt section that:

  • Displays contextual questions relevant to the page content
  • Triggers the Rose widget when questions are clicked
  • Animates smoothly with staggered entrance and shimmer effects
  • Supports custom styling via props or CSS
  • Integrates with site config for consistent branding

Architecture

flowchart LR subgraph Sources["Data Sources"] DB[(ai_sections table)] Site[(site_configs table)] end subgraph Components["Components"] AISections[AISections] Button[AISectionsButton] Sparkle[SparkleIcon] end Widget[Rose Widget] DB -->|questions, styling, customCSS| AISections Site -->|color| AISections AISections --> Button Button --> Sparkle Button -->|onClick| Widget

Component Locations

Component Location Purpose
AISections frontend/shared/src/components/AISections/ Main container component
AISectionsButton frontend/shared/src/components/AISections/ Individual question button
RoseSectionsManager frontend/widget/src/ai-sections/ Widget-integrated manager

Single Bundle Architecture

AI Sections is integrated into the main widget bundle (inboundx-widget.js). There is no separate sections bundle - the widget auto-discovers and renders sections.

Configuration

Database Configuration (Supabase)

AI Sections can be configured per-domain in the ai_sections table:

Column Type Description
section_id string Unique identifier for the section
domain string Site domain this section belongs to
title jsonb Localized title object (e.g., {"en": "Ask us about pricing", "fr": "..."})
questions jsonb Localized questions object (e.g., {"en": ["Q1", "Q2"], "fr": ["Q1 fr", "Q2 fr"]})
styling jsonb Custom styling options
custom_css text Raw CSS for advanced theming
enabled boolean Whether the section is active

Inline Configuration

Sections can also be configured inline when embedding:

<AISections
  config={{
    title: 'Ask us about pricing',
    questions: [
      'What plan fits my needs?',
      'Is there a free trial?',
      'How does billing work?',
    ],
    styling: {
      primaryColor: '#0A42C3',
      buttonBackground: '#F0F4FF',
    },
  }}
/>

Localization Support

Both title and questions support localized content with language keys (en, fr, de, es, it). The widget automatically selects the appropriate language based on visitor context, falling back to en.

Database format:

{
  "title": {"en": "Ask us about pricing", "fr": "Posez-nous vos questions sur les tarifs"},
  "questions": {
    "en": ["What plan fits my needs?", "Is there a free trial?"],
    "fr": ["Quel forfait me convient?", "Y a-t-il un essai gratuit?"]
  }
}

Styling

Style Resolution Architecture

AI Sections uses a three-layer styling architecture. Each property is resolved independently through this cascade:

flowchart TD subgraph Layer1["Layer 1: Explicit Props"] Props["config.styling.primaryColor = '#FF0000'"] end subgraph Layer2["Layer 2: Custom CSS"] CSS["config.customCSS"] Vars["--ai-sections-sparkle-color: #00FF00"] end subgraph Layer3["Layer 3: Defaults"] SiteColor["site_configs.color (Supabase)"] Hardcoded["Hardcoded (#006967)"] end Props -->|"if set"| Final["Final Value"] CSS -->|"if prop not set"| Final SiteColor -->|"if no CSS override"| Final Hardcoded -->|"fallback"| Final style Layer1 fill:#e8f5e9 style Layer2 fill:#fff3e0 style Layer3 fill:#fce4ec

Priority (highest to lowest):

  1. Explicit styling props → Inline styles, always wins
  2. Custom CSS → Injected stylesheet with .ai-sections-* selectors
  3. Site config color → From Supabase site_configs.color (same as search bar)
  4. Hardcoded defaults → Built-in fallback values

How It Works

Per-Property Resolution: Each styling property is resolved independently. For example:

// Config with partial styling
config={{
  styling: {
    buttonBackground: '#FF0000',  // Explicit → Layer 1 wins
    // primaryColor not set → Layers 2 or 3 apply
  },
  customCSS: `
    .ai-sections-button {
      --ai-sections-sparkle-color: #00FF00;  /* Layer 2 for sparkle */
    }
  `
}}

In this example: - buttonBackground → Uses #FF0000 (Layer 1 - explicit prop) - primaryColor → Uses CSS variable if set, otherwise site config color (Layers 2/3)

Layer 3 Default Chain:

Site Config Color (Supabase) → Hardcoded Default (#006967)

The sparkle icon color defaults to the site's primary color from Supabase (same color used in the search bar), ensuring brand consistency without explicit configuration.

Styling Options

Property Type Default Description
primaryColor string Site config color Icon color (sparkle)
backgroundColor string #E8F5F5 Section container background
buttonBackground string #FFFFFF Button background color
buttonTextColor string #1a1a1a Button text color
buttonFontSize string 20px Button text size
buttonFontWeight string 400 Button text weight
iconSize number 20 Sparkle icon size (px)
arrowSize number 24 Arrow icon size (px)
titleColor string #003E3F Section title color
gap string 12px Gap between buttons
layout string stacked stacked or inline

Custom CSS

For advanced theming, use the customCSS property with CSS targeting these classes:

/* Container */
.ai-sections-container {
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
}

/* Title */
.ai-sections-title {
  color: #e0fc63;
  font-size: 40px;
}

/* Buttons */
.ai-sections-button {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px);
}

/* Button text */
.ai-sections-button-text {
  color: #ffffff;
}

/* Sparkle icon color override */
.ai-sections-button {
  --ai-sections-sparkle-color: #e0fc63;
}

/* Arrow icon */
.ai-sections-arrow {
  opacity: 0.8;
}

CSS Variables

Variable Description
--ai-sections-bg Container background
--ai-sections-title-color Title text color
--ai-sections-primary-color Primary/accent color
--ai-sections-button-bg Button background
--ai-sections-button-text Button text color
--ai-sections-gap Gap between buttons
--ai-sections-sparkle-color Override sparkle icon color

Integration

AI Sections is built into the main widget bundle. Just load the widget and add containers with data-rose-section attributes:

<!-- Load the widget (includes AI Sections) -->
<script src="https://cdn.userose.ai/widget/{DOMAIN}/inboundx-widget.js"></script>

<!-- Add sections anywhere on the page - widget auto-discovers them -->
<div data-rose-section="homepage-hero"></div>
<div data-rose-section="pricing-faq"></div>

Conventional Container

Alternatively, use the conventional container ID for auto-loading all sections:

<!-- Widget auto-loads all enabled sections for the domain -->
<div id="rose-ai-sections-container"></div>
<script src="https://cdn.userose.ai/widget/{DOMAIN}/inboundx-widget.js"></script>

Global Config (Alternative)

For more control, define configuration before the widget loads:

<div id="my-section"></div>
<script>
  window.RoseSectionsConfig = {
    sections: [{
      containerId: 'my-section',
      title: 'How can we help?',
      questions: ['What is your product?', 'How much does it cost?']
    }]
  };
</script>
<script src="https://cdn.userose.ai/widget/{DOMAIN}/inboundx-widget.js"></script>

Manual API (Advanced)

For dynamic rendering after page load:

// Render a section manually
window.RoseSections.renderSection({
  containerId: 'my-container',
  sectionId: 'pricing-faq',  // or provide config directly
});

// Destroy a section
window.RoseSections.destroySection('my-container');

React Integration

For React applications within the Rose ecosystem:

import { AISections } from '@inboundx/shared';

function PricingPage() {
  return (
    <AISections
      config={{
        title: 'Pricing Questions',
        questions: ['What plan fits my needs?', 'Is there a free trial?'],
      }}
      onQuestionClick={(question) => console.log('Clicked:', question)}
    />
  );
}

Props Reference

AISections Props

Prop Type Default Description
sectionId string - Database section ID to fetch config
config AISectionConfig - Inline configuration object
showShimmer boolean true Show shimmer effect on first reveal
staggerDelay number 100 Delay (ms) between button animations
collapseTimeout number 10000 Timeout before collapsing if widget fails
onQuestionClick function - Callback when question is clicked
onExpand function - Callback when section expands
onCollapse function - Callback when section collapses
className string - Additional CSS class for container

Behavior

Widget Readiness

AI Sections automatically detects when the Rose widget is ready:

  1. Section starts collapsed (hidden)
  2. Waits for widget to emit rose:ready event
  3. Expands with animation when widget is available
  4. Collapses if widget fails to load within timeout

Question Click Flow

  1. User clicks a question button
  2. triggerQuestion() is called on the widget
  3. Widget opens and sends the question
  4. onQuestionClick callback fires (if provided)

Animation

  • Entrance: Buttons fade in and slide up with staggered delay
  • Shimmer: One-time shimmer effect on first reveal
  • Exit: Smooth collapse if widget becomes unavailable

Testing

Use the preprod-ui to test AI Sections configurations:

  1. Navigate to /ai-sections in preprod-ui
  2. Select a client from the dropdown
  3. Toggle between database and sample configs
  4. Test different layout modes (stacked/inline)
  5. View the current configuration JSON

Analytics

AI Sections interactions are tracked via PostHog:

Event Description
rw_ai_section_impression Section displayed to user
rw_ai_section_question_click Question button clicked