+
A CSS-in-JS solution tailored for Next.js that seamlessly combines the
expressive power of styled-components syntax with efficient build-time
extraction of CSS using Next.js's built-in CSS configuration.
-
-
-
+
+
+
Get started
-
-
+
+
+
Github
-
-
-
+
+
+
+
+ Features
+
+
+ NextJs Compatibility
+ Works smoothly with both React Server and Client Components
+
+
+ Build-time CSS
+ Reduces load time by handling CSS during the build phase, using
+ Next.js built-in CSS Modules features
+
+
+ Lightweight Runtime
+ Operates with minimal impact, simply changing CSS classes without
+ modifying the CSSOM
+
+
+ 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
+
+
+ No significant build-time overhead
+ Doesn't increase the build time significantly, by only transforming
+ statically as much as possible without the need to evaluate arbitrary
+ JavaScript.
+
+);
diff --git a/packages/docs/content/docs/examples.mdx b/packages/docs/content/docs/examples.mdx
index 29f88729..aa9275d1 100644
--- a/packages/docs/content/docs/examples.mdx
+++ b/packages/docs/content/docs/examples.mdx
@@ -2,6 +2,8 @@
title: Examples
---
-## [Showcase](https://github.com/jantimon/next-yak/tree/main/packages/example)
+## Showcase
Small showcase of next-yak in action with all the features.
+
+Code: [https://github.com/jantimon/next-yak/tree/main/packages/example](https://github.com/jantimon/next-yak/tree/main/packages/example)
diff --git a/packages/docs/content/docs/faq.mdx b/packages/docs/content/docs/faq.mdx
index 7336886e..e86e1b60 100644
--- a/packages/docs/content/docs/faq.mdx
+++ b/packages/docs/content/docs/faq.mdx
@@ -1,25 +1,54 @@
---
title: FAQ
-# description: Next-yak is a featured packed static CSS-in-JS framework with a minimal runtime aspect.
---
## Is next-yak production ready?
-`next-yak` is still experimental but we are working hard to release a stable 1.0 version
+Yes, `next-yak` is production ready.
+
+Digitec Galaxus, the biggest online retailer in Switzerland, is using `next-yak` in production with a few thousand components
+and saw a significant improvement in their CSS and web vitals performance especially on mobile devices.
## Can I use next-yak with other frameworks than next.js?
-Not by now - feel free to ask for adding support for your framework in our github issue tracker and we will give it a thought.
+Not at the moment.
+
+Feel free to ask for adding support for your framework in our github issue tracker and we will give it a thought.
## Can I mix/combine next-yak with other CSS-in-JS libraries?
-Yes, you can use next-yak with other CSS-in-JS libraries. You can use it with styled-components, emotion, or any other library that
-adds css classes to your components.
+Yes, you can use next-yak with other CSS-in-JS libraries.
+
+You can use it with styled-components, emotion, tailwind or any other library that adds css classes to your components.
+
+```tsx title="my-component.tsx"
+import { styled, atoms } from 'next-yak';
+
+const Button = styled.button`
+ background: #BF4F74;
+ /* Use any other class */
+ :global(.my-class-from-another-library) {
+ color: white;
+ }
+ /* use tailwind classes */
+ ${atoms("mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8")}
+`;
+```
+
+## I get a compile time error in my app router page
+
+At the moment, there is an issue with styles in files that use the [metadata api](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) of next.js.
+
+We have an open issue for this problem and are working on a solution.
+See the [open next.js issue here](https://github.com/vercel/next.js/issues/67591)
+
+If it's not this issue, please read it carefully as it should indicate how to fix the problem.
## Can I reference a component in another component?
-Yes, you can reference it in the tagged template literal.
-```jsx
+Yes, you can reference it in the tagged template literal the same way you would to it with styled-components.
+
+```jsx title="my-component.tsx"
import { styled } from 'next-yak';
const Button = styled.button`
@@ -34,20 +63,127 @@ const Nav = styled.nav`
`;
```
-
-
-This doesn't work for components outside of the current file, as next-yak only considers one file at a time.
-
-
## Why does next-yak always generate CSS variables when the values are static references that are known at build time?
-It's very hard to determine if a value is static or dynamic. We decided to always generate CSS variables to be on the safe side
+It's very hard to determine statically if a value is static or dynamic. We decided to always generate CSS variables to be on the safe side
and add errors if we detect that a value is static but a CSS variable is used.
## Can I use next-yak with TypeScript?
-Yes, of course. `next-yak` is fully type safe.
+Yes, `next-yak` is fully type safe.
## Can I contribute to next-yak?
-Yes, of course. We are happy about every contribution. Just write an issue or a pull request [here](https://github.com/jantimon/next-yak)
\ No newline at end of file
+Yes.
+
+We are happy about every contribution. Just write an issue or a pull request [here](https://github.com/jantimon/next-yak)
+
+## I get an error about selector that are not pure
+
+If you get an error like this:
+
+
+Error: The selector "div" is not pure. It is not allowed to use a selector that is not pure.
+
+
+You are using the outdated version of postcss-nested, that is automatically bundled with next.js.
+
+You can update the dependency yourself by adding the package to your `package.json`:
+
+
+
+```bash
+npm i postcss-nested
+```
+
+
+```bash
+pnpm i postcss-nested
+```
+
+
+```bash
+yarn add postcss-nested
+```
+
+
+```bash
+bun add postcss-nested
+```
+
+
+
+and create a `postcss.config.cjs` file in your project root with the following content:
+
+```js title="postcss.config.cjs"
+module.exports = {
+ plugins: {
+ 'postcss-nested': {},
+ },
+};
+```
+
+Or you can add an ampersand to the selector:
+
+```jsx title="my-component.tsx"
+import { styled } from 'next-yak';
+
+const Button = styled.button`
+ background: #BF4F74;
+ & div {
+ color: white;
+ }
+`;
+```
+
+so that the old version of postcss-nested does not complain about the selector.
+
+For further information see the [issue on next-yak](https://github.com/jantimon/next-yak/issues/221) and the open [pull request on next.js](https://github.com/vercel/next.js/pull/72622).
+
+## My styles are not applied
+
+If your styles are not applied, the first thing you should check is the transformed output of your component.
+In order to do that, you can enable the `debug` option in the `withYak` function.
+
+
+
+```ts
+export default withYak({
+ experiments: {
+ debug: {
+ filter: (path: string) => path.includes("myPage"),
+ type: "all", // or "css" or "js"
+ },
+ },
+}nextConfig);
+```
+
+
+```js
+module.exports = withYak({
+ experiments: {
+ debug: {
+ filter: (path: string) => path.includes("myPage"),
+ type: "all", // or "css" or "js"
+ },
+ },
+}nextConfig);
+```
+
+
+```js
+export default withYak({
+ experiments: {
+ debug: {
+ filter: (path: string) => path.includes("myPage"),
+ type: "all", // or "css" or "js"
+ },
+ },
+}nextConfig);
+```
+
+
+
+This will log the transformed output of your component to the console.
+
+It could be a specificity issue, a wrong selector, or a wrong usage of the library and if you don't know why your styles are not applied, feel free to [open an issue](https://github.com/jantimon/next-yak/issues/new/choose).
diff --git a/packages/docs/content/docs/features.mdx b/packages/docs/content/docs/features.mdx
index 610497a5..8582e823 100644
--- a/packages/docs/content/docs/features.mdx
+++ b/packages/docs/content/docs/features.mdx
@@ -2,17 +2,15 @@
title: Features
description: Next-yak is a featured packed static CSS-in-JS framework with a minimal runtime aspect.
---
-import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
-
-
+import { Callout } from 'fumadocs-ui/components/callout';
## Static CSS
-At the heart of next-yak lies the extraction of static CSS.
-You can write your styles as you normally would with styled-components.
+At the heart of next-yak lies the extraction of static CSS.
+You can write your styles as you normally would with styled-components.
During build time, these styles are extracted, and your component is assigned a class that encapsulates these styles.
-```jsx
+```jsx title="my-component.tsx"
import { styled } from 'next-yak';
const Headline = styled.h1`
@@ -30,7 +28,7 @@ const Component = () => {
See transformed output
-
+
```jsx
const Headline = styled.h1`
font-size: 2rem;
@@ -58,21 +56,21 @@ const Headline = styled.h1('.Headline');
## Dynamic styles
-The static functionality itself is already very useful, but the bread and butter is an easy way to
-create dynamic styles. Styled-components popularized the approach of using props to drive dynamic CSS parts.
+The static functionality itself is already very useful, but the bread and butter is an easy way to
+create dynamic styles. Styled-components popularized the approach of using props to drive dynamic CSS parts.
With next-yak, you can use the exact same familiar API.
-
-
-```jsx
+
+
+```tsx twoslash
import { css, styled } from 'next-yak';
-const Paragraph = styled.p`
+const Paragraph = styled.p<{ $primary?: boolean }>`
background: ${props => props.$primary ? "#BF4F74" : "white"};
- ${props => props.$primary ?
+ ${props => props.$primary ?
css`
- color: white;
- ` :
+ color: white;
+ ` :
css`
color: #BF4F74
`};
@@ -90,16 +88,16 @@ const Component = () => {
}
```
-
-```tsx twoslash
+
+```jsx
import { css, styled } from 'next-yak';
-const Paragraph = styled.p<{ $primary?: boolean }>`
+const Paragraph = styled.p`
background: ${props => props.$primary ? "#BF4F74" : "white"};
- ${props => props.$primary ?
+ ${props => props.$primary ?
css`
- color: white;
- ` :
+ color: white;
+ ` :
css`
color: #BF4F74
`};
@@ -127,14 +125,14 @@ a CSS variable, which is set on the element itself directly based on the functio
See transformed output
-
+
```jsx
const Paragraph = styled.p`
background: ${props => props.$primary ? "#BF4F74" : "white"};
- ${props => props.$primary ?
+ ${props => props.$primary ?
css`
- color: white;
- ` :
+ color: white;
+ ` :
css`
color: #BF4F74;
`}
@@ -145,9 +143,9 @@ const Paragraph = styled.p`
```jsx
-const Paragraph = styled.p(
- '.Paragraph',
- props => props.$primary ? css('.propsprimary_0') : css('.not_propsprimary_1'),
+const Paragraph = styled.p(
+ '.Paragraph',
+ props => props.$primary ? css('.propsprimary_0') : css('.not_propsprimary_1'),
{
style: { '--var1': props => props.$primary ? "#BF4F74" : "white" }
}
@@ -175,18 +173,17 @@ const Paragraph = styled.p(
-
## Compatible with utility-first CSS frameworks (e.g. Tailwind)
-next-yak is fully compatible with utility-first CSS frameworks like Tailwind. Just use the `atoms` function to
+Next-yak is fully compatible with utility-first CSS frameworks like Tailwind. Just use the `atoms` function to
reference classes from these frameworks.
-
-
-```jsx
+
+
+```tsx twoslash
import { styled, atoms } from 'next-yak';
-const Header = styled.nav`
+const Header = styled.nav<{ $variant?: 'primary' | 'secondary' }>`
${({$variant}) => $variant === "primary"
? atoms("mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8")
: atoms("bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow")
@@ -194,11 +191,11 @@ const Header = styled.nav`
`
```
-
-```tsx twoslash
+
+```jsx
import { styled, atoms } from 'next-yak';
-const Header = styled.nav<{ $variant?: 'primary' | 'secondary' }>`
+const Header = styled.nav`
${({$variant}) => $variant === "primary"
? atoms("mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8")
: atoms("bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow")
@@ -212,7 +209,7 @@ const Header = styled.nav<{ $variant?: 'primary' | 'secondary' }>`
See transformed output
-
+
```jsx
const Header = styled.nav`
${({$variant}) => $variant === "primary"
@@ -225,8 +222,8 @@ const Header = styled.nav`
```jsx
const Header = styled.nav('.Header',
- ({$variant}) => $variant === "primary"
- ? atoms("mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8")
+ ({$variant}) => $variant === "primary"
+ ? atoms("mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8")
: atoms("bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow"))
```
@@ -239,7 +236,7 @@ const Header = styled.nav('.Header',
In order to create CSS animations, you can use the `keyframes` API and specify the keyframes for the animation
you want to create. This can be used in your animation declarations within the same file.
-```jsx
+```jsx title="my-component.tsx"
import { keyframes, styled } from 'next-yak';
const fadeIn = keyframes`
@@ -260,7 +257,7 @@ const FadeInButton = styled.button`
See transformed output
-
+
```jsx
const fadeIn = keyframes`
0% {
@@ -308,7 +305,7 @@ const FadeInButton = styled.button('.FadeInButton', {
Mixins are declarations of the `css` utility function. You can declare a variable which holds the css declaration and
use it inside your `styled` declarations.
-```jsx
+```jsx title="my-component.tsx"
import { css, styled } from 'next-yak';
const mixin = css`
@@ -323,7 +320,7 @@ const MyComp = styled.div`
You can also make it dynamic, where the props are passed to the mixin.
-```jsx
+```jsx title="my-component.tsx"
import { css, styled } from 'next-yak';
const mixin = css`
@@ -342,7 +339,7 @@ During build time the CSS literal is converted to a class name (or multiple clas
See transformed output
-
+
```jsx
const mixin = css`
color: ${(props) => props.$green ? 'green' : 'blue'};
@@ -367,11 +364,11 @@ const MyComp = styled.div('MyComp', mixin);
```css
-.mixin_0 {
+.mixin_0 {
color: var(--yakVar1);
}
-.MyComp {
+.MyComp {
background-color: yellow;
}
```
@@ -385,23 +382,23 @@ const MyComp = styled.div('MyComp', mixin);
You may noticed that we sometimes used css`` and sometimes just a literal string. If the property name is already
present and you want to have dynamic values of that property, you can just use literal strings. These get transformed into CSS variables during build time.
-
-
-```jsx
+
+
+```tsx twoslash
import { styled } from 'next-yak';
-const Box = styled.div`
+const Box = styled.div<{ $variant: "primary" | "secondary", $color: string }>`
font-size: ${props => props.$variant === "primary" ? "2rem" : "1rem" };
color: ${props => props.$color};
display: flex;
`
```
-
-```tsx twoslash
+
+```jsx
import { styled } from 'next-yak';
-const Box = styled.div<{ $variant: "primary" | "secondary", $color: string }>`
+const Box = styled.div`
font-size: ${props => props.$variant === "primary" ? "2rem" : "1rem" };
color: ${props => props.$color};
display: flex;
@@ -417,7 +414,7 @@ The value of the CSS variable is set via the style property of the component, en
See transformed output
-
+
```jsx
const Box = styled.div`
font-size: ${props => props.$variant === "primary" ? "2rem" : "1rem" };
@@ -429,9 +426,9 @@ const Box = styled.div`
```jsx
const Box = styled.div('.Box', {
- style: {
- '--var1': props => props.$variant === "primary" ? "2rem" : "1rem",
- '--var2': props => props.$color
+ style: {
+ '--var1': props => props.$variant === "primary" ? "2rem" : "1rem",
+ '--var2': props => props.$color
}
})
```
@@ -450,12 +447,16 @@ const Box = styled.div('.Box', {
## Theming
+
+ As of next.js >15.0.0, this feature doesn't work with server components anymore.
+
+
As your application grows, theming becomes increasingly important as a shortcut to pass the same values to components.
Next-yak integrates it in a hassle free manner that works for both Server Components and Client Components without
a difference in usage for you. Wrap your root with the ThemeProvider and add a `yak.context.ts` file to your root directory
and you're ready to go.
-```tsx twoslash
+```tsx twoslash title="yak.context.ts"
// @noErrors
import { cookies } from 'next/headers'
import { cache } from "react";
@@ -478,24 +479,7 @@ declare module "next-yak" {
Once this context file is in place, you can access the theme props on every component.
-
-
-```jsx
-import { styled, css } from 'next-yak';
-
-const Button = styled.button`
- display: block;
- ${(props) =>
- props.theme.highContrast
- ? css`
- color: #000;
- `
- : css`
- color: #009688;
- `}
-`;
-```
-
+
```tsx twoslash
//@noErrors
@@ -520,6 +504,23 @@ declare module "next-yak" {
// ---cut---
import { styled, css } from 'next-yak';
+const Button = styled.button`
+ display: block;
+ ${(props) =>
+ props.theme.highContrast
+ ? css`
+ color: #000;
+ `
+ : css`
+ color: #009688;
+ `}
+`;
+```
+
+
+```jsx
+import { styled, css } from 'next-yak';
+
const Button = styled.button`
display: block;
${(props) =>
@@ -541,21 +542,21 @@ We support out of the box the `css` prop which is a shorthand for adding styles
it allows you to write local styles for certain elements on your page. Differently than inline-styles, it allows you to use
selectors that target wrapped elements.
-```jsx
+```jsx title="my-component.tsx"
import { css } from 'next-yak';
const Component = () => {
- return
Hello there!
+ return
Hello there!
}
```
-It's meant for simple styling requirements, where you don't have to think about a name for a specialized component.
+It's meant for simple styling requirements, where you don't have to think about a name for a specialized component.
### TypeScript
To use it with the correct types just add the following line to the top of the file
-```tsx
+```tsx title="my-component.tsx"
/** @jsxImportSource next-yak */ // [!code hl]
import { css } from 'next-yak';
@@ -567,10 +568,10 @@ const Component = () => {
Or just add this to your `tsconfig.json` and all your css props will have the correct types.
-```json
+```json title="tsconfig.json"
{
"compilerOptions": {
- "jsxImportSource": "next-yak"
+ "jsxImportSource": "next-yak" // [!code hl]
}
}
-```
\ No newline at end of file
+```
diff --git a/packages/docs/content/docs/getting-started.mdx b/packages/docs/content/docs/getting-started.mdx
index 4dfc9a5e..9027475c 100644
--- a/packages/docs/content/docs/getting-started.mdx
+++ b/packages/docs/content/docs/getting-started.mdx
@@ -8,10 +8,16 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
# next-yak
-**next-yak** is a CSS-in-JS solution tailored for [Next.js](https://nextjs.org/) that seamlessly combines
-the expressive power of styled-components syntax with efficient build-time extraction of CSS using
+**next-yak** is a CSS-in-JS solution tailored for [Next.js](https://nextjs.org/) that seamlessly combines
+the expressive power of styled-components syntax with efficient build-time extraction of CSS using
Next.js's built-in CSS configuration.
+| next-yak | Next.js | react | swc_core |
+|------------------|-----------------|------------------|------------------|
+| 4.x | >= 15.0.4 | 19.x | 5.0.1 |
+| 3.x | 15.x | 18.x / 19.x | 3.0.2 |
+| 2.x | 14.x | 18.x / 19.x | 0.279.0 |
+
## Installation
@@ -23,23 +29,39 @@ Install next-yak dependency using your favorite package manager.
-```bash
-npm i next-yak
+```bash
+# For Next.js >= 15.0.4
+npm i next-yak@4
+
+# For Next.js 14.x
+npm i next-yak@2
```
-```bash
-pnpm i next-yak
+```bash
+# For Next.js >= 15.0.4
+pnpm i next-yak@4
+
+# For Next.js 14.x
+pnpm i next-yak@2
```
```bash
-yarn add next-yak
+# For Next.js >= 15.0.4
+yarn i next-yak@4
+
+# For Next.js 14.x
+yarn i next-yak@2
```
-```bash
-bun add next-yak
+```bash
+# For Next.js >= 15.0.4
+bun i next-yak@4
+
+# For Next.js 14.x
+bun i next-yak@2
```
@@ -48,16 +70,17 @@ bun add next-yak
### Enable next-yak
-Add next-yak to your `next.config.mjs` or `next.config.js`:
+Add next-yak to your next configuration file:
-
-
-```js
+
+
+```ts
+import type { NextConfig } from 'next'
import { withYak } from "next-yak/withYak";
-const nextConfig = {
+const nextConfig: NextConfig = {
// your next.js config
-};
+}
export default withYak(nextConfig);
```
@@ -73,16 +96,30 @@ const nextConfig = {
module.exports = withYak(nextConfig);
```
+
+```js
+import { withYak } from "next-yak/withYak";
+
+const nextConfig = {
+ // your next.js config
+};
+
+export default withYak(nextConfig);
+```
+
### Start using next-yak
-With the installation and configuration done, you can now use next-yak directly in your components. Here's a simple example:
+With the installation and configuration done, you can now use next-yak directly in your components.
+If you used `styled-components` before, you'll feel right at home.
+
+Here's a simple example:
-```jsx [pages/index.tsx]
+```jsx title="app/page.tsx"
import { styled } from 'next-yak';
const StyledDiv = styled.div`
@@ -98,7 +135,8 @@ function HomePage() {
export default HomePage;
```
-You're now ready to use next-yak in your Next.js project.
+You're now ready to use next-yak in your Next.js project and if you need to migrate from styled-components, you can follow the [migration guide](/docs/migration-from-styled-components).
+
-
\ No newline at end of file
+
diff --git a/packages/docs/content/docs/how-does-it-work.mdx b/packages/docs/content/docs/how-does-it-work.mdx
index 9635dc27..dab3eee3 100644
--- a/packages/docs/content/docs/how-does-it-work.mdx
+++ b/packages/docs/content/docs/how-does-it-work.mdx
@@ -3,6 +3,8 @@ title: How does it work
description: This is for the curious minds who want to know how `next-yak` works under the hood and it's not necessary to understand it in order to use it.
---
+## Playground
+
A live playground to see the code transformation can be found [here](/playground).
## The basics
@@ -13,26 +15,38 @@ A live playground to see the code transformation can be found [here](/playground
2. The runtime part
3. Optional: Context
-The compile time part is responsible for extracting styles and transforming your code into something that uses
-the runtime part. The runtime part is responsible for merging styles and props.
+The compile time part is responsible for extracting styles and transforming your code into something that uses
+the runtime part. The runtime part is responsible for merging styles and props.
## The compile time part
-`next-yak` uses two webpack loaders to transform your code. The first loader is responsible for transforming the
-usages of the tagged template literals (like `styled` and `css`), the second loader reads the results from the first loader, resolves cross module dependencies and writes the finished css in a css module file.
+`next-yak` uses an SWC plugin and an additional webpack loader to transform your code. The plugin is responsible for transforming the
+usages of the tagged template literals (like `styled` and `css`), while the loader reads the results from the plugin, resolves cross module dependencies and writes the finished css in a css-modules file.
+
+### The SWC plugin
-### The first loader [(ts-loader.ts)](https://github.com/jantimon/next-yak/blob/main/packages/next-yak/loaders/ts-loader.ts)
+See: [yak-swc](https://github.com/jantimon/next-yak/tree/main/packages/yak-swc)
-The first loader takes in the source code and transforms the tagged template literals into `next-yak` runtime function
-calls with the imported styles (from the final css module output) as arguments. It also transforms the dynamic parts of the
+The SWC plugin takes in the source code and transforms the tagged template literals into `next-yak` runtime function
+calls with the imported styles (from the final css module output) as arguments. It also transforms the dynamic parts of the
tagged template literals into function calls with the properties as argument and adds it as css value to the style object.
+#### Change import
+
+The first step of the transformation is to change the import statement from `styled` and `css` to the `next-yak` runtime.
+
+```tsx title="output"
+import { styled, css } from "next-yak/internal";
+```
+
+The normal import just references a kind of stub behavior to be used in tests without the need to have a transpilation step.
+
#### Add style import
-The first step of the transformation is to add the import statement for the styles. These styles don't exist yet, but
-will be generated by the second loader.
+The next step of the transformation is to add the import statement for the styles. These styles don't exist yet, but
+will be generated by the webpack loader at a later stage.
-```tsx [output]
+```tsx title="output"
import __styleYak from "./page.yak.module.css!=!./page?./page.yak.module.css";
```
@@ -40,15 +54,18 @@ This strange looking import string is a poorly documented feature of webpack. It
that points to the current file (`./page`). In order that this import statement works in next.js, we need to add
a query parameter that ends with `.module.css`, as this is the way next.js recognizes CSS modules.
-So that means `./page.yak.module.css` is a virtual file that is generated by the second loader and contains the
-styles of the current file. `./page.yak.module.css!=!./page` says that the second loader (matching `.yak.module.css` files) should
+This recognition is not always working correctly as seen with the various issues & PR's we created on the next.js repository like [this one](https://github.com/vercel/next.js/pull/51115),
+[this one](https://github.com/vercel/next.js/pull/53796) or [this one](https://github.com/vercel/next.js/pull/64551).
+
+So that means `./page.yak.module.css` is a virtual file that is afterwards generated by the webpack loader and contains the
+styles of the current file. `./page.yak.module.css!=!./page` says that the loader (matching `.yak.module.css` files) should
be used with the current file as input. Lastly `?./page.yak.module.css` is the query parameter that tells next.js that this
is a CSS module and it's loaders should be used.
#### Transform tagged template literals
-As the next step, the tagged template literals are transformed into `next-yak` runtime function calls. The static
-CSS parts are passed as references to the class names from the "not yet generated" css module file.
+In another step, the tagged template literals are transformed into `next-yak` runtime function calls. The static
+CSS parts are passed as references to the class names from the "not yet generated" css-modules file.
@@ -70,10 +87,10 @@ const Button = styled.button`
```tsx
-import { styled } from "next-yak";
+import { styled } from "next-yak/internal";
import __styleYak from "./page.yak.module.css!=!./page?./page.yak.module.css";
-const Button = styled.button(__styleYak.Button); // [!code focus]
+const Button = styled.button(__styleYak.Button); // [!code hl]
```
@@ -95,10 +112,10 @@ import { styled, css } from "next-yak";
const Button = styled.button`
font-size: 2rem;
font-weight: bold;
- color: ${props => props.$primary ? "white" : "blue"}; // [!code focus]
- ${props => props.$primary ? css`background: black;` : css`background: white;`} // [!code focus]
+ color: ${props => props.$primary ? "white" : "blue"}; // [!code hl]
+ ${props => props.$primary ? css`background: black;` : css`background: white;`} // [!code hl]
&:hover {
- color: ${props => props.$primary ? "red" : "blue"}; // [!code focus]
+ color: ${props => props.$primary ? "red" : "blue"}; // [!code hl]
}
`;
```
@@ -107,45 +124,115 @@ const Button = styled.button`
```tsx
-import { styled, css } from "next-yak";
+import { styled, css } from "next-yak/internal";
import __styleYak from "./page.yak.module.css!=!./page?./page.yak.module.css";
-const Button = styled.button(
- __styleYak.Button,
- props => props.$primary ? css(__styleYak.propsprimary_0) : css(__styleYak.not_propsprimary_1), // [!code focus]
- {
+
+const Button = styled.button(__styleYak.Button,
+ (props)=>props.$primary
+ ? css(__styleYak.Button__props_$primary)
+ : css(__styleYak.Button__props_$primary1),
+ {
"style": {
- "--\uD83E\uDDAC18fi82j0": props => props.$primary ? "white" : "blue", // [!code focus]
- "--\uD83E\uDDAC18fi82j1": props => props.$primary ? "red" : "blue" // [!code focus]
+ "--yrRH4Ik": (props)=>props.$primary ? "white" : "blue",
+ "--yrRH4Ik1": (props)=>props.$primary ? "red" : "blue"
}
+ }
+);
+```
+
+
+
+
+#### Transform CSS
+
+The next step is to extract the CSS to a comment in the source code. This is useful because the transformation should happen
+as quickly as possible and this is way easier and faster with the SWC plugin instead of the webpack loader and we're
+already transforming the current file.
+
+
+
+
+```tsx
+import { styled, css } from "next-yak";
+
+const Button = styled.button`
+ font-size: 2rem;
+ font-weight: bold;
+ color: ${props => props.$primary ? "white" : "blue"};
+ ${props => props.$primary ? css`background: black;` : css`background: white;`}
+ &:hover {
+ color: ${props => props.$primary ? "red" : "blue"};
+ }
+`;
+```
+
+
+
+
+```tsx
+import { styled, css } from "next-yak/internal";
+import __styleYak from "./index.yak.module.css!=!./index?./index.yak.module.css";
+
+const Button = /*YAK Extracted CSS:
+.Button {
+ font-size: 2rem;
+ font-weight: bold;
+ color: var(--yrRH4Ik);
+}
+.Button__props_$primary {
+ background: black;
+}
+.Button__props_$primary1 {
+ background: white;
+}
+.Button {
+ &:hover {
+ color: var(--yrRH4Ik1);
+ }
+}
+*/ /*#__PURE__*/ styled.button(__styleYak.Button, (props)=>props.$primary ? css(__styleYak.Button__props_$primary) : css(__styleYak.Button__props_$primary1), {
+ "style": {
+ "--yrRH4Ik": (props)=>props.$primary ? "white" : "blue",
+ "--yrRH4Ik1": (props)=>props.$primary ? "red" : "blue"
+ }
});
```
-### The second loader [(css-loader.ts)](https://github.com/jantimon/next-yak/blob/main/packages/next-yak/loaders/ts-post-loader.ts)
+The comment gets marked with `/*YAK Extracted CSS:` so that the loader can easily find it and extract the CSS.
+Additionally, the comment is marked with `/*#__PURE__*/` so that the minifier knows that behind the runtime function call there is no side effect and can move it around.
+
+### The webpack loader
+
+See: [css-loader.ts](https://github.com/jantimon/next-yak/blob/main/packages/next-yak/loaders/css-loader.ts)
The second loader takes the output of the first loader and resolves the cross module dependencies. The result is valid CSS that will be written to the context.
#### Resolve cross module dependencies
-To resolve cross module dependencies, the first loader generates a unique string to signal the second loader that this is a dependency with a specific name. The second loader then reads the generated CSS from the first loader and resolves the dependencies.
-Once the final css is generated the loader hands it over as a CSS module file so it can be processed by Next.js like a normal CSS module file.
+To resolve cross module dependencies, the first loader generates a unique string to signal the second loader that this is a dependency with a specific name. The second loader then reads the generated CSS from the SWC plugin and resolves the dependencies.
+Once the final css is generated the loader hands it over as a CSS module file so it can be processed by Next.js like a normal css-modules file.
## The runtime part
-The runtime part is responsible for merging styles and props. It's a simple function that takes in the styles and the props and returns the merged styles.
+See: [styled.tsx](https://github.com/jantimon/next-yak/blob/main/packages/next-yak/runtime/styled.tsx)
-See: [Styled function](https://github.com/jantimon/next-yak/blob/main/packages/next-yak/runtime/styled.tsx)
+The runtime part is responsible for merging styles and props. It's a simple function that takes in the styles and the props and returns the merged styles.
A lot of this code is types and comments to indicate why certain things are done. The actual runtime code is very small.
## Context
+
+ As of next.js >15.0.0, this feature doesn't work with server components anymore.
+
+
The yak theme context allows you to configure the theme of your yak application. It works for react-server components
-and normal react components.
+and normal react components.
-The first part of the puzzle is to export two different modules for the server and the client.
+The first part of the puzzle is to export two different modules for the server and the client.
```json
"./context": {
@@ -272,7 +359,7 @@ it points to the individual `yak.context.ts` file in the root directory.
```ts
-// With the following alias the internal next-yak code
+// With the following alias the internal next-yak code
// is able to import a context which works for server components
const yakContext = resolveYakContext(yakOptions.contextPath, webpackConfig.context);
if (yakContext) {
@@ -281,4 +368,4 @@ if (yakContext) {
```
-
\ No newline at end of file
+
diff --git a/packages/docs/content/docs/migration-from-styled-components.mdx b/packages/docs/content/docs/migration-from-styled-components.mdx
index 26609411..6d32dbf6 100644
--- a/packages/docs/content/docs/migration-from-styled-components.mdx
+++ b/packages/docs/content/docs/migration-from-styled-components.mdx
@@ -1,514 +1,512 @@
---
title: Migration from styled-components
-description: We tried to keep the changes you need to know if you're already familiar with styled-components to a minimum.
+description: next-yak provides a RSC compatible API which is very similar to the styled-components API. In most cases the only change necessary is the import. However there are some edge cases which have to be migrated manually.
---
+import { Callout } from 'fumadocs-ui/components/callout';
-## Familiar API
+## Guide
-### styled
+One of the core goals of `next-yak` is to provide a seamless migration path from `styled-components` to `next-yak`.
+This comprehensive guide will walk you through the migrating, covering common scenarios and edge cases you might encounter.
-You can use the `styled` tag as you know for all kind of elements.
+## Feature comparison
-
-
-```jsx
-import styled from 'styled-components';
+Supported
+- Styled syntax (incl. static and dynamic parts)
+- Css tagged template literal
+- Css prop
+- Keyframes
+- Attrs
+- References to other components
+- Mixins
+- If some features are missing, please let us know and open a feature request on [GitHub](https://github.com/jantimon/next-yak/issues/new/choose)
-const Button = styled.button`
- background: #BF4F74;
-`;
+Missing
+- Object syntax
+- Dynamic usage of the css prop
+- `.withConfig`
+- Special handling for the `as` prop
+- CreateGlobalStyle - You can just import any global styles in your files directly
+- As of next.js 15, the server components theme provider is not supported. We are working on a solution for this.
-const Nav = styled.nav`
- background: #BF4F74;
-`;
-```
-
-
-```tsx twoslash
-import { styled } from 'next-yak';
-const Button = styled.button`
- background: #BF4F74;
-`;
+## Just change the import
-const Nav = styled.nav`
- background: #BF4F74;
-`;
+You need to do the least amount of work for the following changes. All other changes build upon this one.
+Just change the import from `styled-components` to `next-yak` and change the import of `styled` from a default import to a named import.
+
+```tsx title="component.tsx"
+import styled, { css, keyframes } from 'styled-components'; // [!code --]
+import { styled, css, keyframes } from 'next-yak'; // [!code ++]
```
-
-
-You can use static or dynamic parts the same way you would use it in styled-components.
+### Static component styles
-
-
-```jsx
-import styled from 'styled-components';
+For components with static styles, simply updating the import is sufficient:
-const Button = styled.button<{ $primary: boolean }>`
- background: #BF4F74;
- color: ${props => props.$primary ? "white" : "#BF4F74"};
-`;
-```
-
-
-```tsx twoslash
-import { styled } from 'next-yak';
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
-const Button = styled.button<{ $primary: boolean }>`
- background: #BF4F74;
- color: ${props => props.$primary ? "white" : "#BF4F74"};
+const Button = styled.button`
+ background: #BF4F74;
+ color: white;
+ padding: 1em 2em;
+ border-radius: 4px;
+ transition: all 0.2s ease-in-out;
+
+ &:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ }
`;
```
-
-
+
+**Important Note on Selectors**:
+While most selectors work out of the box, you might encounter the error: `Selector "h1" is not pure (pure selectors must contain at least one local class or id)`. To resolve this, either:
+1. Update your Next.js PostCSS version
+2. Add an ampersand (&) before the selector
-### css
+For more detailed information, refer to the [FAQ](/docs/faq#i-get-an-error-about-selector-that-are-not-pure).
+
-The `css` tagged template literal in styled-components is used when you want to use a dynamic
-CSS part "outside" of the styled literal. Next-yak works similar but with the difference that you
-should use it everytime you want to have dynamic properties where the CSS property isn't known
-in the outside literal.
+### Static mixins
-
-
-```jsx
-import styled from 'styled-components';
+For static mixins, you can just change the import and you're done.
-const Button = styled.button<{ $primary: boolean }>`
- background: #BF4F74;
- ${props => props.$primary ? "color: white;" : "color: #BF4F74;"}
-`;
-```
-
-
-```tsx twoslash
-import { styled, css } from 'next-yak';
+```tsx title="component.tsx"
+import styled, { css } from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
-const Button = styled.button<{ $primary: boolean }>`
- background: #BF4F74;
- ${props => props.$primary ? css`color: white` : css`color: #BF4F74`}
+const mixin = css`
+ color: green;
+ font-size: 1rem;
`;
-```
-
-
-
-Next-yak transforms `css` code into a class name that is referenced. So you can think of it as
-an additional css class that gets added/subtracted as needed.
-
-#### css prop
-
-Also the css prop works similar to styled-components. The main difference is that you can't use
-dynamic values in the css prop and that you have to use the `css` tag to define the css.
-
-
-
-```jsx
-
props.theme.colors.text};
- `}
-/>
-
-```
-
-
-```tsx
-import { css } from 'next-yak';
-
-
-
-```
-
-
-
-If you use TypeScript, you can just add the following to your `tsconfig.json` to get type checking for the css prop.
-```json
-{
- "compilerOptions": {
- "jsxImportSource": "next-yak"
- }
-}
+const MyComp = styled.div`
+ background-color: yellow;
+ ${mixin};
+`;
```
+This counts for all static mixins that you use in your styled components including exported mixins.
-### keyframes
+
+**Important note on semicolons**:
+You need to add a semicolon after the mixin to separate it from the rest of the styles.
+Otherwise the parser can not differentiate between a selector, a constant or a mixin.
+
-The api for keyframes is exactly the same as in styled-components. You can define your keyframes
-and use it in your animations.
+### Keyframes
+For keyframes you can just change the import and you're done.
-
-
-```jsx
-import styled, { keyframes } from 'styled-components';
+```tsx title="component.tsx"
+import styled, { keyframes } from 'styled-components'; // [!code --]
+import { styled, keyframes } from 'next-yak'; // [!code ++]
const rotate = keyframes`
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
`;
const Rotate = styled.div`
- display: inline-block;
- animation: ${rotate} 2s linear infinite;
- padding: 2rem 1rem;
- font-size: 2rem;
+ display: inline-block;
+ animation: ${rotate} 2s linear infinite;
+ padding: 2rem 1rem;
+ font-size: 2rem;
`;
```
-
-
-```tsx
-import { styled, keyframes } from 'next-yak';
-const rotate = keyframes`
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-`;
+### Component references
-const Rotate = styled.div`
- display: inline-block;
- animation: ${rotate} 2s linear infinite;
- padding: 2rem 1rem;
- font-size: 2rem;
+Styling based on other components remains straightforward. You just need to change the import
+
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
+import { Button } from './button';
+
+const Container = styled.div`
+ ${Button} {
+ color: red;
+ margin: 0.5em;
+
+ &:hover {
+ color: darkred;
+ }
+ }
`;
```
-
-
-### attrs
+### Attrs
-Next-yak also enables `.attrs` on your components and has the same behaviour as in styled-components
+If you use `.attrs` in your styled components, you can just change the import and you're done.
-
-
-```jsx
-import styled from 'styled-components';
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
const Input = styled.input.attrs(props => ({
- type: "text",
- size: props.size || "1em"
+ type: "text",
+ size: props.size || "1em"
}))`
- color: palevioletred;
- font-size: 1em;
- border: 2px solid palevioletred;
- border-radius: 3px;
+ color: palevioletred;
+ font-size: 1em;
+ border: 2px solid palevioletred;
+ border-radius: 3px;
`;
```
-
-
-```tsx
-import { styled } from 'next-yak';
-const Input = styled.input.attrs(props => ({
- type: "text",
- size: props.size || "1em"
-}))`
- color: palevioletred;
- font-size: 1em;
- border: 2px solid palevioletred;
- border-radius: 3px;
+The same applies to the `.attrs` function for wrapped components.
+
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
+import { Button, type ButtonProps } from './button';
+
+const LocalButton = styled(Button).attrs>(() => ({
+ tabIndex: 0,
+ }))`
+ color: red;
`;
```
-
-
-### References to other components
+## Change some more things
-In order to create a selector that includes another component, you can just reference it in the tagged
-template literal.
+The last part of the migration guide is about more complex cases where you need to change a bit more than just the import.
-
-
-```jsx
-import styled from 'styled-components';
+### Dynamic component styles
-const Button = styled.button`
- color: blue;
-`;
+This will be the most complex part of the migration. Next-yak differentiates between dynamic css properties and property values which is different than styled-components.
+If you use property values you shouldn't need to change more than the import.
-const Wrapper = styled.div`
- ${Button} {
- color: red;
- }
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
+
+const Button = styled.button<{ $primary: boolean }>`
+ background: #BF4F74;
+ color: ${props => props.$primary ? "white" : "#BF4F74"};
`;
```
-
-
-```tsx
-import { styled } from 'next-yak';
+This will be transformed to a css variable that gets injected during build time.
+
+```tsx title="transformed.tsx"
+// pseudo code
const Button = styled.button`
- color: blue;
+ background: #BF4F74;
+ color: var(--next-yak-1);
`;
+```
+
+If you use dynamic css properties, you need to use the `css` tag to define the css.
-const Wrapper = styled.div`
- ${Button} {
- color: red;
- }
+```tsx title="component.tsx"
+import styled, { css } from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
+
+const Button = styled.button<{ $primary: boolean }>`
+ background: #BF4F74;
+ ${props => props.$primary
+ ? ` // [!code --]
+ ? css` // [!code ++]
+ color: white;
+ font-size: 1rem;
+ padding: 1em 2em;
+ : ` // [!code --]
+ : css` // [!code ++]
+ color: #BF4F74;
+ font-size: 2rem;
+ padding: 2em 4em;
+ `
+ }
`;
```
-
-
-During build time the reference is changed to the actual generated class name of the referenced component.
+When next-yak encounters a css tag, it will transform the css into a class name that gets injected during build time.
-### Mixins
+```tsx title="transformed.tsx"
+// pseudo code
-Mixins allow you to predefine CSS styles and reuse them across components. You can just create mixins the same
-way as you would with styled-components.
+const Button = (props) =>
+
+```
-
-
-```jsx
-import styled, { css } from 'styled-components';
+You can nest the css tags arbitrarily deep and next-yak will transform them into class names and css variables.
+It's important to note that you can't nest arbitrary styles inside property values, but you can nest property values inside css tags.
+Generally, you should try to simplify your styles and avoid nesting as much as possible to keep your styles as fast as possible.
-const mixin = css`
- color: green;
+### Dynamic mixins
+
+If you use dynamic mixins in your styled components, you need to change it the same way as you would with dynamic component styles.
+
+```tsx title="component.tsx"
+import styled, { css } from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
+
+const mixin = css<{ $primary: boolean }>`
+ color: green;
+
+ ${props => props.$primary
+ ? css`
+ background: white;
+ `
+ : css`
+ background: black;
+ `
+ }
`;
-const MyComp = styled.div`
- background-color: yellow;
- ${mixin}
+const MyComp = styled.div<{ $primary: boolean }>`
+ background-color: yellow;
+ ${mixin};
`;
```
-
-
-```tsx
-import { css, styled } from 'next-yak';
-const mixin = css`
- color: green;
-`;
+Dynamic mixins work differently in next-yak than in styled-components. With next-yak you're currently not able to export a dynamic mixin and use it in other components.
+As we transform the styles on a per-file basis, we can't share dynamic values between files. If you need to use a dynamic mixin in multiple components, you unfortunately need to duplicate the mixin in each file or move the components to the same file.
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
-const MyComp = styled.div`
- background-color: yellow;
- ${mixin}
+import { mixin } from './mixin'; // [!code --]
+const mixin = css<{ $primary: boolean }>` // [!code ++]
+ color: green; // [!code ++]
+// [!code ++]
+ ${props => props.$primary // [!code ++]
+ ? css`background: white;` // [!code ++]
+ : css`background: black;` // [!code ++]
+ } // [!code ++]
+`; // [!code ++]
+
+const MyComp = styled.div<{ $primary: boolean }>`
+ background-color: yellow;
+ ${mixin};
`;
```
-
-
+```tsx title="mixin.ts"
+import { css } from 'styled-components'; // [!code --]
+
+export const mixin = css<{ $primary: boolean }>` // [!code --]
+ color: green; // [!code --]
+// [!code --]
+ ${props => props.$primary // [!code --]
+ ? `background: white;` // [!code --]
+ : `background: black;` // [!code --]
+ } // [!code --]
+`; // [!code --]
+```
-## Migration
+### Reference external styles
-### Change import
+If you reference external styles (styles that aren't component styles) in your styled components, you need to change the identifier in addition to the import.
-Change the import from `styled-components` to `next-yak` and change the import of `styled` from a default import
-to a named import.
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
-```ts
-import styled, { css, keyframes } from 'styled-components'; // [!code --]
-import { styled, css, keyframes } from 'next-yak'; // [!code ++]
-```
+const Button = styled.button`
+ color: blue;
-### Add yak files
+ .myGlobalClass { // [!code --]
+ :global(.myGlobalClass) { // [!code ++]
+ color: red;
+ }
+`;
+```
-Yak files are used to store static values that are extracted during build time. You can create a `.yak.ts` file
-everywhere in your project and it will be picked up by next-yak.
+The reason for this is that next-yak transforms your styles to module-css styles. And if you want to reference global selectors, you need to use the `:global` selector.
+More can be found in the [docs of css-modules](https://github.com/css-modules/css-modules/blob/master/docs/composition.md#exceptions)
+
+### Functions that generate styles
+
+If you have somewhere utility functions that generate styles, you need to change them. Either transform them so that they cover every different static style or
+create a dynamic mixin.
+
+```tsx title="util.ts"
+export const generateAllColors = (primaryColor: string) => { // [!code --]
+ return { // [!code --]
+ primary: primaryColor, // [!code --]
+ secondary: "#F7B801", // [!code --]
+ }; // [!code --]
+}; // [!code --]
+export const allColors = { // [!code ++]
+ "red": { // [!code ++]
+ primary: "red", // [!code ++]
+ secondary: "#F7B801", // [!code ++]
+ }, // [!code ++]
+ "blue": { // [!code ++]
+ primary: "blue", // [!code ++]
+ secondary: "#F7B801", // [!code ++]
+ }, // [!code ++]
+ "green": { // [!code ++]
+ primary: "green", // [!code ++]
+ secondary: "#F7B801", // [!code ++]
+ } // [!code ++]
+}; // [!code ++]
+```
+or
-```ts [constants.yak.ts]
-export const colors = {
- primary: "#BF4F74",
- secondary: "#F7B801",
-};
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { styled } from 'next-yak'; // [!code ++]
+import { generateAllColors } from './util'; // [!code --]
-export const breakpoints = {
- mobile: "@media (max-width: 420px)",
- tablet: "@media (max-width: 768px)",
- desktop: "@media (min-width: 769px)",
-};
+const Button = styled.button<{ $color: string }>`
+ color: ${generateAllColors}; // [!code --]
+ color: ${props => props.$color}; // [!code ++]
+`;
```
-You can then use these values in your styled components.
+### CSS prop (optional)
-```tsx
-import { styled } from 'next-yak';
-import { colors, breakpoints } from './constants.yak';
+If you use the css prop in your styled components, you can almost just change the import and you're done.
+But you also need to tell TypeScript that native JSX elements can have a css prop. In order to do that, you can add the following to your `tsconfig.json`.
-const Button = styled.button`
- background: ${colors.primary};
- ${breakpoints.mobile} {
- font-size: 1rem;
- }
- ${breakpoints.tablet} {
- font-size: 1.5rem;
- }
- ${breakpoints.desktop} {
- font-size: 2rem;
- }
-`;
+```json title="tsconfig.json"
+{
+ "compilerOptions": {
+ "jsxImportSource": "next-yak" // [!code ++]
+ }
+}
+```
+
+Or if you want to use the css prop in a single file, you can just add the following to the top of the file.
+
+```tsx title="component.tsx"
+/** @jsxImportSource next-yak */ // [!code ++]
```
-It looks and feels like a mixin from styled-components but it's actually a static value that gets injected during build time.
-This is the reason why you can't use dynamic values in yak files, as they have to be known during build time whereas
-mixin values can be dynamic.
+And afterwards you can just change the import and you're done.
-So this doesn't work:
+```tsx title="component.tsx"
+import styled from 'styled-components'; // [!code --]
+import { css, styled } from 'next-yak'; // [!code ++]
-```ts [constants.yak.ts]
-export const colors = {
- primary: "#BF4F74",
- secondary: "#F7B801",
- dynamic: (props: { $primary: boolean }) => props.$primary ? "#BF4F74" : "white", // [!code hl]
+const MyComponent = () => {
+ return (
+
+ );
};
+```
-export const breakpoints = (media: Record) => { // [!code hl]
- return media;
+If you need dynamic values you can use the same interpolation as you would with your other styled components.
+
+```tsx title="component.tsx"
+import { css } from "next-yak";
+
+const MyComponent = ({color}: {color: string}) => {
+ return (
+