Skip to content

Commit

Permalink
feat: Adds negative z-index rule to stylelint (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
orangevolon authored Nov 14, 2024
1 parent 9d4dc30 commit a88fceb
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
63 changes: 63 additions & 0 deletions src/stylelint/__tests__/z-index-value-constraint.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { describe, test, expect } from "vitest";
import stylelint from "stylelint";

import { configBasedir } from "./common.js";

// This is for prettier format: https://github.com/prettier/prettier/issues/2330
// String.raw is an identity function in this context
const css = String.raw;

function runPlugin(code) {
return stylelint.lint({
code,
configBasedir,
config: {
plugins: ["../z-index-value-constraint.js"],
rules: {
"@cloudscape-design/z-index-value-constraint": [true],
},
},
});
}

describe("z-index value contstraint rule", () => {
test("allows non integer z-index values", async () => {
const result = await runPlugin(css`
.styled-circle-motion {
@include styles.with-motion {
z-index: some.$variable;
}
}
`);

expect(result.errored).toBe(false);
});

test.each([0, 1000])("allows non negative z-index values: %s", async zIndexValue => {
const result = await runPlugin(css`
.styled-circle-motion {
@include styles.with-motion {
z-index: ${zIndexValue};
}
}
`);

expect(result.errored).toBe(false);
});

test("does not allow negative z-index values", async () => {
const result = await runPlugin(css`
.styled-circle-motion {
@include styles.with-motion {
z-index: -10;
}
}
`);

expect(result.errored).toBe(true);
expect(result.results[0].warnings[0].text).toBe(`Avoid using negative z-index values: -10.
This can cause the element to disappear behind its container's background color. (@cloudscape-design/z-index-value-constraint)`);
});
});
3 changes: 2 additions & 1 deletion src/stylelint/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
import licenseHeaders from "./license-headers.js";
import noImplicitDescendant from "./no-implicit-descendant.js";
import noMotionOutsideOfMixin from "./no-motion-outside-of-mixin.js";
import zIndexValueConstraint from "./z-index-value-constraint.js";

export default [noImplicitDescendant, noMotionOutsideOfMixin, licenseHeaders];
export default [noImplicitDescendant, noMotionOutsideOfMixin, licenseHeaders, zIndexValueConstraint];
43 changes: 43 additions & 0 deletions src/stylelint/z-index-value-constraint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import stylelint from "stylelint";

const ruleName = "@cloudscape-design/z-index-value-constraint";

const messages = stylelint.utils.ruleMessages(ruleName, {
noNegativeZIndex: zIndexValue => {
return `Avoid using negative z-index values: ${zIndexValue}.
This can cause the element to disappear behind its container's background color.`;
},
});

function zIndexValueConstraint(enabled) {
if (!enabled) {
return;
}

return function (root, result) {
root.walkDecls(function (decl) {
if (decl.prop !== "z-index") return;

const zIndexValue = Number(decl.value);

// If the z-index value is not a number (e.g. variable), don't throw an error.
if (Number.isNaN(zIndexValue)) return;

if (zIndexValue < 0) {
stylelint.utils.report({
result,
ruleName,
message: messages.noNegativeZIndex(zIndexValue),
node: decl,
});
}
});
};
}

zIndexValueConstraint.ruleName = ruleName;
zIndexValueConstraint.messages = messages;

export default stylelint.createPlugin(ruleName, zIndexValueConstraint);

0 comments on commit a88fceb

Please sign in to comment.