Hopp til innholdet
HJ ConsultHJ Consult
esc
Start en brief
Tjenester
Prosjekter
Fagnotater
Om oss
Merkevare
Norskno
English
Bytt modus: Nordlys
Bytt modus: Systems
↑↓ velg, ↵ åpne, esc lukk⌘K
Modus

Levende merkevarebok

Designsystemet, i live

Dette er ikke en PDF. Hver farge, avstand og bevegelse på denne siden leses fra @hjconsult/tokens, de samme tokenene nettstedet er bygget av. Bytter du tema, bytter boka.

310 tokens fra @hjconsult/tokens v0.1.0Temaer: Nordlys og Systems

Prinsipper

Tre regler vi designer etter

Stemme, bevegelse og tilgjengelighet er ikke pynt lagt på til slutt. De ligger i tokenene, i komponentene og i måten vi skriver på.

Stemme og tone

Bokmål

Trygg, varm og rett på sak, med et glimt i øyet. Vi skriver «vi bygger», ikke «det leveres». Korte setninger og ingen buzzord. Tankestrek bare når pausen er selve poenget, og aldri punktum i en overskrift. Humor bare når setningen fortsatt gir mening uten den.

English

Written natively, never translated word for word. Confident, warm and plain-spoken. Contractions are fine, jargon is not. No dash as a pause and no full stop on a heading: a comma, a colon or a new sentence does the job better. The joke is allowed only if the sentence still works without it.

Skriv
  • «Vi setter opp overvåking i fase én.»
  • «Dataene dine blir i EU.»
  • «Dette vet vi ikke ennå. Vi finner det ut i briefen.»
  • «Vi bygger det, og du eier koden.»
Ikke skriv
  • «Vi leverer innovative, skalerbare synergier.»
  • «Kontakt oss for et uforpliktende tilbud!!!»
  • «Enterprise-grade KI-transformasjon.»
  • «Vi skriver ikke bare kode – vi skaper verdi.»

Bevegelse

  1. 01

    Innholdet først

    Alt finnes i HTML-en før JavaScript kjører. Bevegelse legger til, og avslører aldri noe som ellers er skjult.

  2. 02

    Tokens, ikke tall

    Varigheter fra motion.duration.*, kurver fra motion.ease.*, fjærer fra motion.spring.*. Ingen magiske millisekunder i komponentene.

  3. 03

    Respekt for redusert bevegelse

    prefers-reduced-motion nuller alle varigheter og dropper parallakse og shader-animasjon. Alt har en statisk versjon.

  4. 04

    Inn med expo, flytt med standard

    Elementer kommer inn raskt og lander mykt (out-expo). Flytting bruker standard-kurven. Loops bruker in-out.

Tilgjengelighet

  1. 01

    Minst WCAG 2.2 AA

    Tekst på canvas ≥ 7:1 og dempet tekst ≥ 4,5:1, testet for hvert tema og fargeskjema i byggetrinnet.

  2. 02

    Synlig fokus

    color.focus med tykk ring og 2 px avstand. Vi fjerner aldri outline.

  3. 03

    Semantikk før ARIA

    Landemerker, én h1 per side, ekte knapper og lenker. ARIA fyller hull og er aldri en lapp.

  4. 04

    Tastatur og skjermleser

    Alt kan nås med Tab. Dekorative effekter er aria-hidden, og animert tekst beholder den ekte strengen i DOM-en.

Farger

Semantiske farger som følger temaet

Komponenter bruker bare semantiske tokens (color.*). Palettene bak er OKLCH-ramper, og hvert tema peker tokenene til sine egne stopp. Kontrasten under er regnet ut i byggetrinnet, mot color.canvas i hvert temas native fargeskjema.

Flater

TokenBrukNordlysSystems
color.canvas--hj-color-canvas
Page background: the lowest layer everything sits on.––
color.surface--hj-color-surface
Default panel and card background, one step above canvas.1.1:1Kun dekor1.0:1Kun dekor
color.surface-raised--hj-color-surface-raised
Elevated surface: popovers, sticky bars, hovered cards.1.1:1Kun dekor1.1:1Kun dekor

Tekst

