Skip to main content

Installing and Using Custom Promap Themes

RP Promap includes a flexible theme system that allows developers to completely customize the appearance of our app

RP Promap Help Series

Installing and Using Custom Themes

Version: RP Promap v1.x
Last Updated: June 2026
© Rose Perl Technology


Overview

RP Promap includes a flexible theme system that allows developers to completely customize the appearance of maps, location search forms, result cards, markers, and dealer/distributor listings without modifying the core application.

Themes are distributed as JavaScript modules and can be installed dynamically at runtime.

This guide explains how to install and use the Locator Reseller Grid Theme.


Prerequisites

Before installing a theme, ensure:

  • RP Promap is installed and initialized

  • The map container is rendering correctly

  • Location search functionality is operational

  • Your application supports ES Modules

Example:

<div id="scasl-app-container"></div>
import { createPromap } from "@roseperl/promap"; 
createPromap({ target: "#scasl-app-container" });

Installing a Theme

Import the theme module into your application.

import { locatorTheme } from "./promap-theme-locator.js";

After RP Promap has been initialized, install the theme.

locatorTheme.install("#scasl-app-container");

The selector passed to the install method determines which Promap instance receives the styling.


Basic Usage

import { createPromap } from "@roseperl/promap";
import { locatorTheme } from "./promap-theme-locator.js";
createPromap({ target: "#scasl-app-container" }); locatorTheme.install("#scasl-app-container");

Once installed, the theme automatically styles:

  • Search form

  • Map controls

  • Location cards

  • Dealer listings

  • Distributor listings

  • Preferred dealer highlighting

  • Responsive mobile layouts

  • Dealer category tags


Theme Features

Dealer Grid Layout

Locations are displayed using a responsive two-column grid.

Desktop:

+----------------+----------------+ 
| Dealer | Dealer |
+----------------+----------------+
| Dealer | Dealer |
+----------------+----------------+

Mobile:

+----------------+ 
| Dealer |
+----------------+
+----------------+
| Dealer |
+----------------+

Distributor Highlighting

Distributor locations receive a dedicated visual treatment.

Features:

  • Red background

  • White text

  • Enhanced contrast

  • Distinct visual separation from dealer listings

Example:

<li class="tag-DISTRIBUTOR">

Preferred Dealer Highlighting

Priority dealers automatically receive:

  • Green background

  • Preferred badge display

  • Enhanced visibility

Supported priorities:

priority-1 priority-2 priority-3 priority-4 priority-5

Example:

<li class="priority-1 tag-DEALER">

Customizing Theme Colors

The theme supports CSS custom properties.

Add variables to your Promap container:

#scasl-app-container {   
--promap-text: #000;
--promap-border: #000;
--promap-card-bg: #eeeeee;
--promap-distributor-bg: #cc0000;
--promap-preferred-bg: #d9ffd1;
}

Example: Rose Perl Branding

#scasl-app-container {   
--promap-text: #111111;
--promap-border: #A4118D;
--promap-card-bg: #ffffff;
--promap-distributor-bg: #A4118D;
--promap-preferred-bg: #F5E3F2;
}

This applies Rose Perl Technology brand colors while preserving theme functionality.


Using Multiple Themes

Themes can be installed on separate Promap instances.

Example:

locatorTheme.install("#dealer-map");  
anotherTheme.install("#store-map");

Each theme remains isolated to its assigned container.


Theme Architecture

Every RP Promap theme exposes three components:

{   name,   tokens,   css(),   install() }

name

Unique theme identifier.

name: "locator-reseller-grid"

tokens

Default design values.

tokens: {   text: "#000",   border: "#000" }

css()

Returns generated stylesheet content.

theme.css("#scasl-app-container");

install()

Injects the stylesheet into the document.

theme.install("#scasl-app-container");

Troubleshooting

Theme Not Loading

Verify:

locatorTheme.install("#scasl-app-container");

is executed after Promap initialization.


Styles Not Applying

Confirm the container selector matches the rendered Promap instance.

Example:

<div id="scasl-app-container"></div>
locatorTheme.install("#scasl-app-container");

Multiple Style Duplicates

The installer automatically removes previously loaded versions of the same theme before injecting a new stylesheet.

No additional cleanup is required.


