Button Variant Linting Rule
Overview
To ensure consistent use of design tokens and prevent regression to deprecated button styles, we've implemented a custom ESLint rule that enforces proper button variant usage throughout the codebase.
Rule: waldur-custom/enforce-button-variants
This rule identifies and flags deprecated button variants and className patterns, suggesting modern design token alternatives.
What it catches
Deprecated Button Variants
btn-outline-default→tertiaryoutline btn-outline-default→tertiaryoutline→tertiarylight→tertiarylight-danger→dangerbtn-light-danger→dangeractive-light-danger→text-dangerbtn-active-light-danger→text-dangeractive-light-primary→text-secondarybtn-active-light-primary→text-secondaryactive-secondary→text-primarybtn-active-secondary→text-primaryoutline-danger→dangerbtn-outline-danger→dangeroutline-warning→warningbtn-outline-warning→warning
Deprecated className patterns
btn-outline-defaultbtn-active-light-dangerbtn-active-light-primarybtn-active-secondarybtn-light-dangerbtn-outline-dangerbtn-outline-warningbtn-text-primary(when used as className)btn-text-darkbtn-icon-dangerbtn-icon-primary
Example violations
1 2 3 4 5 6 7 8 9 10 11 | |
Auto-fixing
The rule provides automatic fixes for both variant props and many className patterns:
1 | |
This will automatically convert:
Variant props:
variant="btn-outline-default"→variant="tertiary"variant="light-danger"→variant="danger"- And other mappings listed above
ClassName props:
className="btn btn-outline-default"→className="btn btn-tertiary"className="btn btn-active-light-danger"→className="btn btn-text-danger"className="btn btn-text-primary btn-sm"→className="btn btn-sm"(removes deprecated class)- And other simple replacements
Manual fixes required
Some cases still require manual fixes:
- Complex className expressions with template literals or variables
- Classes mixed with non-standard button classes (e.g.,
btn-outline-dashed) - Conditional className logic
Design Token Button Variants
Primary Actions
primary- Main call-to-action buttonssuccess- Positive actions (save, submit, confirm)danger- Destructive actions (delete, remove)warning- Warning actions (pay invoice, etc.)
Secondary Actions
tertiary- Secondary actions, wasoutlineorbtn-outline-defaulttext-primary- Text-only primary actionstext-secondary- Text-only secondary actionstext-danger- Text-only destructive actionstext-success- Text-only positive actions
Special Purpose
icon- Icon-only buttonsflush- Buttons with no background/border
Benefits
- Consistency - Ensures all buttons use standardized design tokens
- Maintainability - Easier to update button styles globally
- Prevention - Catches deprecated patterns before they're committed
- Guidance - Provides clear suggestions for modern alternatives
- Automation - Auto-fixes 90%+ of violations to reduce manual work
- Migration Support - Helps transition from old button patterns to design tokens
Running the linter
1 2 3 4 5 6 7 8 | |
Configuration
The rule is configured in eslint.config.js and the implementation is in eslint-rules/enforce-button-variants.js.
To modify the mappings or add new deprecated patterns, edit the constants at the top of the rule file:
DEPRECATED_BUTTON_VARIANTS- variant prop values to flagRECOMMENDED_VARIANTS- mapping to modern alternativesDEPRECATED_CLASS_NAMES- className patterns to flag