Releases

v6.0.0

Breakpoints become ranges with exact range-syntax queries, helpers to write them by hand, container queries on the same scale, and a layout grid from theme.layout. (#344)

Added

  • Range-syntax queries - every generated query is @media (width >= <start>). A breakpoint that starts at 0 (xs: '0px') is the base: it writes no query and holds until the next one.
  • Named breakpoints everywhere - object values take breakpoint names, each from its size up ({ xs: 'none', md: 'block' }); arrays map by position onto the breakpoints in declared order. css() takes the same objects and arrays.
  • Query helpers - createMediaHelpers(breakpoints) returns up, down, only, between and not, which return exact @media rules: only('md') is @media (840px <= width < 1200px), not('md') is @media (width < 840px), (width >= 1200px). docs
  • Container queries - cq<Name> keys (p={{ xs: 2, cqSm: 4 }}) write @container (width >= 600px) after the media blocks; createContainerQueries(breakpoints) gives the same helpers as @container rules, or for a named container with containerQueries('sidebar').up(400). containerType and containerName style props in layout. docs
  • Layout grid - the layout prop writes theme.layout's content tokens per breakpoint, in two parts that compose: layoutFrame - the page frame: the full width of its parent (border-box) with the margin, capped by a centred max width in fixed mode, so a frame that is a grid or flex item spans its parent rather than its content - and layoutGrid - the column tracks and the gutter on top. The gutter is the element's own columnGap or gap where it sets one - single, by name or as an array, from each breakpoint up - and the theme's elsewhere, so column-gap has one source. layoutGridStyles(theme, value, gap) writes both in a style function. A field in the value replaces the theme's at every breakpoint ({ maxWidth: '1280px' }); an entry under a breakpoint name replaces it from that breakpoint up, mobile-first like every responsive prop ({ lg: { columns: 16 } }). The layout owns the tracks, inline padding and max width it writes.
  • span - how many columns of a grid an element takes, responsive: grid-column: span N, or span="full" (grid-column: 1 / -1) for the whole row whatever the column count. Part of the all preset.
  • createMediaQuery, breakpointQueries, responsiveQueries, containerKey and the Breakpoints, QueryHelpers, ContainerQueries, LayoutGridProps, LayoutFrameProps, LayoutGridGap types.

Changed

  • Media blocks follow breakpoint order, then container blocks; they were sorted by the text of the query. A parser follows the theme's breakpoints when the theme changes.
  • A number breakpoint gets px (768 is 768px).

BREAKING CHANGES

  • Generated media queries are range syntax. @media screen and (min-width: 40em) is now @media (width >= 40em): the same widths, without the screen media type, so the queries also apply when printing. Range syntax needs Chrome 104, Safari 16.4 or Firefox 63 and later; older browsers ignore the blocks. Migrate: nothing in code; update snapshot tests of generated CSS, and drop support for older browsers.
  • A breakpoint that starts at 0 is the base. A scale such as { xs: '0px', sm: '600px' } writes no query for xs, and arrays map position 0 onto it. A 0 breakpoint used to write (min-width: 0).
  • _ is no longer a typed responsive key. At runtime a key that is not a breakpoint still falls back to the base value. Migrate: use your base breakpoint's name (xs).

Packaging

Upgrade

  • From 5.x: see the breaking changes - styles are the same on screen in supported browsers.

v5.8.3

Maintenance release. No public API, behavior, or emitted-output changes - comments and docs only. No scale, prop, or generated style changed.

v5.8.2

Maintenance release - build tooling only. No public API, behavior, or type changes. (#328)

Packaging

  • The workspace moved its formatter from Prettier to oxfmt, which wraps multi-line union types onto leading-pipe lines. That reformatted the ObjectOrArray declaration in src/types.ts; the type it describes is unchanged. No source, runtime, peer, or dev dependency changes.
  • typescript moves to ~7.0.2. It is a dev dependency here, used to typecheck and emit; the emitted output is unchanged.

v5.8.1

Maintenance release - dependency refresh only. No public API or behavior changes. (#280)

Packaging

  • Dev-dependency bumps: eslint ^10.7.0 → ^10.8.0, globals ^17.7.0 → ^17.9.0, tsdown ^0.22.7 → ^0.22.14. No runtime or peer dependency changes.

v5.8.0

Scale flex and grid gaps on space, add aspectRatio to layout, and add whiteSpace and textOverflow to typography - six props the original styled-system never shipped. Additive and backward-compatible. (#313)

Added

  • gap, rowGap, columnGap - resolve against theme.space, the same scale (and default scale) as margins and paddings, and compose into space alongside margin and padding. Upstream only ever scaled the grid-prefixed gridGap/gridRowGap/gridColumnGap, so flex gaps had to be hand-wired through system(); that custom mapping can go. Typed via GapProps/RowGapProps/ColumnGapProps, composed into SpaceProps. The gap parser is also exported standalone, alongside margin and padding.
  • aspectRatio - maps straight to CSS aspect-ratio (no theme scale). Upstream's last release predates the property, so this too was hand-wired; that mapping can go as well. Typed via AspectRatioProps, composed into LayoutProps and re-exported from the /layout subpath.
  • whiteSpace and textOverflow - map straight to CSS white-space and text-overflow (no theme scale). Together with overflow from layout they make text truncation expressible in props alone, instead of dropping into raw CSS for the one declaration the parser was missing. Typed via WhiteSpaceProps/TextOverflowProps, composed into TypographyProps and re-exported from the /typography subpath, with both parsers also exported standalone alongside textAlign and textTransform.
  • All support responsive array and breakpoint-object values, and are filtered from the DOM automatically - none needs adding to a shouldForwardProp blocklist, since props derives from all.propNames.
  • Docs: Space props reference · Layout props reference · Typography props reference · prop/scale table · theme specification.

Upgrade

  • From 5.7.x: drop-in, no code changes. Components that hand-wired gap or aspectRatio through system() can delete that mapping and inherit the props from space/layout.

Packaging

  • No runtime or peer dependency changes.

v5.7.1

Maintenance release - dependency refresh only. No public API or behavior changes.

Packaging

  • Dev-dependency bumps: tsdown ^0.22.4 → ^0.22.7. No runtime or peer dependency changes.

v5.7.0

Extend the typography style function with seven text-styling props the original styled-system never shipped - first-class, theme-aware props alongside textAlign and fontStyle. Additive and backward-compatible. (#258, #259)

Added

  • textTransform, textAlignLast, textDecoration, textDecorationLine, textDecorationStyle, textDecorationThickness - raw CSS pass-through props, each exported standalone and folded into TypographyProps; auto-covered by should-forward-prop.
  • textDecorationColor - resolves against the colors theme scale (like borderColor), in both the parser and the css() object-notation path.
  • Docs: Typography props reference · migration guide.

Upgrade

  • From 5.6.x: drop-in, no code changes.

Packaging

  • No runtime or peer dependency changes (dev-only tooling bumps).

v5.6.1

Changes

  • Raise csstype runtime dependency floor ^3.1.3 → ^3.2.3 (newer CSS property typings).
  • Repository moved to soroush-tech/core.

No public type or API changes.

v5.6.0

Completes props-facing type parity with @types/styled-system - closes the drop-in gaps found migrating a real styled-system v5 monorepo (#215). Recommended upgrade from 5.5.0.

Fixed

  • themeGet matches @types/styled-system__theme-get verbatim - (path: string | Array<string | number>, fallback?: any) => (props: any) => any. No more unknown returns (TS2339 on destructuring) and no more rejecting component prop interfaces (TS2345). Array paths now also resolve as nested lookups (themeGet(['colors','primary'])), fixing a latent bug the upstream runtime never handled.
  • Public type surface loosened to any to match upstream - Props/Theme index signatures, Transform/StyleFn params, StyleObject, ConfigStyle.defaultScale, ThemeValue. Strict unknown/Props no longer breaks CSS-in-JS interpolation or arbitrary component props.
  • boxShadow / textShadow / fontWeight accept string | number - resolves against both object-keyed ({ sm, md }) and array-indexed ([...]) theme scales; restores array-index support that had been dropped.

Added

  • Upstream type-name aliases for drop-in imports: styleFn, Config, ConfigFunction, VariantArgs, LowLevelStyleFunctionArguments.

Changed

  • @emotion/is-prop-valid is now an optional peer dependency (peerDependenciesMeta) - no more missing peer warning for consumers who don't use the ./should-forward-prop subpath.
  • css exports CSSObject (was CssObject) to match @styled-system/css's actual name.

Upgrade

  • From 5.5.0: drop-in, no code changes. This makes the scoped-package migration described in #215 package.json-only.
  • 5.5.0 and earlier are deprecated (see notes).

v5.5.0

Type-resolution fix for classic-node consumers, plus a parity correction to the package root. Recommended upgrade from 5.4.0 (now deprecated).

Fixed

  • Subpath types now resolve under classic moduleResolution: "node" (node10). Classic resolution doesn't read a package's exports map, so tsc couldn't find types for styled-system/theme-get, styled-system/prop-types, styled-system/core, etc. (TS2307), even though runtime worked. Added a typesVersions map (in publishConfig) pointing every subpath at its .d.cts - the mechanism classic node honors. No consumer changes required (no paths, no declare module, no moduleResolution change). Modern resolution (node16/nodenext/bundler) continues to resolve via exports.

Removed (parity)

  • The package root no longer exports themeGet or a default. The original styled-system main package exports neither - both only ever lived in the standalone @styled-system/theme-get. themeGet remains available (named + default) from the ./theme-get subpath: import themeGet from '@soroush.tech/styled-system/theme-get'.

Docs

  • Drop-in guidance now aliases the main styled-system name and imports satellites as subpaths off it - import themeGet from 'styled-system/theme-get' - which resolves through this package's exports (and typesVersions for node10).

Upgrade notes

  • From 5.4.0: drop-in. If you imported themeGet from the package root (5.3.0/5.4.0 only), switch to @soroush.tech/styled-system/theme-get.
  • 5.4.0 is deprecated (root default divergence + the node10 type gap fixed here).

v5.4.0

Finishes drop-in parity with the styled-system@5 ecosystem - head-to-head is now 16/16 with the original packages. Builds on 5.3.0 (per-property prop types + Transform fix).

Added

  • ./prop-types subpath mirroring @styled-system/prop-types: propType, createPropTypes, and a default per-group map (space, color, layout, typography, flexbox, border, background, position, grid, shadow, buttonStyle, textStyle, colorStyle) built from each parser's propNames. Spread it onto a component: Box.propTypes = { ...propTypes.space, ...propTypes.color }.
  • themeGet as the package-root default export (in addition to the named export added in 5.3.0). A package-manager alias can only bind @styled-system/theme-get → the package root, so import themeGet from '@styled-system/theme-get' previously resolved to undefined; both import { themeGet } and import themeGet now work under the alias.

Notes

  • New optional peer dependency prop-types (^15.8.1) - required only if you import ./prop-types. It stays external in the build (~1.6 KB ESM), and the public types use a structural validator so consumers aren't forced to install @types/prop-types.
  • No runtime behavior change to existing exports; fully backward compatible.

v5.3.0

Closes the remaining gaps for a true drop-in replacement of styled-system@5 + @types/styled-system (#213).

Added

  • Per-property prop types. Every atomic interface from @types/styled-system is now exported (WidthProps, HeightProps, OverflowProps, TopProps, ZIndexProps, AlignItemsProps, JustifyContentProps, FlexProps, FontSizeProps, FontWeightProps, LineHeightProps, TextAlignProps, TextColorProps, BackgroundColorProps, OpacityProps, BorderWidthProps, BorderStyleProps, BorderColorProps, BorderRadiusProps, BorderTop/Right/Bottom/LeftProps, BoxShadowProps, TextShadowProps, TextStyleProps, and the full Grid* and Background* families).
  • Each grouped interface (LayoutProps, FlexboxProps, BorderProps, ...) now composes its atomic interfaces via extends, matching upstream's structure.
  • All types are re-exported from their matching subpath (./layout, ./position, ./border, ...) as well as the main entry.
  • themeGet is now also available as a named export from the main entry: import { themeGet } from '@soroush.tech/styled-system'.

Changed

  • Transform is no longer unknown. It now matches @styled-system/core's (value: any, scale?: any) => any, so consumer transforms like (val) => MAP[val] ?? MAP.center compile without casts (no more TS2538).

Notes

  • boxShadow, textShadow, and fontWeight remain intentionally widened over upstream to also accept string theme keys.
  • No runtime behavior changes; fully backward compatible.
  • Still deferred: a @styled-system/prop-types equivalent (issue #213 §3).

@soroush.tech/styled-system v5.2.0

The first release of our ground-up rewrite of styled-system - a maintained, first-class-TypeScript implementation of responsive, theme-aware style props for CSS-in-JS.

It's a drop-in replacement for the styled-system v5 runtime: the root export surface matches upstream verbatim, so existing code keeps working, while everything underneath is new.

Highlights

  • Complete TypeScript rewrite - the entire style engine (system, compose, createParser, createStyleFunction, get) was rebuilt from scratch with first-class types. Every style function carries its own typed prop interface (SpaceProps, ColorProps, LayoutProps, ...).
  • Ships its own types - no more @types/styled-system. Types are theme-scale-aware and bundled in the package.
  • Dual ESM + CJS build with per-category subpath exports (/space, /color, /layout, /css, /theme-get, /props, /should-forward-prop, ...) mirroring the original @styled-system/* packages.
  • Tree-shakeable ("sideEffects": false), zero runtime CSS-in-JS dependency - bring your own Emotion or styled-components.
  • 100% test coverage, MIT licensed.

⚠️ Breaking change: propTypes dropped

Style functions no longer expose a propTypes property, and there is no prop-types companion package. The old @styled-system/prop-types is out of scope for this rewrite, and React 19 removed propTypes for function components entirely.

Migrate by using TypeScript for prop typing - each style function already provides a typed prop interface, so you get compile-time checking instead of runtime propTypes:

import { space, type SpaceProps } from '@soroush.tech/styled-system'

See the TypeScript guide.

Install

npm install @soroush.tech/styled-system

Existing styled-system users can swap with no code changes via a package-manager alias:

"dependencies": {
  "styled-system": "npm:@soroush.tech/styled-system@^5"
}

@emotion/is-prop-valid (^1.4.0) is a peer dependency, needed only if you import the should-forward-prop subpath.