├── .gitignore ├── .prettierrc ├── README.md ├── bun.lockb ├── examples ├── expo-universal │ ├── .gitignore │ ├── README.md │ ├── app.json │ ├── babel.config.js │ ├── bun.lockb │ ├── metro.config.js │ ├── package.json │ ├── src │ │ ├── app │ │ │ ├── +html.tsx │ │ │ ├── _layout.tsx │ │ │ └── index.tsx │ │ ├── lib │ │ │ └── stylex.ts │ │ └── styles │ │ │ └── colors.stylex.ts │ └── tsconfig.json └── nextjs │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── bun.lockb │ ├── next.config.mjs │ ├── package.json │ ├── public │ ├── next.svg │ └── vercel.svg │ ├── src │ ├── app │ │ ├── favicon.ico │ │ ├── layout.tsx │ │ └── page.tsx │ ├── lib │ │ └── nanocss.ts │ └── styles │ │ └── animations.ts │ └── tsconfig.json ├── package.json ├── src ├── __tests__ │ ├── index.test.ts │ └── keyframes.test.ts ├── cli │ ├── extract-hooks.ts │ └── index.ts ├── index.ts └── keyframes.ts ├── tsconfig.json └── tsup.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NanoCSS 2 | 3 | A fast, 2Kb alternative to [StyleX](https://stylexjs.com/), offering the same API without requiring a bundler plugin 4 | 5 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz_small.svg)](https://stackblitz.com/edit/nextjs-nanocss-playground?embed=1&file=src%2Fapp%2Fpage.tsx) 6 | 7 | ## Features 8 | 9 | - 🔮 A drop-in replacement for StyleX with 10 | [react-strict-dom](https://github.com/facebook/react-strict-dom) support 11 | - 🚀 Native inline style generation with no build step required 12 | - 🎨 Intuitive and predictable style composition with "last style wins" approach 13 | - 🖥️ RSC and SSG support out of the box, compiled away to zero runtime overhead 14 | - 🔧 Compatible with latest build tools like Turbopack, SWC, Expo Web and [Expo 15 | DOM Components](https://docs.expo.dev/guides/dom-components/) (`use dom`) 16 | - 🏎️ Optimized for performance in RSC, SSR and CSR environments 17 | - 📦 Tiny runtime footprint in just 2Kb 18 | 19 | ## Installation 20 | 21 | ```bash 22 | npm install @nanocss/nanocss 23 | ``` 24 | 25 | ## Quick Start 26 | 27 | ```typescript 28 | import * as nanocss from '@/lib/nanocss' 29 | 30 | const styles = nanocss.create({ 31 | root: { 32 | padding: 16, 33 | }, 34 | element: { 35 | backgroundColor: { 36 | default: 'red', 37 | ':hover': 'blue', 38 | }, 39 | }, 40 | }) 41 | 42 | export default function App() { 43 | return ( 44 |
Hello, World!
45 | ) 46 | } 47 | ``` 48 | 49 | ## Usage 50 | 51 | ### As a standalone library 52 | 53 | #### 1. Set up NanoCSS 54 | 55 | Create `src/lib/nanocss.ts` with the following contents: 56 | 57 | ```typescript 58 | import { nanocss } from 'nanocss' 59 | 60 | export const { 61 | props, 62 | create, 63 | inline, 64 | defineVars, 65 | createTheme, 66 | keyframes, 67 | styleSheet, 68 | } = nanocss({ 69 | // Hooks defined here can be used inside `create` function. 70 | hooks: [':hover', '@media (max-width: 800px)'], 71 | debug: process.env.NODE_ENV !== 'production', 72 | }) 73 | ``` 74 | 75 | Optional: You can use `nanocss` CLI to scan source code to generate hooks for 76 | quick scaffolding or automatic scanning. 77 | 78 | ```bash 79 | nanocss -i "./src/**/*.{ts,tsx}" -o "./src/lib/nanocss.ts" 80 | ``` 81 | 82 | `--watch` option can be used to dynamically generate hooks as well. 83 | 84 | #### 2. Add stylesheet 85 | 86 | Modify `src/app/layout.tsx` and add the stylesheet: 87 | 88 | ```typescript 89 | export function RootLayout({ children }: { children: React.ReactNode }) { 90 | return ( 91 | 92 | 93 |