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

@ly-sys/layout

v1.0.3

Published

React layout primitives system featuring class deduplication, responsive props, and a candidate protocol for micro-frontends.

Readme

@ly-sys/layout

React layout primitives system featuring class deduplication, responsive props, and a candidate protocol for micro-frontends.

npm version package manager bundle size

The @ly-sys/layout package serves as the unified production entry point (facade) of the entire layout ecosystem. It aggregates and re-exports the core layout engine, high-performance primitive React components, React context providers, and the MFE candidate protocol under a single public interface.


Key Features

  • Tree-shaking Out of the Box: Re-exports sub-packages cleanly. Modern bundlers (Vite, Rsbuild, Webpack) will only bundle the components and code you actively use.
  • Sub-microsecond Resolution: Features a high-performance class deduplication compiler and a 500-entry LRU cache, keeping runtime overhead near-zero.
  • Zero Styling Collisions: Works entirely through native CSS Cascade Layers (@layer layout), allowing complete compatibility and deterministic styling alongside Tailwind CSS or custom style rules.
  • Decoupled MFE Protocol: Enables Server-Side Rendering (SSR) safe candidate-based style extraction for federated micro-frontend architectures.
  • Polymorphism: Native support for the asChild property (via @ly-sys/react-slot), allowing you to render any layout primitive as a semantic HTML tag or custom React component.

Monorepo Architecture

This package aggregates the following modular sub-packages:

| Package | Purpose | Bundle Size (Minified) | |:---------------------------------------------------------------------------------------|:-------------------------------------------------------------------|:-----------------------| | @ly-sys/layout-engine | Parsers, prefixer, class resolver, and LRU cache. | ~3 KB | | @ly-sys/layout-primitives | React elements: Flex, Grid, HStack, VStack, etc. | ~5 KB | | @ly-sys/layout-react | LayoutProvider, useLayout context hook, and engine decorators. | ~3 KB | | @ly-sys/layout-protocol | Versioned CandidateCollector and types for style federation. | < 1 KB | | @ly-sys/react-slot | Polymorphic Slot and Slottable utility components. | ~1 KB |


Installation

Install the facade package via your package manager of choice:

pnpm add @ly-sys/layout
# or
npm install @ly-sys/layout
# or
yarn add @ly-sys/layout

Quick Start

1. Application Setup

Wrap your application in LayoutProvider to supply the layout engine:

import React from "react";
import {createLayoutEngine, LayoutProvider, HStack, Flex} from "@ly-sys/layout";

// 1. Initialize the layout engine with default configuration (prefix: "ly-sys")
const engine = createLayoutEngine({
    breakpoints: ["base", "sm", "md", "lg", "xl"] as const
});

export function App() {
    return (
        <LayoutProvider engine={engine}>
            <HStack gap={4} p={4} justify="space-between" align="center">
                <h1>Dashboard</h1>
                <Flex gap={2}>
                    <button type="button" className="btn-secondary">Cancel</button>
                    <button type="button" className="btn-primary">Save Changes</button>
                </Flex>
            </HStack>
        </LayoutProvider>
    );
}

2. Import Styles in Global CSS

Import Tailwind and the layout precompiled styles in your main CSS file:

/* src/index.css */
@import "tailwindcss";
@import "@ly-sys/layout/styles.css";

[!IMPORTANT] Custom Prefixes and PostCSS Configuration

If you configure a custom prefix (e.g. libPrefix: "ly") or custom breakpoints, the precompiled styles will not match the class names generated by the engine. In this case, you must compile the stylesheet using the PostCSS plugin from @ly-sys/layout-css:

  1. Create or update your postcss.config.js:
    import {layoutPostcssPlugin} from "@ly-sys/layout-css";
    
    export default {
        plugins: [
            layoutPostcssPlugin({
                prefix: "ly", // must match libPrefix
                // breakpoints: { ... } // must match engine config
            })
        ]
    };
  2. Replace the @import statement with the @ly-sys-layout; directive:
    @import "tailwindcss";
    @ly-sys-layout;

If you do not configure a custom prefix (meaning you keep the default "ly-sys"), the PostCSS plugin is not required, and you can simply import @ly-sys/layout/styles.css directly.


Core Layout Primitives

