Skip to content

Theming

gomawt widgets use CSS custom properties (variables) for all visual styling. Every token is prefixed with --goma- and defined on the :host element inside the Shadow DOM. Because inline styles on :host have the highest specificity, consumer overrides always win.

Quick start

js
const el = document.querySelector('goma-events-horizontal')
el.theme = {
  highlightPrimary: '#dc2626',
  backgroundPrimary: '#1a0505',
  buttonBackgroundPrimary: '#dc2626',
}

The widget automatically prepends --goma- to each key, so highlightPrimary becomes --goma-highlightPrimary on the host element. All three key formats are accepted:

Input keyResolved CSS property
highlightPrimary--goma-highlightPrimary
--highlightPrimary--goma-highlightPrimary
--goma-highlightPrimary--goma-highlightPrimary

Using config.theme

You can also pass the theme inside the config object:

js
el.config = {
  apiBaseUrl: 'https://api.example.com',
  theme: {
    backgroundPrimary: '#1a0505',
    highlightPrimary: '#dc2626',
  },
}

Both el.theme = {...} and config.theme use the same code path. Setting either one applies the overrides immediately.

Switching themes at runtime (light / dark)

Define your light and dark palettes as two plain JavaScript objects with the same set of keys, then assign whichever one you want — the widget reflects the change on the next paint without a remount, a reload, or a class swap. The reactive bridge picks up el.theme = … immediately and writes the values to inline custom properties on the host, so every Vue component that reads var(--goma-…) updates in place.

js
const lightTheme = {
  backgroundPrimary: '#ffffff',
  backgroundSecondary: '#f4f5fb',
  backgroundCards: '#ffffff',
  textPrimary: '#0b0d2a',
  textSecondary: '#5a6280',
  highlightPrimary: '#ff6600',
  buttonBackgroundPrimary: '#ff6600',
  buttonTextPrimary: '#ffffff',
  separatorLine: '#e2e5f0',
  // … cover every token you want to differ between modes
}

const darkTheme = {
  backgroundPrimary: '#03061b',
  backgroundSecondary: '#161732',
  backgroundCards: '#1f2147',
  textPrimary: '#ffffff',
  textSecondary: '#939dff',
  highlightPrimary: '#ff6600',
  buttonBackgroundPrimary: '#ff6600',
  buttonTextPrimary: '#ffffff',
  separatorLine: '#2a2d60',
  // … same keys as lightTheme
}

const el = document.querySelector('goma-events-horizontal')

// Apply light mode
el.theme = lightTheme

// Later — flip to dark mode
el.theme = darkTheme

Reacting to the host's prefers-color-scheme

Wire the system preference once and let the watcher swap themes for you:

js
const mql = window.matchMedia('(prefers-color-scheme: dark)')

function syncTheme() {
  el.theme = mql.matches ? darkTheme : lightTheme
}

syncTheme()
mql.addEventListener('change', syncTheme)

One important caveat — keep both objects complete

Each el.theme = … call writes the keys of the object you pass; it does not clear keys set by a previous assignment. If lightTheme defines backgroundCards and darkTheme doesn't, the value from lightTheme will linger after the swap.

The safe pattern is to make both objects exhaustive over the tokens you care about. If you must override a single token on top of a base theme, merge explicitly:

js
el.theme = { ...darkTheme, highlightPrimary: '#dc2626' }

Token reference

All tokens are defined in src/styles/main.css under the :host block. Each token has a DEFAULT and a -dark variant. Set both for consistent rendering.

Backgrounds

TokenCSS variableDefaultDescription
backgroundPrimary--goma-backgroundPrimary#03061bPage / widget background
backgroundSecondary--goma-backgroundSecondary#161732Secondary panels, betslip
backgroundTertiary--goma-backgroundTertiary#1f2147Cards, inputs
backgroundBorder--goma-backgroundBorder#2a2d60Card border backgrounds
backgroundCards--goma-backgroundCards#1f2147Card inner background
backgroundDrop--goma-backgroundDrop#03061bDropdown overlays
backgroundOdds--goma-backgroundOdds#434799Odds button background
backgroundDisabledOdds--goma-backgroundDisabledOdds#2a2d60Suspended odds background

