Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
26fa227
added z-index soft scale
LinKCoding Jul 8, 2026
c01bd80
update eslint messages and desc
LinKCoding Jul 8, 2026
96635b0
updates to zIndex scale
LinKCoding Jul 8, 2026
4d0c25c
added a story
LinKCoding Jul 8, 2026
32cfd25
linting errors
LinKCoding Jul 8, 2026
83c108a
updated snapshots
LinKCoding Jul 8, 2026
715f4f0
add version plan
LinKCoding Jul 8, 2026
2b82038
update docs to reflect changes
LinKCoding Jul 10, 2026
a7d0445
updated naming to zIndexes
LinKCoding Jul 13, 2026
0c81fd4
removed unused import
LinKCoding Jul 13, 2026
1bf763f
updated snapshot
LinKCoding Jul 14, 2026
1899413
update snapshot
LinKCoding Jul 14, 2026
70f6985
remove recommended field in eslint
LinKCoding Jul 14, 2026
bcd1932
undo recommended removal
LinKCoding Jul 15, 2026
7b186c2
add test for selectdropdown menuportal
LinKCoding Jul 15, 2026
79b474e
update eslint mdx story
LinKCoding Jul 15, 2026
9743432
more linting fixes
LinKCoding Jul 16, 2026
b6c600e
updating selectdropdown default zindex
LinKCoding Jul 17, 2026
310a8ec
update zindex type for selectdropdown
LinKCoding Jul 17, 2026
a1d426f
add test for bodyportal
LinKCoding Jul 17, 2026
e23870c
start on zIndex revamp
LinKCoding Jul 21, 2026
09ccff4
2nd batch of zindex updates
LinKCoding Jul 21, 2026
1033bed
update variance to allow for raw values
LinKCoding Jul 21, 2026
a950e83
fix failing test
LinKCoding Jul 21, 2026
4c7bc9c
update version plan
LinKCoding Jul 21, 2026
894c21f
update eslintrc.js to use no-raw-zindex rule
LinKCoding Aug 4, 2026
02f4f53
add new zindex gamut skill and update zindex examples in skils
LinKCoding Aug 4, 2026
ae1f834
merge in main and fix merge conflict
LinKCoding Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
'gamut/prefer-themed': 'error',
'gamut/no-css-standalone': 'error',
'gamut/no-inline-style': 'error',
'gamut/no-raw-z-index': 'error',
'gamut/import-paths': 'error',
'import/no-extraneous-dependencies': 'off',
},
Expand Down
8 changes: 8 additions & 0 deletions .nx/version-plans/version-plan-1784663569372.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
eslint-plugin-gamut: minor
gamut-styles: major
variance: minor
gamut: major
---

Adding new zIndex scale to Gamut. Inclues a new eslint rule for avoiding raw z-index values. Allows variance scales to include raw values if need be.
2 changes: 2 additions & 0 deletions packages/eslint-plugin-gamut/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import gamutImportPaths from './gamut-import-paths';
import noCssStandalone from './no-css-standalone';
import noInlineStyle from './no-inline-style';
import noKbdElement from './no-kbd-element';
import noRawZIndex from './no-raw-z-index';
import preferThemed from './prefer-themed';
import recommended from './recommended';

Expand All @@ -10,6 +11,7 @@ const rules = {
'no-css-standalone': noCssStandalone,
'no-inline-style': noInlineStyle,
'no-kbd-element': noKbdElement,
'no-raw-z-index': noRawZIndex,
'prefer-themed': preferThemed,
};

Expand Down
55 changes: 55 additions & 0 deletions packages/eslint-plugin-gamut/src/no-raw-z-index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ESLintUtils } from '@typescript-eslint/utils';

import rule from './no-raw-z-index';

const ruleTester = new ESLintUtils.RuleTester({
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
});

