@db-ux/core-eslint-plugin
v4.5.3
Published
ESLint plugin for DB UX Design System components
Readme
@db-ux/core-eslint-plugin
ESLint plugin to validate correct usage of DB UX Design System components across React, Vue, and Angular.
Installation
npm install eslint @db-ux/core-eslint-plugin --save-devFor Vue projects, also install vue-eslint-parser:
npm install vue-eslint-parser --save-devFor Angular projects, also install @angular-eslint/template-parser:
npm install @angular-eslint/template-parser --save-devFor React/TypeScript projects, also install @typescript-eslint/parser:
npm install @typescript-eslint/parser --save-devUsage
Add to your ESLint config:
ESLint 9+ (flat config):
// eslint.config.js
import dbUx from "@db-ux/core-eslint-plugin";
export default [
{
plugins: {
"db-ux": dbUx
},
rules: dbUx.configs.recommended.rules
}
];For Vue projects, configure the Vue parser:
import dbUx from "@db-ux/core-eslint-plugin";
import vueParser from "vue-eslint-parser";
import tsParser from "@typescript-eslint/parser";
export default [
{
files: ["**/*.vue"],
languageOptions: {
parser: vueParser,
parserOptions: {
parser: tsParser,
ecmaVersion: "latest",
sourceType: "module"
}
},
plugins: {
"db-ux": dbUx
},
rules: dbUx.configs.recommended.rules
}
];For Angular projects, configure the Angular template parser:
import dbUx from "@db-ux/core-eslint-plugin";
import angularTemplateParser from "@angular-eslint/template-parser";
export default [
{
files: ["**/*.html"],
languageOptions: {
parser: angularTemplateParser
},
plugins: {
"db-ux": dbUx
},
rules: dbUx.configs.recommended.rules
}
];Or enable rules individually:
import dbUx from "@db-ux/core-eslint-plugin";
export default [
{
plugins: {
"db-ux": dbUx
},
rules: {
"db-ux/button-no-text-requires-tooltip": "error"
}
}
];For React/TypeScript projects, configure the TypeScript parser:
import dbUx from "@db-ux/core-eslint-plugin";
import tsParser from "@typescript-eslint/parser";
export default [
{
files: ["**/*.ts", "**/*.tsx"],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: { jsx: true }
}
},
plugins: {
"db-ux": dbUx
},
rules: dbUx.configs.recommended.rules
}
];Rules
button-no-text-requires-tooltip
Ensures that buttons with noText prop have both an icon (or iconLeading/iconTrailing) and a DBTooltip child.
❌ Invalid:
// React
<DBButton noText>Save</DBButton>
<DBButton icon="save" noText>Save</DBButton>
// Angular
<db-button [noText]="true">ABC</db-button>
<db-button icon="x" [noText]="true">ABC</db-button>
// Vue
<DBButton :noText="true">ABC</DBButton>
<DBButton icon="x" :noText="true">ABC</DBButton>✅ Valid:
// React
<DBButton icon="save" noText>
Save
<DBTooltip>Save document</DBTooltip>
</DBButton>
// Angular
<db-button icon="x_placeholder" [noText]="true">
ABC
<db-tooltip>ABC</db-tooltip>
</db-button>
// Vue
<DBButton icon="x_placeholder" :noText="true">
ABC
<DBTooltip>ABC</DBTooltip>
</DBButton>Supported Frameworks
- React (JSX/TSX)
- Vue (SFC)
- Angular (Templates)
The plugin automatically detects the framework based on file extension and parser.
button-type-required
Ensures that DBButton has an explicit type attribute (submit, button, or reset).
❌ Invalid:
<DBButton>Save</DBButton>
<db-button>Save</db-button>✅ Valid:
<DBButton type="button">Save</DBButton>
<DBButton type="submit">Submit</DBButton>
<DBButton type="reset">Reset</DBButton>form-label-required
Ensures that form components (DBInput, DBTextarea, DBSelect, DBCustomSelect, DBCheckbox, DBRadio, DBSwitch) have a label attribute for accessibility.
❌ Invalid:
// React
<DBInput />
<DBCheckbox />
<DBSelect />
// Angular
<db-input></db-input>
<db-checkbox></db-checkbox>
// Vue
<DBInput />
<DBCheckbox />✅ Valid:
// React
<DBInput label="Name" />
<DBCheckbox label="Accept terms" />
<DBSelect label="Country" />
// Angular
<db-input label="Name"></db-input>
<db-checkbox [label]="labelText"></db-checkbox>
// Vue
<DBInput :label="dynamicLabel" />
<DBCheckbox label="Accept terms" />prefer-icon-attribute
Prefer using the icon attribute over <DBIcon> child component for components that support icon attributes.
❌ Invalid:
// React
<DBButton><DBIcon icon="save" /></DBButton>
<DBInput><DBIcon icon="search" /></DBInput>
// Angular
<db-button><db-icon icon="save"></db-icon></db-button>
// Vue
<DBLink><DBIcon icon="external" /></DBLink>✅ Valid:
// React
<DBButton icon="save">Save</DBButton>
<DBInput icon="search" />
// Angular
<db-button icon="save">Save</db-button>
// Vue
<DBLink :icon="iconName">Link</DBLink>text-or-children-required
Ensures that components (DBAccordionItem, DBBadge, DBButton, DBLink, DBIcon, DBInfotext, DBNavigationItem, DBNotification) have either a text property or children content.
❌ Invalid:
// React
<DBButton />
<DBLink />
<DBBadge />
// Angular
<db-button></db-button>
<db-notification></db-notification>
// Vue
<DBIcon icon="test" />✅ Valid:
// React
<DBButton text="Save" />
<DBButton>Save</DBButton>
<DBLink>Click here</DBLink>
// Angular
<db-button text="Save"></db-button>
<db-button>Save</db-button>
// Vue
<DBBadge>New</DBBadge>
<DBIcon icon="test">Label</DBIcon>no-interactive-tooltip-content
Prevents interactive elements (buttons, links, inputs) inside DBTooltip. Use DBPopover for interactive content.
❌ Invalid:
// React
<DBTooltip><button>Click</button></DBTooltip>
<DBTooltip><DBButton>Action</DBButton></DBTooltip>
<DBTooltip><a href="#">Link</a></DBTooltip>
// Angular
<db-tooltip><button>Click</button></db-tooltip>
<db-tooltip><db-button>Action</db-button></db-tooltip>
// Vue
<DBTooltip><DBLink href="#">Link</DBLink></DBTooltip>✅ Valid:
// React
<DBTooltip>Simple text</DBTooltip>
<DBTooltip><span>Text with span</span></DBTooltip>
<DBTooltip><p>Paragraph</p></DBTooltip>
// For interactive content, use DBPopover:
<DBPopover><DBButton>Action</DBButton></DBPopover>tooltip-requires-interactive-parent
Ensures DBTooltip is a child of an interactive element for accessibility (users must be able to focus the parent).
❌ Invalid:
// React
<span>Show more<DBTooltip>XXX</DBTooltip></span>
<div>Text<DBTooltip>Info</DBTooltip></div>
<DBBadge>Badge<DBTooltip>Info</DBTooltip></DBBadge>
// Angular
<span>Show more<db-tooltip>XXX</db-tooltip></span>
// Vue
<div>Text<DBTooltip>Info</DBTooltip></div>✅ Valid:
// React
<button>Save<DBTooltip>Save document</DBTooltip></button>
<DBButton>Save<DBTooltip>Save document</DBTooltip></DBButton>
<a href="#">Link<DBTooltip>More info</DBTooltip></a>
// Angular
<db-button>Save<db-tooltip>Save document</db-tooltip></db-button>
// Vue
<DBLink href="#">Link<DBTooltip>More info</DBTooltip></DBLink>no-nested-accordion
Prevents nesting DBAccordion components inside each other as it confuses users.
❌ Invalid:
// React
<DBAccordion><DBAccordion>Nested</DBAccordion></DBAccordion>
<DBAccordion><DBAccordionItem><DBAccordion>Deep</DBAccordion></DBAccordionItem></DBAccordion>
// Angular
<db-accordion><db-accordion>Nested</db-accordion></db-accordion>
// Vue
<DBAccordion><div><DBAccordion>Nested</DBAccordion></div></DBAccordion>✅ Valid:
// React
<DBAccordion><DBAccordionItem>Item</DBAccordionItem></DBAccordion>
<div><DBAccordion>First</DBAccordion></div>
<DBAccordion>First</DBAccordion><DBAccordion>Second</DBAccordion>badge-corner-placement-rules
Ensures DBBadge with corner placement has max 3 characters and a label attribute for accessibility.
❌ Invalid:
// React
<DBBadge placement="corner-top-left">9999</DBBadge>
<DBBadge placement="corner-top-right" text="1234" />
<DBBadge placement="corner-top-left">99</DBBadge>
// Angular
<db-badge placement="corner-top-left">9999</db-badge>
// Vue
<DBBadge placement="corner-top-right">Long text</DBBadge>✅ Valid:
// React
<DBBadge>Long text is fine</DBBadge>
<DBBadge placement="inline">Long text</DBBadge>
<DBBadge placement="corner-top-left" label="New items">99+</DBBadge>
<DBBadge placement="corner-top-right" text="5" label="Notifications" />
// Auto-fix converts:
<DBBadge placement="corner-top-left">9999</DBBadge>
// to:
<DBBadge placement="corner-top-left" label="9999">999</DBBadge>badge-no-inline-in-interactive
Prevents DBBadge with inline placement inside interactive elements (DBButton, DBLink). Use corner placement instead.
❌ Invalid:
// React
<DBButton><DBBadge placement="inline">Badge</DBBadge>Button</DBButton>
<DBLink><DBBadge placement="inline">Badge</DBBadge>Link</DBLink>
// Angular
<db-button><db-badge placement="inline">Badge</db-badge>Button</db-button>
// Vue
<DBButton><DBBadge placement="inline">Badge</DBBadge>Button</DBButton>✅ Valid:
// React
<DBBadge placement="inline">Badge</DBBadge>
<DBButton><DBBadge placement="corner-top-right" label="New">5</DBBadge>Button</DBButton>
<DBLink><DBBadge placement="corner-top-left" label="Count">3</DBBadge>Link</DBLink>
// Auto-fix converts:
<DBButton><DBBadge placement="inline">Badge</DBBadge>Button</DBButton>
// to:
<DBButton><DBBadge placement="corner-top-right">Badge</DBBadge>Button</DBButton>button-single-icon-attribute
Ensures DBButton uses only one icon attribute (icon, iconLeading, or iconTrailing).
❌ Invalid:
// React
<DBButton icon="save" iconLeading="save">Save</DBButton>
<DBButton icon="save" iconTrailing="arrow">Save</DBButton>
<DBButton iconLeading="save" iconTrailing="arrow">Save</DBButton>
// Angular
<db-button icon="save" [iconLeading]="iconName">Save</db-button>
// Vue
<DBButton icon="save" :iconTrailing="icon">Save</DBButton>✅ Valid:
// React
<DBButton icon="save">Save</DBButton>
<DBButton iconLeading="save">Save</DBButton>
<DBButton iconTrailing="arrow">Next</DBButton>
// Angular
<db-button icon="save">Save</db-button>
<db-button [iconLeading]="iconName">Save</db-button>
// Vue
<DBButton :iconTrailing="icon">Next</DBButton>link-external-security
Ensures external links have proper security attributes (target="_blank" and referrerPolicy).
❌ Invalid:
// React
<DBLink content="external">External</DBLink>
<DBLink content="external" target="_blank">External</DBLink>
<DBLink target="_blank">External</DBLink>
// Angular
<db-link content="external">External</db-link>
// Vue
<DBLink content="external" :target="linkTarget">External</DBLink>✅ Valid:
// React
<DBLink href="#">Internal link</DBLink>
<DBLink content="external" target="_blank" referrerPolicy="no-referrer">External</DBLink>
// Angular
<db-link content="external" target="_blank" referrerPolicy="no-referrer">External</db-link>
// Vue
<DBLink content="external" target="_blank" :referrerPolicy="policy">External</DBLink>select-requires-options
Ensures DBSelect has either an options property or option children.
❌ Invalid:
// React
<DBSelect label="Country" />
<DBSelect label="Country"></DBSelect>
// Angular
<db-select label="Country"></db-select>
// Vue
<DBSelect label="Country" />✅ Valid:
// React
<DBSelect label="Country">
<option value="de">Germany</option>
<option value="us">USA</option>
</DBSelect>
<DBSelect label="Country" options={countryOptions} />
// Angular
<db-select label="Country">
<option value="de">Germany</option>
</db-select>
<db-select label="Country" [options]="options"></db-select>
// Vue
<DBSelect label="Country" :options="options" />close-button-text-required
Ensures components with close buttons have appropriate text attributes for accessibility.
❌ Invalid:
// React
<DBNotification>Message</DBNotification>
<DBDrawer>Content</DBDrawer>
<DBCustomSelect label="Select" />
// Angular
<db-notification>Message</db-notification>
<db-drawer>Content</db-drawer>
// Vue
<DBCustomSelect label="Select" />✅ Valid:
// React
<DBNotification closeButtonText="Close">Message</DBNotification>
<DBDrawer closeButtonText="Close drawer">Content</DBDrawer>
<DBCustomSelect mobileCloseButtonText="Close" label="Select" />
// Angular
<db-notification closeButtonText="Close">Message</db-notification>
<db-drawer [closeButtonText]="closeText">Content</db-drawer>
// Vue
<DBCustomSelect :mobileCloseButtonText="closeText" label="Select" />header-burger-menu-label-required
Ensures DBHeader has burgerMenuLabel attribute for accessibility.
❌ Invalid:
// React
<DBHeader>Content</DBHeader>
<DBHeader closeButtonText="Close">Content</DBHeader>
// Angular
<db-header>Content</db-header>
// Vue
<DBHeader>Content</DBHeader>✅ Valid:
// React
<DBHeader burgerMenuLabel="Menu">Content</DBHeader>
<DBHeader burgerMenuLabel="Open navigation">Content</DBHeader>
// Angular
<db-header burgerMenuLabel="Menu">Content</db-header>
<db-header [burgerMenuLabel]="menuLabel">Content</db-header>
// Vue
<DBHeader :burgerMenuLabel="label">Content</DBHeader>navigation-item-back-button-text-required
Ensures DBNavigationItem has backButtonText attribute for accessibility.
❌ Invalid:
// React
<DBNavigationItem>Item</DBNavigationItem>
<DBNavigationItem icon="home">Item</DBNavigationItem>
// Angular
<db-navigation-item>Item</db-navigation-item>
// Vue
<DBNavigationItem>Item</DBNavigationItem>✅ Valid:
// React
<DBNavigationItem backButtonText="Back">Item</DBNavigationItem>
<DBNavigationItem backButtonText="Go back">Item</DBNavigationItem>
// Angular
<db-navigation-item backButtonText="Back">Item</db-navigation-item>
<db-navigation-item [backButtonText]="backText">Item</db-navigation-item>
// Vue
<DBNavigationItem :backButtonText="text">Item</DBNavigationItem>custom-select-tags-remove-text-required
Ensures DBCustomSelect with selectedType="tag" has removeTagsTexts attribute for accessibility.
❌ Invalid:
// React
<DBCustomSelect label="Select" selectedType="tag" />
<DBCustomSelect label="Select" selectedType="tag" options={opts} />
// Angular
<db-custom-select label="Select" selectedType="tag"></db-custom-select>
// Vue
<DBCustomSelect label="Select" selectedType="tag" />✅ Valid:
// React
<DBCustomSelect label="Select" />
<DBCustomSelect label="Select" selectedType="text" />
<DBCustomSelect label="Select" selectedType="tag" removeTagsTexts={["Remove A", "Remove B"]} />
// Angular
<db-custom-select label="Select" selectedType="tag" removeTagsTexts="texts"></db-custom-select>
// Vue
<DBCustomSelect label="Select" selectedType="tag" :removeTagsTexts="texts" />tag-removable-remove-button-required
Ensures DBTag with behavior="removable" has removeButton attribute for accessibility.
❌ Invalid:
// React
<DBTag behavior="removable">Tag</DBTag>
<DBTag behavior="removable" semantic="successful">Tag</DBTag>
// Angular
<db-tag behavior="removable">Tag</db-tag>
// Vue
<DBTag behavior="removable">Tag</DBTag>✅ Valid:
// React
<DBTag>Tag</DBTag>
<DBTag behavior="static">Tag</DBTag>
<DBTag behavior="removable" removeButton="Remove">Tag</DBTag>
// Angular
<db-tag behavior="removable" removeButton="Remove">Tag</db-tag>
// Vue
<DBTag behavior="removable" :removeButton="removeText">Tag</DBTag>form-validation-message-required
Ensures form components with validation attributes have invalidMessage for user feedback.
❌ Invalid:
// React
<DBInput label="Name" required />
<DBTextarea label="Text" maxLength={100} />
<DBInput label="Age" min={18} />
<DBInput label="Email" pattern=".*@.*" />
// Angular
<db-input label="Name" required></db-input>
// Vue
<DBInput label="Score" :max="100" />✅ Valid:
// React
<DBInput label="Name" />
<DBInput label="Name" required invalidMessage="Required" />
<DBTextarea label="Text" maxLength={100} invalidMessage="Too long" />
<DBInput label="Age" min={18} invalidMessage="Must be 18+" />
<DBInput label="Email" pattern=".*@.*" invalidMessage="Invalid email" />
// Applies to: DBInput, DBTextarea, DBSelect, DBCustomSelect, DBCheckbox
// Checks: required, maxLength, minLength (Input/Textarea), min, max, pattern (Input only)input-type-required
Suggests adding type attribute to DBInput for better developer experience.
❌ Invalid:
// React
<DBInput label="Name" />
<DBInput label="Name" placeholder="Enter name" />
// Angular
<db-input label="Name"></db-input>
// Vue
<DBInput label="Name" />✅ Valid:
// React
<DBInput label="Name" type="text" />
<DBInput label="Email" type="email" />
<DBInput label="Password" type="password" />
// Auto-fix adds:
<DBInput label="Name" type="text" />input-file-type-validation
Ensures DBInput with type="file" has accept attribute, and validates file-only attributes.
❌ Invalid:
// React
<DBInput label="File" type="file" />
<DBInput label="Name" type="text" multiple />
<DBInput label="Name" type="text" accept=".pdf" />
// Angular
<db-input label="File" type="file"></db-input>
// Vue
<DBInput label="Email" type="email" accept=".pdf" multiple />✅ Valid:
// React
<DBInput label="Name" type="text" />
<DBInput label="File" type="file" accept=".pdf" />
<DBInput label="Files" type="file" accept="image/*" multiple />
// Angular
<db-input label="File" type="file" accept=".jpg"></db-input>
// Vue
<DBInput label="File" type="file" accept="image/*" :multiple="true" />