@flitsmeister/design-system
v3.1.2
Published
Flitsmeister design system — Lit web components (v3+). v2.x on npm was Vue; same package name, major bump.
Readme
@flitsmeister/design-system
Flitsmeister design system for modern web apps. Version 3 and higher ships Lit-based web components that can be used from plain HTML, Lit, React, Vue, Angular, Svelte, or any other framework that supports custom elements.
Note: npm v2.x of this package contained Vue components and design tokens. npm v3.x is a new web component package under the same package name.
Install
npm install @flitsmeister/design-systemWith pnpm:
pnpm add @flitsmeister/design-systemRuntime components are browser custom elements built with Lit. Publishing and CI for this repository use Node.js 24; consuming apps can install the package on Node 20+.
Tokens CSS
Lit components read semantic custom properties (--color-*, --spacing-*, --text-*) from :root. Load the published stylesheet once at app entry, as a separate stylesheet from Tailwind:
import '@flitsmeister/design-system/tokens.css'This file is generated in the design-system-v2 repo from Figma exports (styles/fm-design-system/fm-design-system.css) and copied into the package on build. See the repository README for the export workflow.
Values live on --fm-* (for example --fm-color-blue-600). Public names are aliases (--color-blue-600: var(--fm-color-blue-600)). Use the public names in app and component CSS. Dark mode switches the --fm-color-* holders on :root.dark; the aliases keep pointing at those live variables.
The same file also ships v2-compatible .type-* utilities (type-display-lg, type-headline, type-title-md, type-body-sm, type-special, …) mapped onto those tokens (--text-*, --font-weight-*, --leading-*, --font-display / --font-headline / --font-title / --font-body).
The v2-style theme path also works:
import '@flitsmeister/design-system/themes/fm-design-system/fm-design-system.css'Do not @import this file in the same stylesheet as @import "tailwindcss". Tailwind 4 treats --color-* and --spacing-* as theme tokens, tree-shakes unused ones, and remaps max-w-* onto --spacing-*. Load tokens as their own entry instead.
Tailwind
Import the generated @theme snippet in the same stylesheet as Tailwind. It maps utilities to the --fm-* value holders from tokens.css (not same-name var(--color-*), which Tailwind would write back onto :root and empty). It also restores Tailwind max-w-* container sizes so --spacing-md does not collapse max-w-md.
@import "tailwindcss";
@import "@flitsmeister/design-system/tailwind.css";Requires Tailwind 4.1+ (@theme inline). @flitsmeister/design-system/theme.css is an alias for the same file. Keep tokens.css as a separate entry; do not vendor a copy of the token CSS into the app.
Quick Start
Import the components you use, then render the matching custom elements in your HTML.
import '@flitsmeister/design-system/fm-button'
import '@flitsmeister/design-system/fm-input'<fm-input id="email" placeholder="Email" type="email"></fm-input>
<fm-button role="primary" buttontype="filled">Opslaan</fm-button>For icons, import the icon component and register icons before using them.
import '@flitsmeister/design-system/fm-icon/all'<fm-icon name="check" variant="filled" size="md"></fm-icon>
<fm-button role="primary" icon="add" icon-variant="bold">Toevoegen</fm-button>Sprite users can still point at the published SVG set under @flitsmeister/design-system/icons (for example icons/bold/check.svg).
Vue
Vue 3 wrappers live at @flitsmeister/design-system/vue. They register the Lit custom elements, map v-model, set rules as a JS property, forward validate(), and work around Shadow DOM form submit / Enter-to-submit.
import { FmButton, FmInput, FmDropdown } from '@flitsmeister/design-system/vue'<template>
<form @submit.prevent="onSubmit">
<FmInput ref="emailInput" v-model="email" :rules="emailRules" placeholder="Email" />
<FmButton type="submit" role="primary">Opslaan</FmButton>
</form>
</template>Even with wrappers, templates contain <fm-*> tags, so Vite still needs:
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('fm-')
}
}
})Vue is an optional peer dependency. Apps that do not import /vue do not need it.
React
React wrappers live at @flitsmeister/design-system/react. They register the Lit custom elements on the client, set array/function values (rules, options) as JS properties, forward validate() on FmInput, and work around Shadow DOM form submit / Enter-to-submit.
import {
FmButton,
FmInput,
FmDropdown,
FmIcon,
FmRadioInput,
FmSegmentedController
} from '@flitsmeister/design-system/react'<form className="flex flex-col gap-4" onSubmit={onSubmit}>
<FmInput className="w-full" ref={emailRef} value={email} rules={emailRules} onChange={setEmail} placeholder="Email" />
<FmButton type="submit" role="primary">Opslaan</FmButton>
</form>Host className, style, and other native attributes land on the custom element (the layout API). Boolean props such as disabled are omitted when false so React 18 does not set disabled="false".
These modules include a "use client" directive so they work as client components in the Next.js App Router. React is an optional peer dependency. Apps that do not import /react do not need it.
Components
| Component | Import | Description |
| --- | --- | --- |
| fm-button | @flitsmeister/design-system/fm-button | Accessible button with variants, sizes, icons, loading, success, and error states. |
| fm-input | @flitsmeister/design-system/fm-input | Text input with floating label, validation rules, loading, success, and error states. |
| fm-radio-input | @flitsmeister/design-system/fm-radio-input | Radio-card option with label, media, description, and native radio behavior. |
| fm-segmented-controller | @flitsmeister/design-system/fm-segmented-controller | Segmented control backed by a native radio group. |
| fm-dropdown | @flitsmeister/design-system/fm-dropdown | Animated dropdown backed by a hidden native select for forms and accessibility. |
| fm-wizard | @flitsmeister/design-system/fm-wizard | Wizard stepper with declarative fm-wizard-node configuration. |
| fm-icon | @flitsmeister/design-system/fm-icon | Icon element using the generated Flitsmeister icon registry. |
You can also import the package root to register the main component set:
import '@flitsmeister/design-system'Installer CLI
The package includes a small setup CLI:
npx --package @flitsmeister/design-system design-system-installAfter installing the package in a project:
npm exec design-system-installfm-ui-install is available as an alias for the same CLI.
Version History
| Version | Contents | Repository |
| --- | --- | --- |
| 3.x | Lit web components (fm-button, fm-input, fm-dropdown, and more) | design-system-v2 |
| 2.x | Vue components and design tokens | design-system |
