Landing Widget
The <landing-widget> is a lightweight, standalone date selector for landing pages. It does not load any rentals — instead, the renter picks pickup and return dates and the widget redirects them to a URL you define (typically the page on your site that hosts the full <wheelbase-store> or <listing-details> widget).
Selected dates are passed to the target URL as query parameters so the destination widget can pre-fill the booking flow.
Try it live on the Interactive Demo page.
Basic usage
<landing-widget
target-url="https://yoursite.com/book"
button-label="Check availability"
></landing-widget>When the renter selects dates and clicks the button, the browser navigates to:
https://yoursite.com/book?pickup=2026-07-12&return=2026-07-18If the show-times option is enabled, pickup_time and return_time are appended as well. Times are written in canonical 24-hour HH:MM format (e.g. pickup_time=10:00) regardless of the active locale — the dropdown labels are formatted for the user’s locale at display time, but the value sent to your destination URL is always locale-independent so your back-end parser can stay simple.
Layouts
The widget supports three layouts that swap structure but share the same behavior:
| Layout | Use case |
|---|---|
full (default) | A vertical card with title, subtitle, two date fields, button, and a footer (defaults to “Powered by Wheelbase” — see Customizing the footer). Good for hero panels. |
horizontal | A wide bar with two fields and the button inline. Good for top-of-hero placement. |
compact | A single combined “Pickup → Return” pill with the button beside it. Good for headers or sticky bars. |
<landing-widget layout="horizontal" target-url="..."></landing-widget>Attributes
| Attribute | Type | Description | Default |
|---|---|---|---|
target-url | string | URL the button links to. Selected dates are appended as pickup and return query parameters. Optional when an onSubmit callback is attached. If neither is configured, clicking the button is a deliberate no-op — no console error or warning, the widget assumes you’re wiring it up elsewhere. | — |
layout | string | full, horizontal, or compact. | full |
title | string | Heading shown in the full layout. Leave blank to hide. | — |
subtitle | string | Subheading shown in the full layout. Leave blank to hide. | — |
button-label | string | Label for the CTA button. Default is the localized equivalent of “Check availability” — fr-FR sees “Vérifier la disponibilité”, de-DE sees “Verfügbarkeit prüfen”, etc. | translated “Check availability” |
show-times | boolean | When true, pickup and return time dropdowns are shown alongside the dates. Slots cover the full 24-hour day on the half-hour. | false |
pickup-time-start | string | Earliest pickup time, inclusive, as canonical HH:MM (e.g. 09:00). Useful for limiting the dropdown to business hours. | 00:00 |
pickup-time-end | string | Latest pickup time, inclusive. | 23:30 |
return-time-start | string | Earliest return time, inclusive. | 00:00 |
return-time-end | string | Latest return time, inclusive. | 23:30 |
calendar-variant | string | How the calendar surface opens: modal (centered overlay, focus-trapped) or dropdown (anchored below the trigger fields). | modal |
primary-color | string | Accent color used on the button, range fill, and selected dates. | #212831 |
primary-hover-color | string | Button background on hover. Defaults to primary-color (no hover effect) — set explicitly when you want a visible state change. | primary-color |
primary-foreground-color | string | Text color of the CTA label on top of primary-color. Set this when you pick a light primary-color — there’s no auto-contrast detection. | #ffffff |
surface-color | string | Card background behind the title, fields, and footer. | #f6f7f9 |
radius | string | Corner radius: subtle, soft, or round. | soft |
locale | string | Language and region code for labels. | en-us |
Properties
onSubmit is a JavaScript property, not an HTML attribute — assign it
imperatively on the element (el.onSubmit = …). Setting it as a kebab-case
attribute (on-submit="…") does not work.
| Property | Type | Description |
|---|---|---|
onSubmit | function | When set, called on submit with { pickup, returnDate, pickupTime?, returnTime?, url } instead of navigating. Takes precedence over target-url. See Handling submit with a callback for the full wiring pattern. |
This widget does not require a dealer-id. It is a pure date picker — your destination page is responsible for loading rentals and reading the date query parameters.
Slots
The widget exposes one shadow-DOM slot:
| Slot | Description |
|---|---|
footer | Replaces the default Powered by Wheelbase strip at the bottom of the full layout. Only available in the full layout — the horizontal and compact layouts have no footer area. |
Project your own light-DOM content into a slot by setting a slot attribute on
any child of <landing-widget>. Because the slotted DOM stays in your page
(not in the widget’s shadow root), your own CSS, links, click handlers, and
images all work normally — the widget never touches the markup.
<landing-widget target-url="https://yoursite.com/book">
<div slot="footer" class="my-footer">
<a href="/insurance">Insured by Roamly</a> ·
<a href="/policy">Free cancellation</a>
</div>
</landing-widget>To restore the default footer, simply omit the slotted child.
Slot content runs in your page’s normal DOM, so anything you’d write elsewhere
on the page works here — including <img>, <script>-attached handlers, your
design system’s components, etc. The widget cannot see or modify slot markup.
Customizing the footer
The simplest case is replacing the Powered by Wheelbase strip with your own text:
<landing-widget target-url="...">
<div slot="footer" style="text-align:center;font-size:13px;color:#4f5b69">
Trusted by 2,400+ travelers
</div>
</landing-widget>For more elaborate footers — logos, link rows, trust badges — drop a fully styled wrapper in:
<landing-widget target-url="...">
<footer slot="footer" class="hero-trust">
<img src="/badges/insured.svg" alt="" />
<span>Insured by Roamly</span>
<span aria-hidden="true">·</span>
<span>Free cancellation</span>
<span aria-hidden="true">·</span>
<a href="/reviews">★ 4.9 (320)</a>
</footer>
</landing-widget>Reading the dates on the destination page
If you embed <wheelbase-store> on the destination page, it will not auto-consume these query parameters today. Read them in your own page code and pass them down, or use them to scope your own pre-filter UI:
<script>
const params = new URLSearchParams(window.location.search)
const pickup = params.get('pickup') // e.g. "2026-07-12"
const ret = params.get('return') // e.g. "2026-07-18"
// ... pre-fill your booking flow with these values
</script>Handling submit with a callback
Instead of (or alongside) target-url, you can attach a function to react to the
selected dates in your own code — open a modal, fire an analytics event, render
the listings inline, etc. Web component function props must be assigned
imperatively in JavaScript:
<landing-widget id="lw" button-label="Check availability"></landing-widget>
<script>
// r2wc looks up the function by name on `window`, then reads the property
// off the element. Both steps are required.
window.onLandingWidgetSubmit = function onLandingWidgetSubmit(payload) {
console.log(payload)
// { pickup: Date, returnDate: Date, pickupTime?, returnTime?, url: string }
// Note: `returnDate` (not `return`) — `return` is a JS reserved word so
// it can't be destructured. Use `returnDate` everywhere.
// Do whatever you want here — open a modal, navigate, post to your API…
}
document.getElementById('lw').onSubmit = window.onLandingWidgetSubmit
</script>When the callback is set, the widget never navigates on its own — your handler
owns the result. If you want the default URL navigation back, omit onSubmit.
Complete example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RV Pirates — Book your trip</title>
</head>
<body>
<h1>RV rentals in Los Angeles</h1>
<landing-widget
layout="full"
title="Pick your dates"
subtitle="No commitment. Real-time fleet pricing."
button-label="Check availability"
target-url="https://rvpirates.com/book"
primary-color="#B95B46"
radius="soft"
>
<div slot="footer" style="text-align:center;font-size:13px;color:#4f5b69">
Insured by Roamly · Free cancellation
</div>
</landing-widget>
<script type="module" src="https://d2toxav8qvoos4.cloudfront.net/latest/wheelbase-widget.js"></script>
</body>
</html>