skills/accelint-design-foundation/SKILL.md
Use when styling components or elements with @accelint/design-foundation or @accelint/design-toolkit packages, or when users say "style this", "add styling", "theme this component", "add colors", "add spacing", "CSS modules", "setup design foundation", "@variant", or when working with .module.css files. Provides opinionated Tailwind conventions including semantic tokens, custom spacing scale, outline-based borders, variant system, and CSS module setup guidance.
npx skillsauth add gohypergiant/agent-skills accelint-design-foundationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Expert knowledge for styling with @accelint/design-foundation and @accelint/design-toolkit — opinionated Tailwind conventions that differ from vanilla implementations.
p-xxs, gap-m, m-l. Numeric classes like p-4, gap-6 work with a 1:1 relationship (p-1 = 1px, NOT 4px like vanilla Tailwind), but should only be used for rare cases where implementing non-conforming designs. The semantic scale provides design system consistency.dark:bg-gray-900 or className={theme === 'dark' ? 'bg-black' : 'bg-white'}. Use semantic color classes like bg-surface-default and fg-primary-bold that automatically adapt to light/dark themes.outline instead of border classes. Borders add to element dimensions (breaks layouts), while outlines overlay without affecting size. Elements should size consistently based on content and padding only.hover:[&>svg]:opacity-50 break the design system. Use supported React Aria variants or conditional class rendering with clsx.@layer components.l1, @layer components.l2 for cascade hierarchy. Bypassing layers causes specificity wars and makes overrides unpredictable.bg-surface-default, fg-primary-bold) in components. The utility classes (bg-*, fg-*, icon-*, outline-*) provide fallback access to domain-* and primitive-* tokens for rare cases where designs go beyond the design system, but this should be exceptional. Semantic tokens provide theming flexibility and design system consistency.@apply statement. Multiple @apply directives prevent Tailwind IDE plugins from sorting classes and identifying issues. Write @apply bg-surface-default outline-1 outline-interactive p-m; not separate @apply lines.@variant directive blocks, not attribute selectors like [data-size="small"]. Write @variant size-small { @apply p-s; } not .button[data-size="small"] { @apply p-s; }. The @variant directive automatically applies styles when the matching data attribute is present.@reference '#globals'; (if custom entrypoint exists) or @reference '@accelint/design-foundation/styles'; at the top. Without this, semantic tokens and @variant blocks are undefined, causing build errors.@accelint/postcss-tailwind-css-modules plugin is required in postcss.config.mjs. Without it, named group selectors (like group-hover/button:) and @variant selectors fail to resolve in CSS modules.@accelint/design-foundation/lib/utils instead: import { clsx } from '@accelint/design-foundation/lib/utils';. The design foundation re-exports clsx with additional type support and design system integration. Importing directly bypasses these enhancements.Apply these tests to ensure styling aligns with the design system:
@variant light and @variant dark.bg-surface-default, fg-primary-bold). Only use domain-* or primitive-* fallbacks for exceptional cases where design goes beyond the system.domain-* or primitive-* is acceptable but rare.When choosing a token, follow this decision tree:
Example: "I need text color for a primary heading"
→ Purpose: text (fg-*)
→ Hierarchy: primary with emphasis (primary-bold)
→ Result: fg-primary-bold
Example: "I need background for an interactive button in hover state"
→ Purpose: background (bg-*)
→ State: interactive hover (interactive-bold-hover)
→ Result: bg-interactive-bold-hover
xxs/xs/s/m/l/xl/xxl/oversized scale. If a value isn't in the scale, question whether it's needed or use the closest semantic value.p-1, m-12) work with 1:1 relationship (p-1 = 1px, NOT 4px), but only use for rare non-conforming design cases. Semantic scale is strongly preferred for consistency.data-color="info" with supported variants instead of arbitrary classes.className or classNames props, not custom CSS files.@accelint/postcss-tailwind-css-modules plugin is in postcss.config.mjs. Without it, named groups and @variant selectors won't work in CSS modules..module.css file must reference either '#globals' (custom entrypoint) or '@accelint/design-foundation/styles' at the top.CRITICAL: Design foundation requires specific PostCSS and CSS module configuration to work correctly.
Create or update postcss.config.mjs in project root:
export default {
plugins: {
'@tailwindcss/postcss': {},
'@accelint/postcss-tailwind-css-modules': {}, // Required for CSS modules
},
};
Why: The @accelint/postcss-tailwind-css-modules plugin fixes named group resolution in CSS module selectors (e.g., group-hover/button:) and @variant selectors. Without it, these selectors fail to resolve correctly in CSS module files.
If the project implements a custom CSS entrypoint for token/utility configuration:
{
"imports": {
"#globals": "./src/styles/globals.css"
}
}
Purpose: Allows CSS modules to reference the custom entrypoint via @reference '#globals';
Every CSS module file must include a reference directive:
/* If project has custom CSS entrypoint (defined in package.json imports): */
@reference '#globals';
@layer components.l1 {
.button {
@apply px-m py-xs;
}
}
/* If NO custom CSS entrypoint, reference design-foundation directly: */
@reference '@accelint/design-foundation/styles';
@layer components.l1 {
.button {
@apply px-m py-xs;
}
}
Why: The @reference directive imports the design system's tokens, utilities, and variant definitions. Without it, semantic tokens and @variant blocks are undefined.
If implementing custom tokens or utilities, create a CSS entrypoint (e.g., src/styles/globals.css):
/* Import design foundation base */
@import "@accelint/design-foundation/styles";
/* Add custom token overrides or utilities here */
@theme {
--custom-brand-color: #ff0000;
}
Then: Import this file as the first import in your root layout component:
import './styles/globals.css'; // First import
import { ReactNode } from 'react';
export default function RootLayout({ children }: { children: ReactNode }) {
return <html>{children}</html>;
}
This skill uses progressive disclosure to minimize context usage:
Follow the styling patterns and token usage below for consistent implementation.
Load AGENTS.md for quick reference of available tokens, spacing scale, and variant patterns.
MANDATORY loading triggers - Load these references in specific scenarios:
Setting up design foundation for the first time:
Choosing tokens or understanding token hierarchy:
Working with @variant system or component variants:
Understanding spacing scale or numeric fallbacks:
Migrating from vanilla Tailwind:
Troubleshooting build errors or setup issues:
Default approach: Component styles in CSS modules with @apply directives.
user-card.module.css:
@layer components.l1 {
/* ✅ Single @apply per rule - enables IDE plugin support */
.card {
@apply bg-surface-default outline-1 outline-interactive shadow-elevation-raised-muted p-m;
}
.header {
@apply flex items-center justify-between mb-s;
}
.title {
@apply fg-primary-bold text-body-l;
}
.content {
@apply space-y-xs mb-m;
}
.email {
@apply fg-primary-bold text-body-m;
}
.role {
@apply fg-primary-muted text-body-s;
}
.actions {
@apply flex gap-s;
}
}
/* ❌ Wrong - multiple @apply directives break IDE plugins */
/*
.card {
@apply bg-surface-default;
@apply outline-1 outline-interactive;
@apply shadow-elevation-raised-muted;
@apply p-m;
}
*/
user-card.tsx:
import styles from './user-card.module.css';
export function UserCard({ name, email, role }) {
return (
<article className={styles.card}>
<header className={styles.header}>
<h3 className={styles.title}>{name}</h3>
</header>
<div className={styles.content}>
<p className={styles.email}>{email}</p>
<p className={styles.role}>{role}</p>
</div>
</article>
);
}
Inline classes only for one-off overrides:
// ✅ Correct - CSS module + inline override for specific instance
<UserCard className="mb-xl" /> {/* One-off spacing adjustment */}
// ❌ Wrong - all styling inline
<div className="bg-surface-default outline-1 outline-interactive shadow-elevation-raised-muted p-m">
<h3 className="fg-primary-bold text-body-l">{name}</h3>
</div>
Conditional classes with clsx:
// ✅ Correct - import clsx from design foundation
import { clsx } from '@accelint/design-foundation/lib/utils';
import styles from './Button.module.css';
export function Button({ variant, isActive }) {
return (
<button className={clsx(styles.button, isActive && styles.active)}>
Click me
</button>
);
}
// ❌ Wrong - importing directly from clsx package
import clsx from 'clsx';
Background tokens (bg-*):
bg-surface-default - Primary surface (page/card background)bg-surface-raised - Raised/elevated surfacebg-interactive-bold - Primary action backgroundbg-info-muted - Info message backgroundsbg-advisory-muted - Warning message backgroundsbg-critical-muted - Error/danger message backgroundsbg-normal-muted - Success message backgroundsForeground tokens (fg-*):
fg-primary-bold - Primary text (headlines, body text)fg-primary-muted - Subtle text (captions, secondary content)fg-inverse-bold - Text on dark/colored backgroundsfg-accent-primary-bold - Interactive text/linksfg-critical-bold - Error/danger textOutline tokens (outline-*):
outline-interactive - Interactive outlines (buttons, inputs)outline-static - Static outlines (borders, dividers)outline-info-bold - Info state outlinesoutline-advisory-bold - Warning state outlinesoutline-critical-bold - Error/danger state outlinesToken fallback pattern:
// ✅ Preferred - semantic tokens
<div className="bg-surface-default fg-primary-bold">Content</div>
// ⚠️ Acceptable but rare - domain/primitive fallback for edge cases
<div className="bg-domain-brand fg-primitive-blue-500">
{/* Use only when design exceeds system */}
</div>
// ❌ Wrong - using fallbacks when semantic tokens exist
<div className="bg-primitive-neutral-100 fg-primitive-neutral-900">
{/* Should use bg-surface-default fg-primary-bold */}
</div>
Eight-step semantic scale: xxs → xs → s → m → l → xl → xxl → oversized
Think semantic meaning, not pixels. m means "medium for this context", not a specific pixel value.
CSS module usage:
.button {
@apply px-m py-xs; /* ✅ Semantic spacing - preferred */
}
.card {
@apply p-m space-y-s; /* ✅ Semantic scale for consistency */
}
/* ⚠️ Acceptable but rare - numeric fallback for edge cases */
.nonStandardLayout {
@apply p-13; /* 13px exactly - use only for non-conforming designs */
/* Note: p-1 = 1px (not 4px like vanilla Tailwind) */
}
Spacing fallback pattern:
p-m, gap-s, mb-l)Prefer outlines - they don't affect element dimensions.
/* ✅ Correct - outline doesn't impact layout */
.card {
@apply outline-1 outline-interactive;
}
/* ❌ Wrong - border adds to dimensions */
.card {
@apply border-2 border-gray-300;
}
Use borders only when:
Use data attributes for component variants:
Button.module.css:
@layer components.l1 {
.button {
@apply px-m py-xs;
}
}
@layer components.l2 {
/* ✅ Use @variant blocks for conditional styling */
.button {
@variant color-info {
@apply bg-interactive-bold fg-inverse-bold;
}
@variant color-critical {
@apply outline-2 outline-critical-bold fg-critical-bold;
}
@variant size-large {
@apply px-l py-s;
}
}
}
/* ❌ Wrong - attribute selectors */
/*
.button[data-color="primary"] {
@apply bg-interactive-bold;
}
*/
Button.tsx:
import styles from './Button.module.css';
export function Button({ children, color = 'primary', size = 'medium' }) {
return (
<button
className={styles.button}
data-color={color}
data-size={size}
>
{children}
</button>
);
}
Common variants:
data-color: info, success, warning, dangerdata-size: small, medium, largedata-state: active, disabled, loadingAlways use layers in CSS modules:
/* ✅ Correct - layered for predictable specificity */
@layer components.l1 {
.base-styles { /* Base component styles */ }
}
@layer components.l2 {
.variant-styles { /* Variant styles */ }
}
@layer components.l3 {
.state-styles { /* State styles */ }
}
/* ❌ Wrong - no layers causes specificity issues */
.component {
background: var(--bg-surface-default);
}
Layer order: l1 (base) < l2 (variants) < l3 (states)
Use className prop for overrides:
// ✅ Correct - override with inline class
<DesignToolkitButton className="mb-l">
Action
</DesignToolkitButton>
// ✅ Correct - use classNames prop for internal elements
<DesignToolkitButton classNames={{ icon: 'icon-override' }}>
Action
</DesignToolkitButton>
Cause: Missing @reference directive in CSS module.
Fix: Add @reference '#globals'; or @reference '@accelint/design-foundation/styles'; at the top of the CSS module file.
/* ✅ Correct */
@reference '@accelint/design-foundation/styles';
@layer components.l1 {
.card {
@apply bg-surface-default; /* Now defined */
}
}
Cause: Missing @reference directive or PostCSS plugin not configured.
Fix 1: Verify @reference directive exists at top of CSS module.
Fix 2: Check postcss.config.mjs includes @accelint/postcss-tailwind-css-modules plugin:
export default {
plugins: {
'@tailwindcss/postcss': {},
'@accelint/postcss-tailwind-css-modules': {}, // Add this
},
};
Cause: Missing @accelint/postcss-tailwind-css-modules plugin.
Fix: Add plugin to postcss.config.mjs (see above).
Cause: CSS entrypoint not imported or imported too late.
Fix: Ensure globals.css (or @accelint/design-foundation/styles) is the FIRST import in root layout:
// ✅ Correct order
import './styles/globals.css'; // First
import './other-styles.css';
import Component from './Component';
// ❌ Wrong order
import Component from './Component';
import './styles/globals.css'; // Too late
Cause: Missing package.json imports field or path incorrect.
Fix: Add imports to package.json:
{
"imports": {
"#globals": "./src/styles/globals.css"
}
}
Or change @reference to direct path:
@reference './styles/globals.css';
Or use design-foundation directly:
@reference '@accelint/design-foundation/styles';
var(--bg-surface-default). They can be used in custom CSS when utilities aren't sufficient, but prefer utilities.bg-*, fg-*, icon-*, outline-*) check semantic tokens first, then fall back to domain-* and primitive-* tokens. This fallback is intentional for rare cases where designs exceed the design system, but semantic tokens should be the default choice for consistency and theming.@theme static and @variant light/dark syntax is custom. Don't confuse with standard CSS media queries. Themes are applied via class/attribute on root element.className and classNames props.tools
Implement QRSPI-planned OpenSpec changes with intelligent parallelization. Use when the user wants to apply a QRSPI change, implement tasks with parallelization, or says "apply this QRSPI change", "implement with parallelization", "run the parallel slices". This skill is specifically designed for changes created via accelint-qrspi that include "Parallelization Strategy" sections in tasks.md. It orchestrates parallel sub-agent execution for independent task slices using OpenSpec CLI workflows. Make sure to use this skill when the user mentions applying QRSPI changes, running parallel implementation, or working on changes with vertical slices.
development
Generate or update an ARCHITECTURE.md living document for any codebase. Use this skill whenever a user mentions "architecture.md", "ARCHITECTURE.md", "document my architecture", "architecture overview", "system architecture", "generate architecture doc", "create architecture file", "update architecture", "architecture diagram", or wants a technical overview of how their project is structured. Make sure to use this skill whenever users want to document how their system works — even if they phrase it as "write up the system", "document the tech stack", "create a technical overview", or "help me describe the architecture". Always prefer this skill over ad-hoc architecture documentation.
development
Automate the QRSPI + OpenSpec planning workflow (Questions → Research → Design → Structure) for spec-driven development. Use this skill when the user wants to plan a ticket, start a QRSPI workflow, create a change with QRSPI, or says "plan this with QRSPI", "use QRSPI to plan", "start QRSPI workflow", "create spec-driven change", or asks about planning a feature/change before implementation. This skill handles ONLY the planning phase — it does NOT implement code. After completion, the user continues with /opsx:apply for implementation.
development
Comprehensive TypeScript/JavaScript coding standards focusing on type safety, defensive programming, and code correctness. Use when (1) Writing or reviewing TS/JS code, (2) Fixing type errors or avoiding any/enum/null, (3) Implementing control flow, state management, or error handling, (4) Applying zero-value pattern or immutability, (5) Code review for TypeScript anti-patterns. Covers naming conventions, function design, return values, bounded iteration, input validation. For performance optimization, use accelint-ts-performance skill. For documentation, use accelint-ts-documentation skill.