npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eslint-plugin-sting-react

v0.1.1-0

Published

ESLint plugin for validating @chargebee/sting-react component usage

Readme

eslint-plugin-sting-react

ESLint plugin for validating @chargebee/sting-react component usage.

Features

Validate Component Names - Ensures only valid Sting React components are used ✅ Validate Props - Checks if props exist for each component ✅ Validate Prop Values - Validates enum values (variant, size, mode) against component definitions ✅ Enforce Sting Components - Prevents usage of native HTML elements when Sting alternatives exist ✅ Import Validation - Ensures components are imported from the correct package ✅ Design System Consistency - Warns against inline styles and encourages design tokens ✅ Accessibility Checks - Enforces accessibility best practices for all components ✅ Deprecation Warnings - Alerts about deprecated props with auto-fix support ✅ Auto-fix Support - Automatically fixes many common issues ✅ Smart Suggestions - Provides helpful suggestions for typos and invalid values ✅ Works in any editor - Runs during eslint / npm run lintCI/CD Ready - Catch errors before they reach production

Installation

npm install --save-dev eslint-plugin-sting-react

Usage

ESLint Configuration (Flat Config - ES Lint 9+)

// eslint.config.js
import stingReact from 'eslint-plugin-sting-react';

export default [
  {
    plugins: {
      'sting-react': stingReact,
    },
    rules: {
      'sting-react/valid-component-name': 'error',
      'sting-react/valid-prop-name': 'error',
      'sting-react/valid-prop-value': 'error',
      'sting-react/prefer-sting-components': 'warn',
      'sting-react/require-sting-import': 'error',
      'sting-react/no-inline-styles': 'warn',
      'sting-react/accessible-component-usage': 'warn',
      'sting-react/no-deprecated-props': 'warn',
    },
  },
];

ESLint Configuration (Legacy - .eslintrc)

// .eslintrc.js
module.exports = {
  plugins: ['sting-react'],
  rules: {
    'sting-react/valid-component-name': 'error',
    'sting-react/valid-prop-name': 'error',
    'sting-react/valid-prop-value': 'error',
    'sting-react/prefer-sting-components': 'warn',
    'sting-react/require-sting-import': 'error',
    'sting-react/no-inline-styles': 'warn',
    'sting-react/accessible-component-usage': 'warn',
    'sting-react/no-deprecated-props': 'warn',
  },
};

Or Use Recommended Config

// .eslintrc.js
module.exports = {
  extends: ['plugin:sting-react/recommended'],
};

Configurations

This plugin provides three preset configurations:

Recommended (Default)

Balanced configuration for teams adopting Sting design system:

{
  "extends": ["plugin:sting-react/recommended"]
}

Strict

Stricter rules for teams fully committed to the design system:

{
  "extends": ["plugin:sting-react/strict"]
}

Migration

Relaxed configuration for teams migrating from native HTML to Sting components:

{
  "extends": ["plugin:sting-react/migration"]
}

Rules

sting-react/valid-component-name

Ensures that only valid Sting React component names are used.

❌ Invalid

import { Sbutton } from '@chargebee/sting-react';

<Sbutton>Click</Sbutton>  // Error: Invalid component name

<SUnknownComponent />  // Error: Unknown component. Did you mean: SButton?

✅ Valid

import { SButton } from '@chargebee/sting-react';

<SButton>Click</SButton>

sting-react/prefer-sting-components

Enforces the use of Sting React components instead of native HTML elements across all files in the project.

This rule ensures consistent use of the Sting Design System by flagging any usage of native HTML elements that have Sting component alternatives, regardless of whether @chargebee/sting-react is imported.

❌ Invalid

// Error: Use <SButton> from @chargebee/sting-react instead of native <button> element.
<button onClick={handleClick}>Click</button>

// Error: Use <SInput> from @chargebee/sting-react instead of native <input> element.
<input type="text" placeholder="Name" />