Text

TokenCSS variableDefaultDescription
textPrimary--goma-textPrimary#ffffffPrimary text (team names, labels)
textSecondary--goma-textSecondary#939dffSecondary text (competition, time)
textHeadlinePrimary--goma-textHeadlinePrimary#ffffffHeadline text
textDisablePrimary--goma-textDisablePrimary#434799Disabled / muted text
textOdds--goma-textOdds#ffffffOdds value text
textDisabledOdds--goma-textDisabledOdds#434799Suspended odds text

Icons

TokenCSS variableDefaultDescription
iconPrimary--goma-iconPrimary#ffffffPrimary icon fills
iconSecondary--goma-iconSecondary#5559b4Secondary icon fills

Highlights

TokenCSS variableDefaultDescription
highlightPrimary--goma-highlightPrimary#ff6600Primary accent (CTA, active states)
highlightSecondary--goma-highlightSecondary#404cffSecondary accent
highlightTertiary--goma-highlightTertiary#01b72eTertiary accent (green)
highlightPrimaryContrast--goma-highlightPrimaryContrast#ffffffText on primary accent
highlightSecondaryContrast--goma-highlightSecondaryContrast#03061bText on secondary accent

Separators

TokenCSS variableDefaultDescription
separatorLine--goma-separatorLine#2a2d60Divider lines
separatorLineSecondary--goma-separatorLineSecondary#393d83Secondary dividers

Buttons

TokenCSS variableDefaultDescription
buttonBackgroundPrimary--goma-buttonBackgroundPrimary#ff6600Primary button fill
buttonTextPrimary--goma-buttonTextPrimary#ffffffPrimary button text
buttonActiveHoverPrimary--goma-buttonActiveHoverPrimary#ff7e29Primary button hover
buttonBackgroundSecondary--goma-buttonBackgroundSecondary#2a2d60Secondary button fill

Live

TokenCSS variableDefaultDescription
liveTag--goma-liveTag#ff6600"LIVE" badge background
liveBorder1--goma-liveBorder1#ff6000Live card border gradient stop 1
liveBorder2--goma-liveBorder2#ff934cLive card border gradient stop 2
liveBorder3--goma-liveBorder3#7a83ffLive card border gradient stop 3
liveShadowColor--goma-liveShadowColorrgba(235, 92, 104, 1)Live badge drop shadow

Live-count badge (sports-navigation)

Used by <goma-sports-navigation-horizontal> for the small pill on the top-right of each sport tile that has numberOfLiveEvents > 0.

TokenCSS variableDefaultDescription
liveCountBackground--goma-liveCountBackground#ed4f63Pill background
liveCountText--goma-liveCountText#ffffffNumber colour

Both have -dark variants. The badge wraps a 2px --goma-backgroundPrimary ring around the pill so it pops cleanly off the surrounding circle.

Odds-update flash (RegularOdds)

When odds tick up or down on a <RegularOdds> button, the card temporarily highlights with a coloured border + arrow icon. The background during that highlight is controlled by the two tokens below; both default to the resting --goma-backgroundOdds so the card doesn't flash by default — that matches the betsson-france baseline where the only visual cue is the border and the up/down arrow.

TokenCSS variableDefaultDescription
oddsUpdateUp--goma-oddsUpdateUpvar(--goma-backgroundOdds)Card background while odds are flashing up
oddsUpdateDown--goma-oddsUpdateDownvar(--goma-backgroundOdds)Card background while odds are flashing down
oddsUpdateUpBorder--goma-oddsUpdateUpBorder#21ba452 px border + ▲ arrow colour while odds are flashing up
oddsUpdateDownBorder--goma-oddsUpdateDownBorder#ed4f632 px border + ▼ arrow colour while odds are flashing down

