├── .gitignore ├── .vscode └── extensions.json ├── LICENSE.md ├── README.md ├── emotion ├── astro.config.mjs ├── package.json ├── src │ ├── components │ │ └── Counter.tsx │ ├── env.d.ts │ └── pages │ │ └── index.astro └── tsconfig.json ├── linaria ├── astro.config.ts ├── package.json ├── src │ ├── components │ │ └── Counter.tsx │ ├── env.d.ts │ └── pages │ │ └── index.astro └── tsconfig.json ├── package-lock.json ├── package.json ├── solid-styled ├── astro.config.mjs ├── package.json ├── src │ ├── components │ │ └── Counter.tsx │ ├── env.d.ts │ └── pages │ │ └── index.astro └── tsconfig.json ├── stitches ├── astro.config.mjs ├── package.json ├── src │ ├── components │ │ ├── Counter.tsx │ │ └── Styles.tsx │ ├── env.d.ts │ └── pages │ │ └── index.astro ├── stitches.config.ts └── tsconfig.json ├── styled-components ├── astro.config.mjs ├── package.json ├── src │ ├── components │ │ └── Counter.tsx │ ├── env.d.ts │ └── pages │ │ └── index.astro └── tsconfig.json ├── turbo.json ├── typestyle ├── astro.config.mjs ├── package.json ├── src │ ├── components │ │ ├── Counter.tsx │ │ └── Styles.tsx │ ├── env.d.ts │ └── pages │ │ └── index.astro └── tsconfig.json └── vanilla-extract ├── astro.config.mjs ├── package.json ├── src ├── components │ ├── Counter.css.ts │ └── Counter.tsx ├── env.d.ts └── pages │ └── index.astro └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | .pnp 4 | .pnp.js 5 | 6 | # build output 7 | .next/ 8 | out/ 9 | build 10 | dist 11 | 12 | # misc 13 | .DS_Store 14 | *.pem 15 | 16 | # debug 17 | npm-debug.log* 18 | yarn-debug.log* 19 | yarn-error.log* 20 | .pnpm-debug.log* 21 | 22 | # local env files 23 | .env.local 24 | .env.development.local 25 | .env.test.local 26 | .env.production.local 27 | 28 | # turbo 29 | .turbo 30 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "astro-build.astro-vscode", 4 | "styled-components.vscode-styled-components" 5 | ], 6 | "unwantedRecommendations": [] 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mayank 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # astro + css-in-js 2 | 3 | This monorepo will show examples of various CSS-in-JS libraries in Astro. Currently only shows a basic counter example, would be nice to demonstrate more advanced usage for each library. 4 | 5 | ## Compatibility table 6 | 7 | See https://github.com/withastro/astro/issues/4432 8 | 9 | ## Running locally 10 | 11 | Clone the repo and install deps: 12 | 13 | ``` 14 | npm install 15 | ``` 16 | 17 | Start the dev server for all examples in parallel using turborepo: 18 | 19 | ``` 20 | npm run dev 21 | ``` 22 | 23 | Open `localhost:3000`, `localhost:3001`, etc in browser. 24 | 25 | ## Contributing 26 | 27 | To add an example of a new library: 28 | 29 | 1. Create a copy of any folder (e.g. `emotion`). 30 | 2. Rename the folder and the `name` field in the folder's package.json. 31 | 3. Update the dependencies and run `npm install` from the root of the monorepo. 32 | 4. Update the code. Try to keep the actual styles more or less the same. 33 | 5. Update the README.md 34 | -------------------------------------------------------------------------------- /emotion/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import react from '@astrojs/react'; 3 | 4 | // https://astro.build/config 5 | export default defineConfig({ 6 | integrations: [react()], 7 | vite: ({ mode }) => 8 | mode === 'prod' && { 9 | legacy: { buildSsrCjsExternalHeuristics: import.meta.env.SSR }, 10 | ssr: { noExternal: ['@emotion/*'] }, 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /emotion/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emotion-example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11.10.0", 13 | "@emotion/styled": "^11.10.0" 14 | }, 15 | "devDependencies": { 16 | "astro": "2", 17 | "@astrojs/react": "2", 18 | "react": "^18.0.0", 19 | "react-dom": "^18.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /emotion/src/components/Counter.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource @emotion/react */ 2 | import * as React from 'react'; 3 | import styled from '@emotion/styled'; 4 | import { Global } from '@emotion/react'; 5 | 6 | export default function Counter(props: { children: React.ReactNode }) { 7 | const [count, setCount] = React.useState(0); 8 | const add = () => setCount((i) => i + 1); 9 | const subtract = () => setCount((i) => i - 1); 10 | 11 | return ( 12 | <> 13 | 14 | 15 | 16 |
{count}
17 | 18 |
19 | {props.children} 20 | 21 | ); 22 | } 23 | 24 | const Wrapper = styled.div` 25 | display: grid; 26 | font-size: 2em; 27 | grid-template-columns: repeat(3, minmax(0, 1fr)); 28 | margin-top: 2em; 29 | place-items: center; 30 | background-color: hsl(0 0% 50% / 0.1); 31 | `; 32 | 33 | const Message = styled.div` 34 | text-align: center; 35 | `; 36 | -------------------------------------------------------------------------------- /emotion/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /emotion/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Counter from "../components/Counter"; 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Astro + emotion 12 | 13 | 14 |