// Error: Use <SSelect> from @chargebee/sting-react instead of native <select> element.
<select>
  <option value="1">Option 1</option>
</select>

// Error: Use <STextarea> from @chargebee/sting-react instead of native <textarea> element.
<textarea rows={4} />

// Error: Use <SLabel> from @chargebee/sting-react instead of native <label> element.
<label htmlFor="input">Name</label>

✅ Valid

import { SButton, SInput, SSelect, STextarea, SLabel } from '@chargebee/sting-react';

<SButton onClick={handleClick}>Click</SButton>
<SInput placeholder="Name" />
<SSelect options={options} />
<STextarea rows={4} />
<SLabel>Name</SLabel>

// Other HTML elements without Sting alternatives are allowed
<div>
  <span>Text</span>
  <p>Paragraph</p>
  <form>...</form>
</div>

Covered Elements

This rule applies to the following HTML elements that have Sting component equivalents:

  • <button> → Use <SButton>
  • <input> → Use <SInput>
  • <select> → Use <SSelect>
  • <textarea> → Use <STextarea>
  • <label> → Use <SLabel>

Why This Rule?

This rule enforces design system consistency by preventing the use of native HTML form elements anywhere in the codebase, ensuring all user interface elements follow the Sting Design System guidelines.


sting-react/require-sting-import

Ensures Sting components are imported from the correct package (@chargebee/sting-react).

Auto-fixable:

❌ Invalid

// Wrong package
import { SButton } from '@chargebee/sting';
import { SButton } from 'sting-react';

// Missing import
<SButton>Click</SButton>  // Used without import

✅ Valid

import { SButton } from '@chargebee/sting-react';
<SButton>Click</SButton>

sting-react/no-inline-styles

Discourages inline styles on Sting components to maintain design system consistency.

❌ Invalid

import { SButton, SInput } from '@chargebee/sting-react';

<SButton style={{ backgroundColor: 'red', padding: '10px' }}>Click</SButton>
<SInput style={{ width: '100%' }} />

✅ Valid

import { SButton, SInput } from '@chargebee/sting-react';

<SButton variant="primary" className="custom-button">Click</SButton>
<SInput className="w-full" />

Configuration

{
  "sting-react/no-inline-styles": ["warn", {
    "allowedComponents": ["SCard"],
    "severity": "warn"
  }]
}

sting-react/accessible-component-usage

Ensures accessibility best practices when using Sting components.

❌ Invalid

import { SInput, SButton, SIcon, SModal } from '@chargebee/sting-react';

// Input without label
<SInput placeholder="Email" />

// Icon-only button without aria-label
<SButton><SIcon name="close" /></SButton>

// Modal without aria-label
<SModal>Content</SModal>

✅ Valid

import { SInput, SButton, SIcon, SModal } from '@chargebee/sting-react';

<SInput aria-label="Email address" placeholder="Email" />
<SButton aria-label="Close"><SIcon name="close" /></SButton>
<SModal aria-label="Confirmation dialog">Content</SModal>

Configuration

{
  "sting-react/accessible-component-usage": ["warn", {
    "strictMode": true
  }]
}

sting-react/no-deprecated-props

Warns about deprecated props and provides auto-fixes to migrate to new prop names.

Auto-fixable:

❌ Invalid

import { SButton, SModal, SInput, SBadge } from '@chargebee/sting-react';

<SButton type="primary">Click</SButton>  // Deprecated
<SModal visible={true}>Content</SModal>  // Deprecated
<SInput error={true} />  // Deprecated
<SBadge color="success">New</SBadge>  // Deprecated

✅ Valid

import { SButton, SModal, SInput, SBadge } from '@chargebee/sting-react';

<SButton variant="primary">Click</SButton>
<SModal open={true}>Content</SModal>
<SInput isInvalid={true} />
<SBadge variant="success">New</SBadge>

sting-react/valid-prop-name

Ensures that only valid props are used on Sting React components.

