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
dialogBackground--goma-dialogBackground#03061bModal / dialog panel background — decoupled from backgroundPrimary so a transparent host can still paint an opaque modal. Used by <goma-sports-navigation-dialog> and <goma-betslip-floating>.

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
highlightGradientStart--goma-highlightGradientStart#29f2ffFeatured-card neon divider — gradient start. Used by <goma-top-competitions> highlighted rows.
highlightGradientEnd--goma-highlightGradientEnd#875affFeatured-card neon divider — gradient end. Used by <goma-top-competitions> highlighted rows.

Separators

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

Buttons

TokenCSS variableDefaultDescription
buttonBackgroundPrimary--goma-buttonBackgroundPrimary#ff6600Primary button fill — also the selected odds button background
buttonTextPrimary--goma-buttonTextPrimary#ffffffPrimary button text — also the selected odds button text. Use a colour that reads against buttonBackgroundPrimary (e.g. a dark token on a light accent).
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 (market tabs + cards)

<goma-game-details> mostly reuses the shared token set, but it adds five widget-specific tokens for the market-category tab pills and the market card header strip:

TokenCSS variableDefaultDescription
tabPillBackground--goma-tabPillBackground#1f2147Market-category tab pill — inactive background
tabPillBackgroundActive--goma-tabPillBackgroundActive#ff6600Market-category tab pill — active background
tabPillText--goma-tabPillText#939dffTab pill text — inactive
tabPillTextActive--goma-tabPillTextActive#ffffffTab pill text — active
marketCardHeaderBackground--goma-marketCardHeaderBackground#1f2147Market card collapsible-header strip background

The other notable surfaces map to shared tokens:

SurfaceToken(s)
Page background--goma-backgroundPrimary
Header background--goma-backgroundSecondary
LIVE badge + clock--goma-liveTag, --goma-liveBorder1 / 2 / 3
Market card gradient border--goma-cardBorderLineGradient1 / 2 / 3
Market card body--goma-backgroundCards
Odds value text--goma-textOdds

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',
}