Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions components/src/banner.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
width: 100%;
max-width: 100%;
box-sizing: border-box;
position: absolute;
left: 0;
right: 0;
z-index: 10;
}

:host(.position-top) {
top: 0;
}

:host(.position-bottom) {
bottom: 0;
}

.banner {
Expand Down
88 changes: 25 additions & 63 deletions components/src/banner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,16 @@ import {
import { property, state } from 'lit/decorators.js'
import defaultLogo from './assets/wm_logo_animated.svg?url'
import bannerStyles from './banner.css?raw'
import { getWebMonetizationLinkHref } from './utils.js'
import { getWebMonetizationLinkHref, applyFontFamily } from './utils.js'
import { BORDER_RADIUS } from '@shared/types'
import type { FontFamilyKey, BorderRadiusKey } from '@shared/types'

const DEFAULT_BANNER_TITLE = 'How to support?'
const DEFAULT_BANNER_DESCRIPTION =
'You can support this page and my work by a one time donation or proportional to the time you spend on this website through web monetization.'
const DEFAULT_BANNER_LINK_TEXT =
'Install the Web Monetization browser extension'

type BorderRadiusKey = 'Light' | 'Pill' | 'None'
const BORDER_RADIUS_VALUES: Record<BorderRadiusKey, string> = {
Light: '0.375rem',
Pill: '1rem',
None: '0'
}

type FontFamilyKey =
| 'Cookie'
| 'Roboto'
| 'Open Sans'
| 'Titillium Web'
| 'Arial'
| 'Inherit'
const FONT_FAMILY_URLS: Record<
Exclude<FontFamilyKey, 'Arial' | 'Inherit'>,
string
> = {
'Open Sans':
'https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap',
'Cookie': 'https://fonts.googleapis.com/css2?family=Cookie&display=swap',
'Roboto':
'https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap',
'Titillium Web':
'https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap'
}

export interface BannerConfig {
bannerTitleText?: string
bannerDescriptionText?: string
Expand Down Expand Up @@ -206,6 +181,10 @@ export class BannerController implements ReactiveController {
this.applyBorderRadius(updates.bannerBorderRadius)
}

if (updates.bannerPosition) {
this.applyPosition()
}

this.host.requestUpdate()
}

Expand All @@ -220,51 +199,34 @@ export class BannerController implements ReactiveController {
* @param borderRadius The border radius value to apply.
*/
private applyBorderRadius(borderRadius: BorderRadiusKey) {
const borderRadiusValue = BORDER_RADIUS_VALUES[borderRadius]
const borderRadiusValue = BORDER_RADIUS[borderRadius]
this.host.style.setProperty(
'--wm-border-radius',
borderRadiusValue || BORDER_RADIUS_VALUES.None
borderRadiusValue || BORDER_RADIUS.None
)
}

/**
* Applies the specified font family to the host element, removing any existing font link,
* loading the font if necessary, and setting the CSS custom property.
*
* @param fontName The name of the font family to apply.
* Applies the specified position to the host element.
*/
private applyFontFamily(fontName: FontFamilyKey) {
const existingFont = document.getElementById(
'wmt-font-family-banner'
) as HTMLLinkElement
if (existingFont) {
existingFont.remove()
}

if (fontName === 'Inherit') {
this.host.style.setProperty('--wm-font-family', 'inherit')
return
}

if (fontName === 'Arial') {
this.host.style.setProperty('--wm-font-family', fontName)
return
}
applyPosition() {
this.host.classList.remove('position-top', 'position-bottom')

const fontFamilyUrl = FONT_FAMILY_URLS[fontName]
if (!fontFamilyUrl) {
this.host.style.setProperty('--wm-font-family', 'inherit')
return
const position = this._config.bannerPosition || 'Bottom'
if (position === 'Top') {
this.host.classList.add('position-top')
} else {
this.host.classList.add('position-bottom')
}
}

const fontLink = document.createElement('link') as HTMLLinkElement
fontLink.id = 'wmt-font-family-banner'
fontLink.rel = 'stylesheet'
fontLink.type = 'text/css'
fontLink.href = fontFamilyUrl
document.head.appendChild(fontLink)

this.host.style.setProperty('--wm-font-family', fontName)
/**
* Applies the specified font family to the host element.
*
* @param fontName The name of the font family to apply.
*/
private applyFontFamily(fontName: FontFamilyKey) {
applyFontFamily(this.host, fontName, 'banner')
}
applyTheme(element: HTMLElement) {
const theme = this.config.theme
Expand Down
47 changes: 47 additions & 0 deletions components/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
import { FONT_FAMILY_URLS } from '@shared/types'
import type { FontFamilyKey } from '@shared/types'

/**
* Applies the specified font family to an element, removing any existing font link, loading the font if necessary
* @param element - The HTML element to apply the font to
* @param fontName - The name of the font family to apply
* @param componentType - The type of component (for unique font link IDs)
*/
export const applyFontFamily = (
element: HTMLElement,
fontName: FontFamilyKey,
componentType: 'banner' | 'widget' = 'banner'
): void => {
const fontLinkId = `wmt-font-family-${componentType}`
const existingFont = document.getElementById(fontLinkId) as HTMLLinkElement

if (existingFont) {
existingFont.remove()
}

if (fontName === 'Inherit') {
element.style.setProperty('--wm-font-family', 'inherit')
return
}

if (fontName === 'Arial') {
element.style.setProperty('--wm-font-family', fontName)
return
}

const fontFamilyUrl = FONT_FAMILY_URLS[fontName]
if (!fontFamilyUrl) {
element.style.setProperty('--wm-font-family', 'inherit')
return
}

const fontLink = document.createElement('link') as HTMLLinkElement
fontLink.id = fontLinkId
fontLink.rel = 'stylesheet'
fontLink.type = 'text/css'
fontLink.href = fontFamilyUrl
document.head.appendChild(fontLink)

element.style.setProperty('--wm-font-family', fontName)
}

/**
* Gets the appropriate Web Monetization extension download link based on the user agent
* @param userAgent - The user agent string from navigator.userAgent
Expand Down
41 changes: 40 additions & 1 deletion components/src/widget/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import type {
PendingGrant,
WalletAddress
} from '@interledger/open-payments'
import { applyFontFamily } from '../utils.js'
import { WIDGET_POSITION, BORDER_RADIUS } from '@shared/types'
import type { ReactiveController, ReactiveControllerHost } from 'lit'
import type { WidgetConfig, FormatAmountArgs, FormattedAmount } from './types'
import type { FontFamilyKey, BorderRadiusKey } from '@shared/types'

export interface WidgetState {
walletAddress: WalletAddress
Expand Down Expand Up @@ -46,6 +49,7 @@ export class WidgetController implements ReactiveController {
this._config = { ...this._config, ...updates }

this.applyTheme(this.host)
this.applyPosition()
this.host.requestUpdate()
}

Expand Down Expand Up @@ -100,6 +104,29 @@ export class WidgetController implements ReactiveController {
}
}

private applyBorderRadius(borderRadius: BorderRadiusKey) {
const borderRadiusValue = BORDER_RADIUS[borderRadius]
this.host.style.setProperty(
'--wm-border-radius',
borderRadiusValue || BORDER_RADIUS.None
)
}

private applyPosition() {
this.host.classList.remove('position-left', 'position-right')

const position = this._config.widgetPosition || WIDGET_POSITION.Right
if (position === WIDGET_POSITION.Left) {
this.host.classList.add('position-left')
} else {
this.host.classList.add('position-right')
}
}

private applyFontFamily(fontName: FontFamilyKey) {
applyFontFamily(this.host, fontName, 'widget')
}

applyTheme(element: HTMLElement) {
const theme = this._config.theme
if (!theme) return
Expand All @@ -114,7 +141,19 @@ export class WidgetController implements ReactiveController {
element.style.setProperty('--wm-text-color', theme.textColor)
}
if (theme.fontFamily) {
element.style.setProperty('--wm-font-family', theme.fontFamily)
this.applyFontFamily(theme.fontFamily)
}
if (theme.fontSize) {
element.style.setProperty('--wm-font-size', `${theme.fontSize}px`)
}
if (theme.widgetBorderRadius) {
element.style.setProperty(
'--wm-widget-border-radius',
theme.widgetBorderRadius
)
}
if (theme.widgetBorderRadius) {
this.applyBorderRadius(theme.widgetBorderRadius)
}
if (theme.widgetButtonBackgroundColor) {
element.style.setProperty(
Expand Down
35 changes: 17 additions & 18 deletions components/src/widget/views/confirmation/confirmation.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
:host {
display: flex;
flex: auto;
font-family: var(--wm-font-family, system-ui, sans-serif);
width: 100%;

--primary-color: var(--wm-primary-color, #56b7b5);
--background-color: var(--wm-background-color, #ffffff);
Expand Down Expand Up @@ -81,14 +78,10 @@
flex-direction: column;
width: 100%;
box-sizing: border-box;
padding: 0px var(--Paddings-2xl, 32px);
padding: 0px var(--Spacings-2xl, 32px);
flex: 1 1 auto;
}

.margin-top-24 {
margin-top: var(--Spacings-lg, 24px);
}

.preset-buttons {
display: flex;
justify-content: center;
Expand Down Expand Up @@ -152,7 +145,7 @@

.currency-symbol {
position: absolute;
left: var(--Paddings-md, 12px);
left: var(--Spacings-md, 12px);
top: 50%;
transform: translateY(-50%);
color: var(--Text-paragraph-standard, #363636);
Expand All @@ -165,7 +158,7 @@

.payment-details {
display: flex;
padding: var(--Paddings-sm, 12px);
padding: var(--Spacings-md, 12px);
flex-direction: column;
align-items: flex-start;
gap: 10px;
Expand Down Expand Up @@ -196,7 +189,7 @@

.summary-label {
color: var(--Text-paragraph-standard, #363636);
font-size: var(--Font-Size-text-sm, 14px);
font-size: var(--Font-Size-text-base, 14px);
font-style: normal;
font-weight: var(--Font-Weight-Regular, 400);
line-height: var(--Font-Line-Height-sm, 20px);
Expand Down Expand Up @@ -247,10 +240,10 @@
.primary-button {
width: 100%;
height: 44px;
padding: var(--Spacings-xs) var(--Paddings-md);
padding: var(--Spacings-sm) var(--Spacings-md);
color: var(--wm-button-text-color);
border: none;
border-radius: var(--Radius-Moderate-rounding);
border-radius: var(--widget-border-radius, 8px);
font-family: var(--Font-Family-Inter);
font-weight: var(--Font-Weight-Regular);
font-size: var(--Font-Size-text-sm);
Expand Down Expand Up @@ -328,11 +321,11 @@
.back-button {
display: flex;
align-items: center;
gap: var(--Spacings-xs, 8px);
gap: var(--Spacings-sm, 8px);
background: transparent;
border: 1px solid transparent;
color: var(--primary-color);
padding: var(--Paddings-sm, 12px) var(--Paddings-md, 12px);
padding: var(--Spacings-md, 12px);
border-radius: var(--Radius-Moderate-rounding, 8px);
font-family: var(--Font-Family-Inter, Inter);
font-size: var(--Font-Size-text-sm, 14px);
Expand Down Expand Up @@ -385,14 +378,14 @@
}

.form-input.with-currency {
padding-left: calc(var(--Paddings-md, 12px) + 1.5em);
padding-left: calc(var(--Spacings-md, 12px) + 1.5em);
}

.form-input,
.payment-note-input {
width: 100%;
height: 48px;
padding: var(--Paddings-sm, 12px) var(--Paddings-md, 12px);
padding: var(--Spacings-md, 12px);
border: 1px solid var(--Colors-silver-300, #c9c9c9);
border-radius: var(--Radius-Moderate-rounding, 8px);
font-family: var(--Font-Family-Inter, Inter);
Expand Down Expand Up @@ -430,5 +423,11 @@
}

.form-input.with-currency {
padding-left: calc(var(--Paddings-md, 12px) + 1.5em);
padding-left: calc(var(--Spacings-md, 12px) + 1.5em);
}

@media (max-width: 480px) {
.widget-header-container {
padding: var(--Spacings-xs) var(--Spacings-md);
}
}
Loading