E-Reservation
Multi-step reservation widget allowing customers to search for store availability, select a store, and complete their reservation with contact information.
For installation instructions, see Getting Started with Unify Widgets.
Basic Implementation
As a dialog (default)
<unify-ereservation-widget
api-key="your-api-key"
item-id="your-item-id"
></unify-ereservation-widget>
<button onclick="document.querySelector('unify-ereservation-widget').open = true">
Reserve in store
</button>Inline (no dialog)
<unify-ereservation-widget
api-key="your-api-key"
item-id="your-item-id"
no-dialog
></unify-ereservation-widget>Component Attributes
| Attribute | Type | Required | Description |
|---|---|---|---|
api-key | String | Yes | API key for Unify requests |
item-id | String | Yes | Item identifier for product and stock-store calls |
open | Boolean | No | Controls dialog visibility when dialog mode is enabled |
no-dialog | Boolean | No | Renders content inline instead of inside a dialog |
demo | Boolean | No | Enables demo mode (X-Demo-Mode: true header) |
Component Properties
| Property | Type | Required | Description |
|---|---|---|---|
config | Object | No | Configuration object (see Config Options) |
prefill | Object | No | Pre-populate form fields (see Prefill API) |
Prefill API
Pre-populate the user-info form (step 2) with known customer data. All fields are optional and remain editable.
document.querySelector('unify-ereservation-widget').prefill = {
civility: 'MR', // matches one of civilityOptions
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
mobileNumber: '+33612345678', // E.164 format
};Config Options
Pass configuration via the config property to customize text labels, behavior, and thresholds.
document.querySelector('unify-ereservation-widget').config = {
dialogTitle: 'Reserve in store',
locale: 'fr-FR',
maxRange: 25,
// ... more options
};Dialog & Layout
| Option | Default | Description |
|---|---|---|
dialogTitle | "In-Store Reservation" | Title for search and user-info steps |
resultDialogTitle | "Reservation Result" | Title for result/confirmation step |
dialogDescription | "Reserve this item at the store of your choice and pick it up when it's ready." | Intro text below title |
Search & Loading
| Option | Default | Description |
|---|---|---|
loadingMessage | "Searching for stores..." | Text shown while stores are loading |
searchValidationErrorMessage | "Please enter a full address including your city name." | Validation error message |
searchErrorMessage | "An error occurred while searching. Please try again." | API error fallback |
noStoresMessage | "No stores found for the provided information." | Empty result message |
Store Selection
| Option | Default | Description |
|---|---|---|
selectStoreButtonLabel | "Select" | Store selection button label |
editButtonLabel | "Edit" | Button to return to store search |
User Info Form (Step 2)
| Option | Default | Description |
|---|---|---|
civilityOptions | ['MR', 'MRS'] | Array of civility dropdown values |
civilityLabel | "Civility" | Civility field label |
civilityPlaceholder | "Select..." | Civility placeholder text |
firstNameLabel | "First name" | First name field label |
lastNameLabel | "Last name" | Last name field label |
emailLabel | "Email" | Email field label |
mobileNumberLabel | "Mobile number" | Mobile number input label |
phoneCountryLabel | "Country" | Country selector label |
phoneDefaultCountry | "33" | Default country code for phone input |
confirmButtonLabel | "Confirm Reservation" | Submit button label |
confirmingLabel | "Submitting..." | Loading state button text |
formValidationErrorMessage | "Please check the form fields and try again." | Generic form validation error |
mobileNumberErrorMessage | "Please enter a valid mobile number." | Phone validation error |
Store Display Options
| Option | Default | Description |
|---|---|---|
stockLimitedThreshold | 10 | Quantity threshold between "limited" and "available" stock |
hideStoreAddress | false | Hide store address in results |
hideStoreContact | false | Hide store phone number |
hideOpeningHours | false | Hide open/closed status and hours |
storeClosedLabel | "Closed" | Label for closed stores |
storeOpenLabel | "Open" | Label for open stores |
storeOpeningHoursLabel | "Opening Hours" | Section heading |
showClickAndGoInfo | false | Show click-and-go availability |
storeClickAndGoAvailableLabel | "Click and Go Available" | Click-and-go available label |
storeClickAndGoNotAvailableLabel | "Click and Go Not Available" | Click-and-go unavailable label |
Stock Display
| Option | Default | Description |
|---|---|---|
displayStockQuantity | true | Show quantity in stock labels |
stockLimitedLabelWithQuantity | "Limited stock (%qty% remaining)" | Limited stock label with %qty% placeholder |
stockLimitedLabel | "Limited stock" | Limited stock label without quantity |
stockAvailableLabelWithQuantity | "Available (%qty% remaining)" | Available stock label with %qty% |
stockAvailableLabel | "Available" | Available stock label without quantity |
stockUnavailableLabel | "Out of stock" | Out-of-stock label |
Search Form Options
| Option | Default | Description |
|---|---|---|
addressLabel | "Address" | Search input label |
addressPlaceholder | "Your address" | Search input placeholder |
submitButtonLabel | "Submit" | Search submit button |
searchingLabel | "Searching..." | Search loading state |
geolocateButtonLabel | "Use my location" | Geolocation button label |
geolocatingLabel | "Locating..." | Geolocation loading state |
hideAvailableStockToggler | false | Hide "available stock only" checkbox |
availableStock | false | Initial state of stock toggle |
availableStockLabel | "Only display available stock" | Toggle label |
requireFullAddress | false | Require at least one letter in address before submit |
Result Step
| Option | Default | Description |
|---|---|---|
finishButtonLabel | "Done" | Success result button |
errorMessage | "An error occurred. Please try again." | Generic error fallback |
startOverButtonLabel | "Start over" | Reset button after error |
Search Distance & Formatting
| Option | Default | Description |
|---|---|---|
maxRange | 10 | Maximum search distance in km (sets distance_max in API request) |
locale | "en-US" | Locale for prices and day names (e.g. "fr-FR", "de-DE") |
currency | "EUR" | Currency fallback for product price formatting |
weekdayFormat | "long" | Weekday display format: "long" (Monday), "short" (Mon), "narrow" (M) |
daysRangeLabel | "to" | Connector in grouped day ranges ("Monday to Friday") |
colorLabel | "Color" | Product attribute label |
sizeLabel | "Size" | Product attribute label |
noOpeningHoursMessage | "No opening hours available" | Fallback when hours unavailable |
exceptionalDaysLabel | "Exceptional Days" | Header for holiday hours |
informationLabel | "Information" | Header for extra opening hours info |
Styling
CSS Custom Properties (recommended)
All visual tokens (colors, sizes, spacing, fonts) are exposed as CSS custom properties prefixed with --unify-. This is the stable styling API.
Set them on the widget element or any ancestor:
unify-ereservation-widget {
--unify-confirm-button-bg: #1a56db;
--unify-confirm-button-color: white;
--unify-dialog-bg: #f9fafb;
--unify-input-border-radius: 6px;
--unify-geolocate-button-bg: #15803d;
--unify-store-status-open-color: #15803d;
}To discover all available properties:
- Open browser DevTools
- Inspect the
<unify-ereservation-widget>element - Look at the Computed tab for all
--unify-*entries - Edit them live in the Styles panel to preview
CSS Parts
Structural elements can be targeted using ::part():
unify-ereservation-widget::part(dialog) {
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
}
unify-ereservation-widget::part(store-status--open) {
font-weight: bold;
}⚠️ Parts may change between versions. Use CSS custom properties where possible.
To find available parts, inspect the widget's shadow DOM in DevTools — every element with a part attribute is targetable from outside.
Events
dialog-opened
dialog-openedFired when the dialog open/close state changes.
document.querySelector('unify-ereservation-widget').addEventListener('dialog-opened', (event) => {
console.log('Dialog is', event.detail.open ? 'open' : 'closed');
});Detail shape:
{
open: boolean // true when opened, false when closed
}Examples
Basic setup with custom labels
const widget = document.querySelector('unify-ereservation-widget');
widget.config = {
dialogTitle: 'Reserve in store',
resultDialogTitle: 'Reservation confirmed',
selectStoreButtonLabel: 'Choose this store',
confirmButtonLabel: 'Complete reservation',
locale: 'en-US',
currency: 'EUR',
};
// Pre-fill customer info
widget.prefill = {
civility: 'MR',
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
mobileNumber: '+33612345678',
};
// Open the reservation dialog
widget.open = true;
// Listen for dialog state changes
widget.addEventListener('dialog-opened', (e) => {
console.log(e.detail.open ? 'Reservation opened' : 'Reservation closed');
});Styled with custom theme
<style>
unify-ereservation-widget {
/* Colors */
--unify-confirm-button-bg: #0066cc;
--unify-confirm-button-color: white;
--unify-confirm-button-hover-bg: #0052a3;
--unify-geolocate-button-bg: #28a745;
/* Store status */
--unify-store-status-open-color: #28a745;
--unify-store-status-closed-color: #dc3545;
/* Dialog */
--unify-dialog-bg: #ffffff;
--unify-dialog-color: #333333;
--unify-backdrop-bg: rgba(0, 0, 0, 0.5);
/* Spacing & sizing */
--unify-input-border-radius: 8px;
--unify-dialog-width: 600px;
}
</style>
<unify-ereservation-widget
api-key="your-api-key"
item-id="your-item-id"
></unify-ereservation-widget>Updated 3 months ago