typestyles
packages/typestyles/CHANGELOG.md
0.23.0
Minor Changes
- #202
42fb13dThanks @dbanksdesign! - Add typedvarsonstyles.override()and symmetric top-levelvarson component configs. Recipes expose arecipe.varsref tree; theme consumers override with the same logical keys onstyles.override({ vars }).c.vars()auto-stamps override typing metadata — passvars: vin the recipe return (no duplicate definition object).
Patch Changes
- #205
9806e53Thanks @dbanksdesign! - Update README
0.22.0
Minor Changes
- #199
c0642fdThanks @dbanksdesign! - Add typedvarsonstyles.override()and symmetric top-levelvarson component configs. Recipes expose arecipe.varsref tree; theme consumers override with the same logical keys onstyles.override({ vars }).c.vars()auto-stamps override typing metadata — passvars: vin the recipe return (no duplicate definition object).
0.21.0
Minor Changes
- #196
c749aafThanks @dbanksdesign! - Addsupports()andstyles.supports()helpers for typed@supportsfeature-query keys, mirroring thecontainer()pattern. Object forms accept camelCase declaration features (joined withand); string forms pass through raw conditions includingnotandselector(). Raise main-entry gzip budget (+200 B) for the new helper runtime.
Patch Changes
- #197
bf6614fThanks @dbanksdesign! - Fix slot+variant components not emittingc.vars()default assignments when bothslotsand dimensionedvariantsare used together.
0.20.0
Minor Changes
- #192
51a78c0Thanks @dbanksdesign! - Add relative color syntax helpers (color.from,rgbFrom,oklchFrom) and OKLCH manipulation sugar (lighten,darken,saturate,desaturate,rotate,grayscale) ontypestyles/color, plus trigonometric/exponential CSS math helpers (sin,cos,tan,atan2,pow,sqrt,hypot) on the main entry.
Patch Changes
- #195
40ca798Thanks @dbanksdesign! - Fix slot-based components not emittingc.vars()default assignments when values reference other CSS custom properties.
0.19.0
Minor Changes
- #188
0d33463Thanks @dbanksdesign! - Add syntax-typed design tokens viatokens.declare():SyntaxRef<'<color>'>(and other CSS syntaxes) for compile-time ref compatibility increate({ decl })andstyles(), while plaintokens.create()withoutdeclarestays unchanged.
Patch Changes
- #190
046d084Thanks @dbanksdesign! - Fixtokens.use()when passed atokens.declare()handle — rebuild proxies from declared schema paths instead of resolving an empty namespace. Raise main-entry gzip budget (+200 B) for syntax-typed token runtime.
0.18.1
Patch Changes
- #186
db05b28Thanks @dbanksdesign! - Default componentc.var(),c.vars(), and.declare()@propertyregistrations toinherits: true, matchingtokens.declare()behavior. Explicitinherits: falseoverrides are preserved.
0.18.0
Minor Changes
#185
06de0f6Thanks @dbanksdesign! - AddmediaQueriesconstant export with ready-to-use@media (...)strings forprefers-reduced-motion,prefers-contrast, and hover/pointer capability queries (hover,any-hover,pointer,any-pointer), grouped by feature. Drop a leaf value (e.g.mediaQueries.prefersReducedMotion.reduce) directly into astyles.class,styles.override, orstyles.component(nested insidebaseor a variant's style) object as a key.#184
00cf163Thanks @dbanksdesign! - Addtypestyles/testingsubpath export (resetAll,onAfterReset,createTestHarness) for coordinating test-state reset across design systems built on typestyles.
Patch Changes
- #182
748d530Thanks @copilot-swe-agent! - Defaulttokens.declare()typed schema leaves toinherits: truefor@propertyregistration, including directatPropertypreset leaves, while preserving explicitinherits: falseoverrides.
0.17.0
Minor Changes
#176
939a158Thanks @dbanksdesign! - ExportcloneThemeValuesandmergeThemeOverridesfor ref-aware theme override merging (Issue #168)#180
1338c06Thanks @dbanksdesign! - ExportModeAwareTokenLeaf,ModeAwareTokenObject, andTokenRefTree; preserve input shape intokens.create()return types (nested namespaces, mode-aware leaves, plain scalars).#178
eeb4253Thanks @dbanksdesign! - Addstyles.breakpoint()andstyles.media()helpers that build viewport@mediakeys from configuredbreakpoints, matching thecontainer()+atRuleBlockpattern for container queries.
Patch Changes
#175
f96b133Thanks @dbanksdesign! - Discriminate slot+variantstyles.component()configs so callback recipes infer per-slot return types without casts (Issue #166)#179
200359eThanks @dbanksdesign! - ExportOverrideConfigForandMultiSlotReturnso design-system consumers can inferstyles.override()config shapes from recipe return types (Issue #160)#177
3a8feb2Thanks @dbanksdesign! - Fixconditionstype-checking instyles.override()configs and type mode-aware{ light, dark }property values in override and recipe styles (Issue #169)#173
ed956d8Thanks @dbanksdesign! - FixCSSPropertiesassignability forc.vars()computed custom-property keys in nested selectors (Issue #167)
0.16.0
Minor Changes
- #164
aebb0c0Thanks @dbanksdesign! - Add mode-aware token leaves ({ light, dark }) ontokens.create()andtokens.createTheme()whencolorModesis configured. Color/image-compatible values compile tolight-dark()on custom properties; incompatible values (e.g. shadow shorthands) emit dark-mode override rules.createThemeaccepts structuredcolorMode: { light, dark }patches and emitscolor-scheme: light darkon theme surfaces. Preset mode layers (tokens.colorMode.*) are passed viamodesinstead ofcolorMode. Documentation updated in Tokens and Theming patterns guides.
0.15.0
Minor Changes
- #161
7d24e42Thanks @dbanksdesign! - Add conditionalstyles.override()blocks (conditions+ThemeCondition) andcolorModesconfig for{ light, dark }property values that compile tolight-dark()on color/image properties. ExportcolorModesconstant (['light', 'dark']) forcreateStyles/createTypeStyles.
0.14.0
Minor Changes
#157
f163b08Thanks @dbanksdesign! - AddatPropertypresets (atProperty.color,atProperty.angle, etc.) for spreadable@propertyregistration metadata across tokens, components, styles, andtypestyles/css.Add
typestyles/csssubpath withcss.atProperty,css.customProperty,css.customProperties, andcss.varfor exact-name CSS custom property control.Add
styles.property.declare/styles.property.setandctx.vars.declare/ctx.var.declarefor split@propertyregistration and value assignment. Shorthandstyles.property(id, options?)andctx.vars(definitions)behavior is unchanged.Export
PropertyRegistration,PropertyRef, andPropertyOptionstypes.TokenDescriptorandRegisteredPropertyOptionsare deprecated aliases.#159
bc7e94dThanks @dbanksdesign! - Add namespace-optional overloads fortokens.declare(schema)andtokens.create(values)so design systems can register a flat token tree without a namespace segment in emitted--*names.When the namespace is omitted, custom property names use
--{scopeId}-{path}(scoped) or--{path}(unscoped) instead of--{scopeId}-{namespace}-{path}. Pass{ decl }oncreate()to pair with a namespace-lessdeclare()for schema validation and forward references.
0.13.0
Minor Changes
- #155
9865095Thanks @dbanksdesign! -tokens.declare(namespace, schema)accepts a schema object, emits@propertyforsyntaxleaves, and infers ref types from the input shape.tokens.create()accepts plain values only (no inlineTokenDescriptor); pass{ decl }for typed partial fills with merge semantics across calls. Schema-lessdeclare(),declare<T>(), andLooseTokenRefare removed.
0.12.0
Minor Changes
#154
0b1c9e8Thanks @dbanksdesign! - Register@propertywith a syntax-appropriate placeholderinitial-value(e.g.transparentfor<color>,0for<number>) instead of always skipping registration forvar()/env()-dependent token values. The real value still reaches the cascade via the existing unconditional:rootdeclaration. AddTokenDescriptor.initial/RegisteredPropertyOptions.initialto override the placeholder explicitly. Note: a dependent token that previously fell back to CSS's defaultinherits: true(because@propertywas skipped) now respects itsinheritsoption like any other typed token — passinherits: trueexplicitly if you relied on the old implicit-inheritance fallback.#154
0b1c9e8Thanks @dbanksdesign! - Addtokens.declare(namespace, options?)— a lazyvar(--…)reference proxy for referencing a token before its value exists, either within the sametokens.create()call (self-referencing derived tokens) or across modules without a real import cycle. Names resolve through the same logictokens.create/tokens.usealready use, includingscopeIdandnameTemplate.
0.11.2
Patch Changes
- #150
8496b57Thanks @dbanksdesign! - Allow widened CSS keywords onVariantOptionStyleand block multi-slot overload fallthrough when recipe keys are present
0.11.1
Patch Changes
- #147
2364f0fThanks @dbanksdesign! - TightenVariantOptionStylefor CSS IntelliSense while keeping custom-property assignability
0.11.0
Minor Changes
- #144
08cab3bThanks @dbanksdesign! - Add SlotAttrsReturn type
0.10.0
Minor Changes
#141
35e02a7Thanks @dbanksdesign! - Breaking: semantic component class names now useblock,block--dimension-option, andblock__slotforms instead of hyphen semantic names. Compound variants now emit chained modifier selectors instead of*-compound-Nclasses. Attribute mode now kebab-casesdata-*names and supports slots, returning per-slot{ className, attrs, props }results.Upgrade notes: regenerate public-classname snapshots; update hand-written CSS / tests that targeted
*-baseor*-compound-N. Prefer distinct namespaces forstyles.classandstyles.componentwhen they would share a base class string — dev builds warn on that collision. See docs migration guide (0.10 semantic naming).#143
34d7fe2Thanks @dbanksdesign! - Addstyles.override()for recipe-shaped typed component restyling, backed by non-enumerable__tsMetaon everystyles.component()return andgetComponentMeta()for consumers. Supports semantic, bem, template, and attribute naming modes withselectorPrefix+ cascadelayeroptions.Raises the main-entry gzip budget to 26 KB for the new override runtime.
0.9.0
Minor Changes
#130
644a96cThanks @dbanksdesign! -variantStrategy: 'attribute'(from the unreleased PR #130) is nowcreateStyles({ mode: 'attribute' })/createTypeStyles({ mode: 'attribute' })— an instance-wide setting instead of a per-component field, matching howsemantic/hashed/compact/atomicalready work. Every dimensionedstyles.component()call from that instance compilesvariantsto&[data-{dimension}="{option}"]selectors and returns{ className, attrs, props };slotsis rejected at the type level.variantStrategy/defaultVariantStrategyno longer exist. Seespecs/attribute-driven-variants.md.#132
6be2124Thanks @dbanksdesign! - Addmode: 'bem'tocreateStyles/createTypeStyles: dimensioned and slotstyles.component()variants compile to BEM modifier classes (block--modifier,block__element--modifier) instead of the default{namespace}-{dimension}-{option}naming. The base/root class drops the-basesuffix (the bare block class is the base state). Compound variants compile to chained modifier-class selectors with no synthetic class. Dev mode warns when two dimensions would produce the same modifier class name. Seespecs/bem-variant-mode.md.#137
9cf89f1Thanks @dbanksdesign! - Addmode: 'template'tocreateStyles/createTypeStyles: dimensioned and slotstyles.component()variants compile to class names decided by a user-suppliedclassNameTemplate: (ctx) => stringfunction, instead of a fixed convention.mode: 'bem'is now implemented internally as a built-in preset of this same mechanism — its public behavior for valid input is unchanged, though in development it now also validates that emitted class names are legal CSS identifiers (previously invalid variant/slot names could silently produce a broken selector). Seespecs/classname-template-mode.md.
0.8.2
Patch Changes
#125
7111074Thanks @dbanksdesign! - Fixstyles.class()throwing when the same class name is registered twice in one process — e.g. meta-frameworks with multiple server module graphs in a single process (the Vite Environment API, or RSC frameworks like Waku/Vocs) re-evaluate the same source module once per environment, which previously crashed SSR with[typestyles] styles.class('name', ...) was called more than once for scope '...'.In development,
styles.class()now matches the re-registration behaviorstyles.component()already had: it invalidates the previous rule(s) for that class and re-registers instead of throwing (the same trade-off already made for HMR / out-of-orderdisposere-execution). Production behavior is unchanged — it never threw there.Also fixes a related bug in the shared HMR invalidation path (
invalidateKeys/invalidatePrefix, used by bothstyles.class()andstyles.component()): re-registering before the prior registration's CSS had flushed left the stale CSS text queued alongside the new CSS, producing a duplicate, conflicting rule once flushed.
0.8.1
Patch Changes
- #123
f641e3fThanks @dbanksdesign! - Fix two runtime injection bugs that could leave pages completely unstyled in real browsers:@propertyregistrations whose initial value containsvar()/env()now degrade to the universal"*"syntax without aninitial-value(the CSS spec requires initial values to be computationally independent, so browsers rejected the typed rule outright).inheritsbehavior is preserved, and defaults still cascade via the:root/ base-style assignments.- Rules rejected by
CSSStyleSheet.insertRuleare now appended as text to a dedicated<style id="typestyles-fallback">element instead of the main managed element. Appending text to the main element made browsers re-parse it from its text content, silently discarding every rule previously inserted throughinsertRule— a single rejected rule wiped the entire runtime sheet.
0.8.0
Minor Changes
#119
10edb85Thanks @dbanksdesign! - Addstyles.scope()for proximity-correct nested theme overrides via CSS@scope(P5.3).Introduce
@typestyles/cli, a new package with thetypestylesbinary and subcommands. The first command istypestyles snapshot, which scans semanticstyles.class/styles.componentclass names and writes.typestyles-public-classnames.jsonfor semver guarding. Snapshot logic and heavy deps (typescript,fast-glob) live in this package so the coretypestylesruntime stays lean.Also ships the opt-in
@typestyles/no-removed-public-classnameESLint rule (consumes@typestyles/cliprogrammatically).#116
7ea7356Thanks @dbanksdesign! - Add'descendant'as a thirdscopevalue ontokens.when.attr/tokens.when.classNametheme conditions, compiling to a descendant-combinator selector (.theme-name [data-x="y"]) so a mode can match a marker element inside the themed subtree — the relationship a fixed-tone surface (e.g. an always-dark toast on a light page) needs.when.not()on a descendant-scoped condition is rejected with an explicit dev warning (P5.4).#121
4be825aThanks @dbanksdesign! - Add responsive object syntax for breakpoint shorthand in style property values. Register breakpoints once viacreateStyles({ breakpoints })orcreateTypeStyles({ breakpoints }), then use{ base, md, lg }on CSS properties — expands to@mediablocks at serialization time. Supports_alias,breakpoints.fromTokens, atomic mode, and dev-time validation for unknown breakpoints.#120
2bfa8a4Thanks @dbanksdesign! - Add optionalnameTemplateoncreateTokensandtokens.createfor custom CSS custom property names — migration from existing variable systems, Style Dictionary / DTCG naming conventions, and cross-namespace aliasing. Default--{scopeId}-{namespace}-{path}behavior is unchanged whennameTemplateis omitted. Theme overrides,tokens.use(), and@propertyregistration share the same resolved names.
0.7.0
Minor Changes
#94
47bc7bdThanks @dbanksdesign! - Document streaming SSR and RSC patterns against request-scoped collection (P1.9). AddTYPESTYLES_STYLE_ID,typestylesStyleHtml,injectStylesIntoHtml, andstreamingDocumentShellhelpers ontypestyles/server. Expand the SSR guide with request-safe collection, RSC decision table, and streaming examples.#95
f06fb48Thanks @dbanksdesign! - Rename hash-only class naming mode tocompactand implement true per-declarationatomicoutput with cross-component dedup (P2.10).styles.class,styles.component, andstyles.hashClassinatomicmode now emit one class per CSS declaration; identical declarations share a class.#105
0729526Thanks @dbanksdesign! - Add@propertyregistration for typed token leaves ({ value, syntax, inherits? }intokens.create) and standalonestyles.property(id, opts). Both return{ name, var, toString }refs (P3.24).#112
b701e62Thanks @dbanksdesign! - Addtypestyles/color-scalesubpath withparseColor(hex → OKLCH),generateRamp(perceptual OKLCH ramps), andcontrastRatio(WCAG relative luminance). Design-system palette ramps now call the sharedgenerateRampimplementation (P5.1).#113
3459b70Thanks @dbanksdesign! - Addtypestyles/token-scalesubpath withgenerateGeometricScale(modular ladders like font sizes from{ base, ratio, steps }),generateLinearScale(grid-based ladders like radii from{ base, multiplier, steps }), andexpandDurationBand(a{ min, base, max }motion band from{ base, ratio }, rounded to the nearest 5ms by default). Pure numeric outputs with zero naming opinions — mapping steps to token names stays a design-system concern (P5.2).
Patch Changes
#101
23bd4f1Thanks @dbanksdesign! - Consolidate planning docs: remove 6 stale files, update ARCHITECTURE.md and IMPROVEMENTS.md.#98
e17b8a0Thanks @dbanksdesign! - Add npm landing-page READMEs for every published package, an examples index with contributor guidance, and doc-to-example cross-links (P2.13).#103
a4ccfbcThanks @dbanksdesign! -styles.compose()now infers merged variant selection types from composed component functions (P3.22). Unknown variant keys are rejected by TypeScript and logged in development when no composed function accepts them.#104
8de36faThanks @dbanksdesign! -tokens.use()now infers token shapes from atokens.create()return value (P3.23). Pass the created ref for cross-package typing, or declare aTokenRegistryoncreateTokens()for string-based lookups.#107
aff0a8cThanks @dbanksdesign! - Fixreset()to also clearregisteredNamespaces— previously required manual clearing in tests.#102
a984b6bThanks @dbanksdesign! - Dev-mode warning for unscoped namespace collisions (P3.5.2):styles.component()now emits aconsole.warnwhen the same namespace is registered more than once without ascopeId, helping catch cross-file class name collisions before they reach production.
0.6.0
Minor Changes
#78
aa88d25Thanks @dbanksdesign! - AddcreateStyles({ utils })(andcreateTypeStyles({ utils })) so shorthand style expanders attach to one styles instance without a separatewithUtilsobject.styles.withUtilsremains on the default export; there is no globalregisterUtils.#93
60a8383Thanks @dbanksdesign! - Add debug names and optional fallbacks tocreateVar(). Document the dynamic styling story on a dedicated page and cross-link from performance and best-practices guides.#90
f979149Thanks @dbanksdesign! - Movecolorhelpers to thetypestyles/colorsubpath entry to shrink the main runtime bundle (~14.9 KB gzip). CI enforces a gzip budget ondist/index.js.Breaking:
import { color } from 'typestyles'is removed — useimport { color } from 'typestyles/color'(or named imports from that subpath).#89
b29a531Thanks @dbanksdesign! - Request-safe SSR collection (P0.4): isolatecollectStyles/collectStylesFromModulessheet state with NodeAsyncLocalStorage, and add async render support tocollectStyles.
Patch Changes
- #86
fd16badThanks @dbanksdesign! - Fix silent-wrong-output correctness issues (P0.1): refresh the unitless CSS property set, prefixscopeIdonto semantic class names, add dev-mode class-name collision warnings, and wireuseTypestylestosubscribeRegisteredCssviauseSyncExternalStore.
0.5.0
Minor Changes
#52: Add built-in
cx()utility for joining class names with falsy-value filtering#63: Add first-class container query helpers:
container()for typed@containerkeys, readablecontainerRef()/createContainerRef()forcontainer-name, andatRuleBlock()/styles.atRuleBlock()so computed@…nests type-check without casting. Documentation and design-system example updated.#62: Add opt-in CSS cascade layers (
@layer) and a unifiedcreateTypeStylesfactory.createStyles({ layers })— Pass a layer tuple (as const) or{ order, prependFrameworkLayers? }. Emits a single@layer …;preamble (once per stack) and wraps rules in@layer name { … }. When enabled, everyclass,hashClass, andcomponentcall must pass a third argument{ layer: … }(withhashClass, use{ layer, label? }instead of a positional label).createTokens({ layers, tokenLayer })— Whenlayersis set,tokenLayeris required;:rootand theme CSS are emitted into that layer.createTypeStyles(options)— Returns{ styles, tokens }with one sharedscopeIdand optionallayers/tokenLayerfor both class and token output.createTheme/createDarkMode— Optional fourth argument for layer context when using tokens with layers.
Default behavior is unchanged when
layersis omitted (flat CSS, nolayeroption).New exports include
createTypeStyles,StylesApiWithLayers,CreateStylesInput,LayerOption,LayeredComponentFn, cascade layer types (CascadeLayersInput,ResolvedCascadeLayers, etc.), andThemeEmitLayerContext.ClassNamingConfigmay include resolvedcascadeLayers. The sheet exposesregisterCascadeLayerOrderfor the preamble.Documentation: new cascade-layers doc (
docs/content/docs/cascade-layers.md), updates to class naming, API reference, and tokens. The design-system example usescreateTypeStyles.#61: Add function overload for
styles.component(namespace, (ctx) => config)with component-scoped internal custom properties:ctx.var(id, options?)andctx.vars(definitions)using the same nested shape as tokens (string/number leaves or{ value, syntax?, inherits? }). Defaultvalues are merged intobase; optionalsyntaxregisters@property.ctx.varnow takesvalue(notinitialValue) for defaults and typed registration. New exports:ComponentConfigContext,ComponentVarDefinitions,ComponentVarDescriptor,ComponentVarNode,ComponentVarRefTree, and related*Inputtypes for the component overload.#73: typestyles: Extend
global.fontFace/FontFaceProps:srcmay be a string or an array of fragments (joined into one CSSsrc); optional@font-facedescriptorssizeAdjust,ascentOverride,descentOverride, andlineGapOverride; dedupe keys use normalizedsrc(including array vs equivalent comma-separated string). ExportFontFaceSrc. When the same rule dedupe key is registered again with different CSS, the later rule is skipped and non-production builds warn on the mismatch (re-registration with identical CSS stays silent). Tests cover multi-srcfont faces, metric overrides, and global dedupe warnings.@typestyles/next: README examples use
styles.componentand default variant calls; add Fonts and local files guidance for Next extraction (public/fonts/, root-relative URLs) versus Vite asset URLs.#72: Add
createGlobalfor scoped global CSS (optional cascadelayersand defaultglobalLayer), wireglobalintocreateTypeStyles, and ship atypestyles/globalsentry with Josh Comeau’sreset(pluslayersupport for layered stacks) and small selector recipes.createTypeStylesnow returns{ styles, tokens, global }. Withlayers, pass optionalglobalLayersoglobal.style/global.applydefaults match your stack;tokenLayerremains required when layers are enabled.global.styleacceptsGlobalStyleTuplerecipes (fromtypestyles/globals) in addition to selector + properties; rootglobalignores per-calllayer(dev warning) — usecreateGlobal/ layeredcreateTypeStylesfor@layer.global.apply(...tuples)applies multiple tuples in one call.- New
contenthelper for typed CSScontentvalues on the main export. - Types:
GlobalApiUnlayered,GlobalApiLayered,GlobalStyleTuple.
#59: Replace global class naming with instance-based APIs.
Breaking: Remove
configureClassNaming,getClassNamingConfig, andresetClassNaming. UsecreateStyles({ mode?, prefix?, scopeId? })for a dedicated style API (same surface as the defaultstylesexport). The defaultimport { styles } from 'typestyles'iscreateStyles()with default options.Breaking:
createTokens({ scopeId? })returns the token and theme API (create,use,createTheme,createDarkMode,when,colorMode, plus read-onlyscopeId). The defaultimport { tokens } from 'typestyles'iscreateTokens(). WhenscopeIdis set, emitted custom properties and theme class segments are prefixed (sanitized) so multiple bundles on one page do not collide.Breaking: Low-level
createComponent,createClass, andcreateHashClassnow takeClassNamingConfigas the first argument when imported from implementation modules; application code should usecreateStyles()or the defaultstylesobject.Breaking:
createThemeandcreateDarkModeaccept an optional third argumentscopeIdfor unscoped usage; instances fromcreateTokens({ scopeId })bind scope automatically.New exports:
mergeClassNaming,defaultClassNamingConfig,scopedTokenNamespace,StylesApi,TokensApi,CreateTokensOptions. Style instances expose read-onlyclassNaming.Documentation, examples, and the design-system package are updated to describe and use the new pattern.
#49: Add ESLint configuration across all packages, examples, and docs. Create shared
eslint.base.jsconfig with TypeScript rules and add lint scripts to all package.json files. Update CI workflow to run lint via turbo.#56: Support nested token objects in
tokens.createand the same nested shape intokens.createTheme. Nested keys become hyphenated CSS custom properties (for examplecolor.text.primary→--color-text-primaryandvar(--color-text-primary)).Export
flattenTokenEntriesand theFlatTokenEntrytype so consumers can build--namespace-keydeclarations with the same rules as the token APIs.The design-system example now uses this pattern directly instead of local flatten/ref helpers.
#66: Add
fileScopeId(import.meta)for per-filescopeIdso the same logical class or component name in different modules does not collide. In development, registering the samestyles.classorstyles.componentname twice under one scope throws (with guidance to usescopeId/fileScopeId); production behavior is unchanged. In development, unknown variant dimensions, invalid option values, and unknown flat variant keys emitconsole.error.createComponentandstyles.componentoverloads useconsttype parameters for sharper literal inference.#68: Infer multipart
slotsfrom the array literal passed tostyles.component(andcreateComponent) using aconsttype parameter onSlots extends readonly string[]. Slot names are typed asSlots[number], so destructuring and()returnRecord<…>with known keys and errors on unknown properties—withoutas constonslotswhen the array is written inline.Type-only:
MultiSlotConfig,MultiSlotReturn,SlotComponentConfig,SlotComponentFunction, and related inputs now take a readonly string tuple type parameter (theslotsarray) instead of a single string unionS. Call-site inference is unchanged for typical object literals; advancedextends/ explicit generics may need a small adjustment.Docs and the design-system example drop redundant
as constonslotswhere inference applies.#57: Breaking:
tokens.createThemenow takes a config object withbase, and eithermodesorcolorMode(presets). Namespace overrides must live underbase(for example{ base: { color: { … } } }). It returns aThemeSurface(className,name, string coercion) instead of a plain class string—usesurface.classNameor`${surface}`where a string is required.Adds
tokens.when(media,prefersDark/prefersLight, attribute/class scope,selectorescape hatch,and/or/not) andtokens.colorModepresets (mediaOnly,attributeOnly,mediaOrAttribute,systemWithLightDarkOverride), plustokens.createDarkModeas a shorthand for media-only dark overrides.Theme rules use stable dedupe keys (
theme:{name}:base,theme:{name}:mode:{id}:branch:{n}). In development, empty mode overrides and dubiouswhen.selector/when.notshapes log warnings.Types:
ThemeOverridesallows deep partial nested token maps; new exports includeThemeConditionNotandDeepPartialTokenValues.#54: Unify multi-variant styling on
styles.componentwith a CVA-style return value: call it for a composed class string (base always applied) or destructure named class strings. Supports dimensioned variants (variants,compoundVariants,defaultVariants), flat variant maps, and slot-based configs.Remove
styles.createfrom the publicstylesAPI; usestyles.componentinstead.Update Vite and Rollup static namespace extraction to match
styles.component(...)only (no longer scansstyles.create(...)).#64: Add
has,is, andwherehelpers for:has(),:is(), and:where()nested keys (also onstyles). Infer literal@container …keys from typedcontainer()arguments so bracket notation mixes with longhands withoutas CSSProperties; useatRuleBlockwhen the key is only a genericstring. ExportContainerObjectKeyand document the pattern in the docs.
Patch Changes
#45: Add comprehensive test coverage for previously untested modules: props utils/generate/runtime, typestyles build, and migrate transform/css/files.
#34:
withTypestylesExtractnow setsNEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLEDvianext.configenvso client bundles disable runtime style injection under Turbopack as well as webpack (webpackDefinePluginalone does not run for Turbopack). Coresheetreads this env flag alongside__TYPESTYLES_RUNTIME_DISABLED__.README: build-time CSS / Turbopack notes; clarify
getTypestylesMetadataand fix the previousgenerateMetadataexample. Add@typestyles/nexttests forwithTypestylesExtract.TypeScript: module augmentation +
client.d.tsdeclaration foruseServerInsertedHTML(aligned@types/react/@types/react-dom); addtypecheckscript; restorewebpack+typestylesdevDependencies andserver.d.ts/./buildexports.buildTypestylesForNextnow usescollectStylesFromModulesfromtypestyles/build(no separate@typestyles/buildpackage).#50: Add lint-staged for prettier formatting on pre-commit hook and format entire codebase
Unreleased
Breaking changes
- Instance-based APIs replace global class naming. Removed
configureClassNaming,getClassNamingConfig, andresetClassNaming.- Use
createStyles({ mode?, prefix?, scopeId? })for a dedicated style API (same surface as the defaultstylesexport). Defaultimport { styles } from 'typestyles'iscreateStyles(). - Use
createTokens({ scopeId? })for a dedicated token + theme API. Defaultimport { tokens } from 'typestyles'iscreateTokens(). WhenscopeIdis set,tokens.create/createThemeemit scoped--{scope}-namespace-*variables and.theme-{scope}-{name}classes (sanitized segments). - New exports:
mergeClassNaming,defaultClassNamingConfig,scopedTokenNamespace, and typesStylesApi,TokensApi,CreateTokensOptions.
- Use
- Low-level
createComponent,createClass, andcreateHashClassnow takeClassNamingConfigas the first argument when imported from internal modules; app code should usecreateStyles()or the defaultstylesobject instead.
0.4.0
Minor Changes
#25: Updating bundler integrations and adding examples
#27: Add a new
styles.withUtils(utils)API for defining typed style shorthands (for examplemarginX,paddingY, andsize) and using them withstyles.class,styles.create, andstyles.hashClass.#33: Add configurable class naming modes for gradual adoption across packages:
configureClassNaming({ mode, prefix?, scopeId? })with modessemantic(default),hashed, andatomic.- Applies to
styles.create,styles.class,styles.component(including slot recipes), and affectsprefix/ optionalscopeIdmixing forstyles.hashClass. - Export
getClassNamingConfigandresetClassNaming(for tests).
Documentation:
- New site page
docs/content/docs/class-naming.md(sidebar: Class naming) describing modes,scopeId, SSR, and testing. - Cross-links from Getting Started, Styles, Recipes, Atomic CSS utilities, API Reference, and Testing.
#31: Unify variant APIs around
styles.componentand add first-class multipart slot support viaslots.Breaking changes:
- Remove
styles.recipein favor ofstyles.component. - Remove recipe type aliases (
RecipeConfig,RecipeFunction,RecipeVariants) and replace with component terminology (ComponentVariants, plus new slot component types).
New capability:
styles.component(name, { slots, base, variants, compoundVariants, defaultVariants })now returns per-slot class maps for multipart components.
Naming update for slot mode:
- Slot base classes now use
{namespace}-{slot}(without-base).
- Remove
#23: Add
styles.class()for single-class definitions and a three-argumentstyles.create(name, base, variants)API that automatically includes base styles, then updated the Next.js example to use the new DX without affecting published packages.#26: feat: styles.recipe()
0.3.0
Minor Changes
#9: Add support for attribute selectors in nested styles. You can now use
[data-variant],[disabled],[data-size="lg"]and other attribute selectors directly in style definitions:typescriptstyles.create('button', { padding: '8px', '[data-variant="primary"]': { backgroundColor: 'blue' }, '[disabled]': { opacity: 0.5 }, });#10: Fix lint errors and TypeScript issues
- Replace
anytypes withunknownin type definitions - Fix empty object types
{}in defineProperties - Add proper generic type parameters to functions
- Prefix unused parameters with underscore
- Add eslint ignores for generated docs files and scripts
- Fix test assertions to use proper types
- Replace
Patch Changes
- #13: Add CI workflow for lint, typecheck, and test
0.2.0
Minor Changes
#6: Add new
@typestyles/propspackage for type-safe atomic CSS utility generation, withdefineProperties()andcreateProps()APIs supporting responsive conditions, shorthand properties, and automatic CSS injection.Add
composetostylesnamespace for composing multiple selector functions or class strings. AddcreateVar()andassignVars()for CSS custom property management. ExportinsertRules,reset, andflushSyncutilities from the sheet module. AddCSSVarRefandRecipeVariantstype exports.
0.1.0
Minor Changes
- #4: Add
styles.component()API for multi-variant component styles with support for base styles, variant dimensions, compound variants, and default variants. Addglobal.style()andglobal.fontFace()APIs for applying styles to arbitrary CSS selectors and declaring@font-facerules. Update the Vite plugin to support HMR for the new APIs.
0.0.2
Patch Changes
#1: Initial release of typestyles - CSS-in-TypeScript that embraces CSS instead of hiding from it.
Features:
- Core typestyles library with type-safe CSS styling
- Server-side rendering support
- Vite plugin for HMR support