Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Vanilla Extract support #5040

Merged
merged 14 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/giant-kings-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@remix-run/dev": minor
"@remix-run/react": minor
"@remix-run/server-runtime": minor
"@remix-run/testing": minor
---

Add unstable support for [Vanilla Extract](https://vanilla-extract.style) via the `future.unstable_vanillaExtract` feature flag
2 changes: 1 addition & 1 deletion .changeset/hungry-owls-greet.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
"@remix-run/testing": minor
---

Add unstable support for CSS side-effect imports via `future.unstable_cssSideEffectImports` feature flag
Add unstable support for CSS side-effect imports via the `future.unstable_cssSideEffectImports` feature flag
2 changes: 1 addition & 1 deletion .changeset/little-avocados-fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
"@remix-run/testing": minor
---

Add unstable support for CSS Modules via `future.unstable_cssModules` feature flag
Add unstable support for CSS Modules via the `future.unstable_cssModules` feature flag
62 changes: 59 additions & 3 deletions docs/guides/styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ NOTE: You may run into hydration warnings when using Styled Components. Hopefull

Many common approaches to CSS within the React community are only possible when bundling CSS, meaning that the CSS files you write during development are collected into a separate bundle as part of the build process.

When using CSS bundling features, the Remix compiler will generate a single CSS file containing all bundled styles in your application. Note that any [regular stylesheet imports][regular-stylesheet-imports-2] will remain as separate files.
When using CSS bundling features, the Remix compiler will generate a single CSS file containing all bundled styles in your application. Note that any [regular stylesheet imports][regular-stylesheet-imports] will remain as separate files.

Unlike many other tools in the React ecosystem, we do not insert the CSS bundle into the page automatically. Instead, we ensure that you always have control over the link tags on your page. This lets you decide where the CSS file is loaded relative to other stylesheets in your app.

Expand All @@ -790,7 +790,7 @@ import { cssBundleHref } from "@remix-run/css-bundle";

export const links: LinksFunction = () => {
return [
{ rel: "stylesheet", href: cssBundleHref },
...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
// ...
];
};
Expand Down Expand Up @@ -843,6 +843,61 @@ export const Button = React.forwardRef(
Button.displayName = "Button";
```

### Vanilla Extract

<docs-warning>This feature is unstable and currently only available behind a feature flag. We're confident in the use cases it solves but the API and implementation may change in the future.</docs-warning>

[Vanilla Extract][vanilla-extract] is a zero-runtime CSS-in-TypeScript (or JavaScript) library that lets you use TypeScript as your CSS preprocessor. Styles are written in separate `*.css.ts` (or `*.css.js`) files and all code within them is executed during the build process rather than in your user's browser. If you want to keep your CSS bundle size to a minimum, Vanilla Extract also provides an official library called [Sprinkles][sprinkles] that lets you define a custom set of utility classes and a type-safe function for accessing them at runtime.

First, ensure you've set up [CSS bundling][css-bundling] in your application.

Next, install Vanilla Extract's core styling package as a dev dependency.

```sh
npm install -D @vanilla-extract/css
```

Then, to enable Vanilla Extract, set the `future.unstable_vanillaExtract` feature flag in `remix.config.js`.

```js filename=remix.config.js
/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
future: {
unstable_vanillaExtract: true,
},
// ...
};
```

With this feature flag enabled, you can now opt into Vanilla Extract via the `.css.ts`/`.css.js` file name convention. For example:

```ts filename=app/components/button/styles.css.ts
import { style } from "@vanilla-extract/css";

export const root = style({
border: 'solid 1px',
background: 'white',
color: '#454545',
});
```

```tsx filename=app/components/button/index.js lines=[1,9]
import * as styles from "./styles.css"; // Note that `.ts` is omitted here

export const Button = React.forwardRef(
({ children, ...props }, ref) => {
return (
<button
{...props}
ref={ref}
className={styles.root}
/>
);
}
);
Button.displayName = "Button";
```

### CSS Side-Effect Imports

<docs-warning>This feature is unstable and currently only available behind a feature flag. We're confident in the use cases it solves but the API and implementation may change in the future.</docs-warning>
Expand Down Expand Up @@ -889,5 +944,6 @@ module.exports = {
[css modules]: https://github.com/css-modules/css-modules
[regular-stylesheet-imports]: #regular-stylesheets
[server-dependencies-to-bundle]: ../file-conventions/remix-config#serverdependenciestobundle
[regular-stylesheet-imports-2]: #regular-stylesheets
[css-bundling]: #css-bundling
[vanilla-extract]: https://vanilla-extract.style
[sprinkles]: https://vanilla-extract.style/documentation/packages/sprinkles
1 change: 1 addition & 0 deletions integration/css-modules-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ test.describe("CSS Modules", () => {
// ensure features don't clash
unstable_cssModules: true,
unstable_cssSideEffectImports: true,
unstable_vanillaExtract: true,
},
};
`,
Expand Down
1 change: 1 addition & 0 deletions integration/css-side-effect-imports-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ test.describe("CSS side-effect imports", () => {
// ensure features don't clash
unstable_cssModules: true,
unstable_cssSideEffectImports: true,
unstable_vanillaExtract: true,
},
};
`,
Expand Down
27 changes: 26 additions & 1 deletion integration/deterministic-build-output-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,25 @@ test("builds deterministically under different paths", async () => {
// * serverAssetsManifestPlugin (implicitly tested by build)
// * serverEntryModulePlugin (implicitly tested by build)
// * serverRouteModulesPlugin (implicitly tested by build)
// * vanillaExtractPlugin (via app/routes/foo.tsx' .css.ts file import)
let init = {
files: {
"remix.config.js": js`
module.exports = {
future: {
unstable_cssModules: true,
unstable_cssSideEffectImports: true,
unstable_vanillaExtract: true,
},
};
`,
"app/routes/index.mdx": "# hello world",
"app/routes/foo.tsx": js`
export * from "~/foo/bar.server";
import styles from "~/styles/foo.module.css";
import { vanilla } from "~/styles/vanilla.css";
import "~/styles/side-effect.css";
export default () => <div className={styles.foo}>YAY</div>;
export default () => <div className={[styles.foo, vanilla].join(' ')}>YAY</div>;
`,
"app/foo/bar.server.ts": "export const meta = () => []",
"app/styles/foo.module.css": css`
Expand All @@ -63,6 +66,28 @@ test("builds deterministically under different paths", async () => {
<circle cx="50" cy="50" r="50" fill="coral" />
</svg>
`,
"app/styles/vanilla.css.ts": css`
import { style } from "@vanilla-extract/css";
import { chocolate } from "./chocolate.css";
import imageUrl from "~/images/foo.svg";

export const vanilla = style([
chocolate,
{
backgroundImage: [
"url(" + imageUrl + ")",
"url(~/images/foo.svg)",
],
}
]);
`,
"app/styles/chocolate.css.ts": css`
import { style } from "@vanilla-extract/css";

export const chocolate = style({
color: "chocolate",
});
`,
"app/styles/side-effect.css": css`
.side-effect {
color: mintcream;
Expand Down
Loading