Astro

15 | Hi, I'm an emotion Counter 16 | 17 | 18 | -------------------------------------------------------------------------------- /emotion/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // Enable top-level await, and other modern ESM features. 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | // Enable node-style module resolution, for things like npm package imports. 7 | "moduleResolution": "node", 8 | // Enable JSON imports. 9 | "resolveJsonModule": true, 10 | // Enable stricter transpilation for better output. 11 | "isolatedModules": true, 12 | // Astro will directly run your TypeScript code, no transpilation needed. 13 | "noEmit": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /linaria/astro.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import react from '@astrojs/react'; 3 | import linaria from '@linaria/vite'; 4 | 5 | // https://astro.build/config 6 | export default defineConfig({ 7 | build: { 8 | format: 'file', 9 | }, 10 | vite: { 11 | plugins: [ 12 | linaria({ 13 | displayName: true, 14 | classNameSlug: (hash, title, args) => `${args.dir}_${title}_${hash}`, 15 | babelOptions: { 16 | presets: ['react'], 17 | }, 18 | }), 19 | ], 20 | css: { 21 | modules: false, 22 | }, 23 | }, 24 | integrations: [react()], 25 | }); 26 | -------------------------------------------------------------------------------- /linaria/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "linaria-example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview" 10 | }, 11 | "dependencies": {}, 12 | "devDependencies": { 13 | "astro": "2", 14 | "@astrojs/react": "2", 15 | "@babel/core": "^7.20.2", 16 | "@linaria/vite": "^4.2.6", 17 | "@linaria/core": "^4.2.6", 18 | "@linaria/react": "^4.3.4", 19 | "babel-preset-react": "^6.24.1", 20 | "react": "^18.0.0", 21 | "react-dom": "^18.0.0", 22 | "vite": "^4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /linaria/src/components/Counter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { css } from '@linaria/core'; 3 | import { styled } from '@linaria/react'; 4 | 5 | export default function Counter(props: { children: React.ReactNode }) { 6 | const [count, setCount] = React.useState(0); 7 | const add = () => setCount((i) => i + 1); 8 | const subtract = () => setCount((i) => i - 1); 9 | 10 | return ( 11 | <> 12 | 13 | 14 |
{count}
15 | 16 |
17 |
{props.children}
18 | 19 | ); 20 | } 21 | 22 | export const globals = css` 23 | :global(body) { 24 | margin: 0; 25 | font-family: system-ui; 26 | } 27 | `; 28 | 29 | const Wrapper = styled.div` 30 | display: grid; 31 | font-size: 2em; 32 | grid-template-columns: repeat(3, minmax(0, 1fr)); 33 | margin-top: 2em; 34 | place-items: center; 35 | background-color: hsl(0 0% 50% / 0.1); 36 | `; 37 | 38 | const message = css` 39 | text-align: center; 40 | `; 41 | -------------------------------------------------------------------------------- /linaria/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /linaria/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Counter from "../components/Counter"; 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Astro + linaria 12 | 13 | 14 |

Astro

