diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 6a74b124..65a1261e 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,3 +1,5 @@ +const kongponentUtilityClasses = require('./kongponent-utility-classes.cjs') + module.exports = { root: true, parser: 'vue-eslint-parser', @@ -95,6 +97,7 @@ module.exports = { 'vue/no-deprecated-dollar-listeners-api': 'error', 'vue/no-deprecated-events-api': 'error', 'vue/no-deprecated-v-on-native-modifier': 'error', + 'vue/no-restricted-class': ['error', ...kongponentUtilityClasses], // a11y 'vuejs-accessibility/label-has-for': 'off', diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f692850f..a831421d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -30,11 +30,13 @@ updates: timezone: "Asia/Shanghai" target-branch: "main" allow: + - dependency-name: "@kong/design-tokens" - dependency-name: "@kong/kongponents" - dependency-name: "@kong-ui-public/*" - dependency-name: "@playwright/test" groups: kong-packages: patterns: + - "@kong/design-tokens" - "@kong/kongponents" - "@kong-ui-public/*" diff --git a/.github/workflows/.reusable_build.yml b/.github/workflows/.reusable_build.yml index f745e597..27c4be69 100644 --- a/.github/workflows/.reusable_build.yml +++ b/.github/workflows/.reusable_build.yml @@ -33,7 +33,7 @@ jobs: - name: Run lint timeout-minutes: 10 - run: yarn lint + run: yarn lint && yarn stylelint build-assets: name: Build assets diff --git a/.stylelintrc.cjs b/.stylelintrc.cjs new file mode 100644 index 00000000..cf00f8bd --- /dev/null +++ b/.stylelintrc.cjs @@ -0,0 +1,27 @@ +module.exports = { + extends: [ + 'stylelint-config-html', + 'stylelint-config-recommended-scss', + 'stylelint-config-recommended-vue/scss', + ], + overrides: [ + { + files: [ + 'src/**/*.{css,scss,sass,less,styl,vue}', + ], + rules: { + // Only allow @kong/design-tokens or `--kong-ui-*` CSS custom properties + 'custom-property-pattern': [ + '^(kui-|kong-ui-).+$', + { + message: "Expected custom property \"%s\" to have prefix '--kong-ui-' or be sourced from @kong/design-tokens with prefix '--kui-'", + }, + ], + 'custom-property-no-missing-var-function': true, + // Disable the following rules + 'no-descending-specificity': null, + 'scss/comment-no-empty': null + }, + }, + ], +} diff --git a/kongponent-utility-classes.cjs b/kongponent-utility-classes.cjs new file mode 100644 index 00000000..631bfb98 --- /dev/null +++ b/kongponent-utility-classes.cjs @@ -0,0 +1,288 @@ +// List of disallowed utility classes that are exported from Kongponents +// These classes **must not** be used in this repository +module.exports = [ + 'type-xxxl', + 'type-xxl', + 'type-xl', + 'type-lg', + 'type-md', + 'type-sm', + 'type-xs', + 'type-xxs', + 'mono', + 'color-blue-100', + 'color-blue-200', + 'color-blue-300', + 'color-blue-400', + 'color-blue-500', + 'color-blue-600', + 'color-blue-700', + 'color-petrol-100', + 'color-petrol-200', + 'color-purple-100', + 'color-purple-200', + 'color-purple-300', + 'color-purple-400', + 'color-steel-100', + 'color-steel-200', + 'color-steel-300', + 'color-steel-400', + 'color-steel-500', + 'color-steel-600', + 'color-steel-700', + 'color-red-100', + 'color-red-200', + 'color-red-300', + 'color-red-400', + 'color-red-500', + 'color-red-600', + 'color-red-700', + 'color-green-100', + 'color-green-200', + 'color-green-300', + 'color-green-400', + 'color-green-500', + 'color-green-600', + 'color-green-700', + 'color-teal-100', + 'color-teal-200', + 'color-teal-300', + 'color-teal-400', + 'color-teal-500', + 'color-yellow-100', + 'color-yellow-200', + 'color-yellow-300', + 'color-yellow-400', + 'color-yellow-500', + 'color-yellow-600', + 'color-grey-100', + 'color-grey-200', + 'color-grey-300', + 'color-grey-400', + 'color-grey-500', + 'color-grey-600', + 'color-black-85', + 'color-black-70', + 'color-black-45', + 'color-black-25', + 'color-black-10', + 'color-black-100', + 'color-black-200', + 'color-black-300', + 'color-black-400', + 'color-black-500', + 'color-white', + 'style-heading-1', + 'style-heading-2', + 'style-heading-3', + 'style-heading-4', + 'style-body-lg', + 'style-body-lg-bold', + 'style-body-md', + 'style-body-md-bold', + 'style-body-sm', + 'style-body-sm-bold', + 'style-body-tiny', + 'style-body-link', + 'style-body-bc', + 'style-body-code', + 'mx-auto', + 'my-auto', + 'ma-auto', + 'mx-0', + 'my-0', + 'ma-0', + 'px-auto', + 'py-auto', + 'pa-auto', + 'px-0', + 'py-0', + 'pa-0', + 'mt-auto', + 'mt-0', + 'mr-auto', + 'mr-0', + 'mb-auto', + 'mb-0', + 'ml-auto', + 'ml-0', + 'mt-1', + 'mr-1', + 'mb-1', + 'ml-1', + 'mx-1', + 'my-1', + 'ma-1', + 'mt-2', + 'mr-2', + 'mb-2', + 'ml-2', + 'mx-2', + 'my-2', + 'ma-2', + 'mt-3', + 'mr-3', + 'mb-3', + 'ml-3', + 'mx-3', + 'my-3', + 'ma-3', + 'mt-4', + 'mr-4', + 'mb-4', + 'ml-4', + 'mx-4', + 'my-4', + 'ma-4', + 'mt-5', + 'mr-5', + 'mb-5', + 'ml-5', + 'mx-5', + 'my-5', + 'ma-5', + 'mt-6', + 'mr-6', + 'mb-6', + 'ml-6', + 'mx-6', + 'my-6', + 'ma-6', + 'mt-7', + 'mr-7', + 'mb-7', + 'ml-7', + 'mx-7', + 'my-7', + 'ma-7', + 'mt-8', + 'mr-8', + 'mb-8', + 'ml-8', + 'mx-8', + 'my-8', + 'ma-8', + 'pt-0', + 'pr-0', + 'pb-0', + 'pl-0', + 'pt-1', + 'pr-1', + 'pb-1', + 'pl-1', + 'px-1', + 'py-1', + 'pa-1', + 'pt-2', + 'pr-2', + 'pb-2', + 'pl-2', + 'px-2', + 'py-2', + 'pa-2', + 'pt-3', + 'pr-3', + 'pb-3', + 'pl-3', + 'px-3', + 'py-3', + 'pa-3', + 'pt-4', + 'pr-4', + 'pb-4', + 'pl-4', + 'px-4', + 'py-4', + 'pa-4', + 'pt-5', + 'pr-5', + 'pb-5', + 'pl-5', + 'px-5', + 'py-5', + 'pa-5', + 'pt-6', + 'pr-6', + 'pb-6', + 'pl-6', + 'px-6', + 'py-6', + 'pa-6', + 'pt-7', + 'pr-7', + 'pb-7', + 'pl-7', + 'px-7', + 'py-7', + 'pa-7', + 'pt-8', + 'pr-8', + 'pb-8', + 'pl-8', + 'px-8', + 'py-8', + 'pa-8', + 'float-left', + 'float-right', + 'float-none', + 'truncate', + 'multi-line-truncation', + 'truncate-multi', + 'capitalize', + 'lowercase', + 'uppercase', + 'bold-500', + 'bold-600', + 'bold-700', + 'd-none', + 'd-inline', + 'd-inline-block', + 'd-block', + 'd-flex', + 'd-inline-flex', + 'flex-fill', + 'flex-row', + 'flex-column', + 'flex-row-reverse', + 'flex-column-reverse', + 'flex-grow-0', + 'flex-grow-1', + 'justify-content-start', + 'justify-content-end', + 'justify-content-center', + 'justify-content-between', + 'justify-content-around', + 'align-items-start', + 'align-items-end', + 'align-items-center', + 'align-items-baseline', + 'align-items-stretch', + 'align-content-start', + 'align-content-end', + 'align-content-center', + 'align-content-between', + 'align-content-around', + 'align-content-stretch', + 'align-self-auto', + 'align-self-start', + 'align-self-end', + 'align-self-center', + 'align-self-baseline', + 'align-self-stretch', + 'place-self-start', + 'place-self-center', + 'place-self-end', + 'cursor-pointer', + 'overflow-auto', + 'overflow-hidden', + 'w-25', + 'w-50', + 'w-75', + 'w-100', + 'w-auto', + 'h-100', + 'h-auto', + 'h-screen', + 'non-visual-button', + 'k-visually-hidden', +] diff --git a/package.json b/package.json index beec363a..81b3faae 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,12 @@ "playwright": "yarn --cwd tests/playwright run playwright", "preview": "vite build && vite preview", "lint": "eslint --ext .js,.vue,.ts src", + "stylelint": "stylelint --allow-empty-input 'src/**/*.{css,scss,sass,less,styl,vue}'", "postinstall": "husky install" }, "lint-staged": { - "src/**/*.{ts,js,vue}": "eslint --fix" + "src/**/*.{ts,js,vue}": "eslint --fix", + "src/**/*.{css,scss,sass,less,styl,vue}": "stylelint --allow-empty-input --fix 'src/**/*.{css,scss,sass,less,styl,vue}'" }, "dependencies": { "@kong-ui-public/app-layout": "^0.22.10", @@ -42,6 +44,7 @@ "vue-router": "^4.2.2" }, "devDependencies": { + "@kong/design-tokens": "^1.9.0", "@types/lodash-es": "^4.17.8", "@types/node": "^20.3.1", "@typescript-eslint/eslint-plugin": "^5.60.0", @@ -61,7 +64,12 @@ "lint-staged": "^13.2.2", "lodash-es": "^4.17.21", "rollup-plugin-visualizer": "^5.9.2", + "postcss-html": "^1.5.0", "sass": "^1.63.4", + "stylelint": "^15.10.2", + "stylelint-config-html": "^1.1.0", + "stylelint-config-recommended-scss": "^12.0.0", + "stylelint-config-recommended-vue": "^1.5.0", "typescript": "^5.1.3", "vite": "^4.3.9", "vite-plugin-html": "^3.2.0" diff --git a/src/components/EntityForm/ConfirmModalDialog.vue b/src/components/EntityForm/ConfirmModalDialog.vue index 66100a40..2f329bb4 100644 --- a/src/components/EntityForm/ConfirmModalDialog.vue +++ b/src/components/EntityForm/ConfirmModalDialog.vue @@ -17,7 +17,7 @@
diff --git a/src/components/EntityForm/EntityForm.vue b/src/components/EntityForm/EntityForm.vue index e9f60395..8bd41195 100644 --- a/src/components/EntityForm/EntityForm.vue +++ b/src/components/EntityForm/EntityForm.vue @@ -41,7 +41,7 @@ >
@@ -749,5 +749,12 @@ export default { display: none; } + .error-message { + margin-bottom: $kui-space-60; + } + + .button-confirm { + margin-right: $kui-space-40; + } } diff --git a/src/components/EntityForm/NativeEntityForm.vue b/src/components/EntityForm/NativeEntityForm.vue index 87e15da6..9527086b 100644 --- a/src/components/EntityForm/NativeEntityForm.vue +++ b/src/components/EntityForm/NativeEntityForm.vue @@ -27,7 +27,7 @@