bsmnt 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/2026-02-11-test-patch-bump.md +5 -0
- package/.changeset/README.md +10 -0
- package/.changeset/config.json +16 -0
- package/.cursor/rules/README.md +184 -0
- package/.cursor/rules/architecture.mdc +437 -0
- package/.cursor/rules/components.mdc +436 -0
- package/.cursor/rules/integrations.mdc +447 -0
- package/.cursor/rules/main.mdc +278 -0
- package/.cursor/rules/styling.mdc +433 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- package/.github/workflows/.gitkeep +0 -0
- package/.github/workflows/ci.yml +37 -0
- package/.github/workflows/release.yml +54 -0
- package/.tldr/cache/call_graph.json +7 -0
- package/.tldr/languages.json +6 -0
- package/.tldr/status +1 -0
- package/.tldrignore +84 -0
- package/.vscode/extensions.json +20 -0
- package/.vscode/settings.json +98 -0
- package/CHANGELOG.md +13 -0
- package/CLAUDE.md +138 -0
- package/README.md +176 -0
- package/bin/index.js +262 -0
- package/biome.json +44 -0
- package/bun.lock +496 -0
- package/changelog/04-02-26.md +86 -0
- package/changelog/05-02-26.md +101 -0
- package/changelog/09-02-26.md +83 -0
- package/docs/fix-studio-hydration.md +46 -0
- package/docs/plans/2026-01-29-sanity-smart-merge-design.md +196 -0
- package/docs/plans/2026-01-29-sanity-smart-merge-implementation.md +695 -0
- package/docs/sanity-setup-steps.md +199 -0
- package/integrations/basehub/README.md +3 -0
- package/integrations/sanity/app/api/draft-mode/disable/route.ts +7 -0
- package/integrations/sanity/app/api/draft-mode/enable/route.ts +21 -0
- package/integrations/sanity/app/api/revalidate/route.ts +37 -0
- package/integrations/sanity/app/layout.tsx +111 -0
- package/integrations/sanity/app/sitemap.ts +80 -0
- package/integrations/sanity/app/studio/[[...tool]]/page.tsx +8 -0
- package/integrations/sanity/app/studio/layout.tsx +7 -0
- package/integrations/sanity/components/ui/sanity-image/index.tsx +37 -0
- package/integrations/sanity/lib/integrations/README.md +58 -0
- package/integrations/sanity/lib/integrations/check-integration.ts +62 -0
- package/integrations/sanity/lib/integrations/sanity/README.md +144 -0
- package/integrations/sanity/lib/integrations/sanity/client.ts +30 -0
- package/integrations/sanity/lib/integrations/sanity/components/disable-draft-mode.tsx +29 -0
- package/integrations/sanity/lib/integrations/sanity/components/rich-text.tsx +73 -0
- package/integrations/sanity/lib/integrations/sanity/env.ts +38 -0
- package/integrations/sanity/lib/integrations/sanity/live/index.tsx +34 -0
- package/integrations/sanity/lib/integrations/sanity/queries.ts +99 -0
- package/integrations/sanity/lib/integrations/sanity/sanity.cli.ts +20 -0
- package/integrations/sanity/lib/integrations/sanity/sanity.config.ts +94 -0
- package/integrations/sanity/lib/integrations/sanity/sanity.types.ts +337 -0
- package/integrations/sanity/lib/integrations/sanity/schema.json +1850 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/article.ts +132 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/example.ts +203 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/index.ts +37 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/link.ts +127 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/metadata.ts +68 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/navigation.ts +39 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/page.ts +77 -0
- package/integrations/sanity/lib/integrations/sanity/schemas/richText.ts +59 -0
- package/integrations/sanity/lib/integrations/sanity/structure.ts +5 -0
- package/integrations/sanity/lib/integrations/sanity/utils/image.ts +11 -0
- package/integrations/sanity/lib/integrations/sanity/utils/link.ts +61 -0
- package/integrations/sanity/lib/scripts/copy-sanity-mcp.ts +23 -0
- package/integrations/sanity/lib/scripts/generate-page.ts +310 -0
- package/integrations/sanity/lib/utils/metadata.ts +190 -0
- package/layers/experiment/components/layout/header/index.tsx +58 -0
- package/layers/experiment/components/layout/navigation-menu.tsx +127 -0
- package/layers/experiment/lib/constants.ts +12 -0
- package/layers/webgl/app/page.tsx +10 -0
- package/layers/webgl/components/webgl/canvas/dynamic.tsx +34 -0
- package/layers/webgl/components/webgl/canvas/index.tsx +43 -0
- package/layers/webgl/components/webgl/components/scene/index.tsx +21 -0
- package/layers/webgpu/.gitkeep +0 -0
- package/package.json +44 -0
- package/plugins/README.md +21 -0
- package/plugins/no-anchor-element.grit +11 -0
- package/plugins/no-relative-parent-imports.grit +6 -0
- package/plugins/no-unnecessary-forwardref.grit +5 -0
- package/src/commands/add-integration.js +325 -0
- package/src/commands/create.js +415 -0
- package/src/commands/setup-sanity.js +426 -0
- package/src/commands/worktree.js +805 -0
- package/src/mergers/check-integration-merger.js +105 -0
- package/src/mergers/config.js +137 -0
- package/src/mergers/index.js +355 -0
- package/src/mergers/layout-merger.js +223 -0
- package/src/mergers/next-config-merger.js +63 -0
- package/src/mergers/sitemap-merger.js +121 -0
- package/tasks/prd-next-starter-dynamic-layers.md +184 -0
- package/tasks/prd.json +153 -0
- package/tasks/progress.txt +115 -0
- package/template-hooks/use-battery.ts +126 -0
- package/template-hooks/use-device-perf.ts +184 -0
- package/template-hooks/use-intersection-observer.ts +32 -0
- package/template-hooks/use-media.ts +33 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: true
|
|
3
|
+
---
|
|
4
|
+
---
|
|
5
|
+
description: Project overview and cross-cutting concerns
|
|
6
|
+
globs: *.tsx, *.jsx, *.css, *.js, *.ts
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Satus Project Guidelines
|
|
10
|
+
|
|
11
|
+
## Technology Stack
|
|
12
|
+
|
|
13
|
+
- **Next.js 16+** - App Router with Turbopack support and Cache Components
|
|
14
|
+
- **React 19+** - Latest features including `<Activity />`, `useEffectEvent`, and `cacheSignal`
|
|
15
|
+
- **React Compiler** - Automatically optimizes component re-renders and memoization
|
|
16
|
+
- **TypeScript** - Strict mode enabled
|
|
17
|
+
- **Tailwind CSS v4** - CSS-first configuration
|
|
18
|
+
- **Biome** - Linting and formatting
|
|
19
|
+
- **Bun** - JavaScript runtime and package manager
|
|
20
|
+
|
|
21
|
+
## React 19.2 New Features
|
|
22
|
+
|
|
23
|
+
### 1. `<Activity />` Component
|
|
24
|
+
Manage off-screen component visibility and defer updates for better performance.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { Activity } from 'react'
|
|
28
|
+
|
|
29
|
+
// Hide tab content when not visible
|
|
30
|
+
<Activity mode={isActive ? 'visible' : 'hidden'}>
|
|
31
|
+
<ExpensiveComponent />
|
|
32
|
+
</Activity>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Use Cases:**
|
|
36
|
+
- Tab systems or carousels
|
|
37
|
+
- Off-screen WebGL scenes (3D graphics, shaders)
|
|
38
|
+
- Accordion components
|
|
39
|
+
- Drawer/modal systems
|
|
40
|
+
- Image galleries and carousels
|
|
41
|
+
|
|
42
|
+
**Benefits:**
|
|
43
|
+
- Pre-render content without performance impact
|
|
44
|
+
- Automatic effect cleanup when hidden
|
|
45
|
+
- Better resource management for complex UIs
|
|
46
|
+
|
|
47
|
+
### 2. `useEffectEvent` Hook
|
|
48
|
+
Separate event logic from effect dependencies to prevent unnecessary re-runs.
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import { useEffect, useEffectEvent } from 'react'
|
|
52
|
+
|
|
53
|
+
function Component({ url, theme }) {
|
|
54
|
+
const onConnected = useEffectEvent(() => {
|
|
55
|
+
showNotification('Connected!', theme) // theme changes won't trigger reconnect
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const connection = createConnection(url)
|
|
60
|
+
connection.on('connected', onConnected)
|
|
61
|
+
connection.connect()
|
|
62
|
+
return () => connection.disconnect()
|
|
63
|
+
}, [url]) // Only reconnect when url changes
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Use Cases:**
|
|
68
|
+
- Complex event handlers with multiple dependencies
|
|
69
|
+
- Scroll/transform callbacks
|
|
70
|
+
- WebGL mouse/interaction handlers
|
|
71
|
+
- Animation callbacks
|
|
72
|
+
|
|
73
|
+
**Benefits:**
|
|
74
|
+
- Reduces unnecessary effect re-runs
|
|
75
|
+
- Cleaner dependency arrays
|
|
76
|
+
- Better separation of concerns
|
|
77
|
+
|
|
78
|
+
### 3. `cacheSignal` (Server Components Only)
|
|
79
|
+
Provides an `AbortSignal` that triggers when the component's cache scope expires.
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { cacheSignal } from 'react'
|
|
83
|
+
|
|
84
|
+
async function fetchUserData(id: string) {
|
|
85
|
+
const signal = cacheSignal() // Auto-aborts on cache expiry
|
|
86
|
+
const response = await fetch(`/api/users/${id}`, { signal })
|
|
87
|
+
return response.json()
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Use Cases:**
|
|
92
|
+
- Sanity CMS queries
|
|
93
|
+
- Shopify API calls
|
|
94
|
+
- Any server component data fetching
|
|
95
|
+
- Replace custom timeout logic with automatic cleanup
|
|
96
|
+
|
|
97
|
+
**Benefits:**
|
|
98
|
+
- Automatic cleanup of stale requests
|
|
99
|
+
- Better resource management
|
|
100
|
+
- Simpler than manual AbortController
|
|
101
|
+
|
|
102
|
+
### 4. Performance Tracks in Chrome DevTools
|
|
103
|
+
React 19.2 integrates custom performance tracks into Chrome DevTools:
|
|
104
|
+
- **Scheduler Track:** Displays React's workload prioritization
|
|
105
|
+
- **Components Track:** Shows component hierarchy and timing
|
|
106
|
+
|
|
107
|
+
**Usage:** Open Chrome DevTools → Performance tab → Record a profile → Look for React-specific tracks
|
|
108
|
+
|
|
109
|
+
## File Organization
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
├── app/ # Next.js pages and routes
|
|
113
|
+
├── components/ # Shared UI components
|
|
114
|
+
├── lib/ # Everything non-UI
|
|
115
|
+
│ ├── hooks/ # Custom React hooks
|
|
116
|
+
│ ├── integrations/ # Sanity, Shopify, HubSpot, etc.
|
|
117
|
+
│ ├── webgl/ # 3D graphics (optional)
|
|
118
|
+
│ ├── dev/ # Debug tools - CMD+O (optional)
|
|
119
|
+
│ ├── scripts/ # CLI tools (dev, setup)
|
|
120
|
+
│ ├── styles/ # CSS config & Tailwind
|
|
121
|
+
│ └── *.ts # Utils, store, metadata...
|
|
122
|
+
└── public/ # Static assets
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> **Mental model:** "If it renders UI, it's in `components/`. Everything else is in `lib/`."
|
|
126
|
+
|
|
127
|
+
## Cross-Cutting Concerns
|
|
128
|
+
|
|
129
|
+
### React Compiler & Memoization
|
|
130
|
+
|
|
131
|
+
**React Compiler is enabled and handles ALL optimization automatically.**
|
|
132
|
+
|
|
133
|
+
- **DO NOT use `useMemo`, `useCallback`, or `React.memo` in new code.**
|
|
134
|
+
- The compiler optimizes all component re-renders, memoization, and dependencies automatically.
|
|
135
|
+
- Only use manual memoization if you encounter a proven edge case where the compiler cannot optimize (extremely rare).
|
|
136
|
+
- If you see these in existing code, they can likely be removed safely.
|
|
137
|
+
- **CRITICAL EXCEPTION: Use `useRef` for object instantiation** - Creating new object instances on every render creates new references that trigger effects, causing infinite loops.
|
|
138
|
+
- Refer to the [React Compiler documentation](https://react.dev/reference/react/compiler) for edge cases.
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
// ❌ DON'T: Manual memoization for simple calculations (compiler handles this)
|
|
142
|
+
const memoizedValue = useMemo(() => computeExpensive(a, b), [a, b])
|
|
143
|
+
const memoizedCallback = useCallback(() => doSomething(a), [a])
|
|
144
|
+
|
|
145
|
+
// ✅ DO: Let React Compiler optimize automatically
|
|
146
|
+
const value = computeExpensive(a, b)
|
|
147
|
+
const handleClick = () => doSomething(a)
|
|
148
|
+
|
|
149
|
+
// ⚠️ EXCEPTION: Object instantiation MUST use useRef
|
|
150
|
+
// ❌ DON'T: This causes infinite re-renders when passed to effects/deps
|
|
151
|
+
const instance = new SomeClass()
|
|
152
|
+
|
|
153
|
+
// ✅ DO: Use useRef for object instantiation
|
|
154
|
+
const instanceRef = useRef<SomeClass | null>(null)
|
|
155
|
+
if (!instanceRef.current) {
|
|
156
|
+
instanceRef.current = new SomeClass(params)
|
|
157
|
+
}
|
|
158
|
+
const instance = instanceRef.current
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Image Optimization
|
|
162
|
+
|
|
163
|
+
**Always use the custom Image component for all images.**
|
|
164
|
+
|
|
165
|
+
- **DO NOT use `next/image` directly**
|
|
166
|
+
- Use `@/components/ui/image` for standard images
|
|
167
|
+
- **In WebGL contexts, use `@/lib/webgl/components/image`** which wraps the custom Image component for DOM fallback and WebGL texture integration
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
import { Image } from '@/components/ui'
|
|
171
|
+
// For WebGL:
|
|
172
|
+
import { Image as WebGLImage } from '@/lib/webgl/components/image'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Development vs Production
|
|
176
|
+
|
|
177
|
+
- **Always gate debug UI components** - these are NOT automatically removed in production
|
|
178
|
+
- **Gate expensive debug computations** - avoid running heavy operations in production
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
// ✅ Simple logs: Optional to gate (Next.js strips them automatically)
|
|
182
|
+
console.log('Debug info:', data)
|
|
183
|
+
|
|
184
|
+
// ✅ Better: Gate expensive operations to avoid computation overhead
|
|
185
|
+
if (process.env.NODE_ENV === 'development') {
|
|
186
|
+
console.log('Heavy computation:', expensiveDebugCalculation())
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ⚠️ REQUIRED: Always gate debug UI components (not auto-removed)
|
|
190
|
+
{process.env.NODE_ENV === 'development' && <DebugPanel />}
|
|
191
|
+
{process.env.NODE_ENV === 'development' && <Stats />}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Bundle Size Optimization:**
|
|
195
|
+
- Keep production bundles minimal by excluding dev-only code
|
|
196
|
+
- Use tree-shaking friendly imports
|
|
197
|
+
- Check bundle size impact of new dependencies
|
|
198
|
+
- Debug UI components must be gated (Next.js won't remove them automatically)
|
|
199
|
+
|
|
200
|
+
## Core Utility Libraries
|
|
201
|
+
|
|
202
|
+
### Available Utilities
|
|
203
|
+
- **`@/utils/fetch`** - Resilient API calls with `fetchWithTimeout` (default 10s timeout)
|
|
204
|
+
- **`@/utils/metadata`** - Centralized SEO and metadata generation for consistent OpenGraph, Twitter cards, etc.
|
|
205
|
+
- **`@/utils/math`** - Pure math functions: clamp, lerp, mapRange, etc.
|
|
206
|
+
- **`@/utils/strings`** - String utilities: slugify, mergeRefs, etc.
|
|
207
|
+
|
|
208
|
+
### Usage Examples
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
// Fetch with timeout
|
|
212
|
+
import { fetchWithTimeout } from '@/utils/fetch'
|
|
213
|
+
const response = await fetchWithTimeout(url, { timeout: 10000, ...options })
|
|
214
|
+
|
|
215
|
+
// Generate metadata
|
|
216
|
+
import { generatePageMetadata, generateSanityMetadata } from '@/utils/metadata'
|
|
217
|
+
export async function generateMetadata({ params }) {
|
|
218
|
+
const page = await fetchPage(params.slug)
|
|
219
|
+
return generateSanityMetadata({ document: page, url: `/page/${params.slug}` })
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Math utilities
|
|
223
|
+
import { clamp, lerp, mapRange } from '@/utils/math'
|
|
224
|
+
const value = clamp(input, 0, 100)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Getting Started
|
|
228
|
+
|
|
229
|
+
1. Review relevant best practices before starting work in a specific area
|
|
230
|
+
2. Follow the project structure guidelines
|
|
231
|
+
3. Use the provided development tools and debugging features
|
|
232
|
+
4. Consult the documentation for specific implementation details
|
|
233
|
+
5. Use utility libraries for common patterns (API calls, env validation, metadata)
|
|
234
|
+
|
|
235
|
+
## Updates
|
|
236
|
+
|
|
237
|
+
These best practices are regularly updated to reflect:
|
|
238
|
+
- New dependencies and versions
|
|
239
|
+
- Improved patterns and practices
|
|
240
|
+
- Community feedback and learnings
|
|
241
|
+
- Project-specific requirements
|
|
242
|
+
|
|
243
|
+
## Next.js 16 Cache Components
|
|
244
|
+
|
|
245
|
+
Cache Components are enabled globally (`cacheComponents: true` in `next.config.ts`). This provides advanced caching strategies for Server Components.
|
|
246
|
+
|
|
247
|
+
### Important Gotchas
|
|
248
|
+
|
|
249
|
+
**1. Server Components Only**
|
|
250
|
+
- Cache Components work only in Server Components
|
|
251
|
+
- Client Components (`'use client'`) cannot use Cache Components
|
|
252
|
+
- Move data fetching to Server Components, pass props to Client Components
|
|
253
|
+
|
|
254
|
+
**2. Suspense Boundaries Required**
|
|
255
|
+
- Cached components must be wrapped in Suspense boundaries
|
|
256
|
+
- Use proper loading fallbacks for better UX
|
|
257
|
+
|
|
258
|
+
**3. User-Specific Data**
|
|
259
|
+
- ❌ **Never cache** personalized data (user profiles, cart contents, private content)
|
|
260
|
+
- ✅ **Always use** `cache: 'no-store'` for user-specific requests
|
|
261
|
+
- Example: Shopping carts, user accounts, private content
|
|
262
|
+
|
|
263
|
+
**4. Real-Time Data**
|
|
264
|
+
- Live feeds, stock prices, chat messages should use `cache: 'no-store'`
|
|
265
|
+
- Only cache data that doesn't change frequently
|
|
266
|
+
|
|
267
|
+
**5. Testing Caching**
|
|
268
|
+
- Hard refresh (`Cmd+Shift+R`) bypasses router cache
|
|
269
|
+
- Normal navigation uses router cache
|
|
270
|
+
- Test both behaviors, especially with dynamic routes
|
|
271
|
+
- Development and production behave differently
|
|
272
|
+
|
|
273
|
+
**6. Cache Invalidation**
|
|
274
|
+
- Use `revalidateTag()` or `revalidatePath()` in webhook handlers
|
|
275
|
+
- Set proper cache tags: `next: { tags: ['products'] }`
|
|
276
|
+
- Dynamic routes require careful cache tag management
|
|
277
|
+
|
|
278
|
+
Last updated: 2026-01-26
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: true
|
|
3
|
+
---
|
|
4
|
+
---
|
|
5
|
+
description: CSS Modules, Tailwind CSS v4, and responsive design patterns
|
|
6
|
+
globs: *.tsx, *.jsx, *.css, *.js, *.ts
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Styling Guidelines
|
|
10
|
+
|
|
11
|
+
## CSS Modules
|
|
12
|
+
|
|
13
|
+
### File Naming
|
|
14
|
+
Use kebab-case for CSS module files. Match the component name followed by `.module.css`
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
button.tsx
|
|
18
|
+
button.module.css
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Class Naming
|
|
22
|
+
Use camelCase for class names. Use descriptive, semantic names.
|
|
23
|
+
|
|
24
|
+
```css
|
|
25
|
+
.button { /* Base styles */ }
|
|
26
|
+
.isPrimary { /* Variant styles */ }
|
|
27
|
+
.isDisabled { /* State styles */ }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Imports in Components
|
|
31
|
+
Always import CSS modules as `s`
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import s from './component-name.module.css'
|
|
35
|
+
|
|
36
|
+
function Component() {
|
|
37
|
+
return <div className={s.wrapper} />
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Responsive Design
|
|
42
|
+
|
|
43
|
+
### Viewport Functions
|
|
44
|
+
Use custom viewport functions for responsive sizing
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
.element {
|
|
48
|
+
width: tovw(150); /* 6.94vw at desktop viewport */
|
|
49
|
+
margin: toem(50); /* 3.47em at desktop viewport */
|
|
50
|
+
padding: torem(25); /* 1.56rem at desktop viewport */
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Breakpoints
|
|
55
|
+
Desktop breakpoint: 1440px (defined in styles/config.ts)
|
|
56
|
+
|
|
57
|
+
```css
|
|
58
|
+
@media (min-width: 1440px) {
|
|
59
|
+
/* Desktop styles */
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Grid System
|
|
64
|
+
Use the column function for grid-based layouts
|
|
65
|
+
|
|
66
|
+
```css
|
|
67
|
+
.container {
|
|
68
|
+
width: columns(6); /* Span 6 columns */
|
|
69
|
+
margin-left: columns(1); /* Offset by 1 column */
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Typography
|
|
74
|
+
|
|
75
|
+
### Font Hierarchy
|
|
76
|
+
Use typography variables from the theme
|
|
77
|
+
|
|
78
|
+
```css
|
|
79
|
+
.title {
|
|
80
|
+
font-size: var(--font-size-title);
|
|
81
|
+
line-height: var(--line-height-title);
|
|
82
|
+
font-weight: var(--font-weight-bold);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Colors and Themes
|
|
87
|
+
|
|
88
|
+
### Color Variables
|
|
89
|
+
Use theme colors from CSS variables
|
|
90
|
+
|
|
91
|
+
```css
|
|
92
|
+
.element {
|
|
93
|
+
color: var(--color-text);
|
|
94
|
+
background-color: var(--color-background);
|
|
95
|
+
border-color: var(--color-accent);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Theme Switching
|
|
100
|
+
Use theme-specific variables when needed
|
|
101
|
+
|
|
102
|
+
```css
|
|
103
|
+
.element {
|
|
104
|
+
color: var(--theme-dark-text);
|
|
105
|
+
background-color: var(--theme-dark-background);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
[data-theme="light"] .element {
|
|
109
|
+
color: var(--theme-light-text);
|
|
110
|
+
background-color: var(--theme-light-background);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Animations and Transitions
|
|
115
|
+
|
|
116
|
+
### Transition Timing
|
|
117
|
+
Use consistent transition variables
|
|
118
|
+
|
|
119
|
+
```css
|
|
120
|
+
.element {
|
|
121
|
+
transition: opacity var(--transition-duration) var(--transition-ease);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Animation Easings
|
|
126
|
+
Import easings from the theme
|
|
127
|
+
|
|
128
|
+
```css
|
|
129
|
+
.element {
|
|
130
|
+
transition: transform 0.5s var(--ease-out-expo);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Best Practices
|
|
135
|
+
|
|
136
|
+
### Performance
|
|
137
|
+
Prefer CPU-friendly properties (transform, opacity). Use `will-change` sparingly and only when needed.
|
|
138
|
+
|
|
139
|
+
```css
|
|
140
|
+
.animatedElement {
|
|
141
|
+
will-change: transform, opacity;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Organization
|
|
146
|
+
Group related properties together. Order properties consistently.
|
|
147
|
+
|
|
148
|
+
```css
|
|
149
|
+
.element {
|
|
150
|
+
/* Positioning */
|
|
151
|
+
position: absolute;
|
|
152
|
+
top: 0;
|
|
153
|
+
left: 0;
|
|
154
|
+
z-index: 1;
|
|
155
|
+
|
|
156
|
+
/* Box model */
|
|
157
|
+
display: flex;
|
|
158
|
+
width: 100%;
|
|
159
|
+
padding: 1rem;
|
|
160
|
+
|
|
161
|
+
/* Visual */
|
|
162
|
+
background-color: var(--color-background);
|
|
163
|
+
border-radius: 4px;
|
|
164
|
+
|
|
165
|
+
/* Typography */
|
|
166
|
+
font-size: 1rem;
|
|
167
|
+
color: var(--color-text);
|
|
168
|
+
|
|
169
|
+
/* Animation */
|
|
170
|
+
transition: all 0.3s ease;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
# Tailwind CSS v4
|
|
177
|
+
|
|
178
|
+
## Core Changes
|
|
179
|
+
|
|
180
|
+
### CSS-first configuration
|
|
181
|
+
Configuration is now done in CSS instead of JavaScript. Use `@theme` directive in CSS instead of `tailwind.config.js`
|
|
182
|
+
|
|
183
|
+
```css
|
|
184
|
+
@import "tailwindcss";
|
|
185
|
+
|
|
186
|
+
@theme {
|
|
187
|
+
--font-display: "Satoshi", "sans-serif";
|
|
188
|
+
--breakpoint-3xl: 1920px;
|
|
189
|
+
--color-avocado-500: oklch(0.84 0.18 117.33);
|
|
190
|
+
--ease-fluid: cubic-bezier(0.3, 0, 0, 1);
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### CSS import syntax
|
|
195
|
+
Use `@import "tailwindcss"` instead of `@tailwind` directives
|
|
196
|
+
|
|
197
|
+
- Old: `@tailwind base; @tailwind components; @tailwind utilities;`
|
|
198
|
+
- New: `@import "tailwindcss";`
|
|
199
|
+
|
|
200
|
+
### Package changes
|
|
201
|
+
- PostCSS plugin is now `@tailwindcss/postcss` (not `tailwindcss`)
|
|
202
|
+
- CLI is now `@tailwindcss/cli`
|
|
203
|
+
- Vite plugin is `@tailwindcss/vite`
|
|
204
|
+
- No need for `postcss-import` or `autoprefixer` anymore
|
|
205
|
+
|
|
206
|
+
### Native CSS cascade layers
|
|
207
|
+
Uses real CSS `@layer` instead of Tailwind's custom implementation
|
|
208
|
+
|
|
209
|
+
## Theme Configuration
|
|
210
|
+
|
|
211
|
+
### CSS theme variables
|
|
212
|
+
All design tokens are available as CSS variables
|
|
213
|
+
|
|
214
|
+
- Namespace format: `--category-name` (e.g., `--color-blue-500`, `--font-sans`)
|
|
215
|
+
- Access in CSS: `var(--color-blue-500)`
|
|
216
|
+
- Available namespaces:
|
|
217
|
+
- `--color-*` : Color utilities like `bg-red-500` and `text-sky-300`
|
|
218
|
+
- `--font-*` : Font family utilities like `font-sans`
|
|
219
|
+
- `--text-*` : Font size utilities like `text-xl`
|
|
220
|
+
- `--font-weight-*` : Font weight utilities like `font-bold`
|
|
221
|
+
- `--tracking-*` : Letter spacing utilities like `tracking-wide`
|
|
222
|
+
- `--leading-*` : Line height utilities like `leading-tight`
|
|
223
|
+
- `--breakpoint-*` : Responsive breakpoint variants like `sm:*`
|
|
224
|
+
- `--container-*` : Container query variants like `@sm:*` and size utilities like `max-w-md`
|
|
225
|
+
- `--spacing-*` : Spacing and sizing utilities like `px-4` and `max-h-16`
|
|
226
|
+
- `--radius-*` : Border radius utilities like `rounded-sm`
|
|
227
|
+
- `--shadow-*` : Box shadow utilities like `shadow-md`
|
|
228
|
+
- `--inset-shadow-*` : Inset box shadow utilities like `inset-shadow-xs`
|
|
229
|
+
- `--drop-shadow-*` : Drop shadow filter utilities like `drop-shadow-md`
|
|
230
|
+
- `--blur-*` : Blur filter utilities like `blur-md`
|
|
231
|
+
- `--perspective-*` : Perspective utilities like `perspective-near`
|
|
232
|
+
- `--aspect-*` : Aspect ratio utilities like `aspect-video`
|
|
233
|
+
- `--ease-*` : Transition timing function utilities like `ease-out`
|
|
234
|
+
- `--animate-*` : Animation utilities like `animate-spin`
|
|
235
|
+
|
|
236
|
+
### Simplified theme configuration
|
|
237
|
+
Many utilities no longer need theme configuration
|
|
238
|
+
|
|
239
|
+
- Utilities like `grid-cols-12`, `z-40`, and `opacity-70` work without configuration
|
|
240
|
+
- Data attributes like `data-selected:opacity-100` don't need configuration
|
|
241
|
+
|
|
242
|
+
### Dynamic spacing scale
|
|
243
|
+
Derived from a single spacing value
|
|
244
|
+
|
|
245
|
+
- Default: `--spacing: 0.25rem`
|
|
246
|
+
- Every multiple of the base value is available (e.g., `mt-21` works automatically)
|
|
247
|
+
|
|
248
|
+
### Overriding theme namespaces
|
|
249
|
+
- Override entire namespace: `--font-*: initial;`
|
|
250
|
+
- Override entire theme: `--*: initial;`
|
|
251
|
+
|
|
252
|
+
## New Features
|
|
253
|
+
|
|
254
|
+
### Container query support
|
|
255
|
+
Built-in now, no plugin needed
|
|
256
|
+
|
|
257
|
+
- `@container` for container context
|
|
258
|
+
- `@sm:`, `@md:`, etc. for container-based breakpoints
|
|
259
|
+
- `@max-md:` for max-width container queries
|
|
260
|
+
- Combine with `@min-md:@max-xl:hidden` for ranges
|
|
261
|
+
|
|
262
|
+
### 3D transforms
|
|
263
|
+
- `transform-3d` enables 3D transforms
|
|
264
|
+
- `rotate-x-*`, `rotate-y-*`, `rotate-z-*` for 3D rotation
|
|
265
|
+
- `scale-z-*` for z-axis scaling
|
|
266
|
+
- `translate-z-*` for z-axis translation
|
|
267
|
+
- `perspective-*` utilities (`perspective-near`, `perspective-distant`, etc.)
|
|
268
|
+
- `perspective-origin-*` utilities
|
|
269
|
+
- `backface-visible` and `backface-hidden`
|
|
270
|
+
|
|
271
|
+
### Gradient enhancements
|
|
272
|
+
- Linear gradient angles: `bg-linear-45` (renamed from `bg-gradient-*`)
|
|
273
|
+
- Gradient interpolation: `bg-linear-to-r/oklch`, `bg-linear-to-r/srgb`
|
|
274
|
+
- Conic and radial gradients: `bg-conic`, `bg-radial-[at_25%_25%]`
|
|
275
|
+
|
|
276
|
+
### Shadow enhancements
|
|
277
|
+
- `inset-shadow-*` and `inset-ring-*` utilities
|
|
278
|
+
- Can be composed with regular `shadow-*` and `ring-*`
|
|
279
|
+
|
|
280
|
+
### New CSS property utilities
|
|
281
|
+
- `field-sizing-content` for auto-resizing textareas
|
|
282
|
+
- `scheme-light`, `scheme-dark` for `color-scheme` property
|
|
283
|
+
- `font-stretch-*` utilities for variable fonts
|
|
284
|
+
|
|
285
|
+
## New Variants
|
|
286
|
+
|
|
287
|
+
### Composable variants
|
|
288
|
+
Chain variants together
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
// Example: group-has-data-potato:opacity-100
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### New variants
|
|
295
|
+
- `starting` variant for `@starting-style` transitions
|
|
296
|
+
- `not-*` variant for `:not()` pseudo-class
|
|
297
|
+
- `inert` variant for `inert` attribute
|
|
298
|
+
- `nth-*` variants (`nth-3:`, `nth-last-5:`, `nth-of-type-4:`, `nth-last-of-type-6:`)
|
|
299
|
+
- `in-*` variant (like `group-*` but without adding `group` class)
|
|
300
|
+
- `open` variant now supports `:popover-open`
|
|
301
|
+
- `**` variant for targeting all descendants
|
|
302
|
+
|
|
303
|
+
## Custom Extensions
|
|
304
|
+
|
|
305
|
+
### Custom utilities
|
|
306
|
+
Use `@utility` directive
|
|
307
|
+
|
|
308
|
+
```css
|
|
309
|
+
@utility tab-4 {
|
|
310
|
+
tab-size: 4;
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Custom variants
|
|
315
|
+
Use `@variant` directive
|
|
316
|
+
|
|
317
|
+
```css
|
|
318
|
+
@variant pointer-coarse (@media (pointer: coarse));
|
|
319
|
+
@variant theme-midnight (&:where([data-theme="midnight"] *));
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Plugins
|
|
323
|
+
Use `@plugin` directive
|
|
324
|
+
|
|
325
|
+
```css
|
|
326
|
+
@plugin "@tailwindcss/typography";
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Breaking Changes
|
|
330
|
+
|
|
331
|
+
### Removed deprecated utilities
|
|
332
|
+
- `bg-opacity-*` → Use `bg-black/50` instead
|
|
333
|
+
- `text-opacity-*` → Use `text-black/50` instead
|
|
334
|
+
- And others: `border-opacity-*`, `divide-opacity-*`, etc.
|
|
335
|
+
|
|
336
|
+
### Renamed utilities
|
|
337
|
+
- `shadow-sm` → `shadow-xs` (and `shadow` → `shadow-sm`)
|
|
338
|
+
- `drop-shadow-sm` → `drop-shadow-xs` (and `drop-shadow` → `drop-shadow-sm`)
|
|
339
|
+
- `blur-sm` → `blur-xs` (and `blur` → `blur-sm`)
|
|
340
|
+
- `rounded-sm` → `rounded-xs` (and `rounded` → `rounded-sm`)
|
|
341
|
+
- `outline-none` → `outline-hidden` (for the old behavior)
|
|
342
|
+
|
|
343
|
+
### Default style changes
|
|
344
|
+
- Default border color is now `currentColor` (was `gray-200`)
|
|
345
|
+
- Default `ring` width is now 1px (was 3px)
|
|
346
|
+
- Placeholder text now uses current color at 50% opacity (was `gray-400`)
|
|
347
|
+
- Hover styles only apply on devices that support hover (`@media (hover: hover)`)
|
|
348
|
+
|
|
349
|
+
### Syntax changes
|
|
350
|
+
- CSS variables in arbitrary values: `bg-(--brand-color)` instead of `bg-[--brand-color]`
|
|
351
|
+
- Stacked variants now apply left-to-right (not right-to-left)
|
|
352
|
+
- Use CSS variables instead of `theme()` function
|
|
353
|
+
|
|
354
|
+
## Advanced Configuration
|
|
355
|
+
|
|
356
|
+
### Using a prefix
|
|
357
|
+
|
|
358
|
+
```css
|
|
359
|
+
@import "tailwindcss" prefix(tw);
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Results in classes like `tw:flex`, `tw:bg-red-500`, `tw:hover:bg-red-600`
|
|
363
|
+
|
|
364
|
+
### Source detection
|
|
365
|
+
- Automatic by default (ignores `.gitignore` files and binary files)
|
|
366
|
+
- Add sources: `@source "../node_modules/@my-company/ui-lib";`
|
|
367
|
+
- Disable automatic detection: `@import "tailwindcss" source(none);`
|
|
368
|
+
|
|
369
|
+
### Legacy config files
|
|
370
|
+
|
|
371
|
+
```css
|
|
372
|
+
@import "tailwindcss";
|
|
373
|
+
@config "../../tailwind.config.js";
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Dark mode configuration
|
|
377
|
+
|
|
378
|
+
```css
|
|
379
|
+
@import "tailwindcss";
|
|
380
|
+
@variant dark (&:where(.dark, .dark *));
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Container customization
|
|
384
|
+
Extend with `@utility`
|
|
385
|
+
|
|
386
|
+
```css
|
|
387
|
+
@utility container {
|
|
388
|
+
margin-inline: auto;
|
|
389
|
+
padding-inline: 2rem;
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Using `@apply` in Vue/Svelte
|
|
394
|
+
|
|
395
|
+
```html
|
|
396
|
+
<style>
|
|
397
|
+
@import "../../my-theme.css" theme(reference);
|
|
398
|
+
/* or */
|
|
399
|
+
@import "tailwindcss/theme" theme(reference);
|
|
400
|
+
|
|
401
|
+
h1 {
|
|
402
|
+
@apply font-bold text-2xl text-red-500;
|
|
403
|
+
}
|
|
404
|
+
</style>
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
# Project-Specific Custom Utilities
|
|
410
|
+
|
|
411
|
+
The project includes custom utility classes and functions generated by scripts in `styles/scripts`. These are available globally in all CSS.
|
|
412
|
+
|
|
413
|
+
## Custom Utility Classes (`b-*`)
|
|
414
|
+
|
|
415
|
+
### Layout and Grid Utilities
|
|
416
|
+
- `b-grid` — sets display: grid and grid-template-columns based on project columns
|
|
417
|
+
- `b-layout-block` — sets margin-inline and width for layout blocks
|
|
418
|
+
- `b-layout-block-inner` — sets padding-inline and width for inner layout blocks
|
|
419
|
+
- `b-layout-grid` — combines layout block and grid
|
|
420
|
+
- `b-layout-grid-inner` — combines inner layout block and grid
|
|
421
|
+
- `desktop-only` — hides element on mobile
|
|
422
|
+
- `mobile-only` — hides element on desktop
|
|
423
|
+
|
|
424
|
+
## Custom PostCSS Functions
|
|
425
|
+
- `tovw(pixels)` — converts pixels to viewport width
|
|
426
|
+
- `toem(pixels)` — converts pixels to em units
|
|
427
|
+
- `torem(pixels)` — converts pixels to rem units
|
|
428
|
+
- `columns(n)` — calculates width based on number of grid columns
|
|
429
|
+
|
|
430
|
+
## Theme and Utility Generation
|
|
431
|
+
The theme, utilities, and variants are generated from project config and may differ from vanilla Tailwind. Always check `/styles/css/tailwind.css` for the latest generated classes.
|
|
432
|
+
|
|
433
|
+
Last updated: 2026-01-26
|