❌ Invalid

import { SButton } from '@chargebee/sting-react';

<SButton color="blue">Click</SButton>
// Error: Invalid prop "color" on component "SButton". Did you mean: icon?

<STooltip>
  <span>Hover me</span>
</STooltip>
// Error: Missing required prop "content" on component "STooltip"

✅ Valid

import { SButton, STooltip } from '@chargebee/sting-react';

<SButton variant="primary">Click</SButton>

<STooltip content="This is a tooltip">
  <span>Hover me</span>
</STooltip>

sting-react/valid-prop-value

Ensures that prop values match the allowed values for the component.

❌ Invalid

import { SButton, SBadge } from '@chargebee/sting-react';

<SButton variant="huge">Click</SButton>
// Error: Invalid value "huge" for prop "variant" on component "SButton".
// Expected one of: "primary", "primary-outline", "primary-ghost", "neutral",
// "neutral-ghost", "danger", "danger-outline", "danger-ghost"

<SBadge size="massive">Text</SBadge>
// Error: Invalid value "massive" for prop "size" on component "SBadge".
// Expected one of: "regular", "medium", "large"

✅ Valid

import { SButton, SBadge } from '@chargebee/sting-react';

<SButton variant="primary">Click</SButton>
<SButton variant="danger">Delete</SButton>

<SBadge size="regular">Text</SBadge>
<SBadge size="large">Large Text</SBadge>

Supported Components

The plugin validates all Sting React components including:

  • Form Components: SButton, SInput, SCheckbox, SRadioGroup, SSelect, SSwitch, STextarea, SLabel, SFileUpload
  • Layout Components: SCard, SModal, SDrawer, SAccordion, STabs, SContainedList
  • Feedback Components: SBanner, SToast, SNotification, SSpinner, SModalLoader, SInlineError
  • Navigation: SBreadcrumb, SPageHeader
  • Data Display: STable, SBadge
  • Overlays: STooltip, SPopover, SDropdown
  • Progress: SProgressTracker
  • Utilities: SIcon, SPlaceholder

Configuration Options

Rule Severity

You can configure the severity level for each rule:

{
  rules: {
    'sting-react/valid-component-name': 'error',  // or 'warn', 'off'
    'sting-react/valid-prop-name': 'warn',
    'sting-react/valid-prop-value': 'error',
  }
}

Examples

Valid Code

import {
  SButton,
  SBadge,
  SModal,
  SInput,
  STooltip
} from '@chargebee/sting-react';

function MyComponent() {
  return (
    <div>
      {/* ✅ Valid: Correct component, props, and values */}
      <SButton variant="primary" size="large">
        Submit
      </SButton>

      {/* ✅ Valid: All prop values are correct */}
      <SBadge variant="success" size="regular" mode="light">
        Active
      </SBadge>

      {/* ✅ Valid: Required props provided */}
      <STooltip content="Click to save">
        <SButton variant="primary">Save</SButton>
      </STooltip>

      {/* ✅ Valid: Sub-components work */}
      <SModal>
        <SModal.Content>
          <SModal.Header>Title</SModal.Header>
        </SModal.Content>
      </SModal>
    </div>
  );
}

Invalid Code (Will Show Errors)

import { SButton, SBadge } from '@chargebee/sting-react';

function MyComponent() {
  return (
    <div>
      {/* ❌ Error: Invalid component name */}
      <Sbutton>Click</Sbutton>

      {/* ❌ Error: Invalid prop "color" */}
      <SButton color="blue">Click</SButton>

      {/* ❌ Error: Invalid value "massive" for prop "size" */}
      <SButton size="massive">Click</SButton>

      {/* ❌ Error: Invalid value "purple" for prop "variant" */}
      <SBadge variant="purple">Text</SBadge>

      {/* ❌ Error: Missing required prop "content" */}
      <STooltip>
        <span>Hover me</span>
      </STooltip>
    </div>
  );
}

Running the Linter

