@atlaskit/eslint-plugin-design-system 4.16.5 → 4.17.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
+ ## 4.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`c80505045f0`](https://bitbucket.org/atlassian/atlassian-frontend/commits/c80505045f0) - Added new rule to encourage use of @atlaskit/primitives components where relavant. Currently disabled by default, so there should be no expected change to consumers.
8
+
3
9
  ## 4.16.5
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,46 @@
1
+ ---
2
+ order: 2
3
+ ---
4
+
5
+ This plugin contains rules that should be used with the Atlassian Design System.
6
+ Where possible, these rules come with auto fixers.
7
+
8
+ You can read more about configuring ESLint in their [documentation](https://eslint.org/docs/user-guide/configuring).
9
+
10
+ ## Configuration
11
+
12
+ Add the plugin to your `.eslintrc.js` file.
13
+
14
+ ```diff
15
+ module.exports = {
16
+ plugins: [
17
+ + '@atlaskit/design-system',
18
+ ],
19
+ };
20
+ ```
21
+
22
+ Extend the configuration file.
23
+
24
+ ```diff
25
+ module.exports = {
26
+ extends: [
27
+ + 'plugin:@atlaskit/design-system/recommended',
28
+ ],
29
+ };
30
+ ```
31
+
32
+ Enable any desired rules. The rules shown below are strongly recommended.
33
+
34
+ ```diff
35
+ module.exports = {
36
+ rules: {
37
+ + '@atlaskit/design-system/ensure-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
38
+ + '@atlaskit/design-system/ensure-design-token-usage-spacing': 'error',
39
+ + '@atlaskit/design-system/no-deprecated-design-token-usage': 'warn',
40
+ + '@atlaskit/design-system/no-unsafe-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
41
+ + '@atlaskit/design-system/use-visually-hidden': 'error',
42
+ + '@atlaskit/design-system/no-deprecated-imports': 'error',
43
+ + '@atlaskit/design-system/no-deprecated-apis': 'error'
44
+ }
45
+ };
46
+ ```
@@ -1,45 +1,390 @@
1
1
  ---
2
- order: 2
2
+ order: 0
3
3
  ---
4
4
 
5
- This plugin contains rules that should be used with the Atlassian Design System.
6
- Where possible, these rules come with auto fixers.
5
+ import SectionMessage from '@atlaskit/section-message';
7
6
 
8
- You can read more about configuring ESLint in their [documentation](https://eslint.org/docs/user-guide/configuring).
7
+ <SectionMessage
8
+ title="A new color system, design tokens, and themes are coming soon"
9
+ appearance="warning"
10
+ >
11
+ <p>
12
+ This ESLint plugin includes rules to help you use <a href="/foundations/design-tokens">design tokens</a>, which will soon be the new way to apply color and spacing values.
13
+ <br/><br/>Do not use the design token-related rules until design tokens are available for you to adopt.
14
+ </p>
15
+ </SectionMessage>
9
16
 
10
- ## Configuration
17
+ Design tokens are supported by linting rules, which warn you if a token is deprecated, missing, or has no fallback style. Design token lint rules are provided by the Design System ESLint and <a href="/components/stylelint-design-system/usage">Stylelint plugins</a>.
11
18
 
12
- Add the plugin to your `.eslintrc.js` file.
19
+ If you are an Atlassian employee, you must configure the lint rule in your repository and keep it up-to-date. If you are a partner developer, we strongly recommend you to use it as well.
13
20
 
14
- ```diff
15
- module.exports = {
16
- plugins: [
17
- + '@atlaskit/design-system',
18
- ],
19
- };
21
+ Follow the <a href="/get-started/develop/using-tokens-in-code#eslint-plugin">Get started</a> guide to get started with Design Tokens, and set up the ESLint plugin.
22
+
23
+ ## ensure-design-token-usage
24
+
25
+ Ensures that the codebase uses the global `token` function for colors, rather than hard-coded values. This ruleset is great for codebases that are starting to adopt color tokens and those that have already adopted color tokens. This ruleset also prevents new contributors from accidentally adding hard-coded color values.
26
+
27
+ <h3 id="ensure-design-token-usage-do">Do</h3>
28
+
29
+ Use the global `token` function, and design tokens.
30
+
31
+ ```jsx
32
+ import { token } from '@atlaskit/tokens';
33
+
34
+ css({
35
+ boxShadow: token('elevation.shadow.card'),
36
+ });
37
+ ```
38
+
39
+ ```jsx
40
+ import { token } from '@atlaskit/tokens';
41
+
42
+ css`
43
+ color: ${token('color.text.highemphasis')};
44
+ `;
45
+ ```
46
+
47
+ <h3 id="ensure-design-token-usage-dont">Don't</h3>
48
+
49
+ Don't use hard-coded values, such as hexadecimal, CSS colors, or base color values.
50
+
51
+ ```jsx
52
+ css({
53
+ color: 'red',
54
+ ^^^
55
+ });
56
+ ```
57
+
58
+ ```jsx
59
+ css({
60
+ boxShadow: '0px 1px 1px #161A1D32',
61
+ ^^^^^^^^^
62
+ })
63
+ ```
64
+
65
+ ```jsx
66
+ import { e100 } from '@atlaskit/theme/elevation';
67
+
68
+ css`
69
+ ${e100};
70
+ ^^^^
71
+ `;
72
+ ```
73
+
74
+ ```jsx
75
+ import { B100 } from '@atlaskit/theme/colors';
76
+
77
+ css({
78
+ color: B100,
79
+ ^^^^
80
+ });
81
+ ```
82
+
83
+ ## ensure-design-token-usage-spacing
84
+
85
+ Ensures that the codebase uses the global `token` function for spacing, rather than hard-coded values. This ruleset is great for codebases that are starting to adopt space tokens and those that have already adopted space tokens. This ruleset also prevents new contributors from accidentally adding hard-coded space values.
86
+
87
+ <h3 id="ensure-design-token-usage-spacing-do">Do</h3>
88
+
89
+ Use the global `token` function, and design tokens.
90
+
91
+ ```jsx
92
+ import { token } from '@atlaskit/tokens';
93
+
94
+ css({
95
+ padding: token('space.200'),
96
+ });
97
+ ```
98
+
99
+ ```jsx
100
+ import { token } from '@atlaskit/tokens';
101
+
102
+ css`
103
+ gap: ${token('space.100')};
104
+ `;
105
+ ```
106
+
107
+ <h3 id="ensure-design-token-usage-spacing-dont">Don't</h3>
108
+
109
+ Don't use hard-coded values, such as pixel values, relative units, or legacy `gridSize` functions.
110
+
111
+ ```jsx
112
+ css({
113
+ padding: '8px',
114
+ ^^^
115
+ });
116
+ ```
117
+
118
+ ```jsx
119
+ css({
120
+ paddingLeft: gridSize(),
121
+ ^^^^^^^^^^
122
+ })
123
+ ```
124
+
125
+ ## no-deprecated-design-token-usage
126
+
127
+ Will catch deprecated token usage and autofix a replacement.
128
+
129
+ It's recommended to set this rule to "warn" on error to allow for new and old tokens to exist side-by-side for the duration of the deprecation period and avoid big-bang migrations.
130
+
131
+ Once the deprecation period is over for a token, it will be moved into a `deleted` state, at which point the counterpart of this rule `eslint-plugin-design-system/no-unsafe-design-token-usage` will begin to throw errors.
132
+
133
+ Run `eslint --fix` to automatically apply replacement tokens.
134
+
135
+ <h3 id="no-deprecated-design-token-usage-dont">Don't</h3>
136
+
137
+ Don't use deprecated tokens.
138
+
139
+
140
+ ```jsx
141
+ import { token } from '@atlaskit/tokens';
142
+
143
+ css({
144
+ color: token('i.am.deprecated'), // will warn on deprecated tokens
145
+ });
146
+ ```
147
+
148
+
149
+ ## no-unsafe-design-token-usage
150
+
151
+ Ensures usages of the `token` function are done correctly, so that current token names are being used, and the resulting `var(--some-token)` statements aren't being used. This ruleset is great for codebases that have already adopted tokens.
152
+
153
+ <h3 id="no-unsafe-design-token-usage-do">Do</h3>
154
+
155
+ Use the `token` function and token naming functions correctly.
156
+
157
+ ```jsx
158
+ import { token } from '@atlaskit/tokens';
159
+
160
+ css({
161
+ boxShadow: token('elevation.shadow.card'),
162
+ });
163
+ ```
164
+
165
+ ```jsx
166
+ import { token } from '@atlaskit/tokens';
167
+
168
+ css`
169
+ color: ${(token('color.text.highemphasis'), N20)};
170
+ `;
171
+ ```
172
+
173
+ <h3 id="no-unsafe-design-token-usage-dont">Don't</h3>
174
+
175
+ Don’t use outdated token names, or use tokens without the `token` function.
176
+
177
+
178
+ ```jsx
179
+ const textColor = 'red';
180
+
181
+ css({
182
+ color: textColor,
183
+ ^^^^^^^^^
184
+ });
20
185
  ```
21
186
 
22
- Extend the configuration file.
187
+ ```jsx
188
+ css({
189
+ boxShadow: '0px 1px 1px var(--ds-accent-subtleBlue)',
190
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
191
+ })
192
+ ```
193
+
194
+ ## icon-label
195
+
196
+ Enforces accessible usage of icon labels when composed with other Design System components.
197
+
198
+ <h3 id="icon-label-do">Do</h3>
199
+
200
+ Use the icon label prop to ensure accessibility of Design System icons.
201
+
202
+
203
+ ```jsx
204
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
23
205
 
24
- ```diff
25
- module.exports = {
26
- extends: [
27
- + 'plugin:@atlaskit/design-system/recommended',
28
- ],
29
- };
206
+ <ActivityIcon label="Activity">
30
207
  ```
31
208
 
32
- Enable any desired rules. The rules shown below are strongly recommended.
209
+ ```jsx
210
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
33
211
 
34
- ```diff
35
- module.exports = {
36
- rules: {
37
- + '@atlaskit/design-system/ensure-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
38
- + '@atlaskit/design-system/no-deprecated-design-token-usage': 'warn',
39
- + '@atlaskit/design-system/no-unsafe-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
40
- + '@atlaskit/design-system/use-visually-hidden': 'error',
41
- + '@atlaskit/design-system/no-deprecated-imports': 'error',
42
- + '@atlaskit/design-system/no-deprecated-apis': 'error'
43
- }
44
- };
212
+ <Button iconLeft={<ActivityIcon label="Activity">} />
45
213
  ```
214
+
215
+ ```jsx
216
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
217
+
218
+ <ButtonItem iconBefore={<ActivityIcon label="">}>
219
+ My activity
220
+ </ButtonItem>
221
+ ```
222
+
223
+ <h3 id="icon-label-dont">Don't</h3>
224
+
225
+ Don't ignore labels for icons.
226
+
227
+
228
+ ```jsx
229
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
230
+
231
+ <ActivityIcon>
232
+ ^^^^^^^^^^^^^^ missing `label` prop
233
+ ```
234
+
235
+ ```jsx
236
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
237
+
238
+ <Button iconLeft={<ActivityIcon label="">} />
239
+ ^^^^^ label should be defined
240
+ ```
241
+
242
+ ```jsx
243
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
244
+
245
+ <ButtonItem iconBefore={<ActivityIcon label="">}>
246
+ ^^^^^ label should not be defined
247
+ My activity
248
+ </ButtonItem>
249
+ ```
250
+
251
+ ## no-banned-imports
252
+
253
+ Prevents usage of private or experimental Atlassian Design System packages.
254
+
255
+ <h3 id="no-banned-imports-dont">Don't</h3>
256
+
257
+ Don't import or use private or experimental ADS packages.
258
+
259
+ ```ts
260
+ import noop from '@atlaskit/ds-lib/noop';
261
+ ^^^^^^^^^^^^^^^^^^^^^
262
+ ```
263
+
264
+ ```ts
265
+ import { Text } from '@atlaskit/ds-explorations';
266
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
267
+ ```
268
+
269
+ ## no-deprecated-api-usage
270
+
271
+ Ensures usage of current Atlassian Design System APIs.
272
+
273
+ <h3 id="no-deprecated-api-usage-do">Do</h3>
274
+
275
+ ```jsx
276
+ import { SomeElement } from 'some-other-library';
277
+
278
+ const Element = () => <SomeElement cssFn={cssFn()} />;
279
+ ```
280
+
281
+ ```jsx
282
+ import { ButtonItem } from '@atlaskit/menu';
283
+
284
+ const Element = () => <ButtonItem />;
285
+ ```
286
+
287
+ ```jsx
288
+ import Drawer from '@atlaskit/drawer';
289
+
290
+ const Element = () => <Drawer />;
291
+ ```
292
+
293
+ <h3 id="no-deprecated-api-usage-dont">Don't</h3>
294
+
295
+ ```jsx
296
+ import { ButtonItem } from '@atlaskit/menu';
297
+
298
+ const Element = () => (
299
+ <ButtonItem cssFn={cssFn()} />
300
+ ^^^^
301
+ );
302
+ ```
303
+
304
+ ```jsx
305
+ import Drawer from '@atlaskit/drawer';
306
+
307
+ const Element = () => (
308
+ <Drawer overrides={overrides} />
309
+ ^^^^^^^^^
310
+ );
311
+ ```
312
+
313
+
314
+ ## no-deprecated-imports
315
+
316
+ Ensures usage of current Atlassian Design System dependencies.
317
+
318
+ <h3 id="no-deprecated-imports-do">Do</h3>
319
+
320
+ ```ts
321
+ import Modal from '@atlaskit/modal-dialog';
322
+ ```
323
+
324
+ ```ts
325
+ import { ButtonItem } from '@atlaskit/menu';
326
+ ```
327
+
328
+ <h3 id="no-deprecated-imports-dont">Don't</h3>
329
+
330
+ ```ts
331
+ import Item from '@atlaskit/item';
332
+ ^^^^^^^^^^^^^^
333
+ ```
334
+
335
+ ```ts
336
+ import GlobalNav from '@atlaskit/global-navigation';
337
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
338
+ ```
339
+
340
+ ## use-visually-hidden
341
+
342
+ This rule makes Design System consumers aware of existing solutions.
343
+
344
+ <h3 id="use-visually-hidden-do">Do</h3>
345
+
346
+ ```jsx
347
+ import VisuallyHidden from '@atlaskit/visually-hidden';
348
+ ```
349
+
350
+ <h3 id="use-visually-hidden-dont">Don't</h3>
351
+
352
+ ```jsx
353
+ import { css } from '@emotion/core';
354
+
355
+ const visuallyHiddenStyles = css({
356
+ width: '1px',
357
+ height: '1px',
358
+ padding: '0',
359
+ position: 'absolute',
360
+ border: '0',
361
+ clip: 'rect(1px, 1px, 1px, 1px)',
362
+ overflow: 'hidden',
363
+ whiteSpace: 'nowrap',
364
+ });
365
+ ^^^^
366
+ ```
367
+
368
+ ```jsx
369
+ import styled from '@emotion/styled';
370
+
371
+ const VisuallyHidden = styled.span`
372
+ width: 1px;
373
+ height: 1px;
374
+ padding: 0;
375
+ position: absolute;
376
+ border: 0;
377
+ clip: rect(1px, 1px, 1px, 1px);
378
+ overflow: hidden;
379
+ whiteSpace: nowrap;
380
+ `;
381
+ ^^^^
382
+ ```
383
+
384
+ ```jsx
385
+ import { visuallyHidden } from '@atlaskit/theme/constants';
386
+
387
+ const VisuallyHidden = styled.span`${visuallyHidden()}`;
388
+ ^^^^^^^^^^^^^^
389
+ ```
390
+
package/dist/cjs/index.js CHANGED
@@ -20,6 +20,7 @@ var _noDeprecatedApis = _interopRequireDefault(require("./rules/no-deprecated-ap
20
20
  var _noDeprecatedDesignTokenUsage = _interopRequireDefault(require("./rules/no-deprecated-design-token-usage"));
21
21
  var _noDeprecatedImports = _interopRequireDefault(require("./rules/no-deprecated-imports"));
22
22
  var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./rules/no-unsafe-design-token-usage"));
23
+ var _usePrimitives = _interopRequireDefault(require("./rules/use-primitives"));
23
24
  var _useVisuallyHidden = _interopRequireDefault(require("./rules/use-visually-hidden"));
24
25
  var _filterActionableDeprecations = require("./rules/no-deprecated-apis/helpers/filter-actionable-deprecations");
25
26
  var rules = {
@@ -31,7 +32,8 @@ var rules = {
31
32
  'no-banned-imports': _noBannedImports.default,
32
33
  'no-unsafe-design-token-usage': _noUnsafeDesignTokenUsage.default,
33
34
  'use-visually-hidden': _useVisuallyHidden.default,
34
- 'ensure-design-token-usage-spacing': _ensureDesignTokenUsageSpacing.default
35
+ 'ensure-design-token-usage-spacing': _ensureDesignTokenUsageSpacing.default,
36
+ 'use-primitives': _usePrimitives.default
35
37
  };
36
38
  exports.rules = rules;
37
39
  var configs = {
@@ -0,0 +1,109 @@
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 _utils = require("./utils");
9
+ var boxDocsUrl = 'https://atlassian.design/components/primitves/box/examples';
10
+ var inlineDocsUrl = 'https://atlassian.design/components/primitves/inline/examples';
11
+ var stackDocsUrl = 'https://atlassian.design/components/primitves/stack/examples';
12
+ var rule = {
13
+ meta: {
14
+ type: 'suggestion',
15
+ fixable: 'code',
16
+ docs: {
17
+ description: 'UI components should use primitives where possible.',
18
+ recommended: true
19
+ },
20
+ messages: {
21
+ preferPrimitivesBox: "This \"{{element}}\" may be able to be replaced with a \"Box\". See ".concat(boxDocsUrl, " for guidance."),
22
+ preferPrimitivesInline: "This \"{{element}}\" may be able to be replaced with an \"Inline\". See ".concat(inlineDocsUrl, " for guidance."),
23
+ preferPrimitivesStack: "This \"{{element}}\" may be able to be replaced with a \"Stack\". See ".concat(stackDocsUrl, " for guidance.")
24
+ },
25
+ schema: [{
26
+ type: 'object',
27
+ properties: {
28
+ exclude: {
29
+ type: ['string', 'array'],
30
+ items: {
31
+ type: 'string'
32
+ }
33
+ }
34
+ },
35
+ additionalProperties: false
36
+ }]
37
+ },
38
+ create: function create(context) {
39
+ return {
40
+ /**
41
+ * Traverse file
42
+ * Look for any JSX opening element and check what it is
43
+ * a) it's already a component
44
+ * b) it's native HTML
45
+ *
46
+ * if b) suggest alternative use of primitives
47
+ */
48
+ JSXOpeningElement: function JSXOpeningElement(node) {
49
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXOpeningElement')) {
50
+ return;
51
+ }
52
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.name, 'JSXIdentifier')) {
53
+ return;
54
+ }
55
+ var suggestBox = (0, _utils.shouldSuggestBox)(node === null || node === void 0 ? void 0 : node.parent // context.getScope(),
56
+ );
57
+ var suggestInline = (0, _utils.shouldSuggestInline)(node === null || node === void 0 ? void 0 : node.parent, context);
58
+ var suggestStack = (0, _utils.shouldSuggestStack)(node === null || node === void 0 ? void 0 : node.parent, context);
59
+
60
+ // const suggestText = shouldSuggestText(
61
+ // node?.parent as any,
62
+ // // context.getScope(),
63
+ // );
64
+
65
+ if (suggestBox) {
66
+ context.report({
67
+ node: node,
68
+ messageId: 'preferPrimitivesBox',
69
+ data: {
70
+ element: node.name.name
71
+ },
72
+ suggest: [{
73
+ desc: "Convert to Box",
74
+ fix: (0, _utils.primitiveFixer)(node, 'Box', context)
75
+ }]
76
+ });
77
+ }
78
+ if (suggestInline) {
79
+ context.report({
80
+ node: node,
81
+ messageId: 'preferPrimitivesInline',
82
+ data: {
83
+ element: node.name.name
84
+ },
85
+ suggest: [{
86
+ desc: "Convert to Inline",
87
+ fix: (0, _utils.primitiveFixer)(node, 'Inline', context)
88
+ }]
89
+ });
90
+ }
91
+ if (suggestStack) {
92
+ context.report({
93
+ node: node,
94
+ messageId: 'preferPrimitivesStack',
95
+ data: {
96
+ element: node.name.name
97
+ },
98
+ suggest: [{
99
+ desc: "Convert to Stack",
100
+ fix: (0, _utils.primitiveFixer)(node, 'Stack', context)
101
+ }]
102
+ });
103
+ }
104
+ }
105
+ };
106
+ }
107
+ };
108
+ var _default = rule;
109
+ exports.default = _default;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });