Theming

Theming is where many integrations go wrong: a working control gets restyled through random selectors, hard-coded colors or direct shadow DOM assumptions. Monster already gives you a safer contract through tokens, PropertyStyleSheet and stable ::part surfaces.

Tutorial Goal

Style controls so they match your product without fighting the component boundary

This tutorial focuses on the practical styling stack: global properties, paired color tokens, public parts and the line between safe theme overrides and brittle internal DOM hacks.

Before You Start

Use this after a control already works

Theming is not the first step. A control should already render and behave correctly before you start changing tokens, parts or variants.

Know the token pairs

If you are not yet comfortable with paired foreground and background tokens, review Color Foundations first.

The Styling Stack

PropertyStyleSheet

The global token layer defines typography, spacing, radius, paired foreground and background colors and theme primitives. Start there before styling any individual control.

::part surfaces

A control may own Shadow DOM internally, but it can still expose stable parts such as control, button or selection for external styling.

Start with Property Defaults

1. Load the property layer once

The property stylesheet is the base contract for tokens. It should be present before you start talking about control colors or spacing.

import { PropertyStyleSheet } from "@schukai/monster/source/components/stylesheet/property.mjs";

document.adoptedStyleSheets = [PropertyStyleSheet];

2. Override tokens, not random component internals

Global tokens let you shift the system consistently. Use them when you want a theme change across many controls.

:root {
    --monster-border-radius: 0;
    --monster-space-5: 18px;
    --monster-bg-color-primary-2: var(--monster-color-seashell-2);
    --monster-color-primary-2: var(--monster-color-seashell-6);
}

Always style color pairs together

If you set a text-bearing background token, set the matching foreground token as well. --monster-bg-color-secondary-2 belongs with --monster-color-secondary-2. The same rule applies to primary, tertiary, success, warning and destructive pairs.

Style a Control Through Public Parts

Once the global base is in place, use ::part for component-specific accents. That keeps the styling contract explicit even when the control renders through Shadow DOM.

monster-toggle-switch::part(control) {
    border: 1px solid var(--monster-color-border-secondary-2);
    border-radius: var(--monster-border-radius);
    background: var(--monster-bg-color-primary-1);
    color: var(--monster-color-primary-1);
}

Theme Contract Example

This example shows the split clearly: system tokens define the shell, and ::part(control) adds a control-specific border without reaching into internal DOM.

Stable public surface

The toggle still behaves like the same control. Styling is additive, not a rewrite of internal behavior.

Use this stack in order

Properties -> Parts -> States

1. Set global token defaults. 2. Target stable parts for control-specific adjustments. 3. Keep states and values on the control API, not in CSS-only hacks.

What Stays Outside the Shadow Root

Theme tokens

Colors, spacing, radius and typography belong outside so they can be shared across the full interface.

Public parts

Parts are the stable bridge between outer styling and inner structure. They are the right place for targeted control styling.

Component state

Value, disabled state, validation and selected options stay on the component API. CSS may reflect them, but should not invent them.

Layout composition

Surrounding grid, stack and container rules belong in the page layout, not hidden in a control-specific stylesheet.

Common Styling Mistakes

Styling internal shadow DOM selectors directly

If your CSS depends on private markup inside the component, any internal refactor becomes a breaking change.

Using a background token without the matching foreground token

This breaks contrast and dark mode consistency immediately. Use the paired bg-color and color tokens together.

Hard-coding hex colors or ad-hoc radii

That bypasses the Monster system and makes theme changes harder instead of easier.

From Tutorial to Real Control

Theming to Toggle Switch

Inspect a control with clear parts and state-driven visuals

ToggleSwitch is a strong theming example because the public ::part surfaces and the on/off states are easy to read. You can see quickly which styling belongs in token overrides and which belongs in a part-level accent.

Theming to Button

Compare token-driven defaults with variant classes

Button shows the other half of the theming story: global properties define the baseline, while public classes and state variants shape the final appearance. It is a good place to verify that your token changes still produce coherent primary, secondary and outline variants.

Where to Go Next

Read the color foundations

Continue there when you want the full token model, including paired foreground and background colors.

Inspect a production control

Open Select or Toggle Switch and inspect the parts/API together with the live examples.

The current width of the area is too small to display the content correctly.