Static Modifier API
The staticModifier function allows you to create modifiers with fixed CSS selectors. This is the simplest way to add custom modifiers (variants) to BaroCSS.
Basic Syntax
import { staticModifier } from '@barocss/kit';
staticModifier('modifier-name', [
'selector1',
'selector2'
], {
// Optional configuration
});Parameters
Required Parameters
name(string): The modifier name (e.g., 'hover', 'focus', 'dark')selectors(string[]): Array of CSS selectors to apply when the modifier is used
Optional Parameters
interface StaticModifierOptions {
source?: string; // Source identifier for debugging
sort?: number; // Sort order for modifier processingWrapping Types
Understanding Wrapping Types
The wrappingType parameter controls how the modifier's selector is applied to the utility's CSS. This is crucial for creating the correct CSS structure and ensuring proper selector behavior.
Available Wrapping Types
'rule' (Default)
Purpose
Creates a standard CSS rule where the & placeholder is replaced with the actual class name.
// Input: hover:bg-blue-500
// Output: .hover\:bg-blue-500:hover { background-color: #3b82f6; }
staticModifier('hover', ['&:hover'], { source: 'pseudo' });Use when: The & placeholder should be replaced with the actual class name to create proper CSS selectors.
'style-rule'
Purpose
Creates a style rule where the & placeholder remains as-is, preserving the structural selector.
// Input: [&>*]:bg-blue-500
// Output: .\[\&\>\*\]\:bg-blue-500 > * { background-color: #3b82f6; }
staticModifier('[&>*]', ['& > *'], { source: 'child' });Use when: The & placeholder should remain as-is to create structural selectors like child or sibling selectors.
'at-rule'
Purpose
Creates an at-rule (like @media or @supports) that wraps the utility, creating the proper CSS structure for conditional styling.
// Input: print:bg-blue-500
// Output: @media print { .print\:bg-blue-500 { background-color: #3b82f6; } }
staticModifier('print', ['@media print'], { source: 'media' });Use when: Creating media queries, container queries, or other at-rules that need to wrap the utility in a conditional structure.
When to Use Each Type
| Wrapping Type | Use Case | Example Selector | Result |
|---|---|---|---|
'rule' | Standard pseudo-classes | &:hover | .class:hover |
'rule' | Attribute selectors | &[data-state="open"] | .class[data-state="open"] |
'rule' | Parent selectors | .parent & | .parent .class |
'style-rule' | Child selectors | & > * | .class > * |
'style-rule' | Sibling selectors | & ~ .sibling | .class ~ .sibling |
'at-rule' | Media queries | @media print | @media print { .class { ... } } |
Examples by Use Case
Pseudo-classes (use 'rule')
staticModifier('hover', ['&:hover'], { source: 'pseudo' });
staticModifier('focus', ['&:focus'], { source: 'pseudo' });
staticModifier('active', ['&:active'], { source: 'pseudo' });Attribute selectors (use 'rule')
staticModifier('data-open', ['&[data-open]'], { source: 'data' });
staticModifier('aria-pressed', ['&[aria-pressed="true"]'], { source: 'aria' });Child selectors (use 'style-rule')
staticModifier('[&>*]', ['& > *'], { source: 'child' });
staticModifier('[&~.sibling]', ['& ~ .sibling'], { source: 'sibling' });Parent selectors (use 'rule')
staticModifier('group-hover', ['.group:hover &'], { source: 'group' });
staticModifier('peer-focus', ['.peer:focus ~ &'], { source: 'peer' });Media queries (use 'at-rule')
staticModifier('print', ['@media print'], { source: 'media' });
staticModifier('screen', ['@media screen'], { source: 'media' });Common Mistakes
❌ Wrong: Using 'style-rule' for simple selectors
// Don't do this
staticModifier('hover', ['&:hover'], { wrappingType: 'style-rule' });✅ Correct: Using 'rule' for simple selectors
// Do this instead
staticModifier('hover', ['&:hover'], { source: 'pseudo' });❌ Wrong: Using 'rule' for complex child selectors
// Don't do this
staticModifier('[&>*]', ['& > *'], { source: 'child' });✅ Correct: Using 'style-rule' for complex child selectors
// Do this instead
staticModifier('[&>*]', ['& > *'], { wrappingType: 'style-rule', source: 'child' });How Modifiers Work
Modifiers are used to conditionally apply styles based on certain states or conditions. When you use a modifier like hover:bg-blue-500, BaroCSS:
- Detects the
hover:modifier - Finds the corresponding modifier registration
- Applies the registered selectors to wrap the utility's CSS
Real-World Examples
1. Basic Pseudo-class Modifiers
import { staticModifier } from '@barocss/kit';
// Hover modifier
staticModifier('hover', ['&:hover'], { source: 'pseudo' });
// Focus modifier
staticModifier('focus', ['&:focus'], { source: 'pseudo' });
// Active modifier
staticModifier('active', ['&:active'], { source: 'pseudo' });
// Visited modifier
staticModifier('visited', ['&:visited'], { source: 'pseudo' });2. Pseudo-element Modifiers
import { staticModifier } from '@barocss/kit';
// Before pseudo-element
staticModifier('before', ['&::before'], { source: 'pseudo' });
// After pseudo-element
staticModifier('after', ['&::after'], { source: 'pseudo' });
// First-line pseudo-element
staticModifier('first-line', ['&::first-line'], { source: 'pseudo' });
// First-letter pseudo-element
staticModifier('first-letter', ['&::first-letter'], { source: 'pseudo' });3. Dark Mode Modifier
import { staticModifier } from '@barocss/kit';
// Class-based dark mode
staticModifier('dark', ['.dark', '.dark *'], { source: 'theme' });
// Data attribute-based dark mode
staticModifier('dark', ['[data-theme="dark"]', '[data-theme="dark"] *'], { source: 'theme' });
// Media query-based dark mode
staticModifier('dark', ['@media (prefers-color-scheme: dark)'], { source: 'media' });4. Group Modifiers
import { staticModifier } from '@barocss/kit';
// Group hover - applies when parent has hover
staticModifier('group-hover', ['.group:hover &'], { source: 'group' });
// Group focus - applies when parent has focus
staticModifier('group-focus', ['.group:focus &'], { source: 'group' });
// Group active - applies when parent has active
staticModifier('group-active', ['.group:active &'], { source: 'group' });5. Peer Modifiers
import { staticModifier } from '@barocss/kit';
// Peer hover - applies when sibling has hover
staticModifier('peer-hover', ['.peer:hover ~ &'], { source: 'peer' });
// Peer focus - applies when sibling has focus
staticModifier('peer-focus', ['.peer:focus ~ &'], { source: 'peer' });
// Peer checked - applies when sibling is checked
staticModifier('peer-checked', ['.peer:checked ~ &'], { source: 'peer' });6. Complex Selector Modifiers
import { staticModifier } from '@barocss/kit';
// Not modifier - applies when element doesn't match selector
staticModifier('not-first', [':not(:first-child)'], { source: 'structural' });
// Not last modifier
staticModifier('not-last', [':not(:last-child)'], { source: 'structural' });
// Only child modifier
staticModifier('only-child', [':only-child'], { source: 'structural' });
// Empty modifier
staticModifier('empty', [':empty'], { source: 'structural' });7. Form State Modifiers
import { staticModifier } from '@barocss/kit';
// Checked modifier
staticModifier('checked', ['&:checked'], { source: 'form' });
// Disabled modifier
staticModifier('disabled', ['&:disabled'], { source: 'form' });
// Required modifier
staticModifier('required', ['&:required'], { source: 'form' });
// Invalid modifier
staticModifier('invalid', ['&:invalid'], { source: 'form' });
// Valid modifier
staticModifier('valid', ['&:valid'], { source: 'form' });8. Media Query Modifiers
import { staticModifier } from '@barocss/kit';
// Print modifier
staticModifier('print', ['@media print'], { source: 'media' });
// Screen modifier
staticModifier('screen', ['@media screen'], { source: 'media' });
// Reduced motion modifier
staticModifier('motion-reduce', ['@media (prefers-reduced-motion: reduce)'], { source: 'media' });
// High contrast modifier
staticModifier('motion-safe', ['@media (prefers-reduced-motion: no-preference)'], { source: 'media' });9. Custom Theme Modifiers
import { staticModifier } from '@barocss/kit';
// Custom theme modifier
staticModifier('theme-midnight', ['[data-theme="midnight"]'], { source: 'theme' });
// Custom state modifier
staticModifier('loading', ['[data-state="loading"]'], { source: 'state' });
// Custom variant modifier
staticModifier('variant-primary', ['[data-variant="primary"]'], { source: 'variant' });Advanced Patterns
1. Multiple Selectors
import { staticModifier } from '@barocss/kit';
// Modifier with multiple selectors
staticModifier('focus-visible', [
'&:focus-visible',
'&:focus:not(:focus-visible)'
], { source: 'pseudo' });2. Complex Group Modifiers
import { staticModifier } from '@barocss/kit';
// Group modifier with complex selector
staticModifier('group-hover', [
'.group:hover &',
'.group:focus-within &'
], { source: 'group' });3. Conditional Modifiers
import { staticModifier } from '@barocss/kit';
// Modifier that works with different parent classes
staticModifier('parent-hover', [
'.parent:hover &',
'[data-parent="hover"] &'
], { source: 'parent' });Common Use Cases
1. Interactive States
// Basic interactive states
staticModifier('hover', ['&:hover']);
staticModifier('focus', ['&:focus']);
staticModifier('active', ['&:active']);
staticModifier('visited', ['&:visited']);2. Form States
// Form input states
staticModifier('checked', ['&:checked']);
staticModifier('disabled', ['&:disabled']);
staticModifier('required', ['&:required']);
staticModifier('invalid', ['&:invalid']);
staticModifier('valid', ['&:valid']);3. Structural Selectors
// Structural pseudo-classes
staticModifier('first-child', ['&:first-child']);
staticModifier('last-child', ['&:last-child']);
staticModifier('only-child', ['&:only-child']);
staticModifier('empty', ['&:empty']);4. Theme Variants
// Theme-based modifiers
staticModifier('dark', ['.dark', '.dark *']);
staticModifier('light', ['.light', '.light *']);
staticModifier('theme-brand', ['[data-theme="brand"]']);