API Essentials

Merging

Combine multiple Styleframe instances into a single unified configuration. Perfect for composing design systems, sharing configurations across projects, or building modular styling architectures.

Overview

The merge() function allows you to combine multiple Styleframe instances into a single unified instance. This enables composition patterns where you can split your styling configuration into logical modules and merge them together.

Merging is particularly useful for creating shared design system foundations, composing third-party style libraries, or organizing large-scale styling architectures into maintainable modules.

Why merge styleframes?

Merging styleframes helps you:

  • Compose design systems: Build modular design systems by splitting configurations into logical units or themes and combining them.
  • Share configurations: Create reusable style libraries that can be imported and merged into multiple projects.
  • Override and extend: Start with a base configuration and extend it with project-specific customizations.
  • Organize large codebases: Break down complex styling systems into maintainable, focused modules.

Basic Usage

Import the merge() function from Styleframe to combine multiple instances:

import { merge } from 'styleframe';
import base from './base';
import extension from './extension';

const s = merge(base, extension);

export default s;
Good to know: The merge() function returns a new Styleframe instance without modifying the original instances. You can safely reuse the base and extension instances elsewhere.

Merging Multiple Instances

You can merge multiple Styleframe instances at once by passing them as arguments:

import { merge } from 'styleframe';
import colors from './colors';
import typography from './typography';
import spacing from './spacing';

const s = merge(colors, typography, spacing);

export default s;

Merge Behavior

Variables and Declarations

When merging instances, later variable declarations override earlier ones:

import { merge } from 'styleframe';
import base from './base';
import override from './override';

const s = merge(base, override);

export default s;

Utilities, Modifiers, Recipes

Array-based properties like utilities, modifiers, recipes, variables, and children are concatenated:

import { merge } from 'styleframe';
import base from './base';
import extension from './extension';

const s = merge(base, extension);

export default s;
Pro tip: When defining utilities or recipes with the same name across multiple instances, they will all be included in the output. If you need to override rather than extend, use declaration-based approaches.

Themes

Themes are merged by name. When two instances define themes with the same name, they are merged together rather than duplicated. This allows you to compose theme definitions across multiple modules.

  • Array-based properties like children within themes are concatenated
  • When multiple instances define the same variable within the same theme, later instances override earlier ones
import { merge } from 'styleframe';
import base from './base';
import extension from './extension';

const s = merge(base, extension);

export default s;
Good to know: When themes with the same name are merged, their containers are merged using the same rules as root-level merging: variables override by name, and array properties (utilities, modifiers, recipes) are concatenated.

Examples

Shared Design System

Create a shared design system foundation that can be used across multiple projects:

import { styleframe } from 'styleframe';

export function createBase() {
    const s = styleframe();
    const { variable } = s;

    // Color palette
    variable('color--white', '#ffffff');
    variable('color--black', '#000000');
    variable('color--primary', '#3b82f6');
    variable('color--secondary', '#64748b');

    // Typography
    variable('font--sans', 'Inter, system-ui, sans-serif');
    variable('font--mono', 'Fira Code, monospace');

    // Spacing scale
    variable('spacing--1', '0.25rem');
    variable('spacing--2', '0.5rem');
    variable('spacing--3', '0.75rem');
    variable('spacing--4', '1rem');

    return s;
}

Component Library Integration

Merge third-party component library styles with your custom configuration:

import { merge } from 'styleframe';
import { createUILibrary } from '@company/ui-library';
import custom from './custom';

const library = createUILibrary();

// Merge with component library
const s = merge(library, custom);

// Override library variables
const { variable } = s;
variable('ui--button-color', '#7c3aed');

export default s;

Composing Multiple Themes

You can merge instances that define different themes. Each theme is preserved independently:

import { styleframe, merge } from 'styleframe';
import darkTheme from './dark-theme';
import highContrastTheme from './high-contrast-theme';

const defaultTheme = styleframe();

defaultTheme.variable('color--text', '#ffffff');

export default merge(defaultTheme, darkTheme, highContrastTheme);

Layer-Based Architecture

Organize your styles into architectural layers:

import { merge } from 'styleframe';
import tokens from './tokens';
import semantic from './semantic';
import components from './components';

const s = merge(tokens, semantic, components);

export default s;

Feature Flags

Enable optional styling features through merging:

import { merge } from 'styleframe';
import base from './base';
import animations from './animations';
import darkMode from './dark-mode';

// Conditionally merge features
const features = {
    animations: process.env.ENABLE_ANIMATIONS === 'true',
    darkMode: process.env.ENABLE_DARK_MODE === 'true',
};

const instancesToMerge = [base];
if (features.animations) instancesToMerge.push(animations);
if (features.darkMode) instancesToMerge.push(darkMode);

const s = merge(...instancesToMerge);

export default s;

Best Practices

  • Keep modules focused: Each Styleframe instance should represent a logical unit (colors, typography, components) for better maintainability.
  • Merge in order of specificity: Merge from general to specific so that later merges can override earlier ones when needed.
  • Document merge patterns: Clearly document which instances are meant to be merged and in what order for team consistency.
  • Avoid circular dependencies: Don't create circular references between merged instances as this can lead to unexpected behavior.
  • Use factory functions: Wrap Styleframe instances in factory functions to enable parameterization and reuse.

Type Safety

The merge function maintains full TypeScript type safety:

import { styleframe } from 'styleframe';

const base = styleframe();

base.variable('color--primary', '#3b82f6');

export default base;
Pro tip: TypeScript will correctly infer types across merged instances, enabling autocomplete and type checking for variables and references.

FAQ