Skip to main content

7 posts tagged with "release"

View All Tags

· 5 min read
Naman Goel

StyleX v0.9.3 is now available with some big improvements and bug-fixes.

Improvements to Theming APIs

There are some big improvements to the predictability and reliability of our theming APIs — stylex.defineVars and stylex.createTheme.

Breaking Change: Themes are now exclusive

When you create a VarGroup with stylex.defineVars, you are able to theme any subset of the variables within using the stylex.createTheme API. These themes can then be applied like any other StyleX styles using stylex.props (or stylex.attrs). If you try to apply multiple themes for the same VarGroup, on the same element, the last applied theme wins, just as you might expect.

However, previously, if you instead applied one theme on a parent element, and another theme on a child element, the themes would end up being merged.

// tokens.stylex.ts
import * as stylex from '@stylexjs/stylex';

export const varGroup = stylex.defineVars({
primary: 'black',
secondary: 'grey',
});
import * as stylex from '@stylexjs/stylex';
import {varGroup} from './tokens.stylex.ts';

const red = stylex.createTheme(varGroup, {
primary: 'red',
});

const blue = stylex.createTheme(varGroup, {
secondary: 'blue',
});

const styles = stylex.create({
primary: {color: varGroup.primary},
secondary: {color: varGroup.secondary},
});

function App() {
return (
<div {...stylex.props(red)}>
<div {...stylex.props(blue)}>
<span {...stylex.props(styles.primary)}>Hello </span>
<span {...stylex.props(styles.secondary)}>World!</span>
</div>
</div>
);
}

Previously this would have resulted in the text "Hello World!" being styled with a red primary color and a blue secondary color. Now, the text will be styled with a black primary color and a blue secondary color.

You can think of themes conceptually as re-applying the default values for any variables that are not explicitly overridden by the theme. This change simplifies the mental model for how themes work, and has the added benefit of making it easy to create "reset" themes:

const reset = stylex.createTheme(varGroup, {});
tip

You can define this "reset" theme multiple times within your app and they will all be de-duplicated by the compiler. We encourage you to "repeat yourself"!

rootDir is now optional!

Previously, when configuring the StyleX Babel plugin, you had to explicitly specify a rootDir value. Internally, this path was used to generate a canonical file path for every .stylex.js file in your project.

However, this was not only cumbersome, but it also resulted in errors when importing VarGroups from node_modules. Different package managers deal with packages differently, and this can be particularly consequential for mono-repos.

Now, the rootDir option is optional, and StyleX will use the nearest package.json file to determine the canonical path, automatically. This should make theming APIs work more reliably.

note

When determining the canonical path, StyleX will use the name field from the nearest package.json file and the relative path to the .stylex.js file. We intentionally ignore the version number.

This means that your project happens to contain multiple versions of the same package, StyleX will only generate a single set of variables for them. This will usually be the desired behavior, but you may see some unexpected results if the variables within the two versions are different.

We will be making further improvements to minimize any such edge-cases.

More reliable ESM resolution

The StyleX Babel plugin now uses the esm-resolve package to resolve ESM imports. This should fix most situations where the compiler would fail to resolve VarGroup imports in result in the compilation of stylex.create to fail.

Thanks hipstersmoothie!

Dynamic style improvements

Dynamic Styles within StyleX have been improved to be more reliable and efficient. Previously, if the dynamic value of a style resolved to null at runtime, StyleX would represent that with the revert keyword in CSS. This did not always work as expected, ran into certain browser bugs and resulted in styles that were unnecessarily bloated.

In v0.9.3, null values for Dynamic styles work exactly the same as using null as a static value within stylex.create. This means any previously applied value for the given property will be removed and no className will be applied for that property.

@stylexjs/dev-runtime overhaul

The @stylexjs/dev-runtime package is a development-only package that lets you use a much slower version of StyleX that runs entirely at runtime. Previously, it worked by patching the main @stylexjs/stylex package at runtime. However, this did not always work reliably.

Breaking Change: The @stylexjs/dev-runtime package now returns the StyleX API.

import makeStyleX from '@stylexjs/dev-runtime';

const stylex = makeStyleX({
// configuration options
classNamePrefix: 'x',
dev: true,
test: false,
});

const styles = stylex.create({
color: 'red',
});
danger

