@atlaskit/eslint-plugin-design-system 8.20.0 → 8.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 8.21.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#66250](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/66250) [`6ff74a16aee7`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/6ff74a16aee7) - Introducing new rule to encourage adding/referencing accessible name to a ButtonGroup component.
8
+
3
9
  ## 8.20.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -65,6 +65,7 @@ module.exports = {
65
65
  | <a href="./src/rules/no-unsafe-style-overrides/README.md">no-unsafe-style-overrides</a> | Discourage usage of unsafe style overrides used against the Atlassian Design System. | Yes | | |
66
66
  | <a href="./src/rules/no-unsupported-drag-and-drop-libraries/README.md">no-unsupported-drag-and-drop-libraries</a> | Disallow importing unsupported drag and drop modules. | Yes | | |
67
67
  | <a href="./src/rules/prefer-primitives/README.md">prefer-primitives</a> | Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule. | | | |
68
+ | <a href="./src/rules/use-button-group-label/README.md">use-button-group-label</a> | Ensures button groups are described to assistive technology by a direct label or by another element. | Yes | | Yes |
68
69
  | <a href="./src/rules/use-drawer-label/README.md">use-drawer-label</a> | Encourages to provide accessible name for Atlassian Design System Drawer component. | Yes | | Yes |
69
70
  | <a href="./src/rules/use-heading-level-in-spotlight-card/README.md">use-heading-level-in-spotlight-card</a> | Inform developers of eventual requirement of `headingLevel` prop in `SpotlightCard` component. The heading level should be the appropriate level according to the surrounding context. | Yes | Yes | |
70
71
  | <a href="./src/rules/use-href-in-link-item/README.md">use-href-in-link-item</a> | Inform developers of eventual requirement of `href` prop in `LinkItem` component. Elements with a `link` role require an `href` attribute for users to properly navigate, particularly those using assistive technologies. If no valid `href` is required for your use case, consider using a `ButtonItem` instead. | Yes | Yes | Yes |
