typestyles
packages/typestyles/CHANGELOG.md
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