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

@marwes-ui/core

v1.3.0

Published

Framework-agnostic Marwes design system recipes, theme utilities, accessibility contracts, and typed RenderKit metadata.

Readme

Framework-agnostic Marwes design system recipes, theme utilities, accessibility contracts, and typed RenderKit metadata.

Marwes Design System - Core

The framework-agnostic engine behind Marwes themes, recipes, accessibility, and semantic metadata.

Pure TypeScript • No React/Vue dependency • Typed RenderKit • Shared ThemeInput • AI-readable contracts

DocumentationReact StorybookVue StorybookGitHub


Why Use It

Most app teams should install @marwes-ui/react or @marwes-ui/vue. Install core directly when you are building an adapter, validating design-system contracts, or using Marwes theme and recipe utilities without a framework.

Core gives every adapter the same:

  • ThemeInput contract
  • resolved theme model
  • CSS variable generation
  • component recipes
  • accessibility mapping
  • semantic data-* metadata
  • typed enums and token helpers

Package Map

Core is the contract layer, not the normal app entry point.

| Package | Use it when | | --- | --- | | @marwes-ui/react | You are building a React app. | | @marwes-ui/vue | You are building a Vue app. | | @marwes-ui/core | You need framework-agnostic recipes, theme utilities, accessibility contracts, or adapter/tooling APIs. | | @marwes-ui/presets | You need standalone preset CSS or preset theme exports. |

This package is useful for humans and AI agents that need stable contracts without framework rendering: component recipes, theme variable names, semantic attributes, and accessibility mapping all live here.

Install

pnpm add @marwes-ui/core

Theme Engine

import { mwAvailableFonts, resolveThemeInput, themeToCSSVars } from "@marwes-ui/core"

const theme = resolveThemeInput({
  color: {
    primary: "#2457FF",
    background: "#F8FAFC",
    surface: "#FFFFFF",
    text: "#111827",
    border: "#D1D5DB",
    focus: "#2457FF",
  },
  font: {
    primary: mwAvailableFonts.Poppins,
    secondary: mwAvailableFonts.Lora,
  },
  ui: {
    radius: 10,
    density: "comfortable",
  },
})

const cssVars = themeToCSSVars(theme)

React and Vue providers apply these variables to the provider root. Preset CSS consumes them across buttons, inputs, typography, cards, toasts, overlays, and layout primitives.

Marwes is designed to look great from the beginning. ThemeInput is intentionally partial: start from the polished defaults, map an existing design library into the tokens you own, and override only those product decisions.

import { resolveThemeInput, ThemeMode, type ThemeInput } from "@marwes-ui/core"

const themeByMode = {
  [ThemeMode.light]: { color: { primary: "#2457FF" } },
  [ThemeMode.dark]: { color: { primary: "#8BA2FF", background: "#0B1020", text: "#F8FAFC" } },
} satisfies Record<ThemeMode, ThemeInput>

const darkBrandTheme = resolveThemeInput({
  mode: ThemeMode.dark,
  ...themeByMode[ThemeMode.dark],
})

Every omitted token is filled from the selected light or dark default, so adapters can expose simple light/dark toggles without requiring a full theme object.

Light And Dark Mode Contract

Core owns the runtime ThemeMode contract that the React and Vue providers use for useThemeMode(). Use ThemeMode.light and ThemeMode.dark instead of string literals. A mode change resolves a normal theme, swaps the provider-scoped --mw-* variables, and keeps the active class aligned as mw-theme--light or mw-theme--dark.

import { resolveThemeInput, themeToCSSVars, ThemeMode } from "@marwes-ui/core"

function resolveMode(mode: ThemeMode) {
  const theme = resolveThemeInput({ mode })

  return {
    className: `mw-theme--${theme.mode}`,
    cssVars: themeToCSSVars(theme),
  }
}

resolveMode(ThemeMode.dark)
// {
//   className: "mw-theme--dark",
//   cssVars: { "--mw-color-background": "#141414", ... }
// }

Most apps should use useThemeMode() from @marwes-ui/react or @marwes-ui/vue. Core is the framework-agnostic piece that makes the resolved variables and mode classes consistent across adapters.

SSR Theme Rules

SSR adapters can use the same core theme engine to emit light and dark CSS variable rules before hydration. These helpers are pure string utilities; React and Vue expose framework-specific SSR helpers on top.

import { ThemeMode, resolveThemeInput, themeModesToCSSRules } from "@marwes-ui/core"

const css = themeModesToCSSRules({
  light: resolveThemeInput({ mode: ThemeMode.light }),
  dark: resolveThemeInput({ mode: ThemeMode.dark }),
  rootTarget: "html",
  rootAttribute: "class",
})

The generated rules target [data-marwes-theme][data-marwes-mode="light"] and [data-marwes-theme][data-marwes-mode="dark"]. When rootTarget is provided, matching html.light / html.dark or data-attribute selectors are included so a pre-hydration script can switch the resolved mode before provider roots hydrate.

Theme Variables

Marwes components are styled by CSS custom properties on the MarwesProvider root. The theme variable helpers expose that same token surface to application code, adapters, and tooling without creating a second runtime theme system.

Use these helpers when custom styling needs to stay connected to the active provider theme:

  • mwThemeVars is the default custom styling API. It returns CSS var(...) references such as "var(--mw-spacing-sp-24)".
  • mwThemeVarNames returns raw custom property names such as "--mw-spacing-sp-24" for assignment, inspection, tests, and bridge packages.
  • mwVar() wraps a custom --mw-* property name in var(...), with optional fallback support.
  • mwStyledTheme mirrors mwThemeVars as a plain object for styled-components and Emotion theme providers.
