diff --git a/apps/nextjs-example/app/Card.tsx b/apps/nextjs-example/app/Card.tsx
index 57aa3ce2..642528a1 100644
--- a/apps/nextjs-example/app/Card.tsx
+++ b/apps/nextjs-example/app/Card.tsx
@@ -8,8 +8,8 @@
import stylex from '@stylexjs/stylex';
import { globalTokens as $, spacing, text } from './globalTokens.stylex';
-import '@stylexjs/open-props/lib/colors.stylex';
import { colors } from '@stylexjs/open-props/lib/colors.stylex';
+import { tokens } from './CardTokens.stylex';
type Props = Readonly<{
title: string;
@@ -20,15 +20,15 @@ type Props = Readonly<{
export default function Card({ title, body, href }: Props) {
return (
-
- {title} →
+
+ {title} →
-
{body}
+ {body}
);
}
@@ -65,12 +65,12 @@ const styles = stylex.create({
padding: spacing.sm,
transitionProperty: 'background-color, border-color',
transitionDuration: '400ms',
- transform: {
- default: 'translateX(0)',
- ':hover span': 'translateX(4px)',
- },
textAlign: 'center',
textDecoration: 'none',
+ [tokens.arrowTransform]: {
+ default: 'translateX(0)',
+ ':hover': 'translateX(4px)',
+ },
},
h2: {
color: colors.blue3,
@@ -84,6 +84,7 @@ const styles = stylex.create({
span: {
display: 'inline-block',
transitionProperty: 'transform',
+ transform: tokens.arrowTransform,
transitionDuration: {
default: '200ms',
[REDUCE_MOTION]: '0s',
diff --git a/apps/nextjs-example/app/CardTokens.stylex.ts b/apps/nextjs-example/app/CardTokens.stylex.ts
new file mode 100644
index 00000000..d07e3294
--- /dev/null
+++ b/apps/nextjs-example/app/CardTokens.stylex.ts
@@ -0,0 +1,5 @@
+import * as stylex from '@stylexjs/stylex';
+
+export const tokens = stylex.defineVars({
+ arrowTransform: 'translateX(0)',
+});
diff --git a/apps/nextjs-example/typetests/theming1.tsx b/apps/nextjs-example/typetests/theming1.tsx
index bda31c1d..dcd51134 100644
--- a/apps/nextjs-example/typetests/theming1.tsx
+++ b/apps/nextjs-example/typetests/theming1.tsx
@@ -21,10 +21,7 @@ import type {
const DARK = '@media (prefers-color-scheme: dark)';
const buttonTokens = stylex.defineVars({
- bgColor: {
- default: 'cyan',
- [DARK]: 'navy',
- },
+ bgColor: 'cyan',
textColor: {
default: 'black',
[DARK]: 'white',
@@ -74,7 +71,11 @@ type TokensType = TokensFromVarGroup;
}) satisfies TokensType;
const correctTheme = stylex.createTheme(buttonTokens, {
- bgColor: 'red',
+ bgColor: {
+ default: 'pink',
+ [DARK]: 'navy',
+ '@media (max-width: 700px)': 'red',
+ },
textColor: 'white',
cornerRadius: '4px',
paddingBlock: '4px',
diff --git a/packages/eslint-plugin/src/stylex-valid-styles.js b/packages/eslint-plugin/src/stylex-valid-styles.js
index 5a2d6c71..9e310391 100644
--- a/packages/eslint-plugin/src/stylex-valid-styles.js
+++ b/packages/eslint-plugin/src/stylex-valid-styles.js
@@ -2360,12 +2360,24 @@ const stylexValidStyles = {
);
}
const key = style.key;
+ if (key.type === 'PrivateIdentifier') {
+ return context.report(
+ ({
+ node: key,
+ loc: key.loc,
+ message: 'Private properties are not allowed in stylex',
+ }: Rule.ReportDescriptor),
+ );
+ }
const keyName =
key.type === 'Literal'
? key.value
: key.type === 'Identifier' && !style.computed
? key.name
: null;
+ if (isStylexDefineVarsToken(key, stylexDefineVarsTokenImports)) {
+ return undefined;
+ }
if (
typeof keyName !== 'string' ||
(key.type !== 'Literal' && key.type !== 'Identifier')
diff --git a/packages/shared/src/preprocess-rules/flatten-raw-style-obj.js b/packages/shared/src/preprocess-rules/flatten-raw-style-obj.js
index e7f74f38..643b8273 100644
--- a/packages/shared/src/preprocess-rules/flatten-raw-style-obj.js
+++ b/packages/shared/src/preprocess-rules/flatten-raw-style-obj.js
@@ -36,8 +36,11 @@ export function _flattenRawStyleObject(
const flattened: Array<
$ReadOnly<[string, AnyPreRule | PreIncludedStylesRule]>,
> = [];
- for (const key in style) {
- const value = style[key];
+ for (const _key in style) {
+ const value = style[_key];
+ const key: string = _key.match(/var\(--[a-z0-9]+\)/)
+ ? _key.slice(4, -1)
+ : _key;
// Included Styles
if (typeof value === 'object' && value instanceof IncludedStyles) {
diff --git a/packages/stylex/src/StyleXTypes.d.ts b/packages/stylex/src/StyleXTypes.d.ts
index 62589397..84288370 100644
--- a/packages/stylex/src/StyleXTypes.d.ts
+++ b/packages/stylex/src/StyleXTypes.d.ts
@@ -22,14 +22,12 @@ export type StyleXClassName = StyleXClassNameFor;
export type StyleXArray = T | ReadonlyArray>;
declare const StyleXVarTag: unique symbol;
-declare class StyleXVar extends String {
+declare class _StyleXVar {
private _opaque: typeof StyleXVarTag;
private _value: Val;
}
+export type StyleXVar = _StyleXVar & string;
-// Strings that don't start with a dollar sign.
-// So that we can `&` with {$$css: true} without type errors.
-type string = `${NonDollarChars}${string}`;
type PseudoClassStr = `:${string}`;
type AtRuleStr = `@${string}`;
@@ -82,10 +80,10 @@ export type StyleXSingleStyle = false | (null | undefined | NestedCSSPropTypes);
export type Keyframes = Readonly<{ [name: string]: CSSProperties }>;
export type LegacyThemeStyles = Readonly<{ [constantName: string]: string }>;
-type ComplexStyleValueType = T extends string | number | null
- ? T
- : T extends StyleXVar
+type ComplexStyleValueType = T extends StyleXVar
? U
+ : T extends string | number | null
+ ? T
: T extends ReadonlyArray
? U
: T extends Readonly<{ default: infer A; [cond: CondStr]: infer B }>
@@ -165,16 +163,16 @@ export type VarGroup<
[Key in keyof Tokens]: StyleXVar;
}> &
Readonly<{
- $opaqueId: ID;
- $tokens: Tokens;
+ __opaqueId: ID;
+ __tokens: Tokens;
}> &
typeof StyleXVarGroupTag;
export type TokensFromVarGroup> =
- T['$tokens'];
+ T['__tokens'];
export type IDFromVarGroup> =
- T['$opaqueId'];
+ T['__opaqueId'];
type TTokens = Readonly<{
[key: string]: string | { [key: string]: string };