The package exports 8 structural components. All of them support responsive props (e.g., gap={{ base: 2, md: 4 }}), native HTML element properties, and polymorphic rendering via asChild.

Flex

A standard CSS Flexbox container.

  • Props:
    • direction: ResponsiveValue<"row" | "column" | "row-reverse" | "column-reverse">
    • wrap: ResponsiveValue<"wrap" | "nowrap" | "wrap-reverse">
    • align: ResponsiveValue<"flex-start" | "flex-end" | "center" | "baseline" | "stretch">
    • justify: ResponsiveValue<"flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly">
    • grow: ResponsiveValue<number | string>
    • shrink: ResponsiveValue<number | string>
    • basis: ResponsiveValue<string | number>

HStack and VStack

Directional Flexbox wrappers representing Horizontal and Vertical stacks.

  • Props: Inherit all Flex properties except direction (which is locked to "row" and "column" respectively).

Grid

A CSS Grid container.

  • Props:
    • columns: ResponsiveValue<number>
    • minChildWidth: ResponsiveValue<string> (creates an adaptive grid using CSS minmax)
    • rowGap / columnGap: ResponsiveValue<number | string>

[!WARNING] By default, columns and minChildWidth are mutually exclusive. Attempting to supply both simultaneously will throw a development-mode warning/error unless validationMode is configured as "Permissive".

GridItem

A child component within a Grid container to define column and row span/alignment.

  • Props:
    • colSpan / rowSpan: ResponsiveValue<number | "full">
    • colStart / colEnd / rowStart / rowEnd: ResponsiveValue<number | string>

Container

A centered layout container with a maximum width boundary.

  • Props:
    • maxWidth: ResponsiveValue<"xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "7xl" | "full" | "min" | "max" | "fit">
    • centerContent: ResponsiveValue<"auto" | "none"> (defaults to "auto" which applies margin-inline: auto)

Center

A container that centers its children vertically and horizontally.

  • Props:
    • inline: ResponsiveValue<boolean> (renders as inline-flex instead of flex)

Spacer

A flexible spacer that expands to fill available space within a Flexbox container.

  • Props: None (renders a div or target element with flex: 1).

Micro-Frontend Candidate Protocol

In distributed frontends (such as Webpack Module Federation or Rspack), loading duplicate CSS bundles causes size inflation. @ly-sys/layout resolves this by decoupling style generation.

Remotes (Micro-Frontends) do not ship with CSS. Instead, they register the styling "candidates" they need at runtime into a shared CandidateCollector. The Host shell consolidates these candidates and fetches or injects only the critical CSS required.

Server-Side Rendering (SSR) Usage

import {createLayoutEngine, LayoutProvider} from "@ly-sys/layout";
import {createCandidateCollector} from "@ly-sys/layout/protocol";
import ReactDOMServer from "react-dom/server";

// 1. Create a collector instance per request
const collector = createCandidateCollector();
const engine = createLayoutEngine({libPrefix: "ly"});

// 2. Render application
const html = ReactDOMServer.renderToString(
    <LayoutProvider engine={engine} collector={collector}>
        <App/>
    </LayoutProvider>
);

// 3. Flush the captured styling candidates
const batch = collector.flush();
console.log(batch.candidates);
// Output: [{ utility: "flex" }, { utility: "gap-4", breakpoint: "md" }]

// 4. Send HTML and the styling batch to the Host shell

Modularizing Critical & Deferred CSS via ?inline

Instead of writing CSS in plain text within your JavaScript/TypeScript files (which lacks autocomplete, syntax validation, and Tailwind @apply support), you can write real .css files and import them as strings using the ?inline parameter query supported by modern bundlers (like Rsbuild, Rspack, Vite, or Webpack):

  1. Define the module type in your typescript configuration (e.g. env.d.ts):
    declare module "*.css?inline" {
        const content: string;
        export default content;
    }
  2. Import the CSS directly in your component or aggregator file:
    import buttonCss from "./button.critical.css?inline";
  3. Pass the imported string to the collector:
    collector.registerCandidates({
        candidates: [],
        rawCSS: {
            critical: buttonCss,
        }
    }, "my-component-id");

Reference Documentation

For deeper details on design tokens, integration architecture, and federation logs, refer to the guides in the source repository:


License

MIT. See the root LICENSE file.