import { mwStyledTheme, mwThemeVarNames, mwThemeVars, mwVar } from "@marwes-ui/core"

mwThemeVars.spacing.sp24 // "var(--mw-spacing-sp-24)"
mwThemeVars.color.text // "var(--mw-color-text)"
mwThemeVars.color.primary.base // "var(--mw-color-primary-base)"
mwThemeVars.ui.radius // "var(--mw-ui-radius)"

mwThemeVarNames.spacing.sp24 // "--mw-spacing-sp-24"
mwVar("--mw-color-text", "#141414") // "var(--mw-color-text, #141414)"
mwStyledTheme.spacing.sp24 // "var(--mw-spacing-sp-24)"

This enables one theme contract across plain CSS, CSS Modules, CSS-in-JS, vanilla-extract, Tailwind-style config files, inline style objects, React, Vue, and future adapters. Because the helpers only expose CSS variable references and names, they remain framework-agnostic and follow any ThemeInput resolved by the provider.

Keep the APIs separate:

  • Spacings.sp24 returns "sp-24" for Marwes component props.
  • mwThemeVars.spacing.sp24 returns "var(--mw-spacing-sp-24)" for custom styling.
  • mwThemeVarNames.spacing.sp24 returns "--mw-spacing-sp-24" when code needs the property name itself.
  • themeToCSSVars() maps resolved theme values into custom property declarations.
  • Adapter useTheme() hooks return resolved runtime values for logic and inspection.

Recipe Engine

Core recipes return a typed RenderKit object instead of framework elements. Adapters map that object to React, Vue, or future renderers.

RenderKit includes:

  • tag
  • className
  • vars
  • a11y
  • optional data attributes and component-specific control fields

Available Component Contracts

Core currently powers these component families:

  • Buttons and semantic button purposes
  • Inputs, textareas, selects, rich text, OTP, and field wrappers
  • Checkbox and radio families
  • Switches and sliders
  • Cards, typography, icons, avatars, dividers, and spacing
  • Badges and contextual badge variants
  • Toasts, tooltips, dialogs, tabs, accordions, and spinners

React and Vue expose the public components. Core exposes the shared recipes, types, enum objects, semantic utilities, and theme helpers that keep those adapters consistent.

Accessibility Contract

Core is where Marwes accessibility is made reusable. Recipes return typed a11y output alongside classes, vars, and semantic metadata, so every adapter receives the same source of truth.

That contract covers:

  • native-first semantics for controls that should stay native
  • label and description wiring for fields and grouped controls
  • invalid, disabled, selected, expanded, checked, and busy state mapping
  • coordinated widget roles such as dialog, tablist, tab, tabpanel, tooltip, status, and alert
  • stable data-* metadata for purpose components and agent-readable intent

Example: field helpers generate the ids that adapters use to connect helper text and errors to the control:

import { buildInputFieldA11yIds } from "@marwes-ui/core"

buildInputFieldA11yIds({
  id: "email",
  hasHelperText: true,
  hasError: true,
})
// {
//   helperTextId: "email-helper",
//   errorId: "email-error",
//   describedBy: "email-helper email-error"
// }

React and Vue tests run the same shared contracts against their DOM output. Storybook a11y smoke checks then add an axe-powered browser-level signal for the promoted families.

Semantic Metadata

Purpose components use the core semantic registry to emit stable metadata. That makes components easier for tests, audits, and AI agents to reason about.

import { createPurposeSemanticAttributes } from "@marwes-ui/core"

createPurposeSemanticAttributes("destructive")
// {
//   "data-purpose": "destructive",
//   "data-action": "delete",
//   "data-destructive": "true",
//   "data-confirmation-required": "true"
// }

This is intentionally practical. A destructive action can carry data-destructive="true" and data-confirmation-required="true", which gives an AI agent or browser automation rule a clear signal to ask before clicking. It also gives tests a stable assertion target that does not depend on button text, color, or visual styling.

Public API Highlights

Theme:

  • resolveThemeInput
  • themeToCSSVars
  • themeToCSSRule
  • themeModesToCSSRules
  • createMarwesThemeScript
  • createMarwesThemeStyle
  • mwThemeVars
  • mwThemeVarNames
  • mwStyledTheme
  • mwVar
  • lightThemeDefaults
  • darkThemeDefaults
  • mwAvailableFonts
  • mwFontFallbacks
  • mwGoogleFontFamilies
  • createFontStack

Recipe and semantic helpers:

  • component recipe functions such as createButtonRecipe, createInputRecipe, checkboxRecipe, radioRecipe, createDialogRecipe, createToastRecipe
  • accessibility helpers for supported families
  • semantic builders and validators

Types and tokens:

  • Theme, ThemeInput, ThemeMode, ResolvedTheme
  • ColorRole, SecondaryColorRole, ColorInput
  • ButtonVariant, ButtonSize, ButtonAction
  • BadgeVariant, AvatarSize, AvatarType, SwitchSize, IconName, Spacings

Package Boundaries

  • Core has no React, Vue, DOM, or CSS runtime dependency.
  • Presets own static CSS and the default visual layer.
  • React and Vue own rendering, provider lifecycle, and framework APIs.

Scripts

pnpm --filter @marwes-ui/core build
pnpm --filter @marwes-ui/core typecheck
pnpm --filter @marwes-ui/core test

Related Docs