Widget Components Reference

Detailed reference for each Checkout Widget component — lifecycle, states, error handling, styling, and co-branding.

This page provides the detailed technical reference for each of the three Checkout Widget components. For architecture context and the system diagram, see the Widget Overview.


weatherit-widget — Protection Selector

The main component. Manages the full lifecycle from data input through quoting to protection selection.

Mount Lifecycle

flowchart TB
    A["connectedCallback()"] --> B{"Attributes present?<br/>(lat, start, etc.)"}
    B -->|Yes| C["Use attribute values"]
    B -->|No| D["Listen for RoomStay<br/>checkoutView event"]
    D --> C
    C --> E["Fetch partner branding<br/>GET /partners/:id"]
    E -->|Success| F["Apply partner colour +<br/>store logo URL"]
    E -->|Failure| G["Use default WeatherIt<br/>branding, continue"]
    F --> H["Fetch quote<br/>POST /quotes?partner_id=xxx"]
    G --> H
    H --> I["Render protection cards<br/>(Full / Budget)"]
    I --> J["Auto-select Full Protection"]
    J --> K["Fire weatherit:coverage-selected"]

    style A fill:#e8f4f8
    style K fill:#e8f5e9

User Interactions

ActionResult
Select Full / Budget (first time)Fires weatherit:coverage-selected
Switch between Full / BudgetFires weatherit:coverage-changed with new option data
Select "No Protection"Fires weatherit:coverage-declined. Widget stays visible. Customer can re-select at any time.
Click "Learn more"Opens modal with protection details, weather station info, and trigger information

Internal State

interface WidgetState {
  loading: boolean;
  error: string | null;
  quoteData: Quote | null;
  selectedOption: PricingOption | null;  // null when "No Protection" selected
  partnerBranding: Partner | null;
  learnMoreOpen: boolean;
  declined: boolean;                     // true when customer selects "No Protection"
}

Error Handling

ErrorBehaviour
API unreachableWidget hides — checkout continues unaffected
Quote unavailable (location not covered)Widget hides
Partner not foundUses default WeatherIt branding, continues quoting
Invalid attributes (missing required)Widget hides, fires weatherit:widget-error event
📘

In all error cases, the partner's checkout flow is unaffected. The widget is designed to fail silently rather than block checkout.


weatherit-cart-item — Cart Line Item

A passive component. No API calls. Listens for Custom Events from weatherit-widget.

Behaviour

flowchart LR
    A["Mount:<br/>hidden by default"] --> B{"Event received?"}
    B -->|"coverage-selected /<br/>coverage-changed"| C["Show line item:<br/>Rain Protection — tier — $premium"]
    B -->|"coverage-declined"| D["Hide"]
    C --> B
    D --> B

When visible, the line item displays:

  • Title: Rain Protection — {optionName}
  • Amount: ${premium}
  • Subtitle: "Charged securely by WeatherIt"

Internal State

interface CartItemState {
  visible: boolean;
  optionName: string;
  premium: number;
}

weatherit-confirmation — Confirmation Page

A standalone component on the booking confirmation page. No shared state with the checkout widgets — it operates independently on a different URL.

Mount Lifecycle

flowchart TB
    A["connectedCallback()"] --> B["Fetch partner branding<br/>GET /partners/:id"]
    B --> C{"policy-id<br/>attribute set?"}
    C -->|Yes| D{"hide-on-confirmed<br/>attribute set?"}
    D -->|Yes| E["Hide component"]
    D -->|No| F["Show: Rain Protection<br/>confirmed summary"]
    C -->|No| G{"quote-id<br/>attribute set?"}
    G -->|Yes| H["Show: Upsell card<br/>with premium + 'Add now' link"]
    G -->|No| I["Show: Generic offer<br/>'Protect your stay' + link"]

    style F fill:#e8f5e9
    style H fill:#fff3e0
    style I fill:#e8f4f8
    style E fill:#f5f5f5

Display States

StateConditionWidget Shows
Policy confirmedpolicy-id attribute set"Rain Protection confirmed" summary — or hides if hide-on-confirmed is set
Upsellquote-id attribute set (no policy-id)Upsell card with the quote's premium and "Add now" link to QLP
Generic offerNeither policy-id nor quote-id set"Protect your stay from rain" message with link to QLP

Upsell and generic offer links:

https://qlp.weatherit.ai/?partner={partnerId}&booking={bookingRef}

With a quote:

https://qlp.weatherit.ai/?quote_id={quoteId}&partner={partnerId}&booking={bookingRef}

The customer completes the purchase on WeatherIt's hosted page.

Internal State

interface ConfirmationState {
  loading: boolean;
  policyData: Policy | null;
  quoteData: Quote | null;
  partnerBranding: Partner | null;
}

Styling & Co-Branding

All components use Shadow DOM. Styles are fully scoped — zero leakage in either direction between the widget and the partner's page.

Partner Branding

Partner branding is fetched from GET /partners/:id and applied automatically:

  • Primary colour — set as --partner-primary-color CSS custom property
  • Logo — displayed in the "Powered by WeatherIt" lockup

CSS Custom Properties

Partner-controlled:

--partner-primary-color: #005a8b;    /* fetched from partner config, fallback: Trust Blue */
--partner-primary-light: color-mix(in srgb, var(--partner-primary-color) 8%, white);
--partner-primary-dark: color-mix(in srgb, var(--partner-primary-color), black 20%);

WeatherIt design tokens:

--wit-success: #28A745;
--wit-error: #DC3545;
--wit-warning: #FFC107;
--wit-text: #1a1a1a;
--wit-text-secondary: #8B95A1;
--wit-border: #e5e7eb;
--wit-radius: 8px;
--wit-radius-lg: 12px;
--wit-font: 'Inter', 'Open Sans', 'Montserrat', system-ui, sans-serif;

"Powered by WeatherIt" Lockup

Appears at the bottom of weatherit-widget:

  • Partner logo (from partner.logo_url) alongside WeatherIt logo
  • Partner logo minimum 50% of WeatherIt logo size
  • 2x clear space between logos
  • Text: "Powered by WeatherIt"

Responsive Breakpoints

BreakpointWidthLayout
Mobile320-767pxSingle column, stacked cards
Tablet768-1023pxSide-by-side protection cards
Desktop1024px+Full layout

Accessibility

  • Touch targets: 44x44px minimum
  • Input height: 48px minimum
  • Minimum contrast ratio: 4.5:1 (WCAG 2.1 AA)

⚠️

Visual placeholder — Visuals showing each component in its various states will be added here.


Did this page help you?