ruleTester.run('no-raw-z-index', rule, {
valid: [
// Semantic tokens are the expected usage.
`const styles = { zIndex: zIndexes.modal };`,
`<Box zIndex={zIndexes.stickyHeader} />;`,
// Arithmetic on a token is allowed (e.g. Tip's shadow).
`const styles = { zIndex: zIndexes.foreground - 2 };`,
`<Box zIndex={zIndexes.modal + 5} />;`,
// Variables / non-literal expressions are not flagged.
`<Box zIndex={zIndex} />;`,
`const styles = { zIndex };`,
// Unrelated properties.
`const styles = { padding: 0 };`,
`<Box top={0} />;`,
],
invalid: [
{
code: `const styles = { zIndex: 1 };`,
errors: [{ messageId: 'noRawZIndex' }],
},
{
code: `const styles = { zIndex: 0 };`,
errors: [{ messageId: 'noRawZIndex' }],
},
{
code: `const styles = { zIndex: -1 };`,
errors: [{ messageId: 'noRawZIndex' }],
},
{
code: `const styles = { 'z-index': 100 };`,
errors: [{ messageId: 'noRawZIndex' }],
},
{
code: `<Box zIndex={2} />;`,
errors: [{ messageId: 'noRawZIndex' }],
},
{
code: `<Box zIndex={-1} />;`,
errors: [{ messageId: 'noRawZIndex' }],
},
],
});
62 changes: 62 additions & 0 deletions packages/eslint-plugin-gamut/src/no-raw-z-index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils';

import { createRule } from './createRule';

/**
* True for a numeric literal, including a negated one like `-1`.
*/
const isNumericLiteral = (node: TSESTree.Node | null | undefined): boolean => {
if (!node) return false;
if (node.type === AST_NODE_TYPES.Literal && typeof node.value === 'number') {
return true;
}
return (
node.type === AST_NODE_TYPES.UnaryExpression &&
(node.operator === '-' || node.operator === '+') &&
isNumericLiteral(node.argument)
);
};

const isZIndexKey = (key: TSESTree.Node): boolean =>
(key.type === AST_NODE_TYPES.Identifier && key.name === 'zIndex') ||
(key.type === AST_NODE_TYPES.Literal && key.value === 'zIndex') ||
(key.type === AST_NODE_TYPES.Literal && key.value === 'z-index');

export default createRule({
create(context) {
return {
// Style objects: `{ zIndex: 1 }` / `{ 'z-index': 1 }`
Property(node) {
if (isZIndexKey(node.key) && isNumericLiteral(node.value)) {
context.report({ messageId: 'noRawZIndex', node: node.value });
}
},
// JSX props: `<Box zIndex={1} />`
JSXAttribute(node) {
if (
node.name.type === AST_NODE_TYPES.JSXIdentifier &&
node.name.name === 'zIndex' &&
node.value?.type === AST_NODE_TYPES.JSXExpressionContainer &&
isNumericLiteral(node.value.expression as TSESTree.Node)
) {
context.report({ messageId: 'noRawZIndex', node: node.value });
}
},
};
},
defaultOptions: [],
meta: {
docs: {
description:
'Discourage raw numeric z-index values which can lead to z-index stacking issues and encourage usage of semantic tokens from the `zIndexes` scale.',
recommended: 'error',
},
messages: {
noRawZIndex:
'Semantic tokens from the `zIndexes` scale (e.g. `zIndexes.modal`) are recommendedinstead of a raw z-index number. For a deliberate in-between value, disable this rule inline with a justifying comment.',
},
type: 'suggestion',
schema: [],
},
name: 'no-raw-z-index',
});
1 change: 1 addition & 0 deletions packages/eslint-plugin-gamut/src/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export default {
rules: {
'gamut/no-css-standalone': 'error',
'gamut/no-inline-style': 'error',
'gamut/no-raw-z-index': 'error',
'gamut/prefer-themed': 'off',
'gamut/gamut-import-paths': 'error',
},
Expand Down
Loading
Loading