@@ -29,6 +29,7 @@ This plugin contains rules that should be used when working with the [Atlassian
29
29
  | <a href="#no-unsafe-style-overrides">no-unsafe-style-overrides</a> | Discourage usage of unsafe style overrides used against the Atlassian Design System. | Yes | | |
30
30
  | <a href="#no-unsupported-drag-and-drop-libraries">no-unsupported-drag-and-drop-libraries</a> | Disallow importing unsupported drag and drop modules. | Yes | | |
31
31
  | <a href="#prefer-primitives">prefer-primitives</a> | Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule. | | | |
32
+ | <a href="#use-button-group-label">use-button-group-label</a> | Ensures button groups are described to assistive technology by a direct label or by another element. | Yes | | Yes |
32
33
  | <a href="#use-drawer-label">use-drawer-label</a> | Encourages to provide accessible name for Atlassian Design System Drawer component. | Yes | | Yes |
33
34
  | <a href="#use-heading-level-in-spotlight-card">use-heading-level-in-spotlight-card</a> | Inform developers of eventual requirement of `headingLevel` prop in `SpotlightCard` component. The heading level should be the appropriate level according to the surrounding context. | Yes | Yes | |
34
35
  | <a href="#use-href-in-link-item">use-href-in-link-item</a> | Inform developers of eventual requirement of `href` prop in `LinkItem` component. Elements with a `link` role require an `href` attribute for users to properly navigate, particularly those using assistive technologies. If no valid `href` is required for your use case, consider using a `ButtonItem` instead. | Yes | Yes | Yes |
@@ -767,6 +768,65 @@ This rule marks code as violations when it may be able to be replaced with a pri
767
768
  </Component>
768
769
  ```
769
770
 
771
+ ## use-button-group-label
772
+
773
+ ButtonGroup should have an accessible name or a reference to it, so that upon opening, users of assistive technologies could have contextual information of interaction with current element.
774
+
775
+ <h3>Examples</h3>
776
+
777
+ This rule will indicate user with warning to strongly recommend usage of either `label` or `titleId` prop.
778
+
779
+ #### Incorrect
780
+
781
+ ```tsx
782
+ <ButtonGroup>
783
+ ^^^^^^^^^^^ Missing either `label` or `titleId` prop.
784
+ <Button>Save</Button>
785
+ <Button>Edit</Button>
786
+ <Button>Delete</Button>
787
+ </ButtonGroup>
788
+
789
+ <ButtonGroup label="">
790
+ ^^^^^ `label` prop is missing accessible name value.
791
+ <Button>Save</Button>
792
+ <Button>Edit</Button>
793
+ <Button>Delete</Button>
794
+ </ButtonGroup>
795
+
796
+ <h2 id="button-group-title">ButtonGroup content title</hi>
797
+ <ButtonGroup titleId="">
798
+ ^^^^^^^ `titleId` prop is missing reference value.
799
+ <Button>Save</Button>
800
+ <Button>Edit</Button>
801
+ <Button>Delete</Button>
802
+ </ButtonGroup>
803
+
804
+ <h2 id="button-group-title">ButtonGroup content title</h2>
805
+ <ButtonGroup titleId="button-group-title" label="">
806
+ ^^^^^^^ ^^^^^ Do not include both `titleId` and `label` properties. Use `titleId` if the label text is available in the DOM to reference it, otherwise use `label` to provide accessible name explicitly.
807
+ <Button>Save</Button>
808
+ <Button>Edit</Button>
809
+ <Button>Delete</Button>
810
+ </ButtonGroup>
811
+ ```
812
+
813
+ #### Correct
814
+
815
+ ```tsx
816
+ <ButtonGroup label="ButtonGroup content title">
817
+ <Button>Save</Button>
818
+ <Button>Edit</Button>
819
+ <Button>Delete</Button>
820
+ </ButtonGroup>
821
+
822
+ <h2 id="button-group-title">ButtonGroup content title</h2>
823
+ <ButtonGroup titleId="button-group-title">
824
+ <Button>Save</Button>
825
+ <Button>Edit</Button>
826
+ <Button>Delete</Button>
827
+ </ButtonGroup>
828
+ ```
829
+
770
830
  ## use-drawer-label
771
831
 
772
832
  Drawer should have an accessible name or a reference to it, so that upon opening, users of assistive technologies could have contextual information of interaction with current element.
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::6efa1e48692b3e287d6dfcd500a5f0ab>>
9
+ * @codegen <<SignedSource::d1a459e1ea71650f65b2890dc86cc398>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -28,6 +28,7 @@ var _default = exports.default = {
28
28
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
29
29
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
30
30
  '@atlaskit/design-system/prefer-primitives': 'warn',
31
+ '@atlaskit/design-system/use-button-group-label': 'warn',
31
32
  '@atlaskit/design-system/use-drawer-label': 'warn',
32
33
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
33
34
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::be810d87ec2d253e3b053dc06ff1b99a>>
9
+ * @codegen <<SignedSource::3b93cfbbe0ea14514b9600509632394b>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -23,6 +23,7 @@ var _default = exports.default = {
23
23
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
24
24
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
25
25
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
26
+ '@atlaskit/design-system/use-button-group-label': 'warn',
26
27
  '@atlaskit/design-system/use-drawer-label': 'warn',
27
28
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
28
29
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
@@ -21,6 +21,7 @@ var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./no-unsafe-desi
21
21
  var _noUnsafeStyleOverrides = _interopRequireDefault(require("./no-unsafe-style-overrides"));
22
22
  var _noUnsupportedDragAndDropLibraries = _interopRequireDefault(require("./no-unsupported-drag-and-drop-libraries"));
23
23
  var _preferPrimitives = _interopRequireDefault(require("./prefer-primitives"));
24
+ var _useButtonGroupLabel = _interopRequireDefault(require("./use-button-group-label"));
24
25
  var _useDrawerLabel = _interopRequireDefault(require("./use-drawer-label"));
25
26
  var _useHeadingLevelInSpotlightCard = _interopRequireDefault(require("./use-heading-level-in-spotlight-card"));
26
27
  var _useHrefInLinkItem = _interopRequireDefault(require("./use-href-in-link-item"));
@@ -28,7 +29,7 @@ var _usePrimitives = _interopRequireDefault(require("./use-primitives"));
28
29
  var _useVisuallyHidden = _interopRequireDefault(require("./use-visually-hidden"));
29
30
  /**
30
31
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
31
- * @codegen <<SignedSource::ab1f5b129d07027c228dbd79da5f3572>>
32
+ * @codegen <<SignedSource::14cdfdcbd8b999ee097a1a5b245d7117>>
32
33
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
33
34
  */
34
35
  var _default = exports.default = {
@@ -48,6 +49,7 @@ var _default = exports.default = {
48
49
  'no-unsafe-style-overrides': _noUnsafeStyleOverrides.default,
49
50
  'no-unsupported-drag-and-drop-libraries': _noUnsupportedDragAndDropLibraries.default,
50
51
  'prefer-primitives': _preferPrimitives.default,
52
+ 'use-button-group-label': _useButtonGroupLabel.default,
51
53
  'use-drawer-label': _useDrawerLabel.default,
52
54
  'use-heading-level-in-spotlight-card': _useHeadingLevelInSpotlightCard.default,
53
55
  'use-href-in-link-item': _useHrefInLinkItem.default,
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
8
+ var _createRule = require("../utils/create-rule");
9
+ // eslint-disable-next-line import/no-extraneous-dependencies
10
+
11
+ var elementsAccessibleNameProps = ['label', 'titleId'];
12
+ var rule = (0, _createRule.createLintRule)({
13
+ meta: {
14
+ name: 'use-button-group-label',
15
+ type: 'suggestion',
16
+ docs: {
17
+ description: 'Ensures button groups are described to assistive technology by a direct label or by another element.',
18
+ recommended: true,
19
+ severity: 'warn'
20
+ },
21
+ messages: {
22
+ missingLabelProp: 'Missing accessible name. If there is no visible content to associate use `label` prop, otherwise pass id of element to `titleId` prop to be associated as label.',
23
+ labelPropShouldHaveContents: 'Define string that labels the interactive element.',
24
+ titleIdShouldHaveValue: '`titleId` should reference the id of element that define accessible name.',
25
+ noBothPropsUsage: 'Do not include both `titleId` and `label` properties. Use `titleId` if the label text is available in the DOM to reference it, otherwise use `label` to provide accessible name explicitly.'
26
+ },
27
+ hasSuggestions: true
28
+ },
29
+ create: function create(context) {
30
+ var contextLocalIdentifier = [];
31
+ return {
32
+ ImportDeclaration: function ImportDeclaration(node) {
33
+ if (node.source.value === '@atlaskit/button') {
34
+ if (node.specifiers.length) {
35
+ var defaultImport = node.specifiers.filter(function (spec) {
36
+ return spec.type === 'ImportSpecifier';
37
+ });
38
+ if (defaultImport && defaultImport.length) {
39
+ var local = defaultImport[0].local;
40
+ contextLocalIdentifier.push(local.name);
41
+ }
42
+ }
43
+ }
44
+ },
45
+ JSXElement: function JSXElement(node) {
46
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
47
+ return;
48
+ }
49
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier')) {
50
+ return;
51
+ }
52
+ var name = node.openingElement.name.name;
53
+ if (contextLocalIdentifier.includes(name)) {
54
+ var componentLabelProps = node.openingElement.attributes.filter(function (attr) {
55
+ return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute') && (0, _eslintCodemodUtils.isNodeOfType)(attr.name, 'JSXIdentifier') && elementsAccessibleNameProps.includes(attr.name.name);
56
+ });
57
+ if (componentLabelProps.length === 1) {
58
+ var prop = componentLabelProps[0];
59
+ if ('value' in prop && prop.value) {
60
+ if ((0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'Literal') && !prop.value.value || (0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'JSXExpressionContainer') && !prop.value.expression) {
61
+ context.report({
62
+ node: prop,
63
+ messageId: prop.name.name === 'label' ? 'labelPropShouldHaveContents' : 'titleIdShouldHaveValue'
64
+ });
65
+ }
66
+ }
67
+ } else if (componentLabelProps.length > 1) {
68
+ context.report({
69
+ node: node.openingElement,
70
+ messageId: 'noBothPropsUsage'
71
+ });
72
+ } else {
73
+ context.report({
74
+ node: node.openingElement,
75
+ messageId: 'missingLabelProp'
76
+ });
77
+ }
78
+ }
79
+ }
80
+ };
81
+ }
82
+ });
83
+ var _default = exports.default = rule;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::6efa1e48692b3e287d6dfcd500a5f0ab>>
3
+ * @codegen <<SignedSource::d1a459e1ea71650f65b2890dc86cc398>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -22,6 +22,7 @@ export default {
22
22
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
23
23
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
24
24
  '@atlaskit/design-system/prefer-primitives': 'warn',
25
+ '@atlaskit/design-system/use-button-group-label': 'warn',
25
26
  '@atlaskit/design-system/use-drawer-label': 'warn',
26
27
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
27
28
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::be810d87ec2d253e3b053dc06ff1b99a>>
3
+ * @codegen <<SignedSource::3b93cfbbe0ea14514b9600509632394b>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -17,6 +17,7 @@ export default {
17
17
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
18
18
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
19
19
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
20
+ '@atlaskit/design-system/use-button-group-label': 'warn',
20
21
  '@atlaskit/design-system/use-drawer-label': 'warn',
21
22
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
22
23
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::ab1f5b129d07027c228dbd79da5f3572>>
3
+ * @codegen <<SignedSource::14cdfdcbd8b999ee097a1a5b245d7117>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
@@ -19,6 +19,7 @@ import noUnsafeDesignTokenUsage from './no-unsafe-design-token-usage';
19
19
  import noUnsafeStyleOverrides from './no-unsafe-style-overrides';
20
20
  import noUnsupportedDragAndDropLibraries from './no-unsupported-drag-and-drop-libraries';
21
21
  import preferPrimitives from './prefer-primitives';
22
+ import useButtonGroupLabel from './use-button-group-label';
22
23
  import useDrawerLabel from './use-drawer-label';
23
24
  import useHeadingLevelInSpotlightCard from './use-heading-level-in-spotlight-card';
24
25
  import useHrefInLinkItem from './use-href-in-link-item';
@@ -41,6 +42,7 @@ export default {
41
42
  'no-unsafe-style-overrides': noUnsafeStyleOverrides,
42
43
  'no-unsupported-drag-and-drop-libraries': noUnsupportedDragAndDropLibraries,
43
44
  'prefer-primitives': preferPrimitives,
45
+ 'use-button-group-label': useButtonGroupLabel,
44
46
  'use-drawer-label': useDrawerLabel,
45
47
  'use-heading-level-in-spotlight-card': useHeadingLevelInSpotlightCard,
46
48
  'use-href-in-link-item': useHrefInLinkItem,
@@ -0,0 +1,75 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
3
+ import { isNodeOfType } from 'eslint-codemod-utils';
4
+ import { createLintRule } from '../utils/create-rule';
5
+ const elementsAccessibleNameProps = ['label', 'titleId'];
6
+ const rule = createLintRule({
7
+ meta: {
8
+ name: 'use-button-group-label',
9
+ type: 'suggestion',
10
+ docs: {
11
+ description: 'Ensures button groups are described to assistive technology by a direct label or by another element.',
12
+ recommended: true,
13
+ severity: 'warn'
14
+ },
15
+ messages: {
16
+ missingLabelProp: 'Missing accessible name. If there is no visible content to associate use `label` prop, otherwise pass id of element to `titleId` prop to be associated as label.',
17
+ labelPropShouldHaveContents: 'Define string that labels the interactive element.',
18
+ titleIdShouldHaveValue: '`titleId` should reference the id of element that define accessible name.',
19
+ noBothPropsUsage: 'Do not include both `titleId` and `label` properties. Use `titleId` if the label text is available in the DOM to reference it, otherwise use `label` to provide accessible name explicitly.'
20
+ },
21
+ hasSuggestions: true
22
+ },
23
+ create(context) {
24
+ const contextLocalIdentifier = [];
25
+ return {
26
+ ImportDeclaration(node) {
27
+ if (node.source.value === '@atlaskit/button') {
28
+ if (node.specifiers.length) {
29
+ const defaultImport = node.specifiers.filter(spec => spec.type === 'ImportSpecifier');
30
+ if (defaultImport && defaultImport.length) {
31
+ const {
32
+ local
33
+ } = defaultImport[0];
34
+ contextLocalIdentifier.push(local.name);
35
+ }
36
+ }
37
+ }
38
+ },
39
+ JSXElement(node) {
40
+ if (!isNodeOfType(node, 'JSXElement')) {
41
+ return;
42
+ }
43
+ if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
44
+ return;
45
+ }
46
+ const name = node.openingElement.name.name;
47
+ if (contextLocalIdentifier.includes(name)) {
48
+ const componentLabelProps = node.openingElement.attributes.filter(attr => isNodeOfType(attr, 'JSXAttribute') && isNodeOfType(attr.name, 'JSXIdentifier') && elementsAccessibleNameProps.includes(attr.name.name));
49
+ if (componentLabelProps.length === 1) {
50
+ const prop = componentLabelProps[0];
51
+ if ('value' in prop && prop.value) {
52
+ if (isNodeOfType(prop.value, 'Literal') && !prop.value.value || isNodeOfType(prop.value, 'JSXExpressionContainer') && !prop.value.expression) {
53
+ context.report({
54
+ node: prop,
55
+ messageId: prop.name.name === 'label' ? 'labelPropShouldHaveContents' : 'titleIdShouldHaveValue'
56
+ });
57
+ }
58
+ }
59
+ } else if (componentLabelProps.length > 1) {
60
+ context.report({
61
+ node: node.openingElement,
62
+ messageId: 'noBothPropsUsage'
63
+ });
64
+ } else {
65
+ context.report({
66
+ node: node.openingElement,
67
+ messageId: 'missingLabelProp'
68
+ });
69
+ }
70
+ }
71
+ }
72
+ };
73
+ }
74
+ });
75
+ export default rule;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::6efa1e48692b3e287d6dfcd500a5f0ab>>
3
+ * @codegen <<SignedSource::d1a459e1ea71650f65b2890dc86cc398>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -22,6 +22,7 @@ export default {
22
22
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
23
23
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
24
24
  '@atlaskit/design-system/prefer-primitives': 'warn',
25
+ '@atlaskit/design-system/use-button-group-label': 'warn',
25
26
  '@atlaskit/design-system/use-drawer-label': 'warn',
26
27
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
27
28
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::be810d87ec2d253e3b053dc06ff1b99a>>
3
+ * @codegen <<SignedSource::3b93cfbbe0ea14514b9600509632394b>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -17,6 +17,7 @@ export default {
17
17
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
18
18
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
19
19
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
20
+ '@atlaskit/design-system/use-button-group-label': 'warn',
20
21
  '@atlaskit/design-system/use-drawer-label': 'warn',
21
22
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
22
23
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::ab1f5b129d07027c228dbd79da5f3572>>
3
+ * @codegen <<SignedSource::14cdfdcbd8b999ee097a1a5b245d7117>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
@@ -19,6 +19,7 @@ import noUnsafeDesignTokenUsage from './no-unsafe-design-token-usage';
19
19
  import noUnsafeStyleOverrides from './no-unsafe-style-overrides';
20
20
  import noUnsupportedDragAndDropLibraries from './no-unsupported-drag-and-drop-libraries';
21
21
  import preferPrimitives from './prefer-primitives';
22
+ import useButtonGroupLabel from './use-button-group-label';
22
23
  import useDrawerLabel from './use-drawer-label';
23
24
  import useHeadingLevelInSpotlightCard from './use-heading-level-in-spotlight-card';
24
25
  import useHrefInLinkItem from './use-href-in-link-item';
@@ -41,6 +42,7 @@ export default {
41
42
  'no-unsafe-style-overrides': noUnsafeStyleOverrides,
42
43
  'no-unsupported-drag-and-drop-libraries': noUnsupportedDragAndDropLibraries,
43
44
  'prefer-primitives': preferPrimitives,
45
+ 'use-button-group-label': useButtonGroupLabel,
44
46
  'use-drawer-label': useDrawerLabel,
45
47
  'use-heading-level-in-spotlight-card': useHeadingLevelInSpotlightCard,
46
48
  'use-href-in-link-item': useHrefInLinkItem,
@@ -0,0 +1,77 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
3
+ import { isNodeOfType } from 'eslint-codemod-utils';
4
+ import { createLintRule } from '../utils/create-rule';
5
+ var elementsAccessibleNameProps = ['label', 'titleId'];
6
+ var rule = createLintRule({
7
+ meta: {
8
+ name: 'use-button-group-label',
9
+ type: 'suggestion',
10
+ docs: {
11
+ description: 'Ensures button groups are described to assistive technology by a direct label or by another element.',
12
+ recommended: true,
13
+ severity: 'warn'
14
+ },
15
+ messages: {
16
+ missingLabelProp: 'Missing accessible name. If there is no visible content to associate use `label` prop, otherwise pass id of element to `titleId` prop to be associated as label.',
17
+ labelPropShouldHaveContents: 'Define string that labels the interactive element.',
18
+ titleIdShouldHaveValue: '`titleId` should reference the id of element that define accessible name.',
19
+ noBothPropsUsage: 'Do not include both `titleId` and `label` properties. Use `titleId` if the label text is available in the DOM to reference it, otherwise use `label` to provide accessible name explicitly.'
20
+ },
21
+ hasSuggestions: true
22
+ },
23
+ create: function create(context) {
24
+ var contextLocalIdentifier = [];
25
+ return {
26
+ ImportDeclaration: function ImportDeclaration(node) {
27
+ if (node.source.value === '@atlaskit/button') {
28
+ if (node.specifiers.length) {
29
+ var defaultImport = node.specifiers.filter(function (spec) {
30
+ return spec.type === 'ImportSpecifier';
31
+ });
32
+ if (defaultImport && defaultImport.length) {
33
+ var local = defaultImport[0].local;
34
+ contextLocalIdentifier.push(local.name);
35
+ }
36
+ }
37
+ }
38
+ },
39
+ JSXElement: function JSXElement(node) {
40
+ if (!isNodeOfType(node, 'JSXElement')) {
41
+ return;
42
+ }
43
+ if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
44
+ return;
45
+ }
46
+ var name = node.openingElement.name.name;
47
+ if (contextLocalIdentifier.includes(name)) {
48
+ var componentLabelProps = node.openingElement.attributes.filter(function (attr) {
49
+ return isNodeOfType(attr, 'JSXAttribute') && isNodeOfType(attr.name, 'JSXIdentifier') && elementsAccessibleNameProps.includes(attr.name.name);
50
+ });
51
+ if (componentLabelProps.length === 1) {
52
+ var prop = componentLabelProps[0];
53
+ if ('value' in prop && prop.value) {
54
+ if (isNodeOfType(prop.value, 'Literal') && !prop.value.value || isNodeOfType(prop.value, 'JSXExpressionContainer') && !prop.value.expression) {
55
+ context.report({
56
+ node: prop,
57
+ messageId: prop.name.name === 'label' ? 'labelPropShouldHaveContents' : 'titleIdShouldHaveValue'
58
+ });
59
+ }
60
+ }
61
+ } else if (componentLabelProps.length > 1) {
62
+ context.report({
63
+ node: node.openingElement,
64
+ messageId: 'noBothPropsUsage'
65
+ });
66
+ } else {
67
+ context.report({
68
+ node: node.openingElement,
69
+ messageId: 'missingLabelProp'
70
+ });
71
+ }
72
+ }
73
+ }
74
+ };
75
+ }
76
+ });
77
+ export default rule;
@@ -19,6 +19,7 @@ export declare const configs: {
19
19
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
20
20
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
21
21
  '@atlaskit/design-system/prefer-primitives': string;
22
+ '@atlaskit/design-system/use-button-group-label': string;
22
23
  '@atlaskit/design-system/use-drawer-label': string;
23
24
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
24
25
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -40,6 +41,7 @@ export declare const configs: {
40
41
  '@atlaskit/design-system/no-unsafe-design-token-usage': string;
41
42
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
42
43
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
44
+ '@atlaskit/design-system/use-button-group-label': string;
43
45
  '@atlaskit/design-system/use-drawer-label': string;
44
46
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
45
47
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::6efa1e48692b3e287d6dfcd500a5f0ab>>
3
+ * @codegen <<SignedSource::d1a459e1ea71650f65b2890dc86cc398>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  declare const _default: {
@@ -22,6 +22,7 @@ declare const _default: {
22
22
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
23
23
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
24
24
  '@atlaskit/design-system/prefer-primitives': string;
25
+ '@atlaskit/design-system/use-button-group-label': string;
25
26
  '@atlaskit/design-system/use-drawer-label': string;
26
27
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
27
28
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::be810d87ec2d253e3b053dc06ff1b99a>>
3
+ * @codegen <<SignedSource::3b93cfbbe0ea14514b9600509632394b>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  declare const _default: {
@@ -17,6 +17,7 @@ declare const _default: {
17
17
  '@atlaskit/design-system/no-unsafe-design-token-usage': string;
18
18
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
19
19
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
20
+ '@atlaskit/design-system/use-button-group-label': string;
20
21
  '@atlaskit/design-system/use-drawer-label': string;
21
22
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
22
23
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -19,6 +19,7 @@ declare const _default: {
19
19
  'no-unsafe-style-overrides': import("eslint").Rule.RuleModule;
20
20
  'no-unsupported-drag-and-drop-libraries': import("eslint").Rule.RuleModule;
21
21
  'prefer-primitives': import("eslint").Rule.RuleModule;
22
+ 'use-button-group-label': import("eslint").Rule.RuleModule;
22
23
  'use-drawer-label': import("eslint").Rule.RuleModule;
23
24
  'use-heading-level-in-spotlight-card': import("eslint").Rule.RuleModule;
24
25
  'use-href-in-link-item': import("eslint").Rule.RuleModule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ export default rule;
@@ -19,6 +19,7 @@ export declare const configs: {
19
19
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
20
20
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
21
21
  '@atlaskit/design-system/prefer-primitives': string;
22
+ '@atlaskit/design-system/use-button-group-label': string;
22
23
  '@atlaskit/design-system/use-drawer-label': string;
23
24
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
24
25
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -40,6 +41,7 @@ export declare const configs: {
40
41
  '@atlaskit/design-system/no-unsafe-design-token-usage': string;
41
42
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
42
43
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
44
+ '@atlaskit/design-system/use-button-group-label': string;
43
45
  '@atlaskit/design-system/use-drawer-label': string;
44
46
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
45
47
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::6efa1e48692b3e287d6dfcd500a5f0ab>>
3
+ * @codegen <<SignedSource::d1a459e1ea71650f65b2890dc86cc398>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  declare const _default: {
@@ -22,6 +22,7 @@ declare const _default: {
22
22
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
23
23
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
24
24
  '@atlaskit/design-system/prefer-primitives': string;
25
+ '@atlaskit/design-system/use-button-group-label': string;
25
26
  '@atlaskit/design-system/use-drawer-label': string;
26
27
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
27
28
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::be810d87ec2d253e3b053dc06ff1b99a>>
3
+ * @codegen <<SignedSource::3b93cfbbe0ea14514b9600509632394b>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  declare const _default: {
@@ -17,6 +17,7 @@ declare const _default: {
17
17
  '@atlaskit/design-system/no-unsafe-design-token-usage': string;
18
18
  '@atlaskit/design-system/no-unsafe-style-overrides': string;
19
19
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': string;
20
+ '@atlaskit/design-system/use-button-group-label': string;
20
21
  '@atlaskit/design-system/use-drawer-label': string;
21
22
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': string;
22
23
  '@atlaskit/design-system/use-href-in-link-item': string;
@@ -23,6 +23,7 @@ declare const _default: {
23
23
  'no-unsafe-style-overrides': import("eslint").Rule.RuleModule;
24
24
  'no-unsupported-drag-and-drop-libraries': import("eslint").Rule.RuleModule;
25
25
  'prefer-primitives': import("eslint").Rule.RuleModule;
26
+ 'use-button-group-label': import("eslint").Rule.RuleModule;
26
27
  'use-drawer-label': import("eslint").Rule.RuleModule;
27
28
  'use-heading-level-in-spotlight-card': import("eslint").Rule.RuleModule;
28
29
  'use-href-in-link-item': import("eslint").Rule.RuleModule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ export default rule;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
3
  "description": "The essential plugin for use with the Atlassian Design System.",
4
- "version": "8.20.0",
4
+ "version": "8.21.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "publishConfig": {
7
7
  "registry": "https://registry.npmjs.org/"