packages/react-components/eslint-plugin-react-components/README.md
ESLint Plugin for Fluent UI React Components
This ESLint plugin enforces best practices and coding standards for Fluent UI React Components. It helps developers:
Install the plugin using your preferred package manager:
# npm
npm install --save-dev @fluentui/eslint-plugin-react-components
# yarn
yarn add --dev @fluentui/eslint-plugin-react-components
# pnpm
pnpm add --save-dev @fluentui/eslint-plugin-react-components
Add the plugin to your eslint.config.js:
const fluentuiReactComponents = require('@fluentui/eslint-plugin-react-components');
module.exports = [
fluentuiReactComponents.configs.recommended,
// Your other configs...
];
Or configure individual rules manually:
const fluentuiReactComponents = require('@fluentui/eslint-plugin-react-components');
module.exports = [
{
plugins: {
'@fluentui/react-components': fluentuiReactComponents,
},
rules: {
'@fluentui/react-components/prefer-fluentui-v9': 'warn',
},
},
];
Add the plugin to your .eslintrc.js:
module.exports = {
plugins: ['@fluentui/react-components'],
extends: ['plugin:@fluentui/react-components/recommended'],
};
Or configure individual rules manually:
module.exports = {
plugins: ['@fluentui/react-components'],
rules: {
'@fluentui/react-components/prefer-fluentui-v9': 'warn',
},
};
This rule ensures the use of Fluent UI v9 counterparts for Fluent UI v8 components.
✅ Do
// Import and use components that have been already migrated to Fluent UI v9
import { Button } from '@fluentui/react-components';
const Component = () => <Button>...</Button>;
❌ Don't
// Avoid importing and using Fluent UI V8 components that have already been migrated to Fluent UI V9.
import { DefaultButton } from '@fluentui/react';
const Component = () => <DefaultButton>...</DefaultButton>;
Ensures that source files using client-only React features begin with the top-level 'use client' directive, and flags files that include the directive unnecessarily.
The rule looks for any of the following client-only features:
useState, useEffect, useRef, forwardRef, memo)use and are not in the safe set: use, useId)on followed by a capital letter, like onClick)window, document, navigator, localStorage, sessionStorage, history, location)canUseDOM(), makeStyles(), makeResetStyles(), makeStaticStyles())If at least one feature is present, the directive must be the very first statement in the file. If no features are found, any existing 'use client' directive will be reported as unnecessary and auto-fixed.
import * as React from 'react';
export function MyComponent() {
const [value, setValue] = React.useState('');
return <button onClick={() => setValue('clicked')}>{value}</button>;
}
'use client';
import * as React from 'react';
export function MyComponent() {
const [value, setValue] = React.useState('');
return <button onClick={() => setValue('clicked')}>{value}</button>;
}
'use client';
// Pure utilities – no client-only APIs
export function add(a: number, b: number) {
return a + b;
}
// Pure utilities – no client-only APIs
export function add(a: number, b: number) {
return a + b;
}
import * as React from 'react';
import { canUseDOM } from '../ssr/index';
// canUseDOM() accesses browser APIs internally
export const useIsomorphicLayoutEffect = canUseDOM() ? React.useLayoutEffect : React.useEffect;
'use client';
import * as React from 'react';
import { canUseDOM } from '../ssr/index';
export const useIsomorphicLayoutEffect = canUseDOM() ? React.useLayoutEffect : React.useEffect;
import { makeStyles } from '@griffel/react';
export const useStyles = makeStyles({
root: { backgroundColor: 'red' },
});
'use client';
import { makeStyles } from '@griffel/react';
export const useStyles = makeStyles({
root: { backgroundColor: 'red' },
});
No options – enable to enforce consistent usage of the directive.
This project is licensed under the MIT License - see the LICENSE file for details.