npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@skagerakenergi/design

v0.23.0

Published

Skagerak Energi design system — M3 component library (CSS only)

Readme

@skagerakenergi/design

Material Design 3 (M3) component library for Skagerak Energi.

This package ships CSS only:

  • M3 token files
  • Per-component CSS files
  • One convenience bundle (index.css)

Install

pnpm add @skagerakenergi/design

Quick start (all styles)

Use index.css to load token files and all components.

@import '@skagerakenergi/design/index.css';
<button class="se-button se-button--filled">Save</button>

This is the fastest option when you want all components and automatic theme handling.

Recommended import (theme + selected components)

Load auto theme, system tokens, and only the components you use.

@import '@skagerakenergi/design/tokens/theme-auto.css';
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/button.css';
@import '@skagerakenergi/design/icon-button.css';

Use this mode to keep bundle size smaller by importing only the components you use.

Import only a single component

@import '@skagerakenergi/design/tokens/theme-auto.css';
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/chips.css';
<div class="se-chip-set" role="listbox" aria-label="Filter options">
  <button class="se-chip se-chip--filter" aria-pressed="false">Option</button>
</div>

Theming

The package supports six theme variants:

  • light
  • dark
  • light-medium-contrast
  • dark-medium-contrast
  • light-high-contrast
  • dark-high-contrast

Automatic theming (recommended)

theme-auto.css sets light tokens by default and automatically adapts to user OS settings for dark mode and high contrast.

@import '@skagerakenergi/design/tokens/theme-auto.css';
@import '@skagerakenergi/design/tokens/system.css';

theme-auto.css includes:

  • Light defaults on :root
  • Automatic dark mode via prefers-color-scheme: dark
  • Automatic high contrast via prefers-contrast: more
  • Manual override classes (.light, .dark, .light-medium-contrast, .dark-medium-contrast, .light-high-contrast, .dark-high-contrast)

Manual theme swapping

Import explicit scheme files and set a theme class yourself.

@import '@skagerakenergi/design/tokens/light.css';
@import '@skagerakenergi/design/tokens/dark.css';
@import '@skagerakenergi/design/tokens/light-mc.css';
@import '@skagerakenergi/design/tokens/dark-mc.css';
@import '@skagerakenergi/design/tokens/light-hc.css';
@import '@skagerakenergi/design/tokens/dark-hc.css';
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/button.css';

Set a theme class on any ancestor element (html, body, or a section wrapper):

<body class="dark">
  <button class="se-button se-button--filled">Save</button>
</body>

Swap class at runtime in your app to change theme.

Bring your own tokens (custom theme)

Skip library color theme files and provide your own --md-sys-color-* values.

/* Your app token file */
:root {
  --md-sys-color-primary: #1976d2;
  --md-sys-color-on-primary: #ffffff;
  --md-sys-color-surface: #fdfcff;
  --md-sys-color-on-surface: #1a1c1e;
  /* Provide the full M3 system color set used by your components */
}

/* Library imports */
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/button.css';

Use this when you want your own brand palette while keeping the same component CSS API.

Bring your own tokens + auto-engine (OS preferences without custom media queries)

Use this repository's auto-engine to generate a theme-auto.css from your own Material Theme Builder exports, so you keep automatic dark/high-contrast behavior.

Important:

  • @skagerakenergi/design/tokens/theme-auto.css always points to the package's built-in token set.
  • To use your own token set, import your own generated theme-auto.css from your codebase.

Supported input filenames:

  • light.css
  • dark.css
  • light-mc.css
  • dark-mc.css
  • light-hc.css
  • dark-hc.css

Minimal setup (directory input):

pnpm build:theme-auto -- --source-dir ./brand-tokens

This generates tokens/theme-auto.css using your files when present and falls back to the library defaults for missing variants.

Strict mode (require all 6 custom variants):

pnpm build:theme-auto -- --source-dir ./brand-tokens --strict

Per-file override example:

pnpm build:theme-auto -- --source-dir ./brand-tokens --dark ./brand/dark.css --out ./tokens/theme-auto.css

Then import as usual:

@import './tokens/theme-auto.css';
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/button.css';

In short:

  • Import package theme-auto.css when you want the package defaults.
  • Import local theme-auto.css when you want your own upstream tokens.

Icons

Components that display icons expect Material Symbols Outlined to be loaded. The icon font is not bundled — load it yourself so you control which icons are included.

Google Fonts (recommended)

Add a <link> in your <head>. Use the &icon_names= parameter to include only the icons you need (keeps the download small):

