@maggioli-design-system/styles
v17.4.0
Published
This module contains SCSS and CSS styles used by Maggioli Design System, it also makes available a Tailwind config based on Maggioli design tokens.
Downloads
4,273
Readme
@maggioli-design-system/styles
These are the CSS and Tailwind styles used by components libraries of Magma Design System to use the palette generated by @maggioli-design-system/design-tokens.
Compatibility
Use the version of this package matching the major version of @maggioli-design-system/magma you are using:
| magma | design-tokens | styles |
| :--- | :--- | :--- |
| 1.x (before Magma 2) | 13.x (latest 13.7.2) | 15.x (latest 15.11.1) |
| 2.0.0-alpha.0 to 2.0.0-beta.3 (prereleases) | 14.x | 16.x |
| 2.x and later | >= 15 | >= 17 |
Installation
Install the component via npm by running the following command:
npm i @maggioli-design-system/stylesIntegration
The cascade layers are ordered for Tailwind: reset, vendor, theme, base, components, utilities, and your overrides last. Import the files in this order in your global CSS entry point:
@layer reset, vendor, theme, base, components, utilities, overrides;
@import 'normalize.css' layer(reset);
@import '@fontsource/karla/400.css' layer(vendor);
@import '@fontsource/karla/700.css' layer(vendor);
@import '@fontsource/merriweather/300.css' layer(vendor);
@import '@fontsource/merriweather/400.css' layer(vendor);
@import '@fontsource/merriweather/700.css' layer(vendor);
@import '@fontsource/roboto-mono/400.css' layer(vendor);
@import '@fontsource/roboto/500.css' layer(vendor);
@import '@fontsource/roboto/700.css' layer(vendor);
@import '@fontsource/roboto/900.css' layer(vendor);
@import '@maggioli-design-system/styles/dist/css/reset.css' layer(reset);
@import '@maggioli-design-system/styles/dist/css/globals.css' layer(theme);
@import '@maggioli-design-system/styles/dist/css/colors-rgb.css' layer(theme);
@import '@maggioli-design-system/styles/dist/css/typography.css' layer(theme);
@import '@maggioli-design-system/styles/dist/css/semantic.css' layer(theme);
@import '@maggioli-design-system/styles/dist/css/themes.css' layer(theme);
@import '@maggioli-design-system/styles/dist/css/hydrated.css' layer(base);
@import '@maggioli-design-system/styles/dist/css/transitions.css' layer(base);
@import '@maggioli-design-system/styles/dist/css/animations.css' layer(base);
@import '@maggioli-design-system/styles/dist/css/base.css' layer(base);
/* your Tailwind entry point, if any (see Tailwind below) */
@import './tailwind.css';
@layer overrides {
/* your own overrides of the --magma-* globals and --mds-* component tokens */
}base.css already paints the body with the semantic roles (--magma-surface-default
and --magma-text-default), which is why semantic.css is required.
Semantic colors
Color your UI with the semantic roles, not with raw palette steps: a role follows the
mode, the named theme (data-theme-name) and the high-contrast preference, a palette
step only follows the mode.
<section class="bg-surface-raised text-fg-default border border-border-muted">
<p class="text-fg-muted">Secondary text</p>
</section>.panel {
background: rgb(var(--magma-surface-raised));
color: rgb(var(--magma-text-default));
}The values come from dist/css/semantic.css, the Tailwind utilities from
dist/tailwind/theme.css. Every role of the Tailwind bridge carries its light default as
the fallback of its var() (rgb(var(--magma-surface-default, 242 242 242))): Tailwind
IntelliSense reads a utility's colour only from that literal, so the semantic utilities get
a swatch in the editor. Without semantic.css they paint that light default, in every mode:
the file is still required. The roles, their pairing rules and the Magma 1 -> 2 map are
in the color guide shipped with the components package
(@maggioli-design-system/magma/agents/color.md).
Palette
Colors with tailwind or web components
If you use tailwind or web components, you need the rgb format of the palette, the one imported above:
import '@maggioli-design-system/styles/dist/css/colors-rgb.css';The web components, the Tailwind utilities and the semantic layer read the palette as
custom properties in rgb channel format (rr gg bb). colors-rgb.css holds every group;
the per-group files (colors-rgb-{tones,status,label,brand,default,theme}.css) exist for
a custom setup, and the semantic roles need at least default (the --variant-* accents)
and theme (the --surface-*, --border-* and --text-* families) besides tones and
status.
A raw palette step is right only for a colour that encodes data rather than an
interface role (a label-* category, a brand-* identity). Outside tailwind:
.selector {
color: rgb(var(--label-sky-04));
}Hex colors
If you need just the hex format of colors, you can import them like this:
import '@maggioli-design-system/styles/dist/css/colors-hex-tones.css';
import '@maggioli-design-system/styles/dist/css/colors-hex-status.css';
import '@maggioli-design-system/styles/dist/css/colors-hex-label.css';
import '@maggioli-design-system/styles/dist/css/colors-hex-brand.css';Then you can use them like this:
.selector {
color: var(--tone-neutral-01);
}The hex files are for plain CSS only: they cannot take an alpha, and neither the components nor the semantic roles can read them.
Dark mode
The palette and the semantic roles already flip between light and dark. Pick the mode with a
class on the html tag:
<html class="pref-mode-system"><!-- follows the OS --></html>
<html class="pref-mode-light"><!-- always light --></html>
<html class="pref-mode-dark"><!-- always dark --></html>To let the user choose, use the mds-pref-mode component of
@maggioli-design-system/magma: it writes the class and remembers the choice. Tailwind's
dark: variant follows these classes too (and the OS under pref-mode-system), once the
Magma Tailwind theme is imported. The semantic roles flip without it: keep dark: for a
deliberate per-mode choice, never to correct a colour.
Tailwind
With Tailwind 4, import Magma's theme (palette, typography tokens, semantic colors), its typography utilities and its helpers in your Tailwind entry point, after Tailwind's own theme and utilities (Magma ships its own reset, so Tailwind's preflight is left out):
/* tailwind.css */
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/utilities.css' layer(utilities);
@import '@maggioli-design-system/styles/dist/tailwind/theme.css';
@import '@maggioli-design-system/styles/dist/tailwind/typography.css';
@import '@maggioli-design-system/styles/dist/tailwind/utilities.css';With Tailwind 3, extend the JS preset (the package main) and use
the layers in dist/tailwind3/. The preset does not work with Tailwind 4: its colors are
Tailwind 3 color functions.
module.exports = {
content: ['./src/**/*.{ts,tsx}'],
presets: [require('@maggioli-design-system/styles')],
}Fonts
Magma does not bundle webfonts: the type scale uses Roboto (titles and actions: 500,
700, 900), Karla (UI text: 400, 700), Merriweather (reading text: 300, 400, plus 700
for bold) and Roboto Mono (code: 400). Load them with @fontsource; the weights are
the ones of the scale.
TypeScript
import '@fontsource/karla/400.css'
import '@fontsource/karla/700.css'
import '@fontsource/merriweather/300.css'
import '@fontsource/merriweather/400.css'
import '@fontsource/merriweather/700.css'
import '@fontsource/roboto-mono/400.css'
import '@fontsource/roboto/500.css'
import '@fontsource/roboto/700.css'
import '@fontsource/roboto/900.css'CSS
In CSS use the layer(vendor) imports of the Integration block above.
Fontsource supports variable fonts.
Editor autocomplete
dist/css/tokens.editor.css is the single file to point an editor at. It is generated,
holds every public token exactly once - the scales, motion, palette, semantic layer,
globals and the tokens of every component - with each default resolved to a literal, and
it is ordered: a scale runs from its smallest step up, a palette keeps its ramp order.
One deliberate difference from the real stylesheets: a palette token whose value is a bare
rgb triplet is written as rgb(<triplet>), so an editor can show its actual color. No
editor can preview rgb(var(--label-yellow-03)) - a triplet is not a color, and VS Code's
own color support returns nothing for that shape even when the token is in the same file.
The token itself still holds the triplet, to be read as rgb(var(--label-yellow-03)).
Why a generated file rather than the real stylesheets. Editors discover custom properties
by walking declarations, so the @property registrations that publish the --mds-*
component tokens and the --magma-pref-* switches are invisible to them. And the token
layer ships the same names several times over (the design-tokens output is copied into
this package, and every scale exists both as :root and as an @theme bridge), while
editors dedupe per file rather than across files: pointing at the sources yields four to
eight completion entries per token. One file makes that impossible.
With CSS Var Complete, in .vscode/settings.json:
{
"cssvar.files": [
"node_modules/@maggioli-design-system/styles/dist/css/tokens.editor.css"
],
"cssvar.ignore": [],
"cssvar.disableSort": true
}cssvar.ignore defaults to ["**/node_modules/**"] and is applied as an ignore list over
cssvar.files, so the path above is dropped unless you empty it. cssvar.disableSort
turns off the editor's own alphabetical sort and keeps the file's order, which is the
point of generating it.
Two things stay outside the file: --private-*, a component's internal wiring, declared
in the file that uses it where same-document completion already covers it; and the
handful of tokens Tailwind's own theme publishes (--blur-*, --drop-shadow-*, the
--radius steps we do not override), which Tailwind IntelliSense completes.
Never import this file. It only holds light-theme defaults, so loading it would pin every token at the highest-priority origin and freeze theming; it is wrapped in a query that can never match, which makes an accidental import a no-op.
Do not install vunguyentuan.vscode-css-variables next to it: it sorts alphabetically,
never opens the list by itself and duplicates every entry. To share the setup with the
team, recommend the extensions in .vscode/extensions.json:
{
"recommendations": ["phoenisx.cssvar", "bradlc.vscode-tailwindcss"],
"unwantedRecommendations": ["vunguyentuan.vscode-css-variables"]
}Tailwind classes
The classes complete through Tailwind CSS IntelliSense, which
reads the CSS entry importing Tailwind and Magma's theme (see Tailwind above). It finds
that file on its own, split imports included; only if hovering a class shows nothing, add
"tailwindCSS.experimental.configFile": "<path of that CSS file>" to the settings. Classes
built through functions (clsx, cva, cn) complete once those functions are listed in
"tailwindCSS.classFunctions".
To check it works: hovering p-600 shows 1.5rem = 24px, and bg-surface-default gets a
swatch in the completion list (the semantic utilities carry their light default as a
fallback for that; see Semantic colors).
Two limits, with nothing to configure:
- the utilities are listed alphabetically, whatever the order of the theme:
bg-surface-bisque-*comes beforebg-surface-default; - the class list offers Tailwind's stock spacing steps (
p-1...p-96), not Magma's, and with Magma's themep-1is 0.04px. Write the Magma steps in full (p-600,gap-400): they work and hover with their value, they are just not suggested.
Token data
Two kinds of generated JSON describe this package for tools that read tokens rather than
paint with them (a documentation site, a design tool). They complete the DTCG export of
@maggioli-design-system/design-tokens (its README, "Token data (DTCG)"), and use the
same names: a token is keyed by the custom property it is published as, the
$extensions["it.maggioli.magma"].css of its DTCG entry. To style a page, use the
stylesheets.
| File | Content |
| :--- | :--- |
| dist/dtcg/globals.tokens.json | The globals this package declares: the --magma-* of globals.css, the corner axis, the depth axis of theme.css. Same DTCG 2025.10 shape as design-tokens, aliasing its tokens where the CSS names one (--magma-radius-md is {radius.squircle-md}) |
| dist/dtcg/corner-shape-round.tokens.json, theme-depth-flat.tokens.json | What [data-corner-shape='round'] and :root[data-theme-depth='flat'] change |
| dist/dtcg/magma.resolver.json | The resolver of design-tokens plus these sets: base, globals, then the mode, theme, corner-shape and theme-depth modifiers |
| dist/tailwind/consumption.json | How each token is consumed through Tailwind 4 |
design-tokens' base.tokens.json and globals.tokens.json together hold every global
token of tokens.editor.css. Every group and token of globals.tokens.json has a
$description, and every entry of a cssOnly list a description;
tokens.editor.css shows the same line at the end of the declaration. The resolver points at the files of design-tokens as
../../../design-tokens/dist/dtcg/: the two packages sit side by side in
node_modules/@maggioli-design-system/, as they do in this repository.
consumption.json
"--magma-text-muted": { "theme": "--color-fg-muted", "namespace": "--color", "key": "fg-muted" }tokens:themeis the@themevariable that publishes the token;namespaceandkeysplit it the way Tailwind reads it. Its utilities are<root>-<key>for every root ofnamespaces[namespace].utilities(text-fg-muted,bg-fg-muted,border-fg-muted, ...), its variants the patterns ofnamespaces[namespace].variantswith the key for*(max-tablet:,@md:).aliases: the@themevariables that republish the token whole for the utilities of another namespace.w-*,min-w-*,max-w-*andbasis-*read their own namespace, then spacing, then container, so for the keys both scales have (xs...4xl)--container-xscomes with--width-xs,--max-width-xs, ...:max-w-xsis the 320px container, not the 4px spacing step.shadowed: the roots (or variant patterns) where that class reads another variable, and which one (null: none of the theme).--container-xshas"inline": "--spacing-xs": the logical utilities have no namespace of their own, soinline-xsis 4px; the container isinline-(--container-xs).keywords: the@themevariables that hold a CSS keyword and publish no token.--max-width-none: nonemakesmax-w-noneset no limit, where the spacing step would set0px.namespace: null: no utility reads the variable. Tailwind 4 has no--border-*or--duration-*namespace, soborder-xsdoes not exist andduration-200is Tailwind's own 200ms, not the token: writeborder-(length:--border-xs).property: a value that comes with another token, Tailwind's--<variable>--<property>(--text-size-title-h1--line-height).spacing:--spacing: 0.0025remmultiplies every numeric step, sogap-400is400 x 0.0025rem = 1rem.utilitieslists the roots that take a step,keysthe named ones (xs...4xl,phrase,prose, ...),stepsthe numeric keys the theme publishes explicitly.utilities: every@utilityofdist/tailwind/*.cssand of the design-tokens sheets they import, with where it is defined, what it@applys, the tokens and the Tailwind theme variables it reads (text-title-h1reads Tailwind's--font-weight-black) and its compiled CSS.
The map is generated from Tailwind's own design system (the version is in tailwind),
loaded on the entry point of the Tailwind section (entry): every class and
variant Tailwind can generate is compiled, and nothing is listed by hand. It covers
Tailwind 4 only; the Tailwind 3 preset is legacy.
Dist folder
| Folder | For | Files |
| --- | --- | --- |
| css | everyone | layer.css (the cascade layer order), reset.css, globals.css (the --magma-* globals and the corner axis), colors-rgb.css (+ one colors-rgb-<group>.css per group), typography.css (the non-color tokens: fonts, type sizes, spacing, radius, shadows), semantic.css (the semantic color roles), themes.css (the named themes), hydrated.css, transitions.css, animations.css, base.css |
| css | plain css | colors-hex.css (+ per group), utility-typography.css (the typography-* classes), theme.css (the --depth axis) |
| css | editors only, never import | tokens.editor.css |
| css | tailwind (copied from design-tokens) | tailwind-theme-color.css, tailwind-theme-typography.css |
| tailwind | Tailwind 4 | theme.css (palette, typography tokens, semantic colors; imports semantic.css), typography.css (the text-title-*, text-info-*, ... utilities), utilities.css (focus-bounce, focus-zoom, ...), base.css, reset.css, semantic.css |
| tailwind | tools that read tokens | consumption.json (the Tailwind map, see Token data) |
| dtcg | tools that read tokens | globals.tokens.json, corner-shape-round.tokens.json, theme-depth-flat.tokens.json, magma.resolver.json |
| tailwind3 | Tailwind 3 | base.css, components.css, reset.css, typography.css |
