Repository: microsoft/griffel (ts)

Issue:
Animation types have errors when animating CSS custom properties
When animating CSS custom properties Typescript raises an error:

> Type '{ "--my-var": string; }' is not assignable to type 'GriffelResetStylesCSSProperties'.
  Object literal may only specify known properties, and '"--my-var"' does not exist in type 'GriffelResetStylesCSSProperties'.ts(2322)

This issue affects both `makeStyles` and `makeResetStyles`. I believe it originates from #413 as this code worked prior to the type change.

Repro: https://codesandbox.io/s/griffel-css-animation-myhrq4?file=/src/index.tsx

NOTE: repro will only run in a Chrome and Edge at the time of this writing (and [maybe Safari](https://ishoudinireadyyet.com/), but haven't tested there).

This code is taking advantage of the fact that [registered custom properties are animatable](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties#animating_custom_properties). Technically custom properties can be used in animations without registering them, but animations are discrete in that case.

Would be nice for Griffel types to support custom properties in animations.

Pull request description:
fix(style-types): allow CSS variables in animationName
Fixes an issue with `animationName` (fixes #417) to allow usage of CSS variables in `animationName`. The fix is done for modern typings as legacy typings already allow it.

To make it strict, new syntax with template literals. Legacy types now used for TS 4.3 and earlier.

Patch:
diff --git a/change/@griffel-style-types-ce9ebd17-8bff-4a8f-977b-21c6d5621021.json b/change/@griffel-style-types-ce9ebd17-8bff-4a8f-977b-21c6d5621021.json
new file mode 100644
index 0000000..4a3cc89
--- /dev/null
+++ b/change/@griffel-style-types-ce9ebd17-8bff-4a8f-977b-21c6d5621021.json
@@ -0,0 +1,7 @@
+{
+  "type": "patch",
+  "comment": "fix: allow CSS variables in animationName, stricter types for selectors",
+  "packageName": "@griffel/style-types",
+  "email": "olfedias@microsoft.com",
+  "dependentChangeType": "patch"
+}
diff --git a/packages/style-types/package.json b/packages/style-types/package.json
index 17c4020..fee49e0 100644
--- a/packages/style-types/package.json
+++ b/packages/style-types/package.json
@@ -12,7 +12,7 @@
     "csstype": "^3.1.2"
   },
   "typesVersions": {
-    "<4.1": {
+    "<4.4": {
       "src/index.d.ts": [
         "src/legacy/index.d.ts"
       ]
diff --git a/packages/style-types/src/makeResetStyles.ts b/packages/style-types/src/makeResetStyles.ts
index 9261d7a..39cccfc 100644
--- a/packages/style-types/src/makeResetStyles.ts
+++ b/packages/style-types/src/makeResetStyles.ts
@@ -23,5 +23,8 @@ type GriffelCSSPseudos = {
   [Property in CSS.Pseudos]?: GriffelResetStylesStrictCSSObject | GriffelCSSObjectCustom;
 };
 
-export type GriffelResetAnimation = Record<'from' | 'to' | string, GriffelResetStylesCSSProperties>;
+export type GriffelResetAnimation = Record<
+  'from' | 'to' | string,
+  GriffelResetStylesCSSProperties & { [Property in `--${string}`]: string }
+>;
 export type GriffelResetStyle = GriffelResetStylesStrictCSSObject | GriffelCSSObjectCustom;
diff --git a/packages/style-types/src/makeStyles.ts b/packages/style-types/src/makeStyles.ts
index c96802e..d29eff2 100644
--- a/packages/style-types/src/makeStyles.ts
+++ b/packages/style-types/src/makeStyles.ts
@@ -27,5 +27,8 @@ type GriffelCSSPseudos = {
   [Property in CSS.Pseudos]?: GriffelStylesStrictCSSObject | GriffelCSSObjectCustom;
 };
 
-export type GriffelAnimation = Record<'from' | 'to' | string, GriffelStylesCSSProperties>;
+export type GriffelAnimation = Record<
+  'from' | 'to' | string,
+  GriffelStylesCSSProperties & { [Property in `--${string}`]: string }
+>;
 export type GriffelStyle = GriffelStylesStrictCSSObject | GriffelCSSObjectCustom;


Test patch:
diff --git a/e2e/typescript/src/assets/fixture-reset.ts b/e2e/typescript/src/assets/fixture-reset.ts
index 73c5921..1a03132 100644
--- a/e2e/typescript/src/assets/fixture-reset.ts
+++ b/e2e/typescript/src/assets/fixture-reset.ts
@@ -24,6 +24,12 @@ assertType({
     },
   ],
 });
+assertType({
+  animationName: {
+    from: { '--opacity': '0' },
+    to: { '--opacity': '1' },
+  },
+});
 
 assertType({
   // @ts-expect-error "200" is not a valid CSS value for "height"
@@ -31,6 +37,12 @@ assertType({
     to: { height: 200 },
   },
 });
+assertType({
+  // @ts-expect-error Only strings can be used as values for CSS variables
+  animationName: {
+    from: { '--opacity': 0 },
+  },
+});
 
 // Basic styles
 //
@@ -97,6 +109,11 @@ assertType({
   ':hover': { animationName: { from: {}, to: {} } },
 });
 
+assertType({
+  // @ts-expect-error Values of selectors can be only objects
+  ':hover': 'red',
+});
+
 // Custom selectors
 //
 
diff --git a/e2e/typescript/src/assets/fixture.ts b/e2e/typescript/src/assets/fixture.ts
index bf60a9b..9d8dba6 100644
--- a/e2e/typescript/src/assets/fixture.ts
+++ b/e2e/typescript/src/assets/fixture.ts
@@ -24,6 +24,12 @@ assertType({
     },
   ],
 });
+assertType({
+  animationName: {
+    from: { '--opacity': '0' },
+    to: { '--opacity': '1' },
+  },
+});
 
 assertType({
   // @ts-expect-error "200" is not a valid CSS value for "height"
@@ -31,6 +37,12 @@ assertType({
     to: { height: 200 },
   },
 });
+assertType({
+  // @ts-expect-error Only strings can be used as values for CSS variables
+  animationName: {
+    from: { '--opacity': 0 },
+  },
+});
 
 // Basic styles
 //
@@ -94,6 +106,11 @@ assertType({
   ':hover': { animationName: { from: {}, to: {} } },
 });
 
+assertType({
+  // @ts-expect-error Values of selectors can be only objects
+  ':hover': 'red',
+});
+
 // Custom selectors
 //
 
diff --git a/e2e/typescript/src/test.ts b/e2e/typescript/src/test.ts
index b6e9d8d..972a0cd 100644
--- a/e2e/typescript/src/test.ts
+++ b/e2e/typescript/src/test.ts
@@ -76,7 +76,8 @@ async function performTest(tsVersion: string, options: { mode?: 'legacy' | 'mode
 
 (async () => {
   await performTest('3.9', { mode: 'legacy' });
-  await performTest('4.1');
+  await performTest('4.1', { mode: 'legacy' });
+  await performTest('4.3', { mode: 'legacy' });
   await performTest('4.4');
   await performTest('4.9');
   await performTest('5.0');