<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:[email protected]&icon_names=home,search,menu,close&display=block" rel="stylesheet" />
  • [email protected] — enables the filled/outlined toggle used by navigation components
  • &display=block — prevents a flash of unstyled ligature text
  • &icon_names= — comma-separated list of the icons your app uses

Self-hosting

Download the WOFF2 from google/material-design-icons and add:

@font-face {
  font-family: 'Material Symbols Outlined';
  font-style: normal;
  src: url('./material-symbols-outlined.woff2') format('woff2');
}

.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-weight: normal;
  font-style: normal;
  font-size: 24px;
  display: inline-block;
  line-height: 1;
  text-transform: none;
  letter-spacing: normal;
  word-wrap: normal;
  white-space: nowrap;
  direction: ltr;
  font-variation-settings: 'FILL' 0;
}

Using icons in markup

<span class="material-symbols-outlined" aria-hidden="true">home</span>

See .specs/icons.md for the full icon catalog and integration details.

Usage patterns

All components

@import '@skagerakenergi/design/index.css';

Selected components

@import '@skagerakenergi/design/tokens/theme-auto.css';
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/button.css';
@import '@skagerakenergi/design/card.css';
@import '@skagerakenergi/design/text-field.css';

Manual theme + selected components

@import '@skagerakenergi/design/tokens/light.css';
@import '@skagerakenergi/design/tokens/dark.css';
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/navigation-bar.css';
@import '@skagerakenergi/design/switch.css';

Custom tokens + selected components

@import './my-theme.css'; /* provides --md-sys-color-* */
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/text-field.css';

Custom auto-theme + selected components (upstream token files)

@import './tokens/theme-auto.css'; /* generated from your own Theme Builder CSS files */
@import '@skagerakenergi/design/tokens/system.css';
@import '@skagerakenergi/design/text-field.css';

Available imports

Token files:

  • @skagerakenergi/design/tokens/theme-auto.css
  • @skagerakenergi/design/tokens/system.css
  • @skagerakenergi/design/tokens/light.css
  • @skagerakenergi/design/tokens/dark.css
  • @skagerakenergi/design/tokens/light-mc.css
  • @skagerakenergi/design/tokens/dark-mc.css
  • @skagerakenergi/design/tokens/light-hc.css
  • @skagerakenergi/design/tokens/dark-hc.css

Component files:

  • app-bar.css, badge.css, button.css, button-group.css, card.css
  • checkbox.css, chips.css, divider.css, extended-fab.css, fab.css
  • icon-button.css, list.css, loading-indicator.css, menu.css, navigation-bar.css
  • navigation-rail.css, progress-indicator.css, radio.css, snackbar.css
  • split-button.css, switch.css, tabs.css, text-field.css, toolbar.css
  • tooltip.css
  • layout.css — spacing utilities, breakpoints, canonical layouts (list-detail, supporting pane, feed, split-pane), column grids (.se-columns-2/3/4), auto-fill grid (.se-grid), flex containers (.se-row, .se-column), flex/alignment utilities

Optional JavaScript modules (overlay components):

  • menu.js — keyboard navigation + focus management for Menu (ESM, TypeScript declarations at menu.d.ts)

Loading indicator shape asset (avoids inlining the large SVG path data):

  • loading-indicator-shapes.svg — import with ?raw in Vite-based projects
  • loading-indicator-shapes.js — ESM export (loadingIndicatorShapesSvg: string) for non-Vite environments

Brand components (not part of M3 — use Skagerak brand palette, no M3 tokens required):

  • brand/logo.css — Skagerak group logo (sk-logo, sk-logo__mark, sk-logo__brand, sk-logo__subsidiary)
  • brand/skagerak_globe.svg — monochrome globe emblem (fill="currentColor") for inline embedding in the flat logo variant

Figma Code Connect

This project uses Figma Code Connect to link Figma component instances to the corresponding HTML/CSS snippets so designers see real code in the Figma Dev Mode inspector.

Prerequisites

  • Figma access token — create one at Figma → Settings → Personal access tokens with the minimum scopes used by Code Connect publishing:

    • file_code_connect:write (Write and change component code)
    • file_dev_resources:write
    • file_content:read
    • file_metadata:read

    In the Figma token UI, these are shown under Development and Files with human-readable labels. Use the scope IDs above as the source of truth when documenting automation.

    Export the token as FIGMA_ACCESS_TOKEN:

    export FIGMA_ACCESS_TOKEN=figd_xxxxx
  • @figma/code-connect is already a dev dependency (see package.json).