Best Practices

  • Keep theme logic separate from application logic

  • Use CSS variables for branding changes

  • Scope all theme styles to a container selector

  • Avoid editing core Promap styles directly

  • Package reusable themes as standalone modules


Summary

The RP Promap Theme System enables complete visual customization while keeping Promap upgrades simple and maintainable. Themes can be installed dynamically, scoped to specific instances, customized with CSS variables, and distributed independently from the core platform.


Example Theme Code to Install

// promap-theme-locator.js - upload to assets or host externally
export const locatorTheme = {
name: "locator-reseller-grid",

tokens: {
text: "#000",
border: "#000",
mutedBorder: "#ccc",
cardBg: "#eee",
distributorBg: "#cc0000",
preferredBg: "#d9ffd1",
},

css(scope = "#scasl-app-container") {
return `
${scope} {
margin: 0 !important;
text-align: left;
}

${scope} #page-header {
float: none;
max-width: none;
}

${scope} #page-header h1.bh-sl-title {
color: var(--promap-text, #000);
border-bottom: 1px solid var(--promap-border, #000);
display: block !important;
font-size: 24px;
font-weight: 400;
line-height: 1em;
margin-bottom: 25px;
padding-bottom: 25px;
}

/* Form */
${scope} #bh-sl-user-location button {
color: #fff !important;
}

${scope} #bh-sl-user-location button:hover {
background: #333 !important;
}

${scope} #bh-sl-user-location button#bh-sl-submit {
display: block;
width: 100%;
}

${scope} .bh-sl-container .bh-sl-form-container {
margin-top: 0;
float: none;
}

${scope} .bh-sl-container .bh-sl-form-container label {
display: block;
height: 20px;
line-height: 20px;
margin-bottom: 0;
}

${scope} .bh-sl-container .bh-sl-form-container input {
margin: 0 5px 0 0;
}

/* Map */
${scope} #bh-sl-map-container {
position: relative;
padding-top: 605px;
margin: 25px 0 0 !important;
}

${scope} .bh-sl-container .bh-sl-loc-list,
${scope} .bh-sl-container .bh-sl-map {
display: block !important;
float: none !important;
margin-top: 0;
width: 100% !important;
}

${scope} .bh-sl-container .bh-sl-map {
position: absolute;
top: 0;
}

${scope} .bh-sl-container .bh-sl-map button:hover {
background: #fff !important;
color: #000 !important;
}

/* Info Window */
#bh-sl-map #infowindow {
border: 1px solid var(--promap-muted-border, #ccc);
}

#bh-sl-map #infowindow #scasl-title {
font-size: 1em;
margin-bottom: 10px;
}

#bh-sl-map #infowindow #scasl-phone {
margin: 10px 0;
}

#bh-sl-map #infowindow .btn {
display: inline-block;
padding: 10px 15px;
}

/* List */
${scope} .bh-sl-container .bh-sl-loc-list {
border: 0;
height: auto !important;
overflow: visible;
}

${scope} .bh-sl-container .bh-sl-loc-list ul {
float: none;
font-size: 0;
margin-left: -25px;
width: auto !important;
}

${scope} .bh-sl-container .bh-sl-loc-list ul li {
background: none !important;
border: 0 !important;
display: inline-block !important;
float: none;
margin: 0 0 25px !important;
padding: 0 0 0 25px;
text-transform: uppercase;
vertical-align: top;
width: 50%;
}

${scope} .bh-sl-container .bh-sl-loc-list ul li .list-details {
background: var(--promap-card-bg, #eee);
border: 1px solid var(--promap-border, #000);
display: block;
float: none;
margin-left: 0;
padding: 40px 10px 5px;
position: relative;
width: auto;
}

${scope} .list-content {
font-size: 10px;
line-height: 1.2em;
padding: 0;
}

${scope} #scasl-title {
font-size: 1.5em;
}

${scope} #scasl-list-container #scasl-store_image,
${scope}.new-for-mobile ul#scasl-tabs {
display: none !important;
}

/* Tags */
${scope} .list-details #scasl-tags {
background: #fff;
border: 1px solid var(--promap-border, #000);
border-left: 0;
display: block;
font-size: 10px;
padding: 5px 15px 5px 10px;
position: absolute;
top: 10px;
left: -1px;
}

${scope} .list-details #scasl-tags span {
display: none;
background: none;
color: #000 !important;
padding: 0;
}

${scope} .list-details #scasl-tags span.tag-DEALER,
${scope} .list-details #scasl-tags span.tag-DISTRIBUTOR {
display: inline-block;
}

/* Distributor */
${scope} li.tag-DISTRIBUTOR .list-details {
background: var(--promap-distributor-bg, #cc0000) !important;
}

${scope} li.tag-DISTRIBUTOR .list-details,
${scope} li.tag-DISTRIBUTOR .list-details div,
${scope} li.tag-DISTRIBUTOR .list-details span,
${scope} li.tag-DISTRIBUTOR .list-details a,
${scope} li.tag-DISTRIBUTOR .list-details #scasl-title {
color: #fff !important;
}

${scope} li.tag-DISTRIBUTOR .list-details a {
text-decoration: underline;
}

${scope} li.tag-DISTRIBUTOR .list-details .btn:hover {
background: #fff !important;
color: #000 !important;
}

/* Preferred Dealers */
${scope} li.priority-1.tag-DEALER .list-details,
${scope} li.priority-2.tag-DEALER .list-details,
${scope} li.priority-3.tag-DEALER .list-details,
${scope} li.priority-4.tag-DEALER .list-details,
${scope} li.priority-5.tag-DEALER .list-details {
background: var(--promap-preferred-bg, #d9ffd1) !important;
}

${scope} li.priority-1.tag-DEALER .list-details #scasl-tags span.tag-PREFERRED,
${scope} li.priority-2.tag-DEALER .list-details #scasl-tags span.tag-PREFERRED,
${scope} li.priority-3.tag-DEALER .list-details #scasl-tags span.tag-PREFERRED,
${scope} li.priority-4.tag-DEALER .list-details #scasl-tags span.tag-PREFERRED,
${scope} li.priority-5.tag-DEALER .list-details #scasl-tags span.tag-PREFERRED {
display: inline-block !important;
margin-right: 5px;
}

/* Icons */
${scope} li #scasl-icons .icon {
display: none;
filter: invert(1);
margin-right: 5px;
margin-bottom: 5px;
width: 20px;
height: 20px;
line-height: 20px;
}

${scope} li.tag-DEALER.tag-SUNDAY #scasl-icons span.sunday .icon,
${scope} li.tag-DEALER.tag-ODYSSEY #scasl-icons span.odyssey .icon,
${scope} li.tag-DEALER.tag-FAIRDALE #scasl-icons span.fairdale .icon,
${scope} li.tag-DEALER.tag-GSPORT #scasl-icons span.gsport .icon,
${scope} li.tag-DEALER.tag-BSD #scasl-icons span.bsd {
display: inline-block;
}

/* No Results */
${scope} .bh-sl-noresults-title {
color: #000;
font-size: 24px;
}

${scope} .bh-sl-noresults-desc {
font-size: 14px;
text-transform: none;
}

${scope} .bh-sl-noresults-desc a {
display: none;
}

/* Responsive */
@media screen and (max-width: 740px) {
${scope} li.priority-1.tag-DEALER,
${scope} li.priority-2.tag-DEALER,
${scope} li.priority-3.tag-DEALER {
min-width: 100% !important;
}

${scope} li.priority-1.tag-DEALER .list-details .btn,
${scope} li.priority-2.tag-DEALER .list-details .btn,
${scope} li.priority-3.tag-DEALER .list-details .btn {
display: inline-block;
}
}

@media screen and (min-width: 740px) {
${scope} .bh-sl-container .bh-sl-loc-list ul li .list-details {
padding: 40px 25px 20px;
}

${scope} .list-details #scasl-tags {
padding-left: 25px;
}

${scope} .list-details .btn {
display: inline-block;
}
}

@media screen and (max-width: 768px) {
${scope} #bh-sl-user-location button#scapl-geocode-btn {
width: 100%;
}
}
`;
},

install(scope = "#scasl-app-container") {
const id = `promap-theme-${this.name}`;

document.getElementById(id)?.remove();

const style = document.createElement("style");
style.id = id;
style.textContent = this.css(scope);

document.head.appendChild(style);
},
};

Did this answer your question?