The @stylexjs/dev-runtime only exists as a convenience for development purposes. It does not completely match the behavior of the StyleX compiler and will always lack certain features.

DO NOT use it in production.

Improved handling of nested pseudo-elements and pseudo-classes

Fixed a bug where using Pseudo Classes (such as :hover) within Pseudo Elements (such as ::before) (or vice-versa) would sometimes result in surprising behavior. StyleX now handles such cases, with an arbitrary level of nesting, correctly.

Miscellaneous

  • Added support for additional Pseudo Elements and Pseudo Classes to our ESLint rule and type definitions.
  • Slightly better compiler error messages.

· 4 min read
Naman Goel

StyleX v0.8.0 is now available with a bunch of fixes and new ESlint rules.

Linting Enhancements

We've been making a lot of improvements to our ESLint plugin. We've both improved our existing rules and added new ones. Thanks to Melissa Liu!

Here are some of the highlights:

New valid-shorthands rule

This rule enforces our opinions on when and how you should use CSS shorthand properties. It disallows the use of multi-value shorthands for shorthands, and disallows certain properties altogether.

const styles = stylex({
invalidShorthands: {
// border shorthands are entirely disallowed
// Use `borderWidth`, `borderStyle`, and `borderColor` instead
border: '1px solid black',
// Multiple values for different sides within the same shorthand are disallowed
borderWidth: '1px 2px 3px 4px',
margin: '10px 20px 30px',
padding: '10px 20px',
},
validShorthands: {
borderBottomWidth: 3,
borderColor: 'black',
borderInlineEndWidth: 2,
borderInlineStartWidth: 4,
borderStyle: 'solid',
borderTopWidth: 1,
marginBottom: 30,
marginInline: 20,
marginTop: 10,
paddingBlock: 10,
paddingInline: 20,
},
});

These opinions guide you towards the most consistent and most re-usable CSS.

tip

This rule offers an autofix for all disallowed properties.

New enforce-extension rule

This new rule enforces the rules when defining variables._createMdxContent It enforces that usages of stylex.defineVars are named exports within a file with a .stylex.js (or '.ts' or '.jsx' or '.tsx') extension, and that such a file does not have any other exports.

Other Lint fixes

We've updated the ESLint rule to include additional missing properties and values. Notably, the valid-styles rule should now understand:

  • fieldSizing as a valid prop
  • @starting-style as a valid at-rule.

Using lightningcss for post-processing

StyleX's compilation process is conceptually a three step process:

  1. Transform JavaScript source files to replace usages of stylex.create etc. with the resulting classNames and collect the generated CSS.
  2. De-duplicate and sort all the collected CSS.
  3. Write the CSS to a file.

However, often it's useful to post-process the CSS before writing it to a file. This post-processing can include minification, prefixing, or other transformations. After much discussion we have decided to standardize on lightningcss for this post-processing.

As a first step, we're add lightningcss by default for our Rollup Plugin. We will be rolling out support for our other bundler plugins next.

Thanks Prakshal Jain for his work on this!

Theming Improvements

We've made two small but important improvements for theming in StyleX.

Use stylex.firstThatWorks to define fallback values for CSS variables.

StyleX has a stylex.firstThatWorks function that can be used to define fallback values for CSS property. This is akin to using the same property multiple times with different values in CSS.

/* Represent this */
.my-class {
background-color: #808080;
background-color: oklab(0.5 0.5 0.5);
}
const styles = stylex.create({
myClass: {
// as:
backgroundColor: stylex.firstThatWorks(
'oklab(0.5 0.5 0.5)',
'#808080',
),
},
});

Now, the same API will also work for CSS variables.

