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 |
94 |
95 | {children}
96 |
97 | )
98 | }
99 | ```
100 |
101 | #### 3. Define styles
102 |
103 | Create `src/app/page.tsx` with the following contents:
104 |
105 | ```typescript
106 | import * as nanocss from '@/lib/nanocss'
107 |
108 | export default function App() {
109 | return (
110 |
111 |
Title
112 |
Hello, World!
113 |
114 | )
115 | }
116 |
117 | const styles = nanocss.create({
118 | root: {
119 | padding: 16,
120 | },
121 | container: {
122 | color: 'blue',
123 | },
124 | })
125 | ```
126 |
127 | ### As a drop-in replacement of StyleX
128 |
129 | NanoCSS offers the same API as StyleX and react-strict-dom.
130 |
131 | You can configure module aliases in your bundler to resolve `@stylexjs/stylex`
132 | to NanoCSS and get all of the StyleX ecosystem benefits automatically including
133 | [StyleX ESLint
134 | Plugin](https://stylexjs.com/docs/api/configuration/eslint-plugin/) and [react-strict-dom](https://github.com/facebook/react-strict-dom).
135 |
136 | **Next.js**
137 |
138 | #### 1. Create `src/lib/stylex.ts` as a compatibility layer
139 |
140 | Add a file named `src/lib/stylex.ts` in your project.
141 |
142 | ```typescript
143 | import { nanocss } from '@nanocss/nanocss'
144 |
145 | const { styleSheet, ...css } = nanocss({
146 | hooks: [
147 | // Add your hooks here
148 | ],
149 | debug: process.env.NODE_ENV !== 'production',
150 | })
151 |
152 | // For ESM imports
153 | export const { create, props, defineVars, createTheme, keyframes } = css
154 |
155 | export { styleSheet } // Add styleSheet() in your layout.ts
156 |
157 | export default css
158 | ```
159 |
160 | #### 2. Add stylesheet
161 |
162 | Modify `src/app/layout.tsx` and add the stylesheet:
163 |
164 | ```typescript
165 | import { styleSheet } from '@/lib/stylex'
166 |
167 | export function RootLayout({ children }: { children: React.ReactNode }) {
168 | return (
169 |
170 |
171 |
172 |
173 | {children}
174 |
175 | )
176 | }
177 | ```
178 |
179 | #### 3. Configure module aliases
180 |
181 | In your `next.config.mjs`, add a module alias resolving `@stylexjs/stylex` to `src/lib/stylex.ts`
182 |
183 | ```javascript
184 | const __dirname = new URL('.', import.meta.url).pathname
185 |
186 | /** @type {import('next').NextConfig} */
187 | const nextConfig = {
188 | transpilePackages: ['react-strict-dom'], // If you use react-strict-dom, add this file
189 | webpack: (config, { dev, isServer }) => {
190 | config.resolve.alias = {
191 | ...(config.resolve.alias || {}),
192 | '@stylexjs/stylex': path.resolve(__dirname, 'src/lib/stylex'),
193 | }
194 | },
195 | }
196 |
197 | export default nextConfig
198 | ```
199 |
200 | Now, you can author styles using StyleX imports:
201 |
202 | ```typescript
203 | import stylex from '@stylexjs/stylex' // This will resolve to NanoCSS
204 |
205 | const styles = stylex.create({
206 | root: {
207 | color: 'green',
208 | },
209 | })
210 | ```
211 |
212 | **Expo Web**
213 |
214 | Similar to Next.js, NanoCSS can be configured to replace `react-strict-dom` and `@stylexjs/stylex` in [Expo Web](https://docs.expo.dev/workflow/web/) with full support for [Static
215 | Rendering](https://docs.expo.dev/router/reference/static-rendering/), Async Routes and
216 | Experimental [DOM Components](https://docs.expo.dev/guides/dom-components/)(`use
217 | dom`) features. Please see [the example app](./examples/expo-universal) for how to configure module aliases in `metro.config.js`.
218 |
219 | ## Core Concepts
220 |
221 | ### Flattened Conditional Styles
222 |
223 | NanoCSS uses an object syntax to represent pseudo-states and media queries per property:
224 |
225 | ```typescript
226 | const styles = nanocss.create({
227 | text: {
228 | color: {
229 | default: 'black',
230 | ':hover': 'blue',
231 | ':focus': 'green',
232 | },
233 | },
234 | })
235 | ```
236 |
237 | This flattened structure allows for predictable style merging and overriding.
238 |
239 | ### Style Composition
240 |
241 | Compose styles easily using the props function:
242 |
243 | ```typescript
244 |
251 | ```
252 |
253 | Styles are merged in order, with later styles always taking precedence.
254 | When merging multiple styles with the same property, the last value overrides all previous values including conditions.
255 | This is modeled after `Object.assign` behavior.
256 |
257 | ### Runtime Generation
258 |
259 | All styles are generated at runtime, eliminating the need for complex build processes and allowing for flexibility.
260 |
261 | ### Server-Side Rendering
262 |
263 | NanoCSS works out of the box with SSR and RSC setups. The generated styles are included inline with your HTML, improving First Contentful Paint times.
264 |
265 | ### Dynamic Styles
266 |
267 | Create dynamic styles using the function syntax in `create`:
268 |
269 | ```typescript
270 | const styles = nanocss.create({
271 | color: (color: string) => ({
272 | color,
273 | }),
274 | })
275 | ```
276 |
277 | For highly dynamic styles, `nanocss.inline` can be used:
278 |
279 | ```typescript
280 | function Component() {
281 | return (
282 |
292 | Hello, World!
293 |
294 | )
295 | }
296 | ```
297 |
298 | `nanocss.inline` must compute and resolve nested conditions during rendering so
299 | it should be used sparingly.
300 |
301 | ### Themes
302 |
303 | NanoCSS supports `defineVars` and `createTheme` APIs to define CSS variables
304 | declaratively and override CSS variables for specific UI sub-trees.
305 | The APIs are compatible with StyleX and supports nested conditions for both in
306 | `defineVars` and `createTheme`.
307 |
308 | To understand how these APIs work together, you can refer to [StyleX Themes
309 | Docs](https://stylexjs.com/docs/learn/theming/defining-variables/).
310 |
311 | **Defining CSS Variables**
312 |
313 | ```typescript
314 | export const colors = nanocss.defineVars({
315 | primary: 'green',
316 | })
317 | ```
318 |
319 | Unlike StyleX, variables do not need to be defined in separate `.stylex.ts` files and can
320 | be co-located with files defining styles and components. The same restriction
321 | about `create` API still apply, and variables must be defined in the top scope
322 | of the files rather than inside of render functions.
323 |
324 | **Using variables**
325 |
326 | ```typescript
327 | const styles = nanocss.create({
328 | container: {
329 | color: colors.primary,
330 | },
331 | })
332 | ```
333 |
334 | Each CSS variable defined is converted to a unique variable name, and can be
335 | used inside `create` functions.
336 |
337 | **Create themes**
338 |
339 | ```typescript
340 | const theme = nanocss.createTheme(colors, {
341 | primary: 'red',
342 | })
343 | ```
344 |
345 | Themes allow you to override CSS variables defined with `defineVars`. All
346 | variables must be overridden.
347 |
348 | **Using themes**
349 |
350 | ```typescript
351 | function Component() {
352 | return (
353 |
354 |
Text
355 |
356 | )
357 | }
358 | ```
359 |
360 | Themes can be applied via `props` and overrides CSS variables of the same
361 | element and its descendant UI sub-trees.
362 |
363 | ### Keyframes
364 |
365 | NanoCSS offers built-in support for [StyleX `keyframes` API](https://stylexjs.com/docs/api/javascript/keyframes/) for writing CSS
366 | keyframe animations directly in JS, allowing you to create dynamic and complex
367 | animations.
368 |
369 | #### 1. Defining keyframes
370 |
371 | We recommend centralizing your keyframe definitions in a separate file, such as `src/styles/animations.ts`:
372 |
373 | ```typescript
374 | // src/styles/animations.ts
375 | // File name should be `animations.stylex.ts` in StyleX-compatible mode
376 | import * as nanocss from '@/lib/nanocss'
377 |
378 | const { keyframes, defineVars } = nanocss()
379 |
380 | export const fadeIn = keyframes({
381 | '0%': { opacity: 0 },
382 | '100%': { opacity: 1 },
383 | })
384 |
385 | export const pulse = keyframes({
386 | '0%, 100%': { transform: 'scale(1)' },
387 | '50%': { transform: 'scale(1.1)' },
388 | })
389 |
390 | // Define custom variables for your animations
391 | export const animations = defineVars({
392 | fadeIn,
393 | pulse,
394 | })
395 | ```
396 |
397 | #### 2. Add styleSheet
398 |
399 | Modify `src/app/layout.tsx` and specify keyframe names to include in the stylesheet:
400 |
401 | ```typescript
402 | import { fadeIn, pulse } from '@/styles/animations'
403 |
404 | export function RootLayout({ children }: { children: React.ReactNode }) {
405 | return (
406 |
407 |
408 |
415 |
416 | {children}
417 |
418 | )
419 | }
420 | ```
421 |
422 | #### 3. Defining styles
423 |
424 | To use keyframe animations, simply specify the keyframe name in `animationName` prop:
425 |
426 | ```typescript
427 | import * as nanocss from '@/lib/nanocss'
428 | import { animations } from '@/styles/animations'
429 |
430 | const { create, props, styleSheet } = nanocss()
431 |
432 | const styles = create({
433 | root: {
434 | animationName: animations.fadeIn,
435 | animationDuration: '1s',
436 | animationIterationCount: 'infinite',
437 | },
438 | })
439 |
440 | export function Component() {
441 | return
Fade in content
442 | }
443 | ```
444 |
445 | ### Performance Considerations
446 |
447 | NanoCSS is designed with performance in mind:
448 |
449 | - The `create` function does most of the heavy lifting outside of the render cycle.
450 | - The `props` function is optimized for fast merging during rendering.
451 | - CSS variables are used to create a small initial stylesheet, reducing the payload size.
452 |
453 | ### Best Practices
454 |
455 | 1. Define styles outside of your components using `create` for better performance.
456 | 2. Leverage style composition for creating variant styles.
457 | 3. For dynamic styles, prefer conditional styles over style functions in `create`.
458 | 4. `inline` function should be used sparingly to hoist computation outside
459 | rendering.
460 |
461 | ## How does it work?
462 |
463 | NanoCSS is built on top of [CSS Hooks](https://css-hooks.com/), which leverages
464 | the fallback trick of CSS custom properties to enable pseudo-classes and media
465 | queries in inline styles.
466 |
467 |
468 |
469 | Implementation Details
470 |
471 | Given the following style definitions:
472 |
473 | ```typescript
474 | const { create, styleSheet } = nanocss({
475 | hooks: [':hover'],
476 | })
477 |
478 | const styles = nanocss.create({
479 | root: {
480 | color: {
481 | default: 'black',
482 | ':hover': 'red',
483 | },
484 | },
485 | })
486 | ```
487 |
488 | NanoCSS generates the following `styleSheet` and `styles`:
489 |
490 | ```typescript
491 | const styleSheet = () => `
492 | * {
493 | --_hover-0: initial;
494 | --_hover-1: ;
495 | }
496 | *:hover {
497 | --_hover-0: ;
498 | --_hover-1: initial;
499 | }
500 | `
501 |
502 | const styles = {
503 | root: {
504 | style: {
505 | color: 'var(--_hover-1, red) var(--_hover-0, black)',
506 | },
507 | },
508 | }
509 | ```
510 |
511 | The `styleSheet` function generates a small stylesheet with CSS custom properties for each defined hook (e.g., :hover).
512 | The `create` function transforms style definitions into flat inline style objects that utilizes the generated CSS custom properties.
513 |
514 | Then, the `props` function merges multiple nested styles into a single flat style object by iterating over the provided styles and flattening them in the specified order. When encountering conflicting properties, the last style takes precedence, ensuring a predictable "last style wins" approach.
515 |
516 | ```typescript
517 | function props(...styles: StyleProp[]): {
518 | className?: string
519 | style?: React.CSSProperties
520 | } {
521 | const style: Record = {}
522 |
523 | for (const flatStyle of (styles as any[]).flat(Infinity)) {
524 | if (!flatStyle) continue
525 | Object.keys(flatStyle).forEach((key) => {
526 | delete style[key]
527 | style[key] = flatStyle[key]
528 | })
529 | }
530 |
531 | return { style }
532 | }
533 | ```
534 |
535 | The combination of CSS Hooks and a StyleX-compatible API allows NanoCSS to provide a simple and intuitive way to define and compose styles while ensuring predictable behavior and optimal performance across various rendering scenarios.
536 |
537 |
538 |
539 | ## Why NanoCSS?
540 |
541 | NanoCSS offers a unique combination of performance, simplicity, and
542 | compatibility with StyleX:
543 |
544 | - No build step required, making it easy to integrate into any project
545 | - A drop-in compatibility with StyleX without modifying existing code
546 | - Predictable style composition with a "last style wins" approach
547 | - Optimized for various rendering scenarios (RSC, SSR, CSR)
548 | - Tiny runtime footprint, minimizing impact on your bundle size
549 |
550 | ## TypeScript Support
551 |
552 | NanoCSS is written in TypeScript and provides full type definitions out of the box. This ensures type safety when defining and using styles, catching potential errors at compile-time.
553 |
554 | ## Acknowledgements
555 |
556 | - [CSS Hooks](https://github.com/css-hooks/css-hooks) for bringing advanced
557 | CSS capabilities including pseudo classes and media queries to native inline
558 | styles.
559 | - [StyleX](https://github.com/facebook/stylex) for the simple and powerful API
560 | design for predictable and deterministic styling.
561 |
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/javascripter/nanocss/5c2b99148a5dad5bfbe1afc0ec3be6fe2c60b815/bun.lockb
--------------------------------------------------------------------------------
/examples/expo-universal/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .expo/
3 | dist/
4 | npm-debug.*
5 | *.jks
6 | *.p8
7 | *.p12
8 | *.key
9 | *.mobileprovision
10 | *.orig.*
11 | web-build/
12 |
13 | # macOS
14 | .DS_Store
15 |
16 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
17 | # The following patterns were generated by expo-cli
18 |
19 | expo-env.d.ts
20 | # @end expo-cli
--------------------------------------------------------------------------------
/examples/expo-universal/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to your Expo app 👋
2 |
3 | This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
4 |
5 | ## Get started
6 |
7 | 1. Install dependencies
8 |
9 | ```bash
10 | npm install
11 | ```
12 |
13 | 2. Start the app
14 |
15 | ```bash
16 | npx expo start
17 | ```
18 |
19 | In the output, you'll find options to open the app in a
20 |
21 | - [development build](https://docs.expo.dev/develop/development-builds/introduction/)
22 | - [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
23 | - [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
24 | - [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
25 |
26 | You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
27 |
28 | ## Get a fresh project
29 |
30 | When you're ready, run:
31 |
32 | ```bash
33 | npm run reset-project
34 | ```
35 |
36 | This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
37 |
38 | ## Learn more
39 |
40 | To learn more about developing your project with Expo, look at the following resources:
41 |
42 | - [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
43 | - [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
44 |
45 | ## Join the community
46 |
47 | Join our community of developers creating universal apps.
48 |
49 | - [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
50 | - [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
51 |
--------------------------------------------------------------------------------
/examples/expo-universal/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "expo-universal",
4 | "slug": "expo-universal",
5 | "version": "1.0.0",
6 | "orientation": "portrait",
7 | "scheme": "myapp",
8 | "userInterfaceStyle": "automatic",
9 | "ios": {
10 | "supportsTablet": true
11 | },
12 | "web": {
13 | "bundler": "metro",
14 | "output": "static"
15 | },
16 | "plugins": ["expo-router"],
17 | "experiments": {
18 | "typedRoutes": true
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/examples/expo-universal/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/examples/expo-universal/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/javascripter/nanocss/5c2b99148a5dad5bfbe1afc0ec3be6fe2c60b815/examples/expo-universal/bun.lockb
--------------------------------------------------------------------------------
/examples/expo-universal/metro.config.js:
--------------------------------------------------------------------------------
1 | const path = require('node:path')
2 |
3 | // Learn more https://docs.expo.io/guides/customizing-metro
4 | const { getDefaultConfig } = require('expo/metro-config')
5 |
6 | /** @type {import('expo/metro-config').MetroConfig} */
7 | const config = getDefaultConfig(__dirname)
8 |
9 | const ALIASES = {
10 | '@stylexjs/stylex': path.join(__dirname, 'src/lib/stylex'),
11 | }
12 |
13 | config.resolver.resolveRequest = (context, moduleName, platform) => {
14 | return context.resolveRequest(
15 | context,
16 | ALIASES[moduleName] ?? moduleName,
17 | platform
18 | )
19 | }
20 |
21 | module.exports = config
22 |
--------------------------------------------------------------------------------
/examples/expo-universal/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "expo-universal",
3 | "main": "expo-router/entry",
4 | "version": "1.0.0",
5 | "scripts": {
6 | "start": "expo start",
7 | "reset-project": "node ./scripts/reset-project.js",
8 | "android": "expo start --android",
9 | "ios": "expo start --ios",
10 | "web": "expo start --web",
11 | "test": "jest --watchAll",
12 | "lint": "expo lint"
13 | },
14 | "jest": {
15 | "preset": "jest-expo"
16 | },
17 | "dependencies": {
18 | "@expo/vector-icons": "^14.0.2",
19 | "@nanocss/nanocss": "^0.0.6",
20 | "@react-navigation/native": "^6.0.2",
21 | "expo": "~51.0.28",
22 | "expo-constants": "~16.0.2",
23 | "expo-font": "~12.0.9",
24 | "expo-linking": "~6.3.1",
25 | "expo-router": "~3.5.23",
26 | "expo-splash-screen": "~0.27.5",
27 | "expo-status-bar": "~1.12.1",
28 | "expo-system-ui": "~3.0.7",
29 | "expo-web-browser": "~13.0.3",
30 | "react": "18.2.0",
31 | "react-dom": "18.2.0",
32 | "react-native": "0.74.5",
33 | "react-native-gesture-handler": "~2.16.1",
34 | "react-native-reanimated": "~3.10.1",
35 | "react-native-safe-area-context": "4.10.5",
36 | "react-native-screens": "3.31.1",
37 | "react-native-web": "~0.19.10",
38 | "react-strict-dom": "^0.0.24"
39 | },
40 | "devDependencies": {
41 | "@babel/core": "^7.20.0",
42 | "@types/jest": "^29.5.12",
43 | "@types/react": "~18.2.45",
44 | "@types/react-test-renderer": "^18.0.7",
45 | "jest": "^29.2.1",
46 | "jest-expo": "~51.0.3",
47 | "react-test-renderer": "18.2.0",
48 | "typescript": "~5.3.3"
49 | },
50 | "private": true
51 | }
52 |
--------------------------------------------------------------------------------
/examples/expo-universal/src/app/+html.tsx:
--------------------------------------------------------------------------------
1 | import { ScrollViewStyleReset } from 'expo-router/html'
2 | import { type PropsWithChildren } from 'react'
3 | import { styleSheet } from '../lib/stylex'
4 |
5 | /**
6 | * This file is web-only and used to configure the root HTML for every web page during static rendering.
7 | * The contents of this function only run in Node.js environments and do not have access to the DOM or browser APIs.
8 | */
9 | export default function Root({ children }: PropsWithChildren) {
10 | return (
11 |
12 |
13 |
14 |
15 |
19 |
24 |
25 | {children}
26 |
27 | )
28 | }
29 |
30 | const responsiveBackground = `
31 | body {
32 | background-color: #fff;
33 | }
34 | @media (prefers-color-scheme: dark) {
35 | body {
36 | background-color: #000;
37 | }
38 | }`
39 |
--------------------------------------------------------------------------------
/examples/expo-universal/src/app/_layout.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from 'expo-router'
2 | export default Stack
3 |
--------------------------------------------------------------------------------
/examples/expo-universal/src/app/index.tsx:
--------------------------------------------------------------------------------
1 | import { html, css } from 'react-strict-dom'
2 | import { colors } from '../styles/colors.stylex'
3 |
4 | export default function Home() {
5 | return (
6 |
7 | Next.js + NanoCSS
8 | Hello, world!
9 | Text in primary color.
10 | Dynamic width
11 |
12 | )
13 | }
14 |
15 | const styles = css.create({
16 | main: {
17 | padding: 16,
18 | },
19 | h1: {
20 | fontSize: 24,
21 | },
22 | p: {
23 | color: 'green',
24 | },
25 | theme: {
26 | color: colors.primary,
27 | },
28 | dynamic: (width: number) => ({
29 | width,
30 | color: {
31 | default: 'black',
32 | ':hover': 'blue',
33 | },
34 | }),
35 | })
36 |
--------------------------------------------------------------------------------
/examples/expo-universal/src/lib/stylex.ts:
--------------------------------------------------------------------------------
1 | import { nanocss } from '@nanocss/nanocss'
2 |
3 | const { styleSheet, ...css } = nanocss({
4 | hooks: [
5 | ':hover',
6 | // Add your hooks here
7 | ],
8 | debug: process.env.NODE_ENV !== 'production',
9 | })
10 |
11 | // For ESM imports
12 | export const { create, props, defineVars, createTheme } = css
13 |
14 | export { styleSheet } // Add styleSheet() in your layout.ts
15 |
16 | export default css
17 |
--------------------------------------------------------------------------------
/examples/expo-universal/src/styles/colors.stylex.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'react-strict-dom'
2 |
3 | export const colors = css.defineVars({
4 | primary: 'green',
5 | })
6 |
--------------------------------------------------------------------------------
/examples/expo-universal/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "expo/tsconfig.base",
3 | "compilerOptions": {
4 | "strict": true,
5 | "paths": {
6 | "@/*": ["./*"]
7 | }
8 | },
9 | "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/examples/nextjs/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/nextjs/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/examples/nextjs/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | # or
12 | pnpm dev
13 | # or
14 | bun dev
15 | ```
16 |
17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18 |
19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20 |
21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
22 |
23 | ## Learn More
24 |
25 | To learn more about Next.js, take a look at the following resources:
26 |
27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29 |
30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
31 |
32 | ## Deploy on Vercel
33 |
34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35 |
36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
37 |
--------------------------------------------------------------------------------
/examples/nextjs/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/javascripter/nanocss/5c2b99148a5dad5bfbe1afc0ec3be6fe2c60b815/examples/nextjs/bun.lockb
--------------------------------------------------------------------------------
/examples/nextjs/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {};
3 |
4 | export default nextConfig;
5 |
--------------------------------------------------------------------------------
/examples/nextjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextjs",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "react": "^18",
13 | "react-dom": "^18",
14 | "next": "14.2.4",
15 | "@nanocss/nanocss": "file:../../"
16 | },
17 | "devDependencies": {
18 | "typescript": "^5",
19 | "@types/node": "^20",
20 | "@types/react": "^18",
21 | "@types/react-dom": "^18",
22 | "eslint": "^8",
23 | "eslint-config-next": "14.2.4"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/nextjs/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/nextjs/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/nextjs/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/javascripter/nanocss/5c2b99148a5dad5bfbe1afc0ec3be6fe2c60b815/examples/nextjs/src/app/favicon.ico
--------------------------------------------------------------------------------
/examples/nextjs/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from 'next'
2 | import { Inter } from 'next/font/google'
3 | import { styleSheet } from '@/lib/nanocss'
4 | import { fadeIn } from '../styles/animations'
5 |
6 | const inter = Inter({ subsets: ['latin'] })
7 |
8 | export const metadata: Metadata = {
9 | title: 'Create Next App',
10 | description: 'Generated by create next app',
11 | }
12 |
13 | export default function RootLayout({
14 | children,
15 | }: Readonly<{
16 | children: React.ReactNode
17 | }>) {
18 | return (
19 |
20 |
21 |
28 |
29 | {children}
30 |
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/examples/nextjs/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import * as nanocss from '@/lib/nanocss'
2 | import { fadeIn } from '../styles/animations'
3 |
4 | export default function Home() {
5 | return (
6 |
7 |
Next.js + NanoCSS
8 |
Hello, world!
9 |
Text in primary color.
10 |
11 | Text in primary color (with theme).
12 |
13 |
14 | Text in primary color (with theme overrides).
15 |