In Development

npm run lint

Fix Auto-Fixable Issues

npm run lint -- --fix

In CI/CD

# In your CI/CD pipeline
npm run lint -- --max-warnings 0

Integration with IDEs

VS Code

Errors will show up automatically in VS Code if you have the ESLint extension installed:

  1. Install the ESLint extension
  2. Errors will appear as red squiggly lines
  3. Hover over errors to see suggestions

Other Editors

Most modern editors support ESLint integration:

  • WebStorm/IntelliJ: Built-in ES Lint support
  • Sublime Text: via SublimeLinter-eslint
  • Vim/Neovim: via ALE or coc-eslint

Benefits

1. Catch Errors Early

// This error is caught during linting, not at runtime!
<SButton varient="primary">Click</SButton>
// Error: Invalid prop "varient". Did you mean: variant?

2. Enforced Standards

Ensure the entire team uses components correctly:

$ npm run lint

  error  Invalid value "huge" for prop "variant"  sting-react/valid-prop-value

✖ 1 problem (1 error, 0 warnings)

3. CI/CD Integration

Prevent invalid code from being merged:

# .github/workflows/ci.yml
- name: Lint
  run: npm run lint

4. Better DX

Get helpful suggestions for typos:

<SButton varaint="primary">
// Error: Invalid prop "varaint". Did you mean: variant?

Updating Component Metadata

The component metadata is automatically extracted from @chargebee/sting-react component definitions. When component props change, simply run:

npm run generate-metadata

This will:

  1. Scan all components in packages/sting-react/src/components/
  2. Extract TypeScript interface definitions
  3. Extract variant values from tailwind-variants constants
  4. Generate src/utils/generatedComponentMetadata.ts with up-to-date metadata

The metadata generation is automatically run before each build via the prebuild script.

How Metadata Extraction Works

The plugin uses the TypeScript Compiler API to parse component files and extract:

  • Props from TypeScript interfaces: Analyzes interfaces like SButtonProps, BadgeProps, etc.
  • Type information: Captures the type of each prop (string, boolean, React.ReactNode, etc.)
  • Required/optional status: Determines if props are required based on the ? token
  • Union type values: Extracts valid values from string literal unions (e.g., "primary" | "secondary")
  • Variant values from constants: Parses tailwind-variants tv() calls to extract variant options

Development

Scripts

  • npm run build - Build the plugin (also runs metadata generation)
  • npm run generate-metadata - Extract component metadata from Sting React
  • npm run watch - Watch mode for development
  • npm test - Run tests
  • npm run lint - Lint the codebase

Building

npm install
npm run build

Testing

npm test

Local Development

# In the plugin directory
npm link

# In your project
npm link eslint-plugin-sting-react

Project Structure

eslint-plugin-sting-react/
├── scripts/
│   ├── extractComponentMetadata.ts  # Metadata extraction script
│   └── tsconfig.json                # TypeScript config for scripts
├── src/
│   ├── rules/                       # ESLint rule implementations
│   ├── utils/
│   │   ├── componentMetadata.ts     # Main metadata utilities
│   │   └── generatedComponentMetadata.ts  # Auto-generated (DO NOT EDIT)
│   └── index.ts                     # Plugin entry point
└── package.json

Troubleshooting

Plugin Not Working

  1. Check ESLint is installed

    npm list eslint
  2. Verify plugin is in configuration

    // .eslintrc.js
    plugins: ['sting-react']
  3. Check file is being linted

    npm run lint -- path/to/file.tsx

Rules Not Triggering

  1. Make sure you import from @chargebee/sting-react

    • The plugin only validates components imported from this package
  2. Check rule is enabled

    rules: {
      'sting-react/valid-component-name': 'error'  // Not 'off'
    }

False Positives

If you're getting false positives, please open an issue with:

  • The code that's causing the error
  • Expected behavior
  • Actual error message

License

ISC

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.


Made with ❤️ by Chargebee