Project config

figma.config.json at the repo root tells the CLI where to find Code Connect files:

{
  "codeConnect": {
    "include": ["src/components/**/*.figma.ts"],
    "exclude": ["node_modules/**", "dist/**", "storybook-static/**"],
    "label": "HTML"
  }
}
  • include — glob for Code Connect source files.
  • label — the language label shown in Figma Dev Mode (e.g. "HTML").

File naming convention

Each component that has a Code Connect mapping gets a *.figma.ts file alongside its CSS and Storybook files:

src/components/button/
  button.css
  button.stories.ts
  button.figma.ts       ← Code Connect file

Anatomy of a Code Connect file

A Code Connect file imports the HTML helpers and calls figma.connect() once per Figma component set (node). Here is a minimal example:

import figma, { html } from '@figma/code-connect/html'

figma.connect(
  // 1. Figma node URL — right-click a component set in Figma → "Copy link to selection"
  'https://www.figma.com/design/<FILE_KEY>/<FILE_NAME>?node-id=<NODE_ID>',
  {
    // 2. Props — map Figma variant properties to code values
    props: {
      className: figma.className([
        'se-button',
        'se-button--filled',
        figma.enum('Size', {
          XSmall: 'se-button--xs',
          Medium: 'se-button--md',
          Large:  'se-button--lg',
          XLarge: 'se-button--xl'
        })
      ]),
      label: figma.string('Label text'),
      icon: figma.boolean('Show icon', {
        true: html`<span class="se-button__icon material-symbols-outlined">add</span>`,
        false: undefined
      })
    },

    // 3. Example — the HTML snippet shown in Figma Dev Mode
    example: ({ className, label, icon }) => html`\
<button class="${className}">
  ${icon}
  ${label}
</button>`,

    // 4. Imports — CSS import hint displayed alongside the snippet
    imports: ["@import '@skagerakenergi/design/button.css';"]
  }
)

Key prop helpers

| Helper | Purpose | Example | |---|---|---| | figma.className([...]) | Build a class string from static values and variant mappings | figma.className(['se-button', figma.enum('Style', { Filled: 'se-button--filled' })]) | | figma.enum('Prop', map) | Map a Figma enum property to code values | figma.enum('Size', { Small: 'sm', Large: 'lg' }) | | figma.string('Prop') | Pull a text/string property value straight through | figma.string('Label text') | | figma.boolean('Prop', { true, false }) | Map a boolean toggle to different code outputs | figma.boolean('Show icon', { true: html\...`, false: undefined })| |figma.instance('Prop')| Render a nested Figma instance with its own Code Connect |figma.instance('Leading icon')` |

Writing a new Code Connect file step by step

  1. Identify the Figma component set. Open the Figma file, navigate to the component, right-click the top-level component set, and choose Copy link to selection. The URL contains the node-id you need.

  2. Create the file. Add src/components/<name>/<name>.figma.ts.

  3. Map props. Open the component's property panel in Figma to see every variant property (e.g. Size, Type, Style, Show icon). Map each one using the helpers above.

  4. Write the example function. Return an html tagged template that produces the same markup the component's CSS expects. Reference the mapped props by name.

  5. Add imports. List the CSS @import statement(s) a consumer needs.

  6. Handle multiple variants. If the Figma file splits a component into separate component sets (e.g. filled button vs outlined button), add a separate figma.connect() call for each and hardcode the modifier class. See button.figma.ts for a real example.

  7. Validate locally.

    # Parse all Code Connect files and report errors without publishing
    pnpm figma:publish --dry-run
  8. Publish to Figma.

    pnpm figma:publish

    This pushes the snippets to Figma so they appear in Dev Mode for the linked components.

  9. Unpublish (remove all snippets).

    pnpm figma:unpublish

Tips

  • One figma.connect() per component set node. If a component has five style variants as separate nodes in Figma, write five calls.
  • Prop names are case-sensitive and must match the Figma property name exactly (e.g. 'Label text', not 'label text').
  • Use html tagged templates (from @figma/code-connect/html) so Figma renders the snippet with proper syntax highlighting.
  • Backslash after the opening backtick (html\\`) prevents a leading newline in the rendered snippet.
  • imports is an array of strings — each string is shown as-is in the Figma UI. Use the package-level import path (@skagerakenergi/design/...) so consumers see the right import.
  • Keep snippets minimal — show the most common usage; don't try to cover every edge case.
  • Refer to existing files for patterns: button.figma.ts, icon-button.figma.ts.