TokenBrukNordlysSystems
color.fg--hj-color-fg
Primary text and icons. ≥ 7:1 on canvas in every theme and scheme.17.4:1AAA18.1:1AAA
color.fg-muted--hj-color-fg-muted
Secondary text: metadata, descriptions. ≥ 4.5:1 on canvas.7.9:1AAA8.1:1AAA
color.fg-subtle--hj-color-fg-subtle
Tertiary text for placeholders, disabled and decorative content. It only clears 3:1, so keep it to large or non-essential text.5.3:1AA5.2:1AA
color.fg-on-accent--hj-color-fg-on-accent
Text and icons placed on accent fills. ≥ 4.5:1 on accent.vs color.accent14.4:1AAA13.2:1AAA
color.accent-alt-fg--hj-color-accent-alt-fg
Text and icons placed on accent-alt fills.vs color.accent-alt7.0:1AAA14.8:1AAA

Aksent

TokenBrukNordlysSystems
color.accent--hj-color-accent
Primary brand accent: links, primary buttons, highlights.14.4:1AAA13.2:1AAA
color.accent-strong--hj-color-accent-strong
Deeper accent for hover/active states and thin strokes that need ≥ 3:1 against canvas.10.5:1AAA10.1:1AAA
color.accent-soft--hj-color-accent-soft
Accent at ~15 % alpha: selected rows, soft badges, tints.1.4:1Kun dekor1.3:1Kun dekor
color.accent-alt--hj-color-accent-alt
Secondary accent: data visualisation, tags, the second hero colour.7.0:1AAA14.8:1AAA
color.focus--hj-color-focus
Focus ring colour. Pair with border.width.thick and a 2px offset.14.4:1AAA13.2:1AAA

Linjer og glass

TokenBrukNordlysSystems
color.line--hj-color-line
Hairline dividers and default borders (alpha, works over any surface).1.2:1Kun dekor1.2:1Kun dekor
color.line-strong--hj-color-line-strong
Emphasised borders: inputs, table headers, hard rules.1.5:1Kun dekor1.8:1Kun dekor
color.glass--hj-color-glass
Translucent fill for glass panels. Pair it with backdrop-filter.1.1:1Kun dekor1.1:1Kun dekor
color.glass-line--hj-color-glass-line
Border for glass panels.1.4:1Kun dekor1.5:1Kun dekor

Status

TokenBrukNordlysSystems
color.positive--hj-color-positive
Success and confirmation: text-safe on canvas.9.1:1AAA9.3:1AAA
color.warning--hj-color-warning
Caution and pending: text-safe on canvas.10.3:1AAA10.6:1AAA
color.danger--hj-color-danger
Errors and destructive actions: text-safe on canvas.6.7:1AA6.9:1AA

Hero-palett

TokenBrukNordlysSystems
color.hero.a--hj-color-hero-a
Shader / illustration palette stop A: the base (darkest or lightest field).1.0:1Kun dekor1.2:1Kun dekor
color.hero.b--hj-color-hero-b
Shader / illustration palette stop B: the mid-tone wash.4.0:1Stor tekst7.3:1AAA
color.hero.c--hj-color-hero-c
Shader / illustration palette stop C: the accent glow.14.4:1AAA14.9:1AAA
color.hero.d--hj-color-hero-d
Shader / illustration palette stop D: the contrasting flare.4.7:1AA14.8:1AAA

Kontrast regnes på sRGB-fallback med alfa komponert over canvas, slik nettleseren gjør det. Selve fargeprøvene bruker var(--hj-…) og følger temaet du ser på.

Typografi

Én grotesk, én mono, én flytende skala

Display og brødtekst settes i Schibsted Grotesk, kode og etiketter i Geist Mono. Skalaen er flytende: hvert trinn har min og maks mellom breakpoint.sm og breakpoint.xl, med linjehøyde og sperring bakt inn i Tailwind-klassen.

Prøve: Displayvar(--font-schibsted), "Schibsted Grotesk", ui-sans-serif, system-ui, sans-serif

Blåbærsyltetøy, ærlig øl og sære måker på en rå fjordbrygge.

Æ Ø Å æ ø å 0123456789 «sitat» → ← ↑ ↓ 12 °C

Prøve: Brødtekstvar(--font-schibsted), "Schibsted Grotesk", ui-sans-serif, system-ui, sans-serif

Sphinx of black quartz, judge my vow.

