name: tailwind-v4 description: Use when styling with Tailwind CSS v4. Triggers on "Tailwind", "CSS", "styling", "cn()", "classes", "responsive", "dark mode", "mobile-first", "@import tailwindcss", or Tailwind utility questions. allowed-tools: - Read - Edit - Write - Glob - Grep
Tailwind CSS v4 Styling Guidelines
IMPORTANT: This project uses Tailwind CSS v4, not v3. The setup is DIFFERENT.
Tailwind v4 Setup
- Uses @tailwindcss/postcss plugin (NOT the old tailwindcss plugin)
- Uses
.postcssrc.jsonfor PostCSS configuration - Uses
@import "tailwindcss"in CSS files (NOT @tailwind directives) - Uses
@sourcedirective to watch files in monorepo - No
tailwind.config.jsneeded (uses CSS-based configuration)
Styling Rules
- Use Tailwind CSS utility classes for ALL styling (utility-first approach)
- Use CSS only (NOT SCSS) for any necessary custom styles
- Use
clsxandtailwind-mergefor dynamic classes (viacn()utility) - Use
ViewEncapsulation.Nonewith scoped Tailwind classes - Use CSS custom properties (CSS variables) for theming
- Use
@layerdirectives in CSS files (base, components, utilities) - Keep styles in template or inline styles array (avoid separate CSS files unless necessary)
- Ensure responsive design (mobile-first approach)
- Support dark mode via CSS variables and
prefers-color-scheme - Maintain consistent spacing and sizing using design tokens
- Use Tailwind class sorting plugin for consistency
Tailwind v4 CSS Structure
/* styles.css */
@import 'tailwindcss';
/* Watch monorepo packages for Tailwind classes */
@source '../../packages';
/* Theme configuration using CSS */
@layer base {
:root {
--color-primary: #3b82f6;
--color-background: #ffffff;
}
.dark {
--color-primary: #60a5fa;
--color-background: #1f2937;
}
}
@layer components {
.ai-button {
@apply rounded-lg bg-blue-500 px-4 py-2 text-white;
}
}
References:
View Encapsulation Pattern
@Component({
selector: 'ai-component',
encapsulation: ViewEncapsulation.None, // Required for Tailwind
template: `
<div class="ai-component-wrapper">
<!-- Scoped classes with component prefix -->
</div>
`,
})
export class ComponentName {}
Dynamic Classes Pattern (cn utility)
import { cn } from '@angular-ai-kit/utils';
classes = computed(() => {
return cn(
'base-class another-class',
{
'conditional-class': this.condition(),
'active:ring-2': this.isActive(),
},
this.customClasses() // Allow class override from parent
);
});
CSS Custom Properties (Theming)
/* theme.css */
@layer base {
:root {
--ai-primary: theme('colors.blue.600');
--ai-text: theme('colors.gray.900');
--ai-background: theme('colors.white');
}
.dark {
--ai-primary: theme('colors.blue.400');
--ai-text: theme('colors.gray.100');
--ai-background: theme('colors.gray.900');
}
}
Tailwind @layer Pattern
/* component.css (if needed) */
@layer components {
.ai-message-bubble {
@apply rounded-lg px-4 py-3 shadow-sm;
}
}
@layer utilities {
.ai-scrollbar-thin {
scrollbar-width: thin;
}
}
Component Styling Best Practices
- Prefix all custom component classes with
ai-to avoid naming conflicts - Use Tailwind utilities as much as possible before creating custom CSS
- Group related utilities together for readability
- Use responsive modifiers consistently (mobile-first: sm, md, lg, xl, 2xl)
- Apply dark mode variants using CSS variables, not dark: modifier when possible
- Keep inline styles minimal and prefer template-based class bindings
- Allow parent components to override styles via
customClassesinput
Example Component with Tailwind
import { cn } from '@angular-ai-kit/utils';
import {
ChangeDetectionStrategy,
Component,
ViewEncapsulation,
computed,
input,
} from '@angular/core';
@Component({
selector: 'ai-message-bubble',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
template: `
<div [class]="containerClasses()">
<ng-content />
</div>
`,
})
export class MessageBubbleComponent {
role = input.required<'user' | 'assistant'>();
customClasses = input<string>('');
containerClasses = computed(() => {
return cn(
// Base styles
'ai-message-bubble',
'rounded-lg px-4 py-3 shadow-sm',
'transition-colors duration-200',
// Conditional styles
{
'bg-blue-500 text-white': this.role() === 'user',
'bg-gray-100 text-gray-900 dark:bg-gray-800 dark:text-gray-100':
this.role() === 'assistant',
},
// Allow override
this.customClasses()
);
});
}
Dark Mode Support
- Use CSS custom properties for colors
- Support
prefers-color-schememedia query - Provide manual dark mode toggle option
- Test all components in both light and dark modes
@layer base {
:root {
--ai-bg: theme('colors.white');
--ai-text: theme('colors.gray.900');
}
@media (prefers-color-scheme: dark) {
:root {
--ai-bg: theme('colors.gray.900');
--ai-text: theme('colors.gray.100');
}
}
.dark {
--ai-bg: theme('colors.gray.900');
--ai-text: theme('colors.gray.100');
}
}
Responsive Design
- Mobile-first approach (base styles for mobile, then add breakpoints)
- Test on common screen sizes: 320px, 768px, 1024px, 1440px
- Use Tailwind's responsive modifiers: sm, md, lg, xl, 2xl
- Ensure touch targets are at least 44x44px
- Support landscape and portrait orientations
containerClasses = computed(() => {
return cn(
// Mobile first
'flex flex-col gap-2 p-4',
// Tablet
'md:flex-row md:gap-4 md:p-6',
// Desktop
'lg:gap-6 lg:p-8'
);
});