diff --git a/packages/next-yak/README.md b/packages/next-yak/README.md
index 5d4c7187..69a2bcb1 100644
--- a/packages/next-yak/README.md
+++ b/packages/next-yak/README.md
@@ -16,8 +16,7 @@
- **Standard CSS Syntax**: Write styles in familiar, easy-to-use CSS
- **Integrates with Atomic CSS**: Easily combines with atomic CSS frameworks like Tailwind CSS for more design options
-
-
+[Preview (Video)](https://github.com/jantimon/next-yak/assets/4113649/5383f60c-3bab-4aba-906c-d66070b6116c)
## Installation
@@ -90,7 +89,7 @@ const ToggleButton = styled.button`
`;
```
-
+[Dynamic Styles (Video)](https://github.com/jantimon/next-yak/assets/4113649/c5f52846-33e4-4058-9c78-efd98197d75f)
### Dynamic Properties
@@ -121,7 +120,8 @@ const ExampleComponent = () => {
};
```
-
+[Dynamic Props (video)](https://github.com/jantimon/next-yak/assets/4113649/2fa78f82-382c-465f-b294-2504739ea168)
+
### Targeting Components
@@ -158,7 +158,7 @@ const ExampleComponent = () => {
## Nesting
`next-yak` supports nesting out of the box.
-Next.js 13 supports nesting only with the `postcss-nested` plugin.
+[For now](https://github.com/css-modules/postcss-modules-local-by-default/pull/64) Next.js 13 supports nesting only with the `postcss-nested` plugin.
Therefore you have to create a `postcss.config.js` file in your project root:
```js
@@ -170,6 +170,8 @@ module.exports = {
};
```
+[Nesting Example (video)](https://github.com/jantimon/next-yak/assets/4113649/33eeeb13-b0cf-499f-a1d3-ba6f51cf4308)
+
## Motivation
Most of the existing CSS-in-JS libraries are either slow or have a complex api. This project tries to find a middle ground between speed and api complexity.
diff --git a/packages/next-yak/loaders/__tests__/tsloader.test.ts b/packages/next-yak/loaders/__tests__/tsloader.test.ts
index 1ac0bc7f..4bfc337a 100644
--- a/packages/next-yak/loaders/__tests__/tsloader.test.ts
+++ b/packages/next-yak/loaders/__tests__/tsloader.test.ts
@@ -356,8 +356,7 @@ const Wrapper = styled.div\`
`);
});
- // TODO: this test was temporarily disabled because it was failing when inline css literals were introduced
- it.skip("should show error when mixin is used in nested selector", async () => {
+ it("should show error when mixin is used in nested selector", async () => {
await expect(() =>
tsloader.call(
loaderContext,
@@ -378,9 +377,36 @@ const Icon = styled.div\`
`
)
).rejects.toThrowErrorMatchingInlineSnapshot(`
- "/some/special/path/page.tsx: line 11: Expressions are not allowed inside nested selectors:
- \\"bold\\" inside \\"@media (min-width: 640px) { .bar {\\"
- found: \${bold}"
+ "/some/special/path/page.tsx: line 11: Mixins are not allowed inside nested selectors
+ found: \${bold}
+ Use an inline css literal instead or move the selector into the mixin"
+ `);
+ });
+
+ it("should show error when a mixin function is used in nested selector", async () => {
+ await expect(() =>
+ tsloader.call(
+ loaderContext,
+ `
+import { styled, css } from "next-yak";
+
+const bold = () => css\`
+ font-weight: bold;
+\`
+
+const Icon = styled.div\`
+ @media (min-width: 640px) {
+ .bar {
+ \${bold()}
+ }
+ }
+\`
+`
+ )
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
+ "/some/special/path/page.tsx: line 11: Mixins are not allowed inside nested selectors
+ found: \${bold()}
+ Use an inline css literal instead or move the selector into the mixin"
`);
});
@@ -406,9 +432,9 @@ const Icon = styled.div\`
`
)
).rejects.toThrowErrorMatchingInlineSnapshot(`
- "/some/special/path/page.tsx: line 11: Expressions are not allowed inside nested selectors:
- Expression inside \\"@media (min-width: 640px) { .bar {\\"
- found: \${() => css\`\${bold}\`}"
+ "/some/special/path/page.tsx: line 11: Mixins are not allowed inside nested selectors
+ found: \${bold}
+ Use an inline css literal instead or move the selector into the mixin"
`);
});
it("should show error when a dynamic selector is used", async () => {
diff --git a/packages/next-yak/loaders/babel-yak-plugin.cjs b/packages/next-yak/loaders/babel-yak-plugin.cjs
index 07839673..d871a9be 100644
--- a/packages/next-yak/loaders/babel-yak-plugin.cjs
+++ b/packages/next-yak/loaders/babel-yak-plugin.cjs
@@ -340,13 +340,17 @@ module.exports = function (babel, options) {
wasInsideCssValue = false;
if (expression) {
if (quasiTypes[i].currentNestingScopes.length > 0) {
- // TODO: inside a nested scope a foreign css literal must not be used
- // as we can not forward the scope.
- // Therefore the following code must throw an error:
- // import { mixin } from "./some-file";
- // const Button = styled.button`
- // &:focus { ${mixin} }
- // `
+ // inside a nested scope a foreign css literal must not be used
+ // as we can not forward the scope
+ const isReferenceToMixin = t.isIdentifier(expression) || t.isCallExpression(expression);
+ if (isReferenceToMixin) {
+ throw new InvalidPositionError(
+ `Mixins are not allowed inside nested selectors`,
+ expression,
+ this.file,
+ "Use an inline css literal instead or move the selector into the mixin"
+ );
+ }
}
newArguments.add(expression);
}
@@ -393,8 +397,9 @@ class InvalidPositionError extends Error {
* @param {string} message
* @param {import("@babel/types").Expression} expression
* @param {import("@babel/core").BabelFile} file
+ * @param {string} [recommendedFix]
*/
- constructor(message, expression, file) {
+ constructor(message, expression, file, recommendedFix) {
let errorText = message;
const line = expression.loc?.start.line ?? -1;
if (line !== -1) {
@@ -406,6 +411,9 @@ class InvalidPositionError extends Error {
expression.end
)}}`;
}
+ if (recommendedFix) {
+ errorText += `\n${recommendedFix}`;
+ }
super(errorText);
}
}
diff --git a/packages/next-yak/package.json b/packages/next-yak/package.json
index df5ef643..ad34d33a 100644
--- a/packages/next-yak/package.json
+++ b/packages/next-yak/package.json
@@ -1,6 +1,6 @@
{
"name": "next-yak",
- "version": "0.0.21",
+ "version": "0.0.22",
"type": "module",
"types": "./dist/",
"exports": {