15 | Hi, I'm a linaria Counter 16 | 17 | 18 | -------------------------------------------------------------------------------- /linaria/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // Enable top-level await, and other modern ESM features. 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | // Enable node-style module resolution, for things like npm package imports. 7 | "moduleResolution": "node", 8 | // Enable JSON imports. 9 | "resolveJsonModule": true, 10 | // Enable stricter transpilation for better output. 11 | "isolatedModules": true, 12 | // Astro will directly run your TypeScript code, no transpilation needed. 13 | "noEmit": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "astro-css-in-js-tests", 3 | "version": "0.0.0", 4 | "private": true, 5 | "workspaces": [ 6 | "*" 7 | ], 8 | "scripts": { 9 | "build": "turbo run build", 10 | "dev": "turbo run dev --parallel" 11 | }, 12 | "devDependencies": { 13 | "turbo": "latest" 14 | }, 15 | "engines": { 16 | "npm": ">=7.0.0", 17 | "node": ">=14.0.0" 18 | }, 19 | "dependencies": {}, 20 | "packageManager": "npm@8.15.0" 21 | } 22 | -------------------------------------------------------------------------------- /solid-styled/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import solidJs from '@astrojs/solid-js'; 3 | import solidStyled from 'vite-plugin-solid-styled'; 4 | 5 | // https://astro.build/config 6 | export default defineConfig({ 7 | vite: { 8 | plugins: [solidStyled()], 9 | }, 10 | integrations: [solidJs()], 11 | }); 12 | -------------------------------------------------------------------------------- /solid-styled/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solid-styled-example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview" 10 | }, 11 | "dependencies": { 12 | "solid-styled": "^0.7.5" 13 | }, 14 | "devDependencies": { 15 | "@astrojs/solid-js": "2", 16 | "astro": "2", 17 | "vite-plugin-solid-styled": "^0.7.5", 18 | "solid-js": "^1.6.8" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /solid-styled/src/components/Counter.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource solid-js */ 2 | import { createSignal, JSX, ParentProps } from 'solid-js'; 3 | import { css } from 'solid-styled'; 4 | 5 | export default function Counter(props: ParentProps) { 6 | const [count, setCount] = createSignal(0); 7 | const add = () => setCount((i) => i + 1); 8 | const subtract = () => setCount((i) => i - 1); 9 | 10 | css` 11 | :global(body) { 12 | margin: 0; 13 | font-family: system-ui; 14 | } 15 | 16 | .wrapper { 17 | display: grid; 18 | font-size: 2em; 19 | grid-template-columns: repeat(3, minmax(0, 1fr)); 20 | margin-top: 2em; 21 | place-items: center; 22 | background-color: hsl(0 0% 50% / 0.1); 23 | } 24 | 25 | .message { 26 | text-align: center; 27 | } 28 | `; 29 | 30 | return ( 31 | <> 32 |
33 | 34 |
{count}
35 | 36 |
37 |
{props.children}
38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /solid-styled/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /solid-styled/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Counter from "../components/Counter"; 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Astro + solid-styled 12 | 13 | 14 |

Astro

15 | Hi, I'm a solid-styled Counter 16 | 17 | 18 | -------------------------------------------------------------------------------- /solid-styled/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // Enable top-level await, and other modern ESM features. 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | // Enable node-style module resolution, for things like npm package imports. 7 | "moduleResolution": "node", 8 | // Enable JSON imports. 9 | "resolveJsonModule": true, 10 | // Enable stricter transpilation for better output. 11 | "isolatedModules": true, 12 | // Astro will directly run your TypeScript code, no transpilation needed. 13 | "noEmit": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /stitches/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import react from '@astrojs/react'; 3 | 4 | // https://astro.build/config 5 | export default defineConfig({ 6 | integrations: [react()], 7 | }); 8 | -------------------------------------------------------------------------------- /stitches/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stitches-example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview" 10 | }, 11 | "dependencies": { 12 | "@stitches/react": "^1.2.8" 13 | }, 14 | "devDependencies": { 15 | "astro": "2", 16 | "@astrojs/react": "^2", 17 | "@types/react": "^18.0.17", 18 | "react": "^18.0.0", 19 | "react-dom": "^18.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /stitches/src/components/Counter.tsx: -------------------------------------------------------------------------------- 1 | /** @jsxImportSource react */ 2 | import * as React from 'react'; 3 | import { styled, css, globalCss } from '@stitches/react'; 4 | 5 | export default function Counter(props: { children: React.ReactNode }) { 6 | const [count, setCount] = React.useState(0); 7 | const add = () => setCount((i) => i + 1); 8 | const subtract = () => setCount((i) => i - 1); 9 | 10 | globals(); 11 | 12 | return ( 13 | <> 14 | 15 | 16 |
{count}
17 | 18 |
19 |
{props.children}
20 | 21 | ); 22 | } 23 | 24 | const globals = globalCss({ 25 | body: { margin: 0, fontFamily: 'system-ui' }, 26 | }); 27 | 28 | const Wrapper = styled('div', { 29 | display: 'grid', 30 | fontSize: '2em', 31 | gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', 32 | marginTop: '2em', 33 | placeItems: 'center', 34 | backgroundColor: 'hsl(0 0% 50% / 0.1)', 35 | }); 36 | 37 | const message = css({ 38 | textAlign: 'center', 39 | }); 40 | -------------------------------------------------------------------------------- /stitches/src/components/Styles.tsx: -------------------------------------------------------------------------------- 1 | import { getCssText } from '../../stitches.config'; 2 | 3 | export default () => ( 4 |