All four have -dark variants. The borders + arrow inherit the alertSuccess / alertError palette by default so the price-change cue stays vibrant against the resting card. The fill stays unchanged unless a theme overrides oddsUpdateUp / oddsUpdateDown.

Alerts

TokenCSS variableDefaultDescription
alertError--goma-alertError#ed4f63Error state
alertSuccess--goma-alertSuccess#21ba45Success state
alertWarning--goma-alertWarning#f2c037Warning state

Cards

TokenCSS variableDefaultDescription
cardBorderLineGradient1--goma-cardBorderLineGradient1#393d83Card border gradient stop 1
cardBorderLineGradient2--goma-cardBorderLineGradient2#7c4b57Card border gradient stop 2
cardBorderLineGradient3--goma-cardBorderLineGradient3#b25633Card border gradient stop 3

Game details (tab pills + market cards)

Used by <goma-game-details>. Each token falls back to the existing token in parentheses if you don't override it, so a host theme that doesn't know about these still renders consistently.

TokenCSS variableFallbackDescription
tabPillBackground--goma-tabPillBackground--goma-backgroundCardsInactive market-tab pill fill
tabPillBackgroundActive--goma-tabPillBackgroundActive--goma-buttonBackgroundPrimaryActive market-tab pill fill
tabPillText--goma-tabPillText--goma-textSecondaryInactive pill text
tabPillTextActive--goma-tabPillTextActive--goma-buttonTextPrimaryActive pill text
marketCardHeaderBackground--goma-marketCardHeaderBackground--goma-backgroundTertiaryMarket card header strip background (separates the title row from outcomes visually)

Miscellaneous

TokenCSS variableDefaultDescription
favorites--goma-favorites#fac125Favorite star colour
statsHome--goma-statsHome#d99f00Home team stats
statsAway--goma-statsAway#46c1a7Away team stats

Typography & Shape

TokenCSS variableDefaultDescription
fontSize--goma-fontSize13pxBase font size
scoreRadius--goma-scoreRadius4pxScore box border radius

Embedding examples

Vanilla HTML

html
<goma-events-horizontal id="sb"></goma-events-horizontal>
<script type="module">
  import '@gomagaming/events-horizontal'

  const el = document.getElementById('sb')
  el.config = { apiBaseUrl: 'https://api.example.com' }
  el.theme = { highlightPrimary: '#dc2626', backgroundPrimary: '#1a0505' }
</script>

React

jsx
import '@gomagaming/events-horizontal'

function Feed({ config }) {
  return (
    <goma-events-horizontal
      ref={(el) => {
        if (!el) return
        el.config = config
        el.theme = { highlightPrimary: '#dc2626' }
      }}
    />
  )
}

Vue 3

vue
<script setup>
import '@gomagaming/events-horizontal'
import { ref, onMounted } from 'vue'

const el = ref(null)
onMounted(() => {
  el.value.config = { apiBaseUrl: 'https://api.example.com' }
  el.value.theme = { highlightPrimary: '#dc2626' }
})
</script>

<template>
  <goma-events-horizontal ref="el" />
</template>

Full theme example

A complete red theme:

js
el.theme = {
  backgroundPrimary: '#1a0505',
  'backgroundPrimary-dark': '#1a0505',
  backgroundSecondary: '#2d0a0a',
  'backgroundSecondary-dark': '#2d0a0a',
  backgroundCards: '#3d1212',
  'backgroundCards-dark': '#3d1212',
  backgroundOdds: '#5c1a1a',
  'backgroundOdds-dark': '#5c1a1a',
  highlightPrimary: '#dc2626',
  'highlightPrimary-dark': '#dc2626',
  buttonBackgroundPrimary: '#dc2626',
  'buttonBackgroundPrimary-dark': '#dc2626',
  liveBorder1: '#dc2626',
  'liveBorder1-dark': '#dc2626',
  liveShadowColor: 'rgba(220, 38, 38, 0.8)',
  cardBorderLineGradient1: '#5c1a1a',
  cardBorderLineGradient2: '#8b2020',
  cardBorderLineGradient3: '#dc2626',
}