@skagerakenergi/beercss-material-bridge
v0.1.1
Published
BeerCSS theme bridge for Material Design 3 --md-sys-color-* token sheets. Single dependency that re-exports beercss + material-dynamic-colors.
Readme
@skagerakenergi/beercss-material-bridge
Enkel BeerCSS-bro for Material Design 3 fargetokens generert av Material Theme Builder. Ingen Designsystemet-avhengighet — fungerer med alle prosjekter som allerede har MD3-CSS-filer.
Innholdsfortegnelse
- Konsept og arkitektur
- Hurtigstart
- Skrifttype — Arial (standard)
- Detaljert oppsett — steg for steg
- Lys/mørk-modus og temabytte
- Kontrastnivå — mc og hc
- Eksponerte API-er
- Hvordan det fungerer internt
- Avansert bruk — lavnivå API
- Feilsøking
- Ekstern dokumentasjon
1. Konsept og arkitektur
BeerCSS bruker et sett med korte CSS-variabler (--primary, --on-primary, --surface osv.) for å styre all fargelegging. Material Theme Builder eksporterer de tilsvarende fargene som lengre --md-sys-color-*-variabler i separate lys- og mørk-CSS-filer.
Denne pakken er broen mellom de to:
Material Theme Builder
└── light.css (.light { --md-sys-color-primary: …; … })
└── dark.css (.dark { --md-sys-color-primary: …; … })
│
▼
applyMd3Theme({ light, dark })
│
├─ parseVars() → trekker ut --md-sys-color-* fra CSS-tekst
├─ md3ToBeerStyle() → fjerner prefiks: --md-sys-color-primary → --primary
└─ ui('theme', …) → registrerer lys- og mørk-paletten i BeerCSSKildefil uendret: De originale CSS-filene fra Material Theme Builder trenger ikke redigeres. Pakken leser dem som råtekst og tolker dem ved kjøretid.
Ingen Designsystemet-avhengighet: Pakken er helt selvstendig og kan brukes i ethvert prosjekt som har BeerCSS og MD3-temafiler.
2. Hurtigstart
Forutsetter Vite. Tilpass for andre byggverktøy (se seksjon 4.3).
pnpm add @skagerakenergi/beercss-material-bridge// main.ts (eller tilsvarende oppstartsfil)
import { applyMd3Theme } from '@skagerakenergi/beercss-material-bridge'
// Importer MD3-CSS-filene fra Material Theme Builder som råtekst.
// Kontrastvariantene er valgfrie — oppgi bare det du har.
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
import lightMcCss from './theme/light-mc.css?raw'
import darkMcCss from './theme/dark-mc.css?raw'
import lightHcCss from './theme/light-hc.css?raw'
import darkHcCss from './theme/dark-hc.css?raw'
// Parser fargetokenene og registrerer dem i BeerCSS.
// setContrast lar deg bytte kontrastnivå etter oppstart.
const { setContrast } = await applyMd3Theme({
light: lightCss,
dark: darkCss,
lightMc: lightMcCss,
darkMc: darkMcCss, // medium kontrast
lightHc: lightHcCss,
darkHc: darkHcCss // høy kontrast
})
// Sett lys/mørk-modus som normalt:
await ui('mode', 'light') // eller 'dark' / 'auto'
// Bytt kontrastnivå ved behov:
await setContrast('hc') // 'default' | 'mc' | 'hc'3. Skrifttype — Arial (standard)
Skageraks profilfont er ITC Franklin GOthic, med Arial som fallback.
Denne pakken bruker Arial som standardskrift. Dette samsvarer med BeerCSS sitt skriftsystem, der --font-variabelen på :root styrer all typografi.
Når du importerer pakken, injiseres automatisk en <style>-tag som setter:
:root {
--font: "Arial";
}Overstyre standardskriften
Siden fonten injiseres som en vanlig CSS-regel (ikke inline-stil), kan du overstyre den med en hvilken som helst CSS-regel som er like eller mer spesifikk.
1. CSS — re-deklarer --font
/* I prosjektets eget stilark */
:root {
--font: "Min Egne Font";
}2. JavaScript — kall setFont() etter import
import { setFont } from '@skagerakenergi/beercss-material-bridge'
setFont('Min Egne Font')setFont() oppdaterer (eller oppretter) <style>-taggen dynamisk. Du kan kalle den flere ganger for å bytte skrift ved kjøretid.
3. Google Fonts-eksempel
Laster du en skrift fra Google Fonts, importerer du den selv og setter --font:
@import "https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap";
:root {
--font: "Inter";
}Eller programmatisk:
import { setFont } from '@skagerakenergi/beercss-material-bridge'
setFont('Inter')4. Proprietær skrift
@font-face {
font-family: "MinProprietærSkrift";
src: url("/fonts/min-skrift.woff2") format("woff2");
font-weight: 100 900;
}
:root {
--font: "MinProprietærSkrift";
}Deaktivere automatisk skriftinjeksjon
Hvis du ikke ønsker at pakken skal sette --font i det hele tatt, importerer du de individuelle modulene direkte i stedet for pakkerot-endepunktet:
// I stedet for:
import { applyMd3Theme } from '@skagerakenergi/beercss-material-bridge'
// Importer direkte (ingen skriftinjeksjon):
import 'beercss'
import 'material-dynamic-colors'
import { applyMd3Theme } from '@skagerakenergi/beercss-material-bridge/theme'
import { parseVars } from '@skagerakenergi/beercss-material-bridge/parse'
import { md3ToBeerStyle } from '@skagerakenergi/beercss-material-bridge/convert'4. Detaljert oppsett — steg for steg
4.1 Installer pakken
# pnpm
pnpm add @skagerakenergi/beercss-material-bridge
# npm
npm install @skagerakenergi/beercss-material-bridge
# yarn
yarn add @skagerakenergi/beercss-material-bridgePakken tar med seg beercss og material-dynamic-colors som avhengigheter — oppstrømsprosjektet trenger ikke installere disse separat.
4.2 Skaff MD3-CSS-filene
Gå til Material Theme Builder, velg farger og last ned temaet. Arkivet inneholder blant annet:
theme/
├── light.css ← .light { --md-sys-color-primary: …; … } (standard kontrast)
├── dark.css ← .dark { --md-sys-color-primary: …; … } (standard kontrast)
├── light-mc.css ← .light { --md-sys-color-primary: …; … } (medium kontrast)
├── dark-mc.css ← .dark { --md-sys-color-primary: …; … } (medium kontrast)
├── light-hc.css ← .light { --md-sys-color-primary: …; … } (høy kontrast)
└── dark-hc.css ← .dark { --md-sys-color-primary: …; … } (høy kontrast)Legg disse filene i prosjektet ditt, f.eks. under src/theme/. Kontrastvariantene er valgfrie — du kan starte med bare light.css og dark.css og legge til resten senere.
Merk: Selektoren (
.light,.dark,:root, eller annet) spiller ingen rolle —parseVars()leser kun innholdet inni den første{ }-blokken i filen. Du kan beholde originalfilene helt uendret.
4.3 Importer CSS-filene som råtekst
Pakken trenger CSS-innholdet som en vanlig JavaScript-streng, ikke som et importert stilark.
Vite:
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
// Kontrastvariantene er valgfrie:
import lightMcCss from './theme/light-mc.css?raw'
import darkMcCss from './theme/dark-mc.css?raw'
import lightHcCss from './theme/light-hc.css?raw'
import darkHcCss from './theme/dark-hc.css?raw'webpack (raw-loader):
import lightCss from '!!raw-loader!./theme/light.css'
import darkCss from '!!raw-loader!./theme/dark.css'Node.js / Bun (byggskript):
import { readFileSync } from 'node:fs'
const lightCss = readFileSync('./theme/light.css', 'utf-8')
const darkCss = readFileSync('./theme/dark.css', 'utf-8')4.4 Kall applyMd3Theme()
import { applyMd3Theme } from '@skagerakenergi/beercss-material-bridge'
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
// Minimalversjon — bare standard kontrast:
const { setContrast } = await applyMd3Theme({ light: lightCss, dark: darkCss })
// BeerCSS er nå klar. Sett ønsket startmodus:
await ui('mode', 'light')Kall applyMd3Theme() én gang ved oppstart, gjerne i onMounted() i Vue eller useEffect() i React. Etterpå bruker du bare ui('mode', …) for å bytte mellom lys og mørk, og setContrast() / setContrastLevel() for å bytte kontrastnivå.
4.5 TypeScript-typer for ui()
BeerCSS sin ui()-funksjon er global (ikke en ES-modul-import), og TypeScript kjenner den ikke uten en type-deklarasjon. Legg til følgende i tsconfig.json:
{
"compilerOptions": {
"types": ["@skagerakenergi/beercss-material-bridge/globals"]
}
}Alternativt, legg til en triple-slash-referanse øverst i filen der du bruker ui():
/// <reference types="@skagerakenergi/beercss-material-bridge/globals" />4.6 IDE-autofullføring av BeerCSS-klassenavn
WebStorm og andre IntelliJ-baserte IDE-er kan tilby autofullføring av BeerCSS-klassenavn (f.eks. primary, surface, row, card, osv.) i .vue- og .html-filer. For at IDE-en skal indeksere disse klassene, må den få tilgang til en CSS-fil som inneholder dem.
Pakken eksporterer et eget CSS-endepunkt for dette formålet:
// main.ts (eller tilsvarende oppstartsfil)
import '@skagerakenergi/beercss-material-bridge/beer.css'Eller fra et globalt stilark:
/* styles.css */
@import '@skagerakenergi/beercss-material-bridge/beer.css';Hva dette gjør:
- Filen
dist/beer.cssinneholder det fullstendige BeerCSS-stilarket (kopiert under bygget). IDE-en trenger ikke følge@import-kjeder gjennomnode_modules— alle klassedefinisjoner er direkte tilgjengelige. - Dette fungerer med pnpm og andre strenge pakkehåndterere der transitive avhengigheter ikke er tilgjengelige fra konsumentens
node_modules-rot. - IDE-en gir deg autofullføring for alle BeerCSS-hjelpeklasser i maler og HTML.
- Vite dedupliserer CSS-moduler — importerer du filen i samme prosjekt der BeerCSS allerede lastes av JavaScript-siden, vil det ikke lastes dobbelt i produksjonsbygget.
Merk: BeerCSS-stilene injiseres allerede som en side-effekt av JavaScript-importen (
import '@skagerakenergi/beercss-material-bridge'). Denne CSS-importen er primært for at IDE-en skal oppdage og indeksere klassene — ikke for å laste stilene på nytt ved kjøretid.
5. Lys/mørk-modus og temabytte
Etter at applyMd3Theme() er kalt, håndterer BeerCSS modus-byttet selv via ui('mode', …):
// Bytt til mørk modus
await ui('mode', 'dark')
// Bytt til lys modus
await ui('mode', 'light')
// Følg OS-preferansen automatisk
await ui('mode', 'auto')Eksempel — Vue 3 med toggle
<script setup lang="ts">
/// <reference types="@skagerakenergi/beercss-material-bridge/globals" />
import { ref, onMounted, watch } from 'vue'
import { applyMd3Theme } from '@skagerakenergi/beercss-material-bridge'
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
const isDark = ref(false)
onMounted(async () => {
// Les eventuell lagret preferanse
const saved = localStorage.getItem('colorMode')
isDark.value =
saved === 'dark'
? true
: saved === 'light'
? false
: matchMedia('(prefers-color-scheme: dark)').matches
// Registrer MD3-temaet i BeerCSS
await applyMd3Theme({ light: lightCss, dark: darkCss })
// Sett startmodus
await ui('mode', isDark.value ? 'dark' : 'light')
})
watch(isDark, async (dark) => {
await ui('mode', dark ? 'dark' : 'light')
localStorage.setItem('colorMode', dark ? 'dark' : 'light')
})
</script>
<template>
<button @click="isDark = !isDark">
{{ isDark ? '☀️ Lys modus' : '🌙 Mørk modus' }}
</button>
</template>Eksempel — React
import { useEffect, useState } from 'react'
import { applyMd3Theme } from '@skagerakenergi/beercss-material-bridge'
/// <reference types="@skagerakenergi/beercss-material-bridge/globals" />
// Importer CSS som råtekst (krever Vite eller tilsvarende konfigurert bundler)
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [isDark, setIsDark] = useState(false)
useEffect(() => {
applyMd3Theme({ light: lightCss, dark: darkCss }).then(() => {
ui('mode', isDark ? 'dark' : 'light')
})
}, [])
const toggle = async () => {
const next = !isDark
setIsDark(next)
await ui('mode', next ? 'dark' : 'light')
}
return (
<>
<button onClick={toggle}>{isDark ? '☀️ Lys' : '🌙 Mørk'}</button>
{children}
</>
)
}6. Kontrastnivå — mc og hc
Material Theme Builder eksporterer tre kontrastnivåer per lysmodus:
| Fil | Nivå | ContrastLevel |
|----------------|---------------------|-----------------|
| light.css | Standard kontrast | 'default' |
| light-mc.css | Medium kontrast | 'mc' |
| light-hc.css | Høy kontrast (WCAG) | 'hc' |
| dark.css | Standard kontrast | 'default' |
| dark-mc.css | Medium kontrast | 'mc' |
| dark-hc.css | Høy kontrast (WCAG) | 'hc' |
Pass kontrastvariantene til applyMd3Theme() og bruk deretter setContrastLevel() — eller setContrast() returnert direkte fra applyMd3Theme() — for å bytte nivå:
import { applyMd3Theme, setContrastLevel } from '@skagerakenergi/beercss-material-bridge'
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
import lightMcCss from './theme/light-mc.css?raw'
import darkMcCss from './theme/dark-mc.css?raw'
import lightHcCss from './theme/light-hc.css?raw'
import darkHcCss from './theme/dark-hc.css?raw'
const { setContrast } = await applyMd3Theme({
light: lightCss,
dark: darkCss,
lightMc: lightMcCss,
darkMc: darkMcCss,
lightHc: lightHcCss,
darkHc: darkHcCss
})
// Via returverdien (praktisk etter init):
await setContrast('hc')
// Via den standalone-eksporterte funksjonen (praktisk fra andre moduler):
await setContrastLevel('mc')
// Tilbake til standard:
await setContrastLevel('default')Merk: Lys/mørk-modus og kontrastnivå er uavhengige av hverandre.
ui('mode', 'dark')ogsetContrastLevel('hc')kan kombineres fritt — BeerCSS holder styr på modusen mens pakken bytter ut temapaletten.
Fallback: Hvis du bare oppgir
lightogdark(uten kontrastvariantene), vilsetContrastLevel('mc')ogsetContrastLevel('hc')stille falle tilbake til standard-paletten uten å kaste en feil.
Eksempel — Vue 3 med kontrast-velger
<script setup lang="ts">
/// <reference types="@skagerakenergi/beercss-material-bridge/globals" />
import { ref, onMounted, watch } from 'vue'
import {
applyMd3Theme,
setContrastLevel,
type ContrastLevel
} from '@skagerakenergi/beercss-material-bridge'
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
import lightMcCss from './theme/light-mc.css?raw'
import darkMcCss from './theme/dark-mc.css?raw'
import lightHcCss from './theme/light-hc.css?raw'
import darkHcCss from './theme/dark-hc.css?raw'
const isDark = ref(false)
const contrast = ref<ContrastLevel>('default')
onMounted(async () => {
await applyMd3Theme({
light: lightCss,
dark: darkCss,
lightMc: lightMcCss,
darkMc: darkMcCss,
lightHc: lightHcCss,
darkHc: darkHcCss
})
await ui('mode', isDark.value ? 'dark' : 'light')
})
watch(isDark, (dark) => ui('mode', dark ? 'dark' : 'light'))
watch(contrast, (level) => setContrastLevel(level))
</script>
<template>
<button @click="isDark = !isDark">
{{ isDark ? '☀️ Lys' : '🌙 Mørk' }}
</button>
<select v-model="contrast">
<option value="default">Standard kontrast</option>
<option value="mc">Medium kontrast</option>
<option value="hc">Høy kontrast</option>
</select>
</template>7. Eksponerte API-er
applyMd3Theme(options)
Hoved-API. Parser lys- og mørk-CSS og registrerer dem i BeerCSS.
import { applyMd3Theme, type Md3ThemeOptions } from '@skagerakenergi/beercss-material-bridge'
interface Md3ThemeOptions {
light: string // light.css — påkrevd
dark: string // dark.css — påkrevd
lightMc?: string // light-mc.css — valgfri
darkMc?: string // dark-mc.css — valgfri
lightHc?: string // light-hc.css — valgfri
darkHc?: string // dark-hc.css — valgfri
}
const { light, dark, setContrast } = await applyMd3Theme(options)
// light / dark — de genererte BeerCSS-temastrengene (standard kontrast)
// setContrast — snarvei til setContrastLevel()setContrastLevel(level)
Bytt kontrastnivå etter oppstart. Kan importeres og kalles fra hvilken som helst modul.
import { setContrastLevel, type ContrastLevel } from '@skagerakenergi/beercss-material-bridge'
// ContrastLevel = 'default' | 'mc' | 'hc'
await setContrastLevel('hc')parseVars(css)
Lavnivå-hjelper. Trekker ut alle CSS custom properties fra den første { }-blokken i en CSS-streng.
import { parseVars } from '@skagerakenergi/beercss-material-bridge'
const vars = parseVars(lightCss)
// vars: { 'md-sys-color-primary': 'rgb(0 104 123)', 'md-sys-color-on-primary': 'rgb(255 255 255)', … }md3ToBeerStyle(vars)
Lavnivå-hjelper. Konverterer et Record<string, string> fra parseVars() til en BeerCSS inline-style-streng.
Bare variabler med md-sys-color--prefiks tas med; prefikset strippes.
import { md3ToBeerStyle } from '@skagerakenergi/beercss-material-bridge'
const style = md3ToBeerStyle(vars)
// '--primary:rgb(0 104 123);--on-primary:rgb(255 255 255);…'
// Kan brukes direkte med ui():
await ui('theme', { light: style, dark: darkStyle })setFont(family?)
Setter BeerCSS sin --font-variabel på :root. Kjøres automatisk som side-effekt ved import med "Arial" som standard. Kan kalles manuelt for å bytte skrift ved kjøretid.
import { setFont } from '@skagerakenergi/beercss-material-bridge'
// Bytt til en annen skrift:
setFont('Inter')
// Tilbake til standard (Arial):
setFont()Funksjonen injiserer (eller oppdaterer) en <style>-tag i <head> som setter :root { --font: "<family>"; }. Kan kalles flere ganger — eksisterende tag gjenbrukes.
8. Hvordan det fungerer internt
applyMd3Theme({ light: lightCss, dark: darkCss })
│
├─ parseVars(lightCss)
│ Finner første { … } i CSS-teksten (uavhengig av selektor).
│ Returnerer: { 'md-sys-color-primary': 'rgb(0 104 123)', … }
│
├─ parseVars(darkCss)
│ Samme operasjon for mørk-filen.
│
├─ md3ToBeerStyle(lightVars)
│ Filtrerer på 'md-sys-color-'-prefiks, stripper det.
│ Returnerer: '--primary:rgb(0 104 123);--on-primary:rgb(255 255 255);…'
│
├─ md3ToBeerStyle(darkVars)
│ Samme for mørk.
│
└─ ui('theme', { light, dark })
BeerCSS-intern funksjon. Lagrer temastrengene og applicerer
gjeldende modus som inline-stiler på <body>.Variabelmapping: En --md-sys-color-*-variabel i MD3-filen tilsvarer direkte en BeerCSS-variabel etter at prefikset fjernes:
| MD3 (fra Theme Builder) | BeerCSS |
|------------------------------------|-----------------------|
| --md-sys-color-primary | --primary |
| --md-sys-color-on-primary | --on-primary |
| --md-sys-color-primary-container | --primary-container |
| --md-sys-color-secondary | --secondary |
| --md-sys-color-background | --background |
| --md-sys-color-surface | --surface |
| --md-sys-color-outline | --outline |
| --md-sys-color-error | --error |
| … (alle --md-sys-color-*) | … (strippes) |
9. Avansert bruk — lavnivå API
Du kan omgå applyMd3Theme() og bruke de lavnivå-hjelperne direkte for å ha full kontroll:
import { parseVars, md3ToBeerStyle } from '@skagerakenergi/beercss-material-bridge'
import lightCss from './theme/light.css?raw'
import darkCss from './theme/dark.css?raw'
// Trinn 1: Parser CSS-variablene
const lightVars = parseVars(lightCss)
const darkVars = parseVars(darkCss)
// Trinn 2 (valgfritt): Modifiser eller filtrer variabler manuelt
lightVars['md-sys-color-primary'] = 'rgb(255 0 0)' // overstyr enkeltverdi
// Trinn 3: Bygg BeerCSS-temastrengene
const lightStyle = md3ToBeerStyle(lightVars)
const darkStyle = md3ToBeerStyle(darkVars)
// Trinn 4: Send til BeerCSS
await ui('theme', { light: lightStyle, dark: darkStyle })Bruk med flere temaer
import { applyMd3Theme } from '@skagerakenergi/beercss-material-bridge'
import brandALight from './themes/brand-a/light.css?raw'
import brandADark from './themes/brand-a/dark.css?raw'
import brandBLight from './themes/brand-b/light.css?raw'
import brandBDark from './themes/brand-b/dark.css?raw'
// Bygg BeerCSS-temastrengene for hvert tema (uten å applicere dem ennå)
import { parseVars, md3ToBeerStyle } from '@skagerakenergi/beercss-material-bridge'
const themes = {
'brand-a': {
light: md3ToBeerStyle(parseVars(brandALight)),
dark: md3ToBeerStyle(parseVars(brandADark))
},
'brand-b': {
light: md3ToBeerStyle(parseVars(brandBLight)),
dark: md3ToBeerStyle(parseVars(brandBDark))
}
}
// Applier ønsket tema:
await ui('theme', themes['brand-a'])
await ui('mode', 'light')10. Feilsøking
BeerCSS viser fremdeles standard lilla/blå farger
applyMd3Theme() er ikke kalt, eller ble kalt før beercss-pakken var ferdig lastet.
- Kall
applyMd3Theme()ionMounted()/useEffect()— ikke øverst i modulen. - Sjekk at
awaitbrukes foranapplyMd3Theme().
ui is not defined
BeerCSS-scriptet er ikke lastet ennå. Pakken importerer beercss som en ES-modul-avhengighet, så dette håndteres normalt av bundleren. Hvis du bruker BeerCSS via CDN i stedet, sørg for at CDN-scriptet lastes før du kaller applyMd3Theme().
parseVars returnerer tomt objekt {}
CSS-filen har ingen { }-blokk, eller filen er tom. Sjekk at importstien er korrekt og at ?raw-suffikset (eller tilsvarende) er med.
TypeScript: Cannot find name 'ui'
Legg til type-referansen i tsconfig.json:
{
"compilerOptions": {
"types": ["@skagerakenergi/beercss-material-bridge/globals"]
}
}Mørk modus appliceres ikke etter ui('mode', 'dark')
applyMd3Theme() må ha returnert vellykket før du kaller ui('mode', …). Vent på await applyMd3Theme(…) før du setter modus.
11. Ekstern dokumentasjon
| Ressurs | URL |
|----------------------------------------------------|-----------------------------------------------------------------|
| Material Theme Builder — generer MD3-temafiler | https://material-foundation.github.io/material-theme-builder/ |
| Material Design 3 — fargesystem og tokens | https://m3.material.io/styles/color/system/how-the-system-works |
| BeerCSS — hjemmeside og komponent-eksempler | https://www.beercss.com |
| BeerCSS — innstillinger / ui()-dokumentasjon | https://github.com/beercss/beercss/blob/main/docs/SETTINGS.md |
| BeerCSS — CDN (jsDelivr) | https://cdn.jsdelivr.net/npm/beercss/ |
| material-dynamic-colors — npm | https://www.npmjs.com/package/material-dynamic-colors |