/* Represent this */
.my-class {
background-color: var(--bg-color, #808080);
}
const styles = stylex.create({
myClass: {
// as:
backgroundColor: stylex.firstThatWorks(
'var(--bg-color)',
'#808080',
),
},
});

Themes have higher specificity than default var values

The CSS rule created with stylex.createTheme now has higher specificity than the rule created with stylex.defineVars.

This should not have been issue in the vast majority of cases already, as we always sorted the rules in the correct order. However, in extreme edge-cases where you may be loading multiple StyleX CSS files on the same page, this fix will ensure consistency.

Other fixes

We've made some other fixes in various parts of StyleX:

  • fix: Logical values for textAlign are no longer converted to left and right.
  • fix: [CLI] Handle errors while deleting files gracefully (#695)
  • feat: Expand configuration options to CLI (#638)
  • fix: Don't add 'px' units for number values used for variables (#694)
    • fix: Don't add 'px' units for additional properties that accept raw numbers as values (#705)

Documentation Improvements

We've added documentation for options of our various bundler plugin and added additional projects to our ecosystem page.

We've also updated the search on our website to be much more comprehensive and accurate. (Powered by Algolia)

· One min read
Naman Goel

StyleX v0.7.3 is now available with a fix to the Rollup plugin, which didn't previously include all the necessary files in the publish to NPM.

· 2 min read
Naman Goel

We're excited to release StyleX v0.7.0 with a new CLI to make it easier to get started with StyleX, improvements to variables, and various bug-fixes.

CLI

StyleX relies on a compiler that transforms your JavaScript code and generates a static CSS file. However, integrating this compiler with with your bundler can be tricky. So, while we continue to work on improving the quality of our bundler integrations, we are introducing a new CLI as an alternative!

The CLI transforms an entire folder. It generates an output folder where StyleX has already been compiled away and a static CSS file has been generated. Further, the CLI inserts an import statement for the generated CSS file into each file that uses StyleX.

We are excited to offer this alternative to the bundler-based setup and are choosing to release the CLI in an experimental state. We would love to hear your feedback on how it works for you and what improvements you would like to see.

Special thanks to Joel Austin for his work on the CLI.

Literal names for CSS variables

When using, stylex.defineVars, StyleX abstracts away the actual CSS variable name, and lets you use it as a JavaScript reference. Behind the scenes, unique variable names are generated for each variable.

However, there are scenarios where it is useful to know the exact variable name. For example, when you may want to use the variable in a standalone CSS file.

To address such use-cases, we have updated the stylex.defineVars API to use literals that start with -- as is. Other than the keys passed to stylex.defineVars, the API is unchanged.

const vars = stylex.defineVars({
'--primary-color': 'red',
'--secondary-color': 'blue',
});
Note

When using literals for variable names, StyleX cannot guarantee uniqueness.

Bug Fixes and improvements

Additionally bug fixes to types, eslint rules and the bundler plugins has been made.

· 3 min read
Naman Goel

We're excited to release StyleX v0.6.1 with some big improvements for working with CSS custom properties (aka "variables") as well as numerous bug-fixes.

Improvements for variables

We've added some new features and improvements for working with variables and themes in StyleX.

Fallback values for variables

You can now provide a fallback value for variables defined with the stylex.defineVars API. This new capability does not introduce any new API. Instead, the existing stylex.firstThatWorks API now supports variables as arguments.

import * as stylex from '@stylexjs/stylex';
import {colors} from './tokens.stylex';

const styles = stylex.create({
container: {
color: stylex.firstThatWorks(colors.primary, 'black'),
},
});

Using a list of fallbacks variables is supported.

Typed variables

StyleX introduces a brand new set of APIs for defining <syntax> types for CSS variables. This results in @property rules in the generated CSS output which can be used to animate CSS variables as well as other special use-cases.

The new stylex.types.* functions can be used when defining variables to define them with a particular type.

import * as stylex from '@stylexjs/stylex';

const typedTokens = stylex.defineVars({
bgColor: stylex.types.color<string>({
default: 'cyan',
[DARK]: 'navy',
}),
cornerRadius: stylex.types.length<string | number>({
default: '4px',
'@media (max-width: 600px)': 0,
}),
translucent: stylex.types.number<number>(0.5),
angle: stylex.types.angle<string>('0deg'),
shortAnimation: stylex.types.time<string>('0.5s'),
});

Once variables have been defined with types, they can be animated with stylex.keyframes just like any other CSS property.

import * as stylex from '@stylexjs/stylex';
import {typedTokens} from './tokens.stylex';

const rotate = stylex.keyframes({
from: { [typedTokens.angle]: '0deg' },
to: { [typedTokens.angle]: '360deg' },
});

const styles = stylex.create({
gradient: {
backgroundImage: `conic-gradient(from ${tokens.angle}, ...colors)`,
animationName: rotate,
animationDuration: '10s',
animationTimingFunction: 'linear',
animationIterationCount: 'infinite',
},
})

This can be used achieve some interesting effects, such as animating the angle of a conic-gradient:

This new capability is primarily about CSS types, but the new API also makes the TypeScript (or Flow) types for the variables more powerful.

As can be seen in the example, generic type arguments can be used to constrain the values the variable can take when creating themes with stylex.createTheme.

ESlint plugin

New sort-keys rule

We've added a new sort-keys rule to the StyleX ESlint plugin. This rule is a stylistic rule to enforce a consistent order for keys for your StyleX styles.

Thanks nedjulius

Improvements to propLimits for valid-styles rule.

The valid-styles rule has been improved to allow more expressive "prop limits".

Miscellaneous

  • ESlint 'valid-styles' rule now allows using variables created with stylex.defineVars as keys within dynamic styles.
  • Bug-fixes to the experimental stylex.include API
  • Fixed debug className generation for stylex.createTheme
  • Units are no longer removed from 0 values
  • Compilation bug-fixes

Our Ecosystem page continues to grow with community projects. Including a Prettier plugin for sorting StyleX styles.

· 2 min read
Naman Goel

We're excited to release Stylex v0.5.0 with some big improvements and fixes!

New stylex.attrs function

The stylex.props function returns an object with a className string and a style object. Some frameworks may expect class instead of className and a string value for style.

We are introducing a new stylex.attrs function so StyleX works well in more places. stylex.attrs returns an object with a class string and a style string.

New sort-keys rule for the Eslint plugin

A new @stylexjs/sort-keys plugin has been introduced which will sort styles alphabetically and by priority. This will make media query order more predictable.

Thanks @nedjulius!

New aliases option for the StyleX Babel plugin

A new aliases field can be used to configure StyleX to resolve custom aliases that may be set up in your tsconfig file. NOTE: StyleX currently needs to be configured with absolute paths for your aliases.

Thanks @rayan1810!

New Esbuild plugin

A new official plugin for Esbuild has been introduced as @stylexjs/esbuild-plugin.

Thanks @nedjulius!

Other Enhancements

  • Configuration options passed to the StyleX Babel plugin will now be validated.
  • The @stylexjs/stylex now has ESM exports alongside the commonJS exports.
  • The ESLint valid-styles rule will catch when using empty strings as string values.

Bug Fixes

  • Some CSS properties which previously caused type and lint errors will now be accepted.
  • Using variables for opacity will no longer cause type errors.
  • Using stylex.keyframes within stylex.defineVars will now work correctly
  • runtimeInjection will correctly be handled
  • Setting the value of variables from defineVars as dynamic styles will now work correctly.
  • Usage of 0px within CSS functions will no longer be simplified to a unit-less 0 as this doesn't work in certain cases.
  • Spaces around CSS operators will be maintained.

In addition to these, we've added an "Ecosystem" page to our website to highlight various community projects around StyleX.

· 2 min read
Naman Goel

Three weeks ago, we open-sourced StyleX. Since then, we've been diligently fixing bugs and making improvements. Here are some of the highlights:

Enhancements

  • The amount of JavaScript generated after compilation has been further reduced.
  • Added support for some previously missing CSS properties to the ESLint plugin.
  • Added support for using variables in stylex.keyframes.
  • Removed the code for style injection from the production runtime, reducing the size of the runtime by over 50%.
  • Added Flow and TypeScript types for the Rollup Plugin.
  • Added the option to use CSS Layers in all bundler plugins.
  • TypeScript will now auto-complete style property names.
  • Bundler plugins will now skip files that don't contain StyleX, resulting in faster build times.

Bug Fixes

  • Fixed a bug where the ESLint plugin was sometimes unable to resolve local constants used for Media Queries and Pseudo Classes.
  • Resolved a bug where the runtime injection of styles in dev mode would sometimes fail.
  • Addressed a bug where styles injected at runtime during development would sometimes suffer from specificity conflicts.
  • The TypeScript types for Theme will now correctly throw an error when applying a theme for the wrong VarGroup.

In addition to these, we've made other improvements to the types and documentation. I want to extend my gratitude to all the contributors for their pull requests. ♥️

Happy New Year!