From harness-claude
Scopes CSS to components using CSS Modules for collision-free class names and co-located styles. Covers .module.css files, object imports, composes, dynamic classes, :global, TypeScript typing in Next.js/Vite/Webpack.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Scope CSS to components with CSS Modules for collision-free class names and co-located styles
Applies Tailwind CSS utility-first patterns to style React components consistently without custom CSS. Groups utilities by concern, uses design tokens, orders logically for rapid prototyping and maintenance.
Guides creation of new styled CSS components with semantic naming, Tailwind @apply composition, dark mode support, and static/rendering tests. Use for 'create component', 'new button', 'add styles'.
Generates CSS modules and configurations for React and Vue frontend projects. Provides step-by-step guidance, best practices, and production-ready code for scoped styling tasks.
Share bugs, ideas, or general feedback.
Scope CSS to components with CSS Modules for collision-free class names and co-located styles
.module.css suffix: Button.module.css. The bundler generates unique class names.import styles from './Button.module.css'.className={styles.button}.composes to inherit styles from other classes or modules.styles[variant].:global(.class) to escape scoping./* Button.module.css */
.button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
font-weight: 500;
transition: all 0.2s;
}
.primary {
composes: button;
background-color: var(--color-primary);
color: white;
}
.primary:hover {
filter: brightness(1.1);
}
.secondary {
composes: button;
background-color: var(--color-gray-100);
color: var(--color-gray-900);
}
.large {
padding: 0.75rem 1.5rem;
font-size: 1.125rem;
}
.fullWidth {
width: 100%;
}
// Button.tsx
import styles from './Button.module.css';
import clsx from 'clsx';
interface ButtonProps {
variant?: 'primary' | 'secondary';
size?: 'default' | 'large';
fullWidth?: boolean;
children: React.ReactNode;
}
function Button({ variant = 'primary', size = 'default', fullWidth, children }: ButtonProps) {
return (
<button
className={clsx(
styles[variant],
size === 'large' && styles.large,
fullWidth && styles.fullWidth
)}
>
{children}
</button>
);
}
How it works: The bundler (Webpack, Vite, Next.js) transforms class names from .button to .Button_button_a1b2c (component name + class name + hash). This guarantees no collisions between components.
TypeScript support: Generate type declarations for CSS Modules:
# typed-css-modules
npm install -D typed-css-modules
tcm src/
# Or use the Vite plugin
npm install -D vite-plugin-css-modules-typescript
This creates .module.css.d.ts files:
// Button.module.css.d.ts
declare const styles: {
readonly button: string;
readonly primary: string;
readonly secondary: string;
readonly large: string;
readonly fullWidth: string;
};
export default styles;
composes keyword: Inherit styles from other classes:
.base {
padding: 1rem;
border-radius: 0.5rem;
}
.error {
composes: base;
border: 2px solid red;
}
/* .error gets both base and error styles */
/* Compose from another module */
.card {
composes: surface from './shared.module.css';
}
:global escape hatch: Apply a class globally (useful for overriding library styles):
.wrapper :global(.third-party-class) {
color: red;
}
CSS Modules + Tailwind: Use CSS Modules for complex styles and Tailwind for utilities:
<div className={clsx(styles.card, 'p-4 flex gap-2')}>
When to use CSS Modules vs Tailwind: CSS Modules are better for complex pseudo-selectors, animations with many keyframes, and teams that prefer traditional CSS. Tailwind is better for rapid iteration and design consistency.
https://github.com/css-modules/css-modules