Blåbærsyltetøy, ærlig øl og sære måker på en rå fjordbrygge. Æ Ø Å æ ø å 0123456789 «sitat» → ← ↑ ↓ 12 °C

Æ Ø Å æ ø å 0123456789 «sitat» → ← ↑ ↓ 12 °C

Prøve: Monovar(--font-geist-mono), "Geist Mono", ui-monospace, "SFMono-Regular", monospace

Æ Ø Å æ ø å 0123456789 «sitat» → ← ↑ ↓ 12 °C

:root {
  --hj-color-accent: oklch(0.877 0.15 167);
  --hj-motion-ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
}

Flytende skala

RollePrøveMinMaksLinjehøydeSperringTailwind
display-1Aa Ææ Øø Åå3rem8rem1.05-0.03emtext-display-1
display-2Aa Ææ Øø Åå2.5rem5.5rem1.05-0.03emtext-display-2
h1Aa Ææ Øø Åå2.25rem4rem1.05-0.015emtext-h1
h2Aa Ææ Øø Åå1.75rem2.75rem1.15-0.015emtext-h2
h3Aa Ææ Øø Åå1.375rem1.875rem1.15-0.015emtext-h3
h4Aa Ææ Øø Åå1.125rem1.375rem1.30text-h4
h5Aa Ææ Øø Åå1rem1.125rem1.30text-h5
h6Aa Ææ Øø Åå0.875rem1rem1.30.08emtext-h6
leadAa Ææ Øø Åå1.125rem1.375rem1.650text-lead
bodyAa Ææ Øø Åå1rem1.125rem1.50text-body
smallAa Ææ Øø Åå0.875rem0.9375rem1.50text-small
captionAa Ææ Øø Åå0.75rem0.8125rem1.50text-caption

Tokens

Avstand, radius, skygge og bevegelse

Alt under er hentet fra tokenpakken i byggetrinnet. Verdiene er de faktiske; visualiseringene bruker var(--hj-…) og følger derfor temaet.

Avstand

4 px-rutenett. Tailwind-klassene speiler multiplikatoren: p-4 = space.4 = 1 rem. De flytende trinnene (gutter, section-*) er clamp() mellom sm og xl.

TokenVerdiAvstandTailwind
space.px--hj-space-px1pxp-px
space.0-5--hj-space-0-50.125remp-0.5
space.1--hj-space-10.25remp-1
space.2--hj-space-20.5remp-2
space.3--hj-space-30.75remp-3
space.4--hj-space-41remp-4
space.5--hj-space-51.25remp-5
space.6--hj-space-61.5remp-6
space.8--hj-space-82remp-8
space.10--hj-space-102.5remp-10
space.12--hj-space-123remp-12
space.16--hj-space-164remp-16
space.20--hj-space-205remp-20
space.24--hj-space-246remp-24
space.32--hj-space-328remp-32
space.40--hj-space-4010remp-40
space.48--hj-space-4812remp-48
space.64--hj-space-6416remp-64
space.fluid.gutter.*--hj-space-gutter1rem → 2.5remPage gutter at the sm breakpoint (16px).px-gutter
space.fluid.section.sm.*--hj-space-section-sm2.25rem → 5remCompact section padding on a phone (36px).py-section-sm
space.fluid.section.md.*--hj-space-section-md3.25rem → 8remDefault section padding on a phone (52px).py-section-md
space.fluid.section.lg.*--hj-space-section-lg4.5rem → 12remHero/feature section padding on a phone (72px).py-section-lg

Radius

Fra xs for chips til 3xl for store paneler. full gir pillform og sirkler.

  • radius.xs2pxrounded-xs
  • radius.sm4pxrounded-sm
  • radius.md6pxrounded-md
  • radius.lg8pxrounded-lg
  • radius.xl12pxrounded-xl
  • radius.2xl16pxrounded-2xl
  • radius.3xl24pxrounded-3xl
  • radius.full9999pxrounded-full

Skygge

Tre nivåer pluss glow. Fargen på glow følger temaets aksent.

  • shadow.1shadow-1
  • shadow.2shadow-2
  • shadow.3shadow-3
  • shadow.glowshadow-glow

Bevegelse

Varigheter, kurver, forsinkelser og fjærer. Under redusert bevegelse ganges alt med motion.reduced.multiplier (0).

Varigheter

TokenVerdiBruk
motion.duration.instant0msNo animation, for reduced motion and instant state swaps.
motion.duration.fast120msHover, focus, toggles.
motion.duration.base240msDefault UI transition for reveals, menus and accordions.
motion.duration.slow480msPage-level transitions, large panels.
motion.duration.hero1200msCinematic hero reveals and shader fades.
motion.stagger.base40msStagger between list/grid children.
motion.stagger.slow80msStagger for hero lines and large cards.
motion.reduced.multiplier0Multiply durations by this when prefers-reduced-motion is set (0 = instant).

Kurver

TokenVerdiTailwind
motion.ease.standardDefault easing for UI state changes.cubic-bezier(0.2, 0, 0, 1)ease-standard
motion.ease.out-quartFast start and soft landing, for reveals and enters.cubic-bezier(0.25, 1, 0.5, 1)ease-out-quart
motion.ease.out-expoVery fast start and long settle, for the hero and scroll-linked reveals.cubic-bezier(0.16, 1, 0.3, 1)ease-out-expo
motion.ease.in-outSymmetric, for page transitions and looping motion.cubic-bezier(0.83, 0, 0.17, 1)ease-in-out
motion.ease.anticipatePulls back before overshooting, for playful kinetic accents.cubic-bezier(0.68, -0.4, 0.32, 1.4)ease-anticipate

Fjærer

TokenstiffnessdampingmassBruk
motion.spring.snappy400301Stiffness of the snappy spring, for UI feedback.
motion.spring.gentle170261Stiffness of the gentle spring, for drifts and layout shifts.
motion.spring.bouncy300121Stiffness of the bouncy spring, for motion that should catch the eye.

Se kurvene

Spill av hver kurve med sin typiske varighet. Under redusert bevegelse vises sluttbildet med én gang, slik nettstedet også oppfører seg.

  • Kurvemotion.ease.standardVarighet: 240ms (motion.duration.base)
  • Kurvemotion.ease.out-quartVarighet: 480ms (motion.duration.slow)
  • Kurvemotion.ease.out-expoVarighet: 480ms (motion.duration.slow)
  • Kurvemotion.ease.in-outVarighet: 480ms (motion.duration.slow)
  • Kurvemotion.ease.anticipateVarighet: 1200ms (motion.duration.hero)

Komponenter

Hele @hjconsult/ui, i sine viktigste varianter

Hver komponent leser tokens gjennom Tailwind-utilities, så alt her bytter tema sammen med resten av siden. Navnet i hjørnet er registry-elementet.

  • ButtonInstaller r/button.json
  • IconButtonInstaller r/icon-button.json
  • LinkInstaller r/link.json
  • HeadingInstaller r/heading.json
    display-2

    Vi bygger det andre sier er vanskelig.

    h1

    Vi bygger det andre sier er vanskelig.

    h2

    Vi bygger det andre sier er vanskelig.

    h3

    Vi bygger det andre sier er vanskelig.

    h4

    Vi bygger det andre sier er vanskelig.

    h5

    Vi bygger det andre sier er vanskelig.

    h6

    Vi bygger det andre sier er vanskelig.

  • TextInstaller r/text.json

    Ingress: den første setningen leseren møter.

    Brødtekst: rolig, lesbar og aldri lengre enn 65 tegn per linje når measure er på.

    Liten tekst til bildetekster og metadata.

    Caption i mono til etiketter.

  • EyebrowInstaller r/eyebrow.json
    EtikettMed prikk07Med indeksAksent
  • BadgeInstaller r/badge.json
    NøytralAksentAlternativI driftForsinketNede
  • LogoMarkInstaller r/logo-mark.json
    HJ ConsultHJ ConsultHJ ConsultHJ Consult
  • AvatarInstaller r/avatar.json
  • ContainerInstaller r/container.json

    Container sentrerer innholdet og gir det den flytende margen. Fire bredder: prose, narrow, default, wide.

    size="prose"size="narrow"size="default"size="wide"
  • SectionInstaller r/section.json

    Section gir vertikal rytme fra space.fluid.section.* og en innebygd container.

    space="sm"space="md"space="lg"
  • GridInstaller r/grid.json
    Celle 1
    Celle 2
    Celle 3
    Celle 4
    Celle 5
    Celle 6
  • BentoInstaller r/grid.json
    Spenner 8 av 12
    Spenner 4
    Spenner 4
    Spenner 8
  • SeparatorInstaller r/separator.json

    Separator: dekorativ som standard, semantisk hr når decorative er false.

  • Card (surface)Installer r/card.json

    Korttittel

    Beskrivelse under tittelen.

    Kortets innhold. Fire varianter med de samme slotene: surface, raised, glass og outline.

    surfaceBunntekst
  • Card (raised)Installer r/card.json

    Korttittel

    Beskrivelse under tittelen.

    Kortets innhold. Fire varianter med de samme slotene: surface, raised, glass og outline.

    raisedBunntekst
  • Card (glass)Installer r/card.json

    Korttittel

    Beskrivelse under tittelen.

    Kortets innhold. Fire varianter med de samme slotene: surface, raised, glass og outline.

    glassBunntekst
  • Card (outline)Installer r/card.json

    Korttittel

    Beskrivelse under tittelen.

    Kortets innhold. Fire varianter med de samme slotene: surface, raised, glass og outline.

    outlineBunntekst
  • Card (interactive)Installer r/card.json
  • Card (link)Installer r/card.json
  • Field + InputInstaller r/input.json
    Valgfritt

    Vi bruker den bare til å svare deg.

  • Field (error)Installer r/field.json

    Org.nr har ni siffer.

  • Field + TextareaInstaller r/textarea.json

  • StatInstaller r/stat.json
    2Eksempelverdi
    16Eksempelverdieksempel
    0Eksempelverdistabilt
  • SkeletonInstaller r/skeleton.json

    Skeleton skimrer i motion-safe og står stille under redusert bevegelse.

  • MarqueeInstaller r/marquee.json
    Next.jsSupabaseVippsStripeArduino OptaMistral
  • RevealInstaller r/motion.json
    010203

    Reveal: innholdet finnes i HTML-en, og GSAP animerer det inn når det rulles inn i bildet.

  • SplitHeadingInstaller r/motion.json

    Overskrift som stiger linje for linje.

  • MagneticInstaller r/motion.json
  • ParallaxInstaller r/motion.json
    Parallax: rull forbi meg.
  • CounterInstaller r/motion.json
    329

    Counter teller opp til verdien, som står i HTML-en fra start

  • SkipLinkInstaller r/a11y.json

    SkipLink er første tab-stopp på hver side. Trykk Tab her for å se den.

    Hopp til innholdet
  • VisuallyHiddenInstaller r/a11y.json

    Synlig tekst – og en usynlig del for skjermlesere.

    – og en usynlig del for skjermlesere.
  • LiveRegion with announce()Installer r/a11y.json

    LiveRegion og announce() gir skjermlesere beskjed uten å flytte fokus.

Bruk det

Tokens som pakke, komponenter som registry

Designsystemet er laget for å tas i bruk av oss, av kunder og av agenter som skriver kode.

@hjconsult/tokens

DTCG 2025.10-tokens kompilert til CSS-variabler, Tailwind v4-tema, JSON og TypeScript. Importer stilarkene, sett data-theme, ferdig.

  1. 1. Pek @hjconsult mot GitHub Packages og installer (tilgang på forespørsel)
    npm config set @hjconsult:registry https://npm.pkg.github.com
    pnpm add @hjconsult/tokens
  2. 2. Importer stilarkene etter Tailwind
    @import "tailwindcss";
    @import "@hjconsult/tokens/css";
    @import "@hjconsult/tokens/theme.css";
    @import "@hjconsult/tokens/fluid.css";
  3. 3. Velg tema og fargeskjema på html-elementet
    <html data-theme="nordlys" data-scheme="dark">
shadcn-registry

Hver komponent kan installeres rett inn i et prosjekt med shadcn CLI. Kilden kopieres til hj/components/…, så du eier koden.

npx shadcn add https://hjconsult.no/r/button.json

For agenter

DESIGN.md i tokenpakken beskriver hver token, hver permutasjon og do/don't-lista. /r/registry.json lister alle elementer. Begge er skrevet for å leses av maskiner like mye som av folk.

@hjconsult/tokens/design.md@hjconsult/tokens/json/r/registry.json