Add "Powered by Probo" branding to cookie banner SDK
Renders a subtle branded link at the bottom of both the banner and preference panel, conditionally hidden via show_branding config flag. Extracts all icon and HTML template constants into a shared html.ts module. Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import { LOCK_ICON } from "./html";
|
||||
|
||||
const ATTR_CATEGORY = "data-cookie-consent";
|
||||
const ATTR_SRC = "data-src";
|
||||
const ATTR_HREF = "data-href";
|
||||
@@ -39,7 +41,6 @@ const VISUAL_TAGS = new Set([
|
||||
"OBJECT",
|
||||
]);
|
||||
|
||||
const LOCK_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>`;
|
||||
|
||||
const PLACEHOLDER_STYLES = `
|
||||
[${ATTR_HIDDEN}] {
|
||||
|
||||
@@ -43,6 +43,7 @@ export interface BannerConfig {
|
||||
privacy_policy_url: string;
|
||||
consent_expiry_days: number;
|
||||
consent_mode: "OPT_IN" | "OPT_OUT";
|
||||
show_branding: boolean;
|
||||
categories: Category[];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import { COOKIE_ICON } from "../html";
|
||||
import type { ProboRootElement } from "./base";
|
||||
import type { ProboCookieBannerRoot } from "./cookie-banner-root";
|
||||
|
||||
const COOKIE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="8" cy="9" r="1" fill="currentColor"/><circle cx="15" cy="11" r="1" fill="currentColor"/><circle cx="10" cy="15" r="1" fill="currentColor"/><circle cx="13" cy="7" r="1" fill="currentColor"/></svg>`;
|
||||
|
||||
export class ProboSettingsButton extends HTMLElement {
|
||||
private shadow: ShadowRoot;
|
||||
private root: ProboRootElement | null = null;
|
||||
|
||||
25
packages/cookie-banner/src/html.ts
Normal file
25
packages/cookie-banner/src/html.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
export const CLOSE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`;
|
||||
|
||||
export const CHEVRON_DOWN = `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>`;
|
||||
|
||||
export const COOKIE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="8" cy="9" r="1" fill="currentColor"/><circle cx="15" cy="11" r="1" fill="currentColor"/><circle cx="10" cy="15" r="1" fill="currentColor"/><circle cx="13" cy="7" r="1" fill="currentColor"/></svg>`;
|
||||
|
||||
export const LOCK_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>`;
|
||||
|
||||
const PROBO_LOGO = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 25 24" fill="none" aria-hidden="true"><g clip-path="url(#pc)"><rect width="24" height="24" x=".85" fill="currentColor" rx="5.14"/><path stroke="#fff" stroke-width="3.53" d="M20.57 6.17c2.96 4.47-6.43 13.97-20.32 5.66"/><path stroke="url(#pg)" stroke-width="3.53" d="M20.57 6.17c2.96 4.47-6.43 13.97-20.32 5.66"/><path fill="#fff" d="M19.07 7.1a1.77 1.77 0 0 0 3-1.86l-1.5.93-1.5.94ZM8.82 25.18l1.71-.41c-2.3-9.67.01-14.66 2.54-16.83A6.25 6.25 0 0 1 17 6.33c1.22-.01 1.87.44 2.08.78l1.5-.94 1.5-.93c-1.1-1.74-3.16-2.46-5.13-2.44-2.03.03-4.26.81-6.17 2.45-3.9 3.35-6.16 9.92-3.67 20.33l1.72-.41Z"/></g><defs><linearGradient id="pg" x1="18.77" x2="1.2" y1="13.56" y2="13.56" gradientUnits="userSpaceOnUse"><stop stop-color="#101E1C" stop-opacity="0"/><stop offset="1" stop-color="#fff"/></linearGradient><clipPath id="pc"><rect width="24" height="24" x=".85" fill="#fff" rx="5.14"/></clipPath></defs></svg>`;
|
||||
|
||||
export const BRANDING = `<div class="branding" data-branding><a href="https://www.getprobo.com/cookie-policy" target="_blank" rel="noopener noreferrer">Powered by ${PROBO_LOGO} Probo</a></div>`;
|
||||
@@ -84,12 +84,16 @@ export const THEMED_STYLES = `
|
||||
border-radius: var(--_radius);
|
||||
box-shadow: var(--_shadow);
|
||||
width: 100%;
|
||||
padding: 24px;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
probo-banner .card {
|
||||
max-width: 450px;
|
||||
padding: 24px 24px 12px 24px;
|
||||
}
|
||||
|
||||
probo-banner .buttons {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
probo-preference-panel .card {
|
||||
@@ -97,7 +101,6 @@ export const THEMED_STYLES = `
|
||||
max-height: 75vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
probo-preference-panel probo-category-list {
|
||||
@@ -188,9 +191,13 @@ export const THEMED_STYLES = `
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
probo-preference-panel .buttons {
|
||||
probo-preference-panel .footer {
|
||||
border-top: 1px solid var(--_border);
|
||||
padding: 20px 24px 24px;
|
||||
padding: 10px 24px;
|
||||
}
|
||||
|
||||
probo-preference-panel .buttons {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
probo-category {
|
||||
@@ -347,6 +354,28 @@ export const THEMED_STYLES = `
|
||||
color: var(--_text);
|
||||
}
|
||||
|
||||
.branding {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.branding a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: calc(var(--_font-size) - 2px);
|
||||
font-weight: 400;
|
||||
color: var(--_text-secondary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.branding a:hover {
|
||||
color: var(--_text);
|
||||
}
|
||||
|
||||
.branding svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@@ -15,11 +15,9 @@
|
||||
import { registerComponents } from "../components";
|
||||
import type { ProboCookieBannerRoot } from "../components/cookie-banner-root";
|
||||
import type { BannerConfig } from "../client";
|
||||
import { BRANDING, CHEVRON_DOWN, CLOSE_ICON } from "../html";
|
||||
import { THEMED_STYLES } from "./styles";
|
||||
|
||||
const CLOSE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`;
|
||||
const CHEVRON_DOWN = `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>`;
|
||||
|
||||
export class ProboThemedBanner extends HTMLElement {
|
||||
private shadow: ShadowRoot;
|
||||
|
||||
@@ -62,6 +60,7 @@ export class ProboThemedBanner extends HTMLElement {
|
||||
<probo-reject-button><button class="btn">Reject all</button></probo-reject-button>
|
||||
<probo-customize-button><button class="btn btn-link">Customize</button></probo-customize-button>
|
||||
</div>
|
||||
${BRANDING}
|
||||
</div>
|
||||
</div>
|
||||
</probo-banner>
|
||||
@@ -103,12 +102,15 @@ export class ProboThemedBanner extends HTMLElement {
|
||||
</probo-cookie-list>
|
||||
</template>
|
||||
</probo-category-list>
|
||||
<div class="buttons">
|
||||
<probo-accept-button><button class="btn btn-primary">Accept all</button></probo-accept-button>
|
||||
<probo-reject-button><button class="btn">Reject all</button></probo-reject-button>
|
||||
<probo-save-button>
|
||||
<button class="btn btn-link" style="flex:1">Save preferences</button>
|
||||
</probo-save-button>
|
||||
<div class="footer">
|
||||
<div class="buttons">
|
||||
<probo-accept-button><button class="btn btn-primary">Accept all</button></probo-accept-button>
|
||||
<probo-reject-button><button class="btn">Reject all</button></probo-reject-button>
|
||||
<probo-save-button>
|
||||
<button class="btn btn-link" style="flex:1">Save preferences</button>
|
||||
</probo-save-button>
|
||||
</div>
|
||||
${BRANDING}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -123,6 +125,11 @@ export class ProboThemedBanner extends HTMLElement {
|
||||
root.addEventListener("probo-ready", (e: Event) => {
|
||||
const config = (e as CustomEvent).detail.config as BannerConfig;
|
||||
this.updateDescription(config);
|
||||
if (!config.show_branding) {
|
||||
this.shadow.querySelectorAll("[data-branding]").forEach(el => {
|
||||
(el as HTMLElement).setAttribute("hidden", "");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.shadow.querySelector("[data-action=back]")?.addEventListener("click", () => {
|
||||
|
||||
Reference in New Issue
Block a user