feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
# Tailwind CSS Dynamic Class Generation
|
||||
|
||||
## Rule
|
||||
|
||||
Never construct Tailwind CSS class names dynamically using string concatenation or template literals. Tailwind's build process cannot detect dynamically generated class names, causing styles to be missing in production.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
- Tailwind uses static analysis at build time to determine which CSS classes to include
|
||||
- Dynamically constructed class names (e.g., `bg-${color}-500`) are invisible to Tailwind's scanner
|
||||
- Classes work in development with JIT but fail silently in production builds
|
||||
- This is a common source of "it works locally but not in production" bugs
|
||||
|
||||
## Bad Code
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
color: String, // 'red', 'blue', 'green'
|
||||
size: String // 'sm', 'md', 'lg'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- WRONG: Tailwind cannot detect these classes -->
|
||||
<div :class="`bg-${color}-500 text-${size}`">
|
||||
Content
|
||||
</div>
|
||||
|
||||
<!-- WRONG: String concatenation -->
|
||||
<div :class="'p-' + padding">
|
||||
Content
|
||||
</div>
|
||||
|
||||
<!-- WRONG: Template literal in array -->
|
||||
<div :class="[`gap-x-${spacing}`]">
|
||||
Content
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Good Code
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
color: String,
|
||||
size: String
|
||||
})
|
||||
|
||||
// Use a mapping object with complete class names
|
||||
const colorClasses = {
|
||||
red: 'bg-red-500',
|
||||
blue: 'bg-blue-500',
|
||||
green: 'bg-green-500'
|
||||
}
|
||||
|
||||
const sizeClasses = {
|
||||
sm: 'text-sm p-2',
|
||||
md: 'text-base p-4',
|
||||
lg: 'text-lg p-6'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- CORRECT: Full class names that Tailwind can detect -->
|
||||
<div :class="[colorClasses[color], sizeClasses[size]]">
|
||||
Content
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Using Conditional Objects
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
variant: String // 'primary', 'secondary', 'danger'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- CORRECT: All class names are complete strings -->
|
||||
<button :class="{
|
||||
'bg-blue-500 hover:bg-blue-600': variant === 'primary',
|
||||
'bg-gray-500 hover:bg-gray-600': variant === 'secondary',
|
||||
'bg-red-500 hover:bg-red-600': variant === 'danger'
|
||||
}">
|
||||
Click me
|
||||
</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Safelist for Truly Dynamic Classes
|
||||
|
||||
If you must use dynamic classes, add them to Tailwind's safelist:
|
||||
|
||||
```javascript
|
||||
// tailwind.config.js
|
||||
module.exports = {
|
||||
safelist: [
|
||||
'bg-red-500',
|
||||
'bg-blue-500',
|
||||
'bg-green-500',
|
||||
// Or use patterns (use sparingly - increases bundle size)
|
||||
{
|
||||
pattern: /bg-(red|blue|green)-(100|500|900)/
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Alternative: CSS Custom Properties
|
||||
|
||||
For truly dynamic values, use CSS custom properties:
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
customColor: String // Any hex color
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Use CSS variable for truly dynamic values -->
|
||||
<div
|
||||
class="dynamic-bg"
|
||||
:style="{ '--dynamic-color': customColor }"
|
||||
>
|
||||
Content
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.dynamic-bg {
|
||||
background-color: var(--dynamic-color);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Tailwind CSS Dynamic Class Names](https://tailwindcss.com/docs/content-configuration#dynamic-class-names)
|
||||
- [Tailwind Safelist](https://tailwindcss.com/docs/content-configuration#safelisting-classes)
|
||||
Reference in New Issue
Block a user