diff --git a/.prettierrc b/.prettierrc index 75af443ba3..96f9e2239d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,16 +1,22 @@ { - "trailingComma": "es5", - "tabWidth": 4, - "semi": true, - "singleQuote": false, - "bracketSpacing": true, - "arrowParens": "always", - "overrides": [ - { - "files": ".github/**/*.yml", - "options": { - "tabWidth": 2 - } - } - ] -} \ No newline at end of file + "trailingComma": "es5", + "tabWidth": 4, + "semi": true, + "singleQuote": false, + "bracketSpacing": true, + "arrowParens": "always", + "overrides": [ + { + "files": "**/*.styles.ts", + "options": { + "printWidth": 120 + } + }, + { + "files": ".github/**/*.yml", + "options": { + "tabWidth": 2 + } + } + ] +} diff --git a/.stylelintignore b/.stylelintignore index ece8d76393..85096a2d4d 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -1,3 +1,4 @@ node_modules dist -*/coverage/lcov-report \ No newline at end of file +*/coverage/lcov-report +playwright-report \ No newline at end of file diff --git a/.stylelintrc.json b/.stylelintrc.json deleted file mode 100644 index 47b5149e3c..0000000000 --- a/.stylelintrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": ["stylelint-config-standard", "stylelint-config-recess-order"], - "plugins": ["@stylistic/stylelint-plugin"], - "rules": { - "declaration-block-no-duplicate-properties": true, - "no-descending-specificity": true, - "selector-max-id": 0, - "custom-property-empty-line-before": "never", - "color-hex-length": "long", - - "@stylistic/color-hex-case": "upper", - "@stylistic/indentation": 4, - "@stylistic/max-empty-lines": 1 - } -} diff --git a/.vscode/settings.json b/.vscode/settings.json index 8310dc83ef..e21320e41c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,7 +16,15 @@ "typescript", "typescriptreact" ], - "stylelint.validate": ["css", "postcss", "scss", "less"], + "stylelint.validate": [ + "css", + "postcss", + "scss", + "less", + "typescript", + "typescriptreact" + ], + "stylelint.configFile": "${workspaceFolder}/stylelint.config.mjs", "auto-close-tag.activationOnLanguage": [ "html", "javascriptreact", diff --git a/e2e/nextjs-app/eslint.config.mjs b/e2e/nextjs-app/eslint.config.mjs index ec2aaf6e26..6328e15108 100644 --- a/e2e/nextjs-app/eslint.config.mjs +++ b/e2e/nextjs-app/eslint.config.mjs @@ -1,7 +1,7 @@ import { defineConfig, globalIgnores } from "eslint/config"; import nextVitals from "eslint-config-next/core-web-vitals"; import nextTs from "eslint-config-next/typescript"; -import localRules from "../../eslint-local-rules/import-path-preferences.mjs"; +import localRules from "../../eslint-local-rules/index.mjs"; const eslintConfig = defineConfig([ ...nextVitals, diff --git a/eslint-local-rules/import-path-preferences.mjs b/eslint-local-rules/import-path-preferences.rule.mjs similarity index 74% rename from eslint-local-rules/import-path-preferences.mjs rename to eslint-local-rules/import-path-preferences.rule.mjs index 6cb224c824..b7b0c67a95 100644 --- a/eslint-local-rules/import-path-preferences.mjs +++ b/eslint-local-rules/import-path-preferences.rule.mjs @@ -13,7 +13,6 @@ const RELATIVE_STORYBOOK_COMMON_PATTERN = const SRC_IN_STORIES_OR_TESTS_PATTERN = /^(?:\.\.\/)+src(?:\/|$)/; const STORYBOOK_COMMON_IN_STORIES_PATTERN = /^(?:(?:\.\.\/)+|\.\/)storybook-common(?:\/|$)/; -const SAME_DIR_STYLE_MODULE_IMPORT_PATTERN = /^\.\/[^/]+\.styles$/; function normalizePath(filePath) { return filePath.replaceAll("\\", "/"); @@ -40,20 +39,6 @@ function getQuote(rawSource) { return quote === "'" || quote === '"' ? quote : '"'; } -function getStyleNamespaceLocalName(node) { - const namespaceSpecifier = node.specifiers.find( - (specifier) => specifier.type === "ImportNamespaceSpecifier" - ); - if (namespaceSpecifier) return namespaceSpecifier.local.name; - - const defaultSpecifier = node.specifiers.find( - (specifier) => specifier.type === "ImportDefaultSpecifier" - ); - if (defaultSpecifier) return defaultSpecifier.local.name; - - return "styles"; -} - function toKebabCase(value) { return value .replaceAll(/([a-z0-9])([A-Z])/g, "$1-$2") @@ -201,7 +186,7 @@ function getMessageId(zone, importSource) { return null; } -const importPathPreferencesRule = { +export const importPathPreferencesRule = { meta: { type: "suggestion", docs: { @@ -259,64 +244,3 @@ const importPathPreferencesRule = { }; }, }; - -const styleNamespaceImportRule = { - meta: { - type: "suggestion", - docs: { - description: - "Enforce namespace imports for style modules (*.styles).", - }, - fixable: "code", - schema: [], - messages: { - namespaceStyleImport: - "Import style modules using a namespace import (e.g. import * as styles from './component.styles').", - }, - }, - create(context) { - return { - ImportDeclaration(node) { - if (!node?.source || typeof node.source.value !== "string") { - return; - } - - const importSource = node.source.value; - if (!SAME_DIR_STYLE_MODULE_IMPORT_PATTERN.test(importSource)) { - return; - } - - // Type-only imports are ignored to avoid rewriting TS type flows. - if (node.importKind === "type") return; - - // Side-effect imports are allowed (no bindings to enforce). - if (!node.specifiers.length) return; - - const hasOnlyNamespaceSpecifiers = node.specifiers.every( - (specifier) => specifier.type === "ImportNamespaceSpecifier" - ); - if (hasOnlyNamespaceSpecifiers) return; - - context.report({ - node, - messageId: "namespaceStyleImport", - // TODO: Autofix is disabled until linaria migration is complete. - - // fix(fixer) { - // const quote = getQuote(node.source.raw); - // const localName = getStyleNamespaceLocalName(node); - // const fixedImport = `import * as ${localName} from ${quote}${importSource}${quote};`; - // return fixer.replaceText(node, fixedImport); - // }, - }); - }, - }; - }, -}; - -export default { - rules: { - "import-path-preferences": importPathPreferencesRule, - "style-namespace-import": styleNamespaceImportRule, - }, -}; diff --git a/eslint-local-rules/index.mjs b/eslint-local-rules/index.mjs new file mode 100644 index 0000000000..c9e6225b16 --- /dev/null +++ b/eslint-local-rules/index.mjs @@ -0,0 +1,11 @@ +import { importPathPreferencesRule } from "./import-path-preferences.rule.mjs"; +import { noNegativeLinariaInterpolationRule } from "./no-negative-linaria-interpolation.rule.mjs"; +import { styleNamespaceImportRule } from "./style-namespace-import.rule.mjs"; + +export default { + rules: { + "import-path-preferences": importPathPreferencesRule, + "style-namespace-import": styleNamespaceImportRule, + "no-negative-linaria-interpolation": noNegativeLinariaInterpolationRule, + }, +}; diff --git a/eslint-local-rules/no-negative-linaria-interpolation.rule.mjs b/eslint-local-rules/no-negative-linaria-interpolation.rule.mjs new file mode 100644 index 0000000000..a7519151f2 --- /dev/null +++ b/eslint-local-rules/no-negative-linaria-interpolation.rule.mjs @@ -0,0 +1,81 @@ +export const noNegativeLinariaInterpolationRule = { + meta: { + type: "problem", + docs: { + description: + "Disallow negative Linaria interpolations like -${token} in css templates.", + }, + fixable: "code", + schema: [], + messages: { + negativeLinariaInterpolation: + "Avoid -${...} in Linaria css templates. Use calc(${...} * -1) instead.", + }, + }, + create(context) { + return { + TaggedTemplateExpression(node) { + // Only lint Linaria `css` tagged template literals. + if ( + node.tag.type !== "Identifier" || + node.tag.name !== "css" || + node.quasi.type !== "TemplateLiteral" + ) { + return; + } + + const template = node.quasi; + for (let i = 0; i < template.expressions.length; i += 1) { + const beforeExpression = template.quasis[i]?.value?.raw; + if (!beforeExpression) continue; + + // Detect patterns like `...: -${token};` where unary minus is + // applied before interpolation and compiles to invalid CSS values. + const negativePrefixMatch = beforeExpression.match(/-\s*$/); + if (negativePrefixMatch) { + const beforeMinus = beforeExpression.slice( + 0, + beforeExpression.length - + negativePrefixMatch[0].length + ); + const previousNonWhitespace = + beforeMinus.match(/\S\s*$/)?.[0]?.trim() || ""; + + // Only flag unary negatives like `: -${x}` or `(-${x}`. + // Skip binary subtraction contexts like `100% - ${x}`. + if ( + previousNonWhitespace && + ![":", "(", ","].includes(previousNonWhitespace) + ) { + continue; + } + + context.report({ + node: template.expressions[i], + messageId: "negativeLinariaInterpolation", + fix(fixer) { + const expression = template.expressions[i]; + const negativePrefixLength = + negativePrefixMatch[0].length; + // Replace from the trailing `-${` prefix to the closing `}` + // of the interpolation with `calc(${expr} * -1)`. + const replacementStart = + expression.range[0] - + negativePrefixLength - + 2; + const replacementEnd = expression.range[1] + 1; + const expressionText = + context.sourceCode.getText(expression); + + return fixer.replaceTextRange( + [replacementStart, replacementEnd], + `calc($\{${expressionText}} * -1)` + ); + }, + }); + } + } + }, + }; + }, +}; diff --git a/eslint-local-rules/style-namespace-import.rule.mjs b/eslint-local-rules/style-namespace-import.rule.mjs new file mode 100644 index 0000000000..d23aec88a3 --- /dev/null +++ b/eslint-local-rules/style-namespace-import.rule.mjs @@ -0,0 +1,55 @@ +const SAME_DIR_STYLE_MODULE_IMPORT_PATTERN = /^\.\/[^/]+\.styles$/; + +export const styleNamespaceImportRule = { + meta: { + type: "suggestion", + docs: { + description: + "Enforce namespace imports for style modules (*.styles).", + }, + fixable: "code", + schema: [], + messages: { + namespaceStyleImport: + "Import style modules using a namespace import (e.g. import * as styles from './component.styles').", + }, + }, + create(context) { + return { + ImportDeclaration(node) { + if (!node?.source || typeof node.source.value !== "string") { + return; + } + + const importSource = node.source.value; + if (!SAME_DIR_STYLE_MODULE_IMPORT_PATTERN.test(importSource)) { + return; + } + + // Type-only imports are ignored to avoid rewriting TS type flows. + if (node.importKind === "type") return; + + // Side-effect imports are allowed (no bindings to enforce). + if (!node.specifiers.length) return; + + const hasOnlyNamespaceSpecifiers = node.specifiers.every( + (specifier) => specifier.type === "ImportNamespaceSpecifier" + ); + if (hasOnlyNamespaceSpecifiers) return; + + context.report({ + node, + messageId: "namespaceStyleImport", + // TODO: Autofix is disabled until linaria migration is complete. + + // fix(fixer) { + // const quote = getQuote(node.source.raw); + // const localName = getStyleNamespaceLocalName(node); + // const fixedImport = `import * as ${localName} from ${quote}${importSource}${quote};`; + // return fixer.replaceText(node, fixedImport); + // }, + }); + }, + }; + }, +}; diff --git a/eslint.config.mjs b/eslint.config.mjs index d8bc78cb2f..f16a30bb6f 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -10,7 +10,7 @@ import pluginSimpleImportSort from "eslint-plugin-simple-import-sort"; import storybook from "eslint-plugin-storybook"; import globals from "globals"; -import localRules from "./eslint-local-rules/import-path-preferences.mjs"; +import localRules from "./eslint-local-rules/index.mjs"; const sourceFileGlobs = ["**/*.{js,jsx,mjs,cjs,ts,tsx}"]; const reactSourceFileGlobs = ["**/*.{js,jsx,ts,tsx}"]; @@ -176,6 +176,7 @@ export default defineConfig([ rules: { "local/import-path-preferences": "warn", "local/style-namespace-import": "warn", + "local/no-negative-linaria-interpolation": "error", "react-hooks/exhaustive-deps": [ "warn", { diff --git a/package-lock.json b/package-lock.json index c4446ce6c9..e8c9ecbbe3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,7 @@ "@lifesg/react-icons": "^1.12.0", "@linaria/babel-preset": "^5.0.4", "@linaria/core": "^7.0.0", + "@linaria/postcss-linaria": "^7.0.0", "@playwright/test": "^1.58.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-image": "^3.0.3", @@ -135,7 +136,7 @@ "@lifesg/react-icons": "^1.5.0", "react": "^17.0.2 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0", - "styled-components": "^6.1.19" + "styled-components": "^6.4.0" } }, "node_modules/@adobe/css-tools": { @@ -2257,6 +2258,23 @@ "node": ">=18" } }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "license": "CC0-1.0", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, "node_modules/@dnd-kit/accessibility": { "version": "3.1.0", "dev": true, @@ -4122,6 +4140,340 @@ "node": ">=16.0.0" } }, + "node_modules/@linaria/postcss-linaria": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@linaria/postcss-linaria/-/postcss-linaria-7.0.0.tgz", + "integrity": "sha512-rNdLA5PHEWpCRVH7uvPQD3MLx6Ea0JDkh+FtyyZTA9+CvDU0AtrsW1zA/453wrGEQYlgtqrXPQa1QBuolIAb5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.23.5", + "@babel/parser": "^7.23.5", + "@babel/traverse": "^7.23.5", + "stylelint": "^14.11.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@linaria/postcss-linaria/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@linaria/postcss-linaria/node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/stylelint": { + "version": "14.16.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.16.1.tgz", + "integrity": "sha512-ErlzR/T3hhbV+a925/gbfc3f3Fep9/bnspMiJPorfGEmcBbXdS+oo6LrVtoUZ/w9fqD6o6k7PtUlCOsCRdjX/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^7.1.0", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.2.0", + "ignore": "^5.2.1", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.26.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.19", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^2.3.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^4.0.2" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@linaria/postcss-linaria/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/@linaria/postcss-linaria/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/@linaria/shaker": { "version": "5.0.3", "dev": true, @@ -4517,9 +4869,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4541,9 +4890,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -4565,9 +4911,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4589,9 +4932,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -4613,9 +4953,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4637,9 +4974,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5069,9 +5403,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5086,9 +5417,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5103,9 +5431,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5120,9 +5445,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5137,9 +5459,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5154,9 +5473,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5171,9 +5487,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5188,9 +5501,6 @@ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5205,9 +5515,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5222,9 +5529,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5239,9 +5543,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5255,9 +5556,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5272,9 +5570,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -6034,9 +6329,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6054,9 +6346,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6074,9 +6363,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6094,9 +6380,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6165,9 +6448,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6596,6 +6876,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ms": { "version": "0.7.34", "dev": true, @@ -6619,6 +6906,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/prop-types": { "version": "15.7.12", "dev": true, @@ -7360,9 +7654,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7377,9 +7668,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7394,9 +7682,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7411,9 +7696,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7428,9 +7710,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7445,9 +7724,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7462,9 +7738,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7479,9 +7752,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -8269,6 +8539,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "dev": true, @@ -8818,6 +9098,24 @@ "node": ">=6" } }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelize": { "version": "1.0.1", "dev": true, @@ -9499,6 +9797,43 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decimal.js": { "version": "10.6.0", "devOptional": true, @@ -11585,6 +11920,16 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/harmony-reflect": { "version": "1.6.2", "dev": true, @@ -12012,6 +12357,16 @@ "node": ">=4" } }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/import-local": { "version": "3.2.0", "dev": true, @@ -14158,6 +14513,13 @@ "graceful-fs": "^4.1.11" } }, + "node_modules/known-css-properties": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.26.0.tgz", + "integrity": "sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==", + "dev": true, + "license": "MIT" + }, "node_modules/leven": { "version": "3.1.0", "dev": true, @@ -14610,6 +14972,19 @@ "tmpl": "1.0.5" } }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/markdown-table": { "version": "3.0.3", "dev": true, @@ -19682,6 +20057,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minimist-options/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/minimist-options/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/minipass": { "version": "7.1.3", "dev": true, @@ -20685,6 +21095,13 @@ "postcss": "^8.0.0" } }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true, + "license": "MIT" + }, "node_modules/postcss-modules-extract-imports": { "version": "3.1.0", "dev": true, @@ -20740,6 +21157,13 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "dev": true, + "license": "MIT" + }, "node_modules/postcss-safe-parser": { "version": "7.0.1", "dev": true, @@ -21152,6 +21576,16 @@ ], "license": "MIT" }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/randombytes": { "version": "2.1.0", "dev": true, @@ -21382,6 +21816,90 @@ "node": ">=8" } }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, "node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", "dev": true, @@ -22755,9 +23273,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -24666,6 +25181,16 @@ "node": ">=18" } }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/trough": { "version": "2.2.0", "dev": true, @@ -24760,6 +25285,19 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "dev": true, @@ -25303,6 +25841,13 @@ "node": ">=6" } }, + "node_modules/v8-compile-cache": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true, + "license": "MIT" + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "dev": true, diff --git a/package.json b/package.json index 095ec76590..97b3d89d83 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "lint": "npm run lint:js && npm run lint:css", "lint:js": "eslint '**/*.{ts,tsx,js,jsx}' && npm --prefix e2e/nextjs-app run lint:src", "lint:js:fix": "eslint '**/*.{ts,tsx,js,jsx}' --fix && npm --prefix e2e/nextjs-app run lint:src:fix", - "lint:css": "stylelint '**/*.css'", - "lint:css:fix": "stylelint '**/*.css' --fix", + "lint:css": "stylelint '**/*.css' '**/*.styles.ts'", + "lint:css:fix": "stylelint '**/*.css' '**/*.styles.ts' --fix", "test:eslint-rules": "node tests/eslint-rules/import-path-preferences.rule-test.mjs" }, "repository": { @@ -80,6 +80,7 @@ "@lifesg/react-icons": "^1.12.0", "@linaria/babel-preset": "^5.0.4", "@linaria/core": "^7.0.0", + "@linaria/postcss-linaria": "^7.0.0", "@playwright/test": "^1.58.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-image": "^3.0.3", @@ -193,6 +194,9 @@ ], "*.{css,module.css}": [ "stylelint --fix" + ], + "*.styles.ts": [ + "stylelint --fix" ] } } diff --git a/src/accordion/accordion-item.styles.ts b/src/accordion/accordion-item.styles.ts index 19cf7bbde6..4e2dab937e 100644 --- a/src/accordion/accordion-item.styles.ts +++ b/src/accordion/accordion-item.styles.ts @@ -1,14 +1,6 @@ import { css } from "@linaria/core"; -import { - Border, - Colour, - Font, - MediaQuery, - Motion, - Radius, - Spacing, -} from "../theme"; +import { Border, Colour, Font, MediaQuery, Motion, Radius, Spacing } from "../theme"; // ============================================================================= // STYLING @@ -23,20 +15,19 @@ export const containerExpanded = css` `; export const expandCollapseButton = css` - background: transparent; - border: none; - border-radius: ${Radius["sm"]}; - outline: none; - text-align: left; - user-select: text; - - width: 100%; display: flex; flex-direction: row; + gap: ${Spacing["spacing-48"]}; align-items: center; justify-content: space-between; - gap: ${Spacing["spacing-48"]}; + width: 100%; padding: ${Spacing["spacing-16"]} 0; + text-align: left; + user-select: text; + outline: none; + background: transparent; + border: none; + border-radius: ${Radius["sm"]}; &:focus-visible { outline: 2px solid ${Colour["focus-ring"]}; @@ -54,8 +45,8 @@ export const expandCollapseButtonCollapsible = css` export const title = css` flex: 1; - transition: all ${Motion["duration-250"]} ${Motion["ease-standard"]}; color: ${Colour["text"]}; + transition: all ${Motion["duration-250"]} ${Motion["ease-standard"]}; ${Font["heading-sm-bold"]} `; @@ -65,7 +56,7 @@ export const titleSmall = css` export const iconContainer = css` transform: rotate(180deg); - transition: transform ${Motion["duration-250"]}${Motion["ease-default"]}; + transition: transform ${Motion["duration-250"]} ${Motion["ease-default"]}; `; export const iconContainerExpanded = css` @@ -73,8 +64,8 @@ export const iconContainerExpanded = css` `; export const chevronIcon = css` - height: 1.25rem; width: 1.25rem; + height: 1.25rem; color: ${Colour["icon-primary"]}; `; diff --git a/src/accordion/accordion.styles.ts b/src/accordion/accordion.styles.ts index 7245d41ad6..f1fd3b33eb 100644 --- a/src/accordion/accordion.styles.ts +++ b/src/accordion/accordion.styles.ts @@ -26,8 +26,8 @@ export const titleWrapperHidden = css` export const title = css` display: flex; - align-self: flex-start; flex: 1; + align-self: flex-start; ${Font["heading-md-bold"]} color: ${Colour["text"]}; @@ -46,6 +46,6 @@ export const titleHidden = css` export const expandCollapseLink = css` margin: calc(${Spacing["spacing-16"]} * -1); - margin-left: 0px; + margin-left: 0; white-space: nowrap; `; diff --git a/src/alert/alert.styles.ts b/src/alert/alert.styles.ts index b308a39382..abf4dc3da1 100644 --- a/src/alert/alert.styles.ts +++ b/src/alert/alert.styles.ts @@ -3,16 +3,15 @@ import { css } from "@linaria/core"; import { Border, Colour, Font, Motion, Spacing } from "../theme/tokens"; export const tokens = { - maxCollapsedHeight: - "--fds-internal-alert-textWrapperContainer-maxCollapsedHeight", + maxCollapsedHeight: "--fds-internal-alert-textWrapperContainer-maxCollapsedHeight", }; // ============================================================================= // WRAPPER // ============================================================================= export const wrapper = css` - padding: ${Spacing["spacing-8"]} ${Spacing["spacing-16"]}; display: flex; + padding: ${Spacing["spacing-8"]} ${Spacing["spacing-16"]}; border-left: ${Border["width-020"]} ${Border["solid"]}; `; @@ -104,8 +103,8 @@ export const actionLinkText = css` align-self: flex-start; svg { - height: 1rem; width: 1rem; + height: 1rem; margin-left: ${Spacing["spacing-4"]}; } `; @@ -125,8 +124,8 @@ export const actionLinkTextSmall = css` // ============================================================================= export const contentContainer = css` display: flex; - flex-direction: column; flex: 1; + flex-direction: column; overflow-wrap: anywhere; `; @@ -135,8 +134,8 @@ export const contentContainer = css` // ============================================================================= export const textWrapperContainer = css` display: flex; - flex-direction: column; flex: 1; + flex-direction: column; order: 1; `; @@ -146,6 +145,7 @@ export const textWrapperContainerShowMoreWithLink = css` export const textWrapperContainerCollapsed = css` ${tokens.maxCollapsedHeight}: initial; + max-height: var(${tokens.maxCollapsedHeight}); overflow: hidden; -webkit-mask-image: linear-gradient(to bottom, black 50%, transparent 100%); @@ -164,18 +164,16 @@ export const textWrapper = css` // ============================================================================= export const showMoreButton = css` display: flex; + gap: ${Spacing["spacing-4"]}; align-items: center; align-self: flex-start; - gap: ${Spacing["spacing-4"]}; - margin-top: ${Spacing["spacing-8"]}; order: 2; - + margin-top: ${Spacing["spacing-8"]}; + color: ${Colour["text-primary"]}; cursor: pointer; user-select: none; - border: none; background: transparent; - - color: ${Colour["text-primary"]}; + border: none; `; export const showMoreButtonDefault = css` diff --git a/src/animations/loading-dots-spinner/loading-dots-spinner.styles.ts b/src/animations/loading-dots-spinner/loading-dots-spinner.styles.ts index 1afa40ba77..418bc55d74 100644 --- a/src/animations/loading-dots-spinner/loading-dots-spinner.styles.ts +++ b/src/animations/loading-dots-spinner/loading-dots-spinner.styles.ts @@ -5,11 +5,11 @@ export const tokens = { } as const; export const container = css` - ${tokens.containerColor}: initial; margin: 0 auto; + ${tokens.containerColor}: initial; `; export const placeholder = css` - height: 200px; width: 200px; + height: 200px; `; diff --git a/src/animations/loading-dots-spinner/lottie-animation.styles.ts b/src/animations/loading-dots-spinner/lottie-animation.styles.ts index d995b3d225..7944f7d366 100644 --- a/src/animations/loading-dots-spinner/lottie-animation.styles.ts +++ b/src/animations/loading-dots-spinner/lottie-animation.styles.ts @@ -1,6 +1,6 @@ import { css } from "@linaria/core"; export const view = css` - height: 200px; width: 200px; + height: 200px; `; diff --git a/src/animations/loading-dots/loading-dots.styles.ts b/src/animations/loading-dots/loading-dots.styles.ts index 3e45c88369..38eff3bf3e 100644 --- a/src/animations/loading-dots/loading-dots.styles.ts +++ b/src/animations/loading-dots/loading-dots.styles.ts @@ -5,6 +5,6 @@ export const container = css` `; export const placeholder = css` - height: 16px; width: 64px; + height: 16px; `; diff --git a/src/animations/loading-dots/lottie-animation.styles.ts b/src/animations/loading-dots/lottie-animation.styles.ts index 1d9adf66ce..de3b1b8ea7 100644 --- a/src/animations/loading-dots/lottie-animation.styles.ts +++ b/src/animations/loading-dots/lottie-animation.styles.ts @@ -1,6 +1,6 @@ import { css } from "@linaria/core"; export const view = css` - height: 16px; width: 64px; + height: 16px; `; diff --git a/src/animations/loading-spinner/loading-spinner.styles.ts b/src/animations/loading-spinner/loading-spinner.styles.ts index 8e7acc4c6e..05adde3c89 100644 --- a/src/animations/loading-spinner/loading-spinner.styles.ts +++ b/src/animations/loading-spinner/loading-spinner.styles.ts @@ -3,11 +3,11 @@ import { css } from "@linaria/core"; import { Spacing } from "../../theme"; export const container = css` - margin: 0 auto; padding: ${Spacing["spacing-32"]} ${Spacing["spacing-16"]}; + margin: 0 auto; `; export const placeholder = css` - height: 200px; width: 200px; + height: 200px; `; diff --git a/src/animations/loading-spinner/lottie-animation.styles.ts b/src/animations/loading-spinner/lottie-animation.styles.ts index d995b3d225..7944f7d366 100644 --- a/src/animations/loading-spinner/lottie-animation.styles.ts +++ b/src/animations/loading-spinner/lottie-animation.styles.ts @@ -1,6 +1,6 @@ import { css } from "@linaria/core"; export const view = css` - height: 200px; width: 200px; + height: 200px; `; diff --git a/src/avatar/avatar.styles.ts b/src/avatar/avatar.styles.ts index bbaf143ba9..0fde87a381 100644 --- a/src/avatar/avatar.styles.ts +++ b/src/avatar/avatar.styles.ts @@ -6,11 +6,11 @@ import { Colour } from "../theme"; // STYLING // ============================================================================= export const avatarDisplay = css` - border-radius: 50%; - background-color: ${Colour["bg-primary-subtler"]}; + display: flex; align-items: center; justify-content: center; - display: flex; + background-color: ${Colour["bg-primary-subtler"]}; + border-radius: 50%; `; export const avatarDisplayDefault = css` diff --git a/src/badge/badge.styles.ts b/src/badge/badge.styles.ts index 115832d789..ac43c119d6 100644 --- a/src/badge/badge.styles.ts +++ b/src/badge/badge.styles.ts @@ -31,23 +31,22 @@ export const badgeOverlay = css` export const badgeWrapper = css``; export const badgeWrapperIsOverlay = css` + ${tokens.wrapper.offsetX}: 0px; + ${tokens.wrapper.offsetY}: 0px; + position: absolute; top: 0; right: 0; - transform: translate(50%, -25%) - translate( - var(${tokens.wrapper.offsetX}, 0px), - var(${tokens.wrapper.offsetY}, 0px) - ); + transform: translate(50%, -25%) translate(var(${tokens.wrapper.offsetX}), var(${tokens.wrapper.offsetY})); `; export const badge = css` - background-color: ${Colour["bg-primary"]}; - color: ${Colour["text-inverse"]}; display: flex; align-items: center; justify-content: center; width: fit-content; + color: ${Colour["text-inverse"]}; + background-color: ${Colour["bg-primary"]}; &[data-variant="number"] { ${numberBadgeStyles} @@ -70,14 +69,14 @@ export const badge = css` } &[data-variant="square-number"] { + padding: 0.25rem 0.4375rem; ${numberBadgeStyles} border-radius: ${Radius.sm}; - padding: 0.25rem 0.4375rem; } &[data-variant="square-number"][data-color="default"] { - background-color: ${Colour["bg-primary-subtler"]}; color: ${Colour["text-primary"]}; + background-color: ${Colour["bg-primary-subtler"]}; } &[data-color="important"] { diff --git a/src/badge/badge.tsx b/src/badge/badge.tsx index 4521d33e1a..620cf95fc1 100644 --- a/src/badge/badge.tsx +++ b/src/badge/badge.tsx @@ -38,8 +38,8 @@ export const Badge = ({ const wrapperRef = useRef(null); useApplyStyle(wrapperRef, { - [styles.tokens.wrapper.offsetX]: badgeOffset?.[0], - [styles.tokens.wrapper.offsetY]: badgeOffset?.[1], + [styles.tokens.wrapper.offsetX]: badgeOffset?.[0] ?? "0px", + [styles.tokens.wrapper.offsetY]: badgeOffset?.[1] ?? "0px", }); // ============================================================================= diff --git a/src/box-container/box-container.styles.ts b/src/box-container/box-container.styles.ts index 7ea50461cd..bd4c485f46 100644 --- a/src/box-container/box-container.styles.ts +++ b/src/box-container/box-container.styles.ts @@ -1,14 +1,6 @@ import { css } from "@linaria/core"; -import { - Border, - Colour, - Font, - MediaQuery, - Motion, - Radius, - Spacing, -} from "../theme"; +import { Border, Colour, Font, MediaQuery, Motion, Radius, Spacing } from "../theme"; export const handleIconContainer = css` transition: ${Motion["duration-250"]} ${Motion["ease-default"]}; @@ -23,9 +15,9 @@ export const handleIconContainerCollapsed = css` `; export const container = css` + margin-bottom: ${Spacing["spacing-32"]}; border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; border-radius: ${Radius["sm"]}; - margin-bottom: ${Spacing["spacing-32"]}; `; export const expandable = css` @@ -41,14 +33,14 @@ export const childContainer = css` `; export const header = css` - padding: ${Spacing["spacing-16"]} ${Spacing["spacing-32"]}; display: flex; align-items: center; justify-content: space-between; + padding: ${Spacing["spacing-16"]} ${Spacing["spacing-32"]}; ${MediaQuery.MaxWidth.sm} { - padding: ${Spacing["spacing-16"]} ${Spacing["spacing-20"]}; display: block; + padding: ${Spacing["spacing-16"]} ${Spacing["spacing-20"]}; } `; @@ -58,12 +50,11 @@ export const headerInteractive = css` export const labelText = css` ${Font["heading-sm-semibold"]} - color: ${Colour["text"]}; - word-wrap: break-word; - overflow-wrap: anywhere; display: flex; align-items: center; margin-right: ${Spacing["spacing-16"]}; + color: ${Colour["text"]}; + overflow-wrap: anywhere; `; export const labelWrapper = css` @@ -71,11 +62,11 @@ export const labelWrapper = css` `; export const alertIcon = css` - height: ${Font.Spec["heading-size-sm"]}; - width: ${Font.Spec["heading-size-sm"]}; + flex-shrink: 0; align-self: center; + width: ${Font.Spec["heading-size-sm"]}; + height: ${Font.Spec["heading-size-sm"]}; margin-right: ${Spacing["spacing-40"]}; - flex-shrink: 0; ${MediaQuery.MaxWidth.sm} { margin-right: 0; @@ -103,30 +94,31 @@ export const callToActionContainerCollapsible = css` margin-right: ${Spacing["spacing-40"]}; ${MediaQuery.MaxWidth.sm} { - margin-right: 0; margin-top: ${Spacing["spacing-16"]}; + margin-right: 0; } `; export const handle = css` - background: transparent; - border: none; - cursor: pointer; - padding: ${Spacing["spacing-16"]}; - margin: calc(${Spacing["spacing-16"]} * -1); display: flex; align-items: center; + padding: ${Spacing["spacing-16"]}; + margin: calc(${Spacing["spacing-16"]} * -1); + cursor: pointer; + background: transparent; + border: none; ${MediaQuery.MaxWidth.sm} { - margin: calc(${Spacing["spacing-16"]} * -1) - calc(${Spacing["spacing-16"]} * -1) - calc(${Spacing["spacing-16"]} * -1) 0; + margin-top: calc(${Spacing["spacing-16"]} * -1); + margin-right: calc(${Spacing["spacing-16"]} * -1); + margin-bottom: calc(${Spacing["spacing-16"]} * -1); + /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties */ margin-left: auto; } `; export const handleIcon = css` - color: ${Colour["icon"]}; - height: ${Font.Spec["heading-size-sm"]}; width: ${Font.Spec["heading-size-sm"]}; + height: ${Font.Spec["heading-size-sm"]}; + color: ${Colour["icon"]}; `; diff --git a/src/breadcrumb/breadcrumb.styles.ts b/src/breadcrumb/breadcrumb.styles.ts index 327d2eed65..f42a73b3a0 100644 --- a/src/breadcrumb/breadcrumb.styles.ts +++ b/src/breadcrumb/breadcrumb.styles.ts @@ -13,8 +13,8 @@ export const tokens = { // ============================================================================= export const wrapper = css` position: relative; - width: 100%; z-index: 1; + width: 100%; margin: ${Spacing["spacing-32"]} 0; ${MediaQuery.MaxWidth.xl} { @@ -28,13 +28,12 @@ export const wrapper = css` export const content = css` display: inline-flex; - width: 100%; flex-wrap: wrap; - white-space: nowrap; + width: 100%; margin-left: calc(${Spacing["spacing-8"]} * -1); + overflow: scroll hidden; font-size: ${Font.Spec["body-size-md"]}; - overflow-x: scroll; - overflow-y: hidden; + white-space: nowrap; scrollbar-width: none; /* Firefox */ -ms-overflow-style: none; /* IE 10+ */ &::-webkit-scrollbar { @@ -48,12 +47,13 @@ export const content = css` export const fade = css` ${tokens.fade.backgroundColor}: initial; - width: ${Spacing["spacing-64"]}; - height: calc(1lh + ${Spacing["spacing-4"]}); + position: absolute; top: 50%; - transform: translateY(-50%); + width: ${Spacing["spacing-64"]}; + height: calc(1lh + ${Spacing["spacing-4"]}); pointer-events: none; + transform: translateY(-50%); `; export const fadeLeft = css` @@ -62,7 +62,7 @@ export const fadeLeft = css` background-image: linear-gradient( to right, var(${tokens.fade.backgroundColor}, ${Colour.bg}), - rgba(255, 255, 255, 0.001) + rgb(255 255 255 / 0.1%) ); } `; @@ -73,7 +73,7 @@ export const fadeRight = css` background-image: linear-gradient( to left, var(${tokens.fade.backgroundColor}, ${Colour.bg}), - rgba(255, 255, 255, 0.001) + rgb(255 255 255 / 0.1%) ); } `; @@ -82,13 +82,13 @@ export const item = css` display: flex; flex-direction: row; align-items: center; - line-height: inherit; font-size: inherit; + line-height: inherit; `; export const caret = css` - height: 1em; width: 1em; + height: 1em; color: ${Colour["icon-subtle"]}; `; diff --git a/src/button/button.styles.ts b/src/button/button.styles.ts index 788843a1cb..9c72b5ed1d 100644 --- a/src/button/button.styles.ts +++ b/src/button/button.styles.ts @@ -1,31 +1,23 @@ import { css } from "@linaria/core"; -import { - Border, - Colour, - Font, - MediaQuery, - Motion, - Radius, - Spacing, -} from "../theme"; +import { Border, Colour, Font, MediaQuery, Motion, Radius, Spacing } from "../theme"; export const main = css` - border: ${Border["width-010"]} ${Border["solid"]} transparent; - transition: all ${Motion["duration-250"]} ${Motion["ease-default"]}; - cursor: pointer; display: flex; + gap: 0.5rem; align-items: center; justify-content: center; padding: ${Spacing["spacing-8"]} ${Spacing["spacing-16"]}; - gap: 0.5rem; + cursor: pointer; + border: ${Border["width-010"]} ${Border["solid"]} transparent; border-radius: ${Radius.sm}; + transition: all ${Motion["duration-250"]} ${Motion["ease-default"]}; svg, img { flex-shrink: 0; - height: 1em; width: 1em; + height: 1em; } `; @@ -41,8 +33,9 @@ export const mainHasMinWidth = css` // BUTTON STYLE + TEXT COLOR // ------------------------------------------------------------------------- export const mainStyleDefault = css` - background-color: ${Colour["bg-primary"]}; color: ${Colour["text-inverse"]}; + background-color: ${Colour["bg-primary"]}; + &:hover, &:active { @media (pointer: fine) { @@ -52,8 +45,9 @@ export const mainStyleDefault = css` `; export const mainStyleDefaultDanger = css` - background-color: ${Colour["bg-error-strong"]}; color: ${Colour["text-inverse"]}; + background-color: ${Colour["bg-error-strong"]}; + &:hover, &:active { @media (pointer: fine) { @@ -63,9 +57,10 @@ export const mainStyleDefaultDanger = css` `; export const mainStyleSecondary = css` + color: ${Colour["text-primary"]}; background-color: ${Colour.bg}; border-color: ${Colour["border-primary"]}; - color: ${Colour["text-primary"]}; + &:hover, &:active { @media (pointer: fine) { @@ -75,9 +70,10 @@ export const mainStyleSecondary = css` `; export const mainStyleSecondaryDanger = css` + color: ${Colour["text-error"]}; background-color: ${Colour.bg}; border-color: ${Colour["border-error-strong"]}; - color: ${Colour["text-error"]}; + &:hover, &:active { @media (pointer: fine) { @@ -87,9 +83,10 @@ export const mainStyleSecondaryDanger = css` `; export const mainStyleLight = css` + color: ${Colour["text-primary"]}; background-color: ${Colour.bg}; border-color: ${Colour.border}; - color: ${Colour["text-primary"]}; + &:hover, &:active { @media (pointer: fine) { @@ -99,9 +96,10 @@ export const mainStyleLight = css` `; export const mainStyleLightDanger = css` + color: ${Colour["text-error"]}; background-color: ${Colour.bg}; border-color: ${Colour.border}; - color: ${Colour["text-error"]}; + &:hover, &:active { @media (pointer: fine) { @@ -111,8 +109,9 @@ export const mainStyleLightDanger = css` `; export const mainStyleLink = css` - background-color: transparent; color: ${Colour["text-primary"]}; + background-color: transparent; + &:hover, &:active { @media (pointer: fine) { @@ -122,8 +121,9 @@ export const mainStyleLink = css` `; export const mainStyleLinkDanger = css` - background-color: transparent; color: ${Colour["text-error"]}; + background-color: transparent; + &:hover, &:active { @media (pointer: fine) { @@ -133,9 +133,10 @@ export const mainStyleLinkDanger = css` `; export const mainStyleDisabled = css` - background-color: ${Colour["bg-disabled"]}; - cursor: not-allowed; color: ${Colour["text-disabled"]}; + cursor: not-allowed; + background-color: ${Colour["bg-disabled"]}; + &:hover { box-shadow: none; } @@ -153,8 +154,8 @@ export const mainSizeDefault = css` `; export const mainSizeDefaultIconOnly = css` - height: 3rem; width: 3rem; + height: 3rem; `; export const mainSizeSmall = css` @@ -166,8 +167,8 @@ export const mainSizeSmall = css` `; export const mainSizeSmallIconOnly = css` - height: 2.5rem; width: 2.5rem; + height: 2.5rem; `; export const mainSizeLarge = css` @@ -179,8 +180,8 @@ export const mainSizeLarge = css` `; export const mainSizeLargeIconOnly = css` - height: 4rem; width: 4rem; + height: 4rem; `; export const spinnerHasChildren = css` diff --git a/src/card/card.styles.ts b/src/card/card.styles.ts index 2bd8112a33..1d651a8917 100644 --- a/src/card/card.styles.ts +++ b/src/card/card.styles.ts @@ -3,9 +3,9 @@ import { css } from "@linaria/core"; import { Border, Colour, Radius, Shadow, Spacing } from "../theme"; export const card = css` - border-radius: ${Radius["md"]}; - background: ${Colour.bg}; padding: ${Spacing["spacing-16"]} ${Spacing["spacing-32"]}; + background: ${Colour.bg}; + border-radius: ${Radius["md"]}; `; export const cardDarkMode = css` diff --git a/src/checkbox/checkbox.styles.ts b/src/checkbox/checkbox.styles.ts index 447902d7a3..9828add3ad 100644 --- a/src/checkbox/checkbox.styles.ts +++ b/src/checkbox/checkbox.styles.ts @@ -11,16 +11,16 @@ export const icon = css` 0% { opacity: 0; } + 100% { opacity: 1; } } - animation: ${Motion["duration-150"]} ${Motion["ease-default"]} - checkbox-icon-fade-in; width: 100%; height: 100%; transition: color ${Motion["duration-150"]} ${Motion["ease-default"]}; + animation: ${Motion["duration-150"]} ${Motion["ease-default"]} checkbox-icon-fade-in; `; export const uncheckedIcon = css` @@ -36,31 +36,31 @@ export const iconDisabled = css` `; export const container = css` + position: relative; display: flex; - justify-content: center; align-items: center; - position: relative; - height: 2rem; + justify-content: center; width: 2rem; + height: 2rem; input:focus-visible + svg { outline: 2px solid ${Colour["focus-ring"]}; - outline-offset: 0px; + outline-offset: 0; border-radius: 4px; } `; export const containerSmall = css` - height: 1.5rem; width: 1.5rem; + height: 1.5rem; `; export const input = css` position: absolute; - opacity: 0; width: 100%; height: 100%; cursor: pointer; + opacity: 0; `; export const inputActive = css` diff --git a/src/dashed-border/dashed-border.styles.ts b/src/dashed-border/dashed-border.styles.ts index c2e3b14288..614c355de4 100644 --- a/src/dashed-border/dashed-border.styles.ts +++ b/src/dashed-border/dashed-border.styles.ts @@ -3,15 +3,18 @@ import { css } from "@linaria/core"; export const tokens = { rootRadius: "--fds-internal-dashedBorder-root-radius", rootBackgroundColor: "--fds-internal-dashedBorder-root-backgroundColor", - overlayBackgroundImage: - "--fds-internal-dashedBorder-overlay-backgroundImage", + overlayBackgroundImage: "--fds-internal-dashedBorder-overlay-backgroundImage", } as const; export const root = css` + ${tokens.rootRadius}: initial; + ${tokens.rootBackgroundColor}: initial; + ${tokens.overlayBackgroundImage}: initial; + position: relative; overflow: hidden; - border-radius: var(${tokens.rootRadius}, 0); background-color: var(${tokens.rootBackgroundColor}, transparent); + border-radius: var(${tokens.rootRadius}, 0); `; export const overlay = css` @@ -19,9 +22,9 @@ export const overlay = css` inset: 0; width: 100%; height: 100%; + pointer-events: none; background-image: var(${tokens.overlayBackgroundImage}, none); background-repeat: no-repeat; background-position: center; background-size: 100% 100%; - pointer-events: none; `; diff --git a/src/divider/divider.styles.ts b/src/divider/divider.styles.ts index 561642ec0f..a835f86e57 100644 --- a/src/divider/divider.styles.ts +++ b/src/divider/divider.styles.ts @@ -13,20 +13,25 @@ export const tokens = { } as const; export const lineBase = css` + ${tokens.thickness}: initial; + ${tokens.color}: initial; + width: 100%; + height: var(${tokens.thickness}, 1px); margin: 0; border: none; - ${tokens.thickness}: initial; - height: var(${tokens.thickness}, 1px); `; export const solidLine = css` ${tokens.color}: initial; + background-color: var(${tokens.color}, ${Colour.border}); `; export const dashedLine = css` + ${tokens.backgroundImage}: initial; + background-color: transparent; - background-repeat: repeat-x; background-image: var(${tokens.backgroundImage}); + background-repeat: repeat-x; `; diff --git a/src/drawer/drawer.styles.ts b/src/drawer/drawer.styles.ts index 6e82b46be6..a292966993 100644 --- a/src/drawer/drawer.styles.ts +++ b/src/drawer/drawer.styles.ts @@ -1,32 +1,19 @@ import { css } from "@linaria/core"; -import { - Border, - Colour, - Font, - MediaQuery, - Motion, - Radius, - Shadow, - Spacing, -} from "../theme"; +import { Border, Colour, Font, MediaQuery, Motion, Radius, Shadow, Spacing } from "../theme"; export const container = css` position: fixed; top: 0; - display: flex; flex-direction: column; - - height: 100%; width: 40%; + height: 100%; overflow: hidden; - background-color: ${Colour["bg"]}; - box-shadow: ${Shadow["lg-subtle"]}; border-top-left-radius: ${Radius["md"]}; border-bottom-left-radius: ${Radius["md"]}; - + box-shadow: ${Shadow["lg-subtle"]}; transition-property: right, visibility; &[data-status="initial"] { @@ -35,17 +22,17 @@ export const container = css` } &[data-status="open"] { - transition-duration: ${Motion["duration-800"]}; - transition-timing-function: ${Motion["ease-entrance"]}; right: 0; visibility: visible; + transition-timing-function: ${Motion["ease-entrance"]}; + transition-duration: ${Motion["duration-800"]}; } &[data-status="close"] { - transition-duration: ${Motion["duration-800"]}; - transition-timing-function: ${Motion["ease-exit"]}; right: -100%; visibility: hidden; + transition-timing-function: ${Motion["ease-exit"]}; + transition-duration: ${Motion["duration-800"]}; } ${MediaQuery.MaxWidth.xl} { @@ -64,42 +51,45 @@ export const container = css` export const header = css` top: 0; display: flex; - align-items: center; gap: ${Spacing["spacing-16"]}; - padding: ${Spacing["spacing-32"]} ${Spacing["spacing-16"]} - ${Spacing["spacing-16"]} - calc(${Font.Spec["heading-lh-md"]} + ${Spacing["spacing-32"]}); + align-items: center; + padding-top: ${Spacing["spacing-32"]}; + padding-right: ${Spacing["spacing-16"]}; + padding-bottom: ${Spacing["spacing-16"]}; + /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties */ + padding-left: calc(${Font.Spec["heading-lh-md"]} + ${Spacing["spacing-32"]}); background-color: ${Colour["bg"]}; border-bottom: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; ${MediaQuery.MaxWidth.lg} { gap: ${Spacing["spacing-8"]}; - padding: ${Spacing["spacing-32"]} ${Spacing["spacing-20"]} - ${Spacing["spacing-16"]} - calc(${Font.Spec["heading-lh-md"]} + ${Spacing["spacing-24"]}); + padding-top: ${Spacing["spacing-32"]}; + padding-right: ${Spacing["spacing-20"]}; + padding-left: calc(${Font.Spec["heading-lh-md"]} + ${Spacing["spacing-24"]}); } `; export const closeButton = css` - color: ${Colour["icon"]}; - padding: 0; position: absolute; top: ${Spacing["spacing-32"]}; left: ${Spacing["spacing-16"]}; + padding: 0; + color: ${Colour["icon"]}; + &:active, &:focus { color: ${Colour["icon-hover"]}; } svg { - height: ${Font.Spec["heading-lh-md"]}; width: ${Font.Spec["heading-lh-md"]}; + height: ${Font.Spec["heading-lh-md"]}; } `; export const heading = css` - text-overflow: ellipsis; overflow: hidden; + text-overflow: ellipsis; white-space: nowrap; `; diff --git a/src/e-signature/e-signature.styles.ts b/src/e-signature/e-signature.styles.ts index ad27d3d11b..8fe9b5f70e 100644 --- a/src/e-signature/e-signature.styles.ts +++ b/src/e-signature/e-signature.styles.ts @@ -5,15 +5,7 @@ import { DashedBorder } from "../dashed-border"; import { Modal } from "../modal"; import { Border, Colour, Radius } from "../theme"; import { Typography } from "../typography"; -import { - V3_Border, - V3_Breakpoint, - V3_Colour, - V3_Font, - V3_MediaQuery, - V3_Radius, - V3_Spacing, -} from "../v3_theme"; +import { V3_Border, V3_Breakpoint, V3_Colour, V3_Font, V3_MediaQuery, V3_Radius, V3_Spacing } from "../v3_theme"; // ============================================================================= // STYLE INTERFACES @@ -27,19 +19,14 @@ interface SignatureAreaProps { // ============================================================================= // for mobileL and below in both orientations const mobileMediaQuery = css` - ${(props) => ` - ${V3_MediaQuery.MaxWidth.sm(props)}, - (orientation: landscape) and (max-height: ${V3_Breakpoint["sm-max"]( - props - )}px) - `} + ${(props) => + V3_MediaQuery.MaxWidth.sm(props) + + ", (orientation: landscape) and (max-height: " + + V3_Breakpoint["sm-max"](props) + + "px)"} `; const mobileLandscapeMediaQuery = css` - ${(props) => ` - @media (orientation: landscape) and (max-height: ${V3_Breakpoint[ - "sm-max" - ](props)}px) - `} + ${(props) => "@media (orientation: landscape) and (max-height: " + V3_Breakpoint["sm-max"](props) + "px)"} `; // ============================================================================= @@ -50,14 +37,12 @@ const mobileLandscapeMediaQuery = css` // MAIN FIELD // ----------------------------------------------------------------------------- -export const SignatureArea = styled(DashedBorder).attrs( - (props) => ({ - thickness: Border["width-040"], - radius: Radius["sm"], - colour: props.$disabled ? Colour["border-disabled"] : Colour["border"], - backgroundColor: props.$disabled ? Colour["bg-disabled"] : Colour["bg"], - }) -)` +export const SignatureArea = styled(DashedBorder).attrs((props) => ({ + thickness: Border["width-040"], + radius: Radius["sm"], + colour: props.$disabled ? Colour["border-disabled"] : Colour["border"], + backgroundColor: props.$disabled ? Colour["bg-disabled"] : Colour["bg"], +}))` position: relative; display: flex; align-items: center; @@ -86,24 +71,23 @@ export const EditSignatureButton = styled(Button)` export const SignaturePreviewImage = styled.img` display: block; - object-fit: contain; - object-position: center; width: calc(100% - (3rem + ${V3_Spacing["spacing-16"]}) * 2); height: 100%; + object-fit: contain; + object-position: center; `; export const ProgressBox = styled.div` - background: ${V3_Colour["bg-primary-subtlest"]}; - border: ${V3_Border["width-010"]} ${V3_Border["solid"]} - ${V3_Colour["border"]}; - border-radius: ${V3_Radius["sm"]}; - margin: 0 ${V3_Spacing["spacing-20"]}; - padding: ${V3_Spacing["spacing-16"]}; display: flex; - gap: ${V3_Spacing["spacing-16"]}; flex: 1; flex-direction: column; + gap: ${V3_Spacing["spacing-16"]}; align-items: center; + padding: ${V3_Spacing["spacing-16"]}; + margin: 0 ${V3_Spacing["spacing-20"]}; + background: ${V3_Colour["bg-primary-subtlest"]}; + border: ${V3_Border["width-010"]} ${V3_Border["solid"]} ${V3_Colour["border"]}; + border-radius: ${V3_Radius["sm"]}; `; export const Instructions = styled(Typography.BodySM)` @@ -124,32 +108,31 @@ export const ScrollableModal = styled(Modal)` export const GrowContainer = styled.div` width: 100%; - margin: auto; padding: ${V3_Spacing["layout-xxl"]} ${V3_Spacing["layout-sm"]}; + margin: auto; ${mobileMediaQuery} { - padding: 0; width: 100%; height: 100%; + padding: 0; } `; export const ModalBox = styled(Modal.Box)` width: 100%; - height: 29rem; max-width: 672px; + height: 29rem; max-height: none; - margin: 0 auto; padding: ${V3_Spacing["spacing-16"]}; + margin: 0 auto; ${mobileMediaQuery} { display: flex; flex-direction: column; max-width: none; height: 100%; - border-radius: 0; padding: 0; - + border-radius: 0; --close-button-top-inset: ${V3_Spacing["spacing-8"]}; --close-button-right-inset: ${V3_Spacing["spacing-20"]}; } @@ -157,8 +140,8 @@ export const ModalBox = styled(Modal.Box)` export const ModalTitle = styled.h2` ${V3_Font["body-baseline-semibold"]} - color: ${V3_Colour["text"]}; margin-bottom: ${V3_Spacing["spacing-16"]}; + color: ${V3_Colour["text"]}; text-align: center; ${mobileMediaQuery} { @@ -170,12 +153,12 @@ export const ModalTitle = styled.h2` export const ESignatureContainer = styled.div` width: 100%; height: 20rem; - border-radius: ${V3_Radius["lg"]}; overflow: hidden; + border-radius: ${V3_Radius["lg"]}; ${mobileMediaQuery} { - border-radius: 0; flex: 1; + border-radius: 0; } ${mobileLandscapeMediaQuery} { @@ -187,16 +170,18 @@ export const ESignatureDrawable = styled.div` position: relative; width: 100%; height: 100%; - background: ${V3_Colour["bg-stronger"]}; margin: auto; + background: ${V3_Colour["bg-stronger"]}; ${mobileMediaQuery} { aspect-ratio: 4/3; } + ${V3_MediaQuery.MaxWidth.sm} { width: 100%; height: auto; } + ${mobileLandscapeMediaQuery} { width: auto; height: 100%; @@ -205,18 +190,18 @@ export const ESignatureDrawable = styled.div` export const SignatureLine = styled.div` position: absolute; - left: 50%; top: calc(75% - 1px); + left: 50%; width: 300px; height: 2px; - transform: translateX(-50%); - background-color: ${V3_Colour["border-strong"]}; pointer-events: none; + background-color: ${V3_Colour["border-strong"]}; + transform: translateX(-50%); ${mobileMediaQuery} { + left: 50%; width: calc(100% - ${V3_Spacing["spacing-40"]}); max-width: 300px; - left: 50%; } `; @@ -227,9 +212,12 @@ export const ModalButtons = styled.div` ${V3_MediaQuery.MaxWidth.sm} { flex-direction: column-reverse; - margin: ${V3_Spacing["spacing-16"]} ${V3_Spacing["spacing-24"]} - ${V3_Spacing["spacing-48"]}; gap: ${V3_Spacing["spacing-16"]}; + margin-top: ${V3_Spacing["spacing-16"]}; + margin-right: ${V3_Spacing["spacing-24"]}; + margin-bottom: ${V3_Spacing["spacing-48"]}; + /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties */ + margin-left: ${V3_Spacing["spacing-24"]}; } ${mobileLandscapeMediaQuery} { @@ -238,11 +226,13 @@ export const ModalButtons = styled.div` } `; -export const ModalActionButton = styled(Button.Default)` +export const ModalActionButton = styled(Button)` width: 8.5rem; + ${V3_MediaQuery.MaxWidth.sm} { width: 100%; } + ${mobileLandscapeMediaQuery} { height: 2.5rem; } diff --git a/src/error-display/error-display.styles.ts b/src/error-display/error-display.styles.ts index f211d6cb77..328aba20e6 100644 --- a/src/error-display/error-display.styles.ts +++ b/src/error-display/error-display.styles.ts @@ -3,11 +3,11 @@ import { css } from "@linaria/core"; import { Colour, MediaQuery, Spacing } from "../theme"; export const container = css` + position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; - position: relative; `; export const img = css` @@ -52,8 +52,8 @@ export const descriptionContainer = css` `; export const actionButton = css` - margin: ${Spacing["spacing-32"]} auto 0; width: 21rem; + margin: ${Spacing["spacing-32"]} auto 0; ${MediaQuery.MaxWidth.sm} { width: 100%; diff --git a/src/form/form-label-addon.styles.ts b/src/form/form-label-addon.styles.ts index 7707a042eb..027a92170a 100644 --- a/src/form/form-label-addon.styles.ts +++ b/src/form/form-label-addon.styles.ts @@ -3,6 +3,6 @@ import { css } from "@linaria/core"; import { Spacing } from "../theme"; export const addonWrapper = css` - padding-left: ${Spacing["spacing-4"]}; display: inline; + padding-left: ${Spacing["spacing-4"]}; `; diff --git a/src/form/form-label.styles.ts b/src/form/form-label.styles.ts index 21319ebd00..410bf60e62 100644 --- a/src/form/form-label.styles.ts +++ b/src/form/form-label.styles.ts @@ -10,16 +10,16 @@ export const labelContainer = css` `; export const label = css` - color: ${Colour["text-subtle"]}; display: inline-block; ${Font["form-label"]} font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-subtle"]}; `; export const errorIcon = css` - height: 1lh; - width: 1em; flex-shrink: 0; + width: 1em; + height: 1lh; color: ${Colour["icon-error-strong"]}; `; @@ -31,14 +31,14 @@ export const errorMessageContainer = css` `; export const errorMessage = css` - color: ${Colour["text-error"]}; ${Font["body-sm-semibold"]} margin-bottom: 0; + color: ${Colour["text-error"]}; outline: none; `; export const subtitle = css` ${Font["form-description"]} - color: ${Colour["text-subtler"]}; display: block; + color: ${Colour["text-subtler"]}; `; diff --git a/src/form/form-textarea.styles.ts b/src/form/form-textarea.styles.ts index df81b02fcd..754a96f48a 100644 --- a/src/form/form-textarea.styles.ts +++ b/src/form/form-textarea.styles.ts @@ -11,8 +11,8 @@ export const labelContainer = css` export const errorMessageContainer = css` display: flex; flex: 1; - margin-right: ${Spacing["spacing-12"]}; gap: ${Spacing["spacing-4"]}; + margin-right: ${Spacing["spacing-12"]}; `; export const errorMessageLabel = css` diff --git a/src/histogram-slider/histogram-slider.styles.ts b/src/histogram-slider/histogram-slider.styles.ts index 160f06991b..45bfaa5488 100644 --- a/src/histogram-slider/histogram-slider.styles.ts +++ b/src/histogram-slider/histogram-slider.styles.ts @@ -1,4 +1,4 @@ -import styled, { css } from "styled-components"; +import styled from "styled-components"; import { InputRangeSlider } from "../input-range-slider"; import { V3_Colour, V3_Radius, V3_Spacing } from "../v3_theme"; @@ -10,8 +10,8 @@ interface BarStyleProps { export const Label = styled.div` display: flex; - margin-bottom: ${V3_Spacing["spacing-16"]}; align-items: baseline; + margin-bottom: ${V3_Spacing["spacing-16"]}; `; export const Separator = styled.div` @@ -19,32 +19,32 @@ export const Separator = styled.div` `; export const Histogram = styled.div` - width: 100%; - height: 4rem; display: flex; align-items: flex-end; + width: 100%; + height: 4rem; padding: 0 0.4375rem; `; +const getBarBackgroundColor = (props: BarStyleProps) => { + if (props.$disabled && props.$selected) { + return V3_Colour["bg-selected-stronger-disabled"]; + } + if (props.$disabled) { + return V3_Colour["bg-disabled"]; + } + if (props.$selected) { + return V3_Colour["bg-selected-stronger"]; + } + return V3_Colour["bg-strongest"]; +}; + export const Bar = styled.div` flex: 1; - border-radius: ${V3_Radius["sm"]} ${V3_Radius["sm"]} 0 0; - border: 0.5px solid transparent; // space between bars + background-color: ${(props) => getBarBackgroundColor(props)}; background-clip: content-box; - - ${(props) => { - let color = V3_Colour["bg-strongest"]; - if (props.$disabled && props.$selected) { - color = V3_Colour["bg-selected-stronger-disabled"]; - } else if (props.$disabled) { - color = V3_Colour["bg-disabled"]; - } else if (props.$selected) { - color = V3_Colour["bg-selected-stronger"]; - } - return css` - background-color: ${color}; - `; - }} + border: 0.5px solid transparent; /* space between bars */ + border-radius: ${V3_Radius["sm"]} ${V3_Radius["sm"]} 0 0; `; export const Slider = styled(InputRangeSlider)` diff --git a/src/image-button/image-button.styles.ts b/src/image-button/image-button.styles.ts index 0e8ed8d827..61527c3e3d 100644 --- a/src/image-button/image-button.styles.ts +++ b/src/image-button/image-button.styles.ts @@ -7,22 +7,22 @@ export const main = css` flex: 1; flex-direction: column; gap: 0.5rem; - justify-content: center; align-items: center; + justify-content: center; + max-width: 13rem; padding: 1.5rem 1rem; + ${Font["body-baseline-semibold"]} + color: ${Colour["text"]}; + overflow-wrap: anywhere; + cursor: pointer; background-color: ${Colour.bg}; border: ${Border["width-010"]} ${Border.solid} transparent; border-radius: ${Radius["md"]}; - cursor: pointer; - max-width: 13rem; transition: all ${Motion["duration-250"]} ${Motion["ease-default"]}; - ${Font["body-baseline-semibold"]} - color: ${Colour["text"]}; - overflow-wrap: anywhere; img { - min-width: 3.5rem; width: 3.5rem; + min-width: 3.5rem; height: 3.5rem; object-fit: contain; } @@ -32,8 +32,8 @@ export const main = css` } ${MediaQuery.MaxWidth.sm} { - padding: 0.5rem 0.25rem; gap: 0.25rem; + padding: 0.5rem 0.25rem; ${Font["body-md-semibold"]} } `; diff --git a/src/input-range-slider/input-range-slider.styles.ts b/src/input-range-slider/input-range-slider.styles.ts index a3ac833b55..691abb881b 100644 --- a/src/input-range-slider/input-range-slider.styles.ts +++ b/src/input-range-slider/input-range-slider.styles.ts @@ -4,8 +4,7 @@ import { Border, Colour, Radius, Shadow, Spacing } from "../theme"; export const tokens = { track: { - backgroundColor: - "--fds-internal-inputRangeSlider-track-backgroundColor", + backgroundColor: "--fds-internal-inputRangeSlider-track-backgroundColor", }, }; @@ -14,10 +13,10 @@ export const wrapper = css` `; export const labelContainer = css` - margin-top: ${Spacing["spacing-8"]}; display: flex; - justify-content: space-between; gap: ${Spacing["spacing-8"]}; + justify-content: space-between; + margin-top: ${Spacing["spacing-8"]}; `; export const indicatorLabelContainer = css` @@ -29,33 +28,31 @@ export const labelText = css` `; export const slider = css` - height: 0.875rem; position: relative; + height: 0.875rem; `; export const knob = css` - height: 2.5rem; - width: 2.5rem; position: absolute; top: 50%; left: 50%; + width: 2.5rem; + height: 2.5rem; transform: translate(-50%, -50%); &::after { - content: ""; - display: block; - height: 0.875rem; - width: 0.875rem; position: absolute; top: 50%; left: 50%; - transform: translate(-50%, -50%); - + display: block; + width: 0.875rem; + height: 0.875rem; + content: ""; background-color: ${Colour["bg"]}; - box-shadow: ${Shadow["sm-subtle"]}; - border: ${Border["width-010"]} ${Border["solid"]} - ${Colour["border-strong"]}; + border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border-strong"]}; border-radius: ${Radius["full"]}; + box-shadow: ${Shadow["sm-subtle"]}; + transform: translate(-50%, -50%); } `; @@ -76,27 +73,23 @@ export const knobInteractive = css` `; export const sliderThumb = css` - height: 0.875rem; - width: 0.875rem; position: relative; + width: 0.875rem; + height: 0.875rem; outline: none; &:focus .${knob}::after, &[data-focused="true"] .${knob}::after { + outline: ${Border["width-040"]} ${Border["solid"]} ${Colour["border-selected"]}; outline-offset: -1px; - outline: ${Border["width-040"]} ${Border["solid"]} - ${Colour["border-selected"]}; } `; export const sliderTrack = css` - height: 0.25rem; + ${tokens.track.backgroundColor}: initial; + top: 50%; - transform: translateY(-50%); + height: 0.25rem; + background: var(${tokens.track.backgroundColor}); border-radius: ${Radius["full"]}; - - ${tokens.track.backgroundColor}: initial; - background: var( - ${tokens.track.backgroundColor}, - ${Colour["border-strong"]} - ); + transform: translateY(-50%); `; diff --git a/src/input-textarea/textarea-counter.styles.ts b/src/input-textarea/textarea-counter.styles.ts index 18cd337cec..af35f42b22 100644 --- a/src/input-textarea/textarea-counter.styles.ts +++ b/src/input-textarea/textarea-counter.styles.ts @@ -3,7 +3,7 @@ import { css } from "@linaria/core"; import { Colour, Font } from "../theme"; export const counterLabel = css` - text-align: right; ${Font["body-sm-semibold"]} color: ${Colour["text-subtler"]}; + text-align: right; `; diff --git a/src/input-textarea/textarea.styles.ts b/src/input-textarea/textarea.styles.ts index 578680cb61..3b107d42dd 100644 --- a/src/input-textarea/textarea.styles.ts +++ b/src/input-textarea/textarea.styles.ts @@ -8,24 +8,22 @@ export const wrapper = css` `; export const element = css` - border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; - border-radius: ${Radius["sm"]}; - background: ${Colour.bg}; - outline: none; - overflow: auto; - display: block; - padding: ${Spacing["spacing-12"]} ${Spacing["spacing-16"]}; width: 100%; + padding: ${Spacing["spacing-12"]} ${Spacing["spacing-16"]}; + overflow: auto; ${Font["body-baseline-regular"]} color: ${Colour["text"]}; + outline: none; + background: ${Colour.bg}; + border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; + border-radius: ${Radius["sm"]}; &:focus, &:active { + outline: ${Border["width-020"]} ${Border["solid"]} ${Colour["border-focus"]}; outline-offset: -1px; - outline: ${Border["width-020"]} ${Border["solid"]} - ${Colour["border-focus"]}; } &::placeholder, @@ -43,16 +41,16 @@ export const element = css` &::-webkit-scrollbar-thumb { background: ${Colour["bg-inverse-subtlest"]}; + background-clip: padding-box; border: 5px solid transparent; border-radius: ${Radius["full"]}; - background-clip: padding-box; } `; export const elementReadOnly = css` - border-color: transparent; - background: transparent !important; padding: ${Spacing["spacing-12"]} 0; + background: transparent !important; + border-color: transparent; &:focus, &:active { @@ -61,8 +59,8 @@ export const elementReadOnly = css` `; export const elementDisabled = css` - background: ${Colour["bg-disabled"]}; cursor: not-allowed; + background: ${Colour["bg-disabled"]}; &:focus, &:active { diff --git a/src/input/input.styles.ts b/src/input/input.styles.ts index 083c582f8c..aab62063f2 100644 --- a/src/input/input.styles.ts +++ b/src/input/input.styles.ts @@ -29,8 +29,8 @@ export const inputElementPaddingRight = css` export const clearButton = css` height: auto; padding: ${Spacing["spacing-12"]} ${Spacing["spacing-16"]}; - cursor: pointer; color: ${Colour.icon}; + cursor: pointer; `; export const clearButtonNoBorder = css` @@ -38,8 +38,8 @@ export const clearButtonNoBorder = css` `; export const clearIcon = css` - height: 1.25rem; width: 1.25rem; + height: 1.25rem; vertical-align: middle; `; @@ -55,9 +55,9 @@ export const defaultWrapper = css` `; export const defaultWrapperReadOnly = css` - border-color: transparent; padding: 0; background: transparent !important; + border-color: transparent; &:focus-within { outline-color: ${Colour["border-focus"]}; @@ -65,8 +65,8 @@ export const defaultWrapperReadOnly = css` `; export const defaultWrapperDisabled = css` - background: ${Colour["bg-disabled"]}; cursor: not-allowed; + background: ${Colour["bg-disabled"]}; &:focus-within { outline-color: ${Colour["border-disabled"]}; diff --git a/src/layout/col-div.styles.ts b/src/layout/col-div.styles.ts index ebfd6b3bbd..63fddae7a1 100644 --- a/src/layout/col-div.styles.ts +++ b/src/layout/col-div.styles.ts @@ -28,36 +28,33 @@ export const tokens = { export const colDiv = css` ${Object.values(tokens) - .map((token) => `${token}: initial;`) + .map((token) => token + ": initial;") .join("")} position: relative; - - grid-column: var(${tokens.xxsStart}, auto) / - var(${tokens.xxsEnd}, span var(${tokens.xxsSpan}, 1)); + grid-column: var(${tokens.xxsStart}, auto) / var(${tokens.xxsEnd}, span var(${tokens.xxsSpan}, 1)); ${MediaQuery.MinWidth.xs} { - grid-column: var(${tokens.xsStart}, auto) / - var(${tokens.xsEnd}, span var(${tokens.xsSpan}, 1)); + grid-column: var(${tokens.xsStart}, auto) / var(${tokens.xsEnd}, span var(${tokens.xsSpan}, 1)); } + ${MediaQuery.MinWidth.sm} { - grid-column: var(${tokens.smStart}, auto) / - var(${tokens.smEnd}, span var(${tokens.smSpan}, 1)); + grid-column: var(${tokens.smStart}, auto) / var(${tokens.smEnd}, span var(${tokens.smSpan}, 1)); } + ${MediaQuery.MinWidth.md} { - grid-column: var(${tokens.mdStart}, auto) / - var(${tokens.mdEnd}, span var(${tokens.mdSpan}, 1)); + grid-column: var(${tokens.mdStart}, auto) / var(${tokens.mdEnd}, span var(${tokens.mdSpan}, 1)); } + ${MediaQuery.MinWidth.lg} { - grid-column: var(${tokens.lgStart}, auto) / - var(${tokens.lgEnd}, span var(${tokens.lgSpan}, 1)); + grid-column: var(${tokens.lgStart}, auto) / var(${tokens.lgEnd}, span var(${tokens.lgSpan}, 1)); } + ${MediaQuery.MinWidth.xl} { - grid-column: var(${tokens.xlStart}, auto) / - var(${tokens.xlEnd}, span var(${tokens.xlSpan}, 1)); + grid-column: var(${tokens.xlStart}, auto) / var(${tokens.xlEnd}, span var(${tokens.xlSpan}, 1)); } + ${MediaQuery.MinWidth.xxl} { - grid-column: var(${tokens.xxlStart}, auto) / - var(${tokens.xxlEnd}, span var(${tokens.xxlSpan}, 1)); + grid-column: var(${tokens.xxlStart}, auto) / var(${tokens.xxlEnd}, span var(${tokens.xxlSpan}, 1)); } `; diff --git a/src/layout/container.styles.ts b/src/layout/container.styles.ts index a30ebecd33..118bceb5be 100644 --- a/src/layout/container.styles.ts +++ b/src/layout/container.styles.ts @@ -4,28 +4,33 @@ import { MediaQuery } from "../theme"; import { Breakpoint } from "../theme/tokens/breakpoint"; export const container = css` - flex-grow: 1; - margin: 0 auto; position: relative; + flex-grow: 1; width: auto; height: auto; padding: 0 ${Breakpoint["xxs-margin"]}; + margin: 0 auto; ${MediaQuery.MinWidth.xs} { padding: 0 ${Breakpoint["xs-margin"]}; } + ${MediaQuery.MinWidth.sm} { padding: 0 ${Breakpoint["sm-margin"]}; } + ${MediaQuery.MinWidth.md} { padding: 0 ${Breakpoint["md-margin"]}; } + ${MediaQuery.MinWidth.lg} { padding: 0 ${Breakpoint["lg-margin"]}; } + ${MediaQuery.MinWidth.xl} { padding: 0 ${Breakpoint["xl-margin"]}; } + ${MediaQuery.MinWidth.xxl} { padding: 0 ${Breakpoint["xxl-margin"]}; } @@ -36,51 +41,38 @@ export const containerNotStretched = css` `; export const containerGrid = css` - column-gap: ${Breakpoint["xxs-gutter"]}; display: grid; grid-template-columns: repeat(${Breakpoint["xxs-column"]}, minmax(0, 1fr)); + column-gap: ${Breakpoint["xxs-gutter"]}; ${MediaQuery.MinWidth.xs} { + grid-template-columns: repeat(${Breakpoint["xs-column"]}, minmax(0, 1fr)); column-gap: ${Breakpoint["xs-gutter"]}; - grid-template-columns: repeat( - ${Breakpoint["xs-column"]}, - minmax(0, 1fr) - ); } + ${MediaQuery.MinWidth.sm} { + grid-template-columns: repeat(${Breakpoint["sm-column"]}, minmax(0, 1fr)); column-gap: ${Breakpoint["sm-gutter"]}; - grid-template-columns: repeat( - ${Breakpoint["sm-column"]}, - minmax(0, 1fr) - ); } + ${MediaQuery.MinWidth.md} { + grid-template-columns: repeat(${Breakpoint["md-column"]}, minmax(0, 1fr)); column-gap: ${Breakpoint["md-gutter"]}; - grid-template-columns: repeat( - ${Breakpoint["md-column"]}, - minmax(0, 1fr) - ); } + ${MediaQuery.MinWidth.lg} { + grid-template-columns: repeat(${Breakpoint["lg-column"]}, minmax(0, 1fr)); column-gap: ${Breakpoint["lg-gutter"]}; - grid-template-columns: repeat( - ${Breakpoint["lg-column"]}, - minmax(0, 1fr) - ); } + ${MediaQuery.MinWidth.xl} { + grid-template-columns: repeat(${Breakpoint["xl-column"]}, minmax(0, 1fr)); column-gap: ${Breakpoint["xl-gutter"]}; - grid-template-columns: repeat( - ${Breakpoint["xl-column"]}, - minmax(0, 1fr) - ); } + ${MediaQuery.MinWidth.xxl} { + grid-template-columns: repeat(${Breakpoint["xxl-column"]}, minmax(0, 1fr)); column-gap: ${Breakpoint["xxl-gutter"]}; - grid-template-columns: repeat( - ${Breakpoint["xxl-column"]}, - minmax(0, 1fr) - ); } `; diff --git a/src/layout/section.styles.ts b/src/layout/section.styles.ts index a16f7e89b5..3530688101 100644 --- a/src/layout/section.styles.ts +++ b/src/layout/section.styles.ts @@ -5,8 +5,8 @@ export const tokens = { }; export const section = css` - display: block; position: relative; + display: block; `; export const sectionStretched = css``; diff --git a/src/masthead/masthead.styles.ts b/src/masthead/masthead.styles.ts index 211e2faa4b..422ccf5a26 100644 --- a/src/masthead/masthead.styles.ts +++ b/src/masthead/masthead.styles.ts @@ -2,11 +2,8 @@ import { css } from "@linaria/core"; import { Breakpoint, MediaQuery } from "../theme"; -// ============================================================================= -// STYLING -// ============================================================================= export const wrapper = css` - // matches Layout.Container + /* matches Layout.Container */ --sgds-mainnav-padding-x: ${Breakpoint["xxl-margin"]}; --sgds-mainnav-mobile-padding-x: ${Breakpoint["xxl-margin"]}; --sgds-mainnav-max-width: 1440px; diff --git a/src/menu/menu-content.styles.ts b/src/menu/menu-content.styles.ts index 4c311a4530..fccec58ce8 100644 --- a/src/menu/menu-content.styles.ts +++ b/src/menu/menu-content.styles.ts @@ -1,13 +1,6 @@ import { css } from "@linaria/core"; -import { - Border, - Breakpoint, - Colour, - MediaQuery, - Radius, - Shadow, -} from "../theme/tokens"; +import { Border, Breakpoint, Colour, MediaQuery, Radius, Shadow } from "../theme/tokens"; export const tokens = { panel: { @@ -19,16 +12,19 @@ export const tokens = { } as const; export const panel = css` - border-radius: ${Radius["md"]}; - border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; - background: ${Colour["bg"]}; - box-shadow: ${Shadow["md-subtle"]}; - ${tokens.panel.maxHeight}: initial; ${tokens.panel.overflow}: initial; ${tokens.panel.xSpacing}: 0px; - ${tokens.panel.availableWidth}: calc(100vw - var(${tokens.panel - .xSpacing}) * 2); + ${tokens.panel.availableWidth}: calc(100vw - var(${tokens.panel.xSpacing}) * 2); + + min-width: min(15rem, var(${tokens.panel.availableWidth})); + max-width: min(24rem, var(${tokens.panel.availableWidth})); + max-height: var(${tokens.panel.maxHeight}); + overflow-y: var(${tokens.panel.overflow}); + background: ${Colour["bg"]}; + border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; + border-radius: ${Radius["md"]}; + box-shadow: ${Shadow["md-subtle"]}; ${MediaQuery.MaxWidth.sm} { ${tokens.panel.xSpacing}: ${Breakpoint["sm-margin"]}px; @@ -42,11 +38,6 @@ export const panel = css` ${tokens.panel.xSpacing}: ${Breakpoint["xxs-margin"]}px; } - min-width: min(15rem, var(${tokens.panel.availableWidth})); - max-width: min(24rem, var(${tokens.panel.availableWidth})); - max-height: var(${tokens.panel.maxHeight}); - overflow-y: var(${tokens.panel.overflow}); - &:focus { outline: none; } @@ -61,8 +52,8 @@ export const panel = css` &::-webkit-scrollbar-thumb { background: ${Colour["bg-inverse-subtlest"]}; + background-clip: padding-box; border: 5px solid transparent; border-radius: ${Radius["full"]}; - background-clip: padding-box; } `; diff --git a/src/menu/menu-link.styles.ts b/src/menu/menu-link.styles.ts index c98a0aca35..f327ee96cd 100644 --- a/src/menu/menu-link.styles.ts +++ b/src/menu/menu-link.styles.ts @@ -9,23 +9,19 @@ export const menuLinkDiv = css` `; export const link = css` - color: ${Colour["text"]}; - margin: 0 ${Spacing["spacing-8"]}; - + color: ${Colour["text"]}; + ${lineClampCss(2)} + white-space: pre-wrap; border: ${Border["solid"]} transparent; border-width: ${Spacing["spacing-8"]} ${Spacing["spacing-8"]}; - border-radius: ${Radius["md"]}; - ${lineClampCss(2)} - white-space: pre-wrap; - &:hover, &:active, &:focus { - background-color: ${Colour["bg-hover"]}; color: ${Colour["text"]}; + background-color: ${Colour["bg-hover"]}; } &:focus-visible { diff --git a/src/modal-v2/modal-v2.styles.ts b/src/modal-v2/modal-v2.styles.ts index 7aeae32c1f..96dcba8cd6 100644 --- a/src/modal-v2/modal-v2.styles.ts +++ b/src/modal-v2/modal-v2.styles.ts @@ -3,8 +3,7 @@ import { css } from "@linaria/core"; import { MediaQuery, Motion } from "../theme"; const CLOSED_POSITION_OFFSET = "-3%"; -const IS_INITIAL_OR_CLOSE = - ':is([data-status="initial"], [data-status="close"])'; +const IS_INITIAL_OR_CLOSE = ':is([data-status="initial"], [data-status="close"])'; export const tokens = { container: { @@ -14,18 +13,17 @@ export const tokens = { } as const; export const container = css` + ${tokens.container.verticalHeight}: initial; + ${tokens.container.offsetTop}: initial; + position: relative; width: 100%; height: 100%; - overflow: auto; - ${tokens.container.verticalHeight}: initial; - ${tokens.container.offsetTop}: initial; - ${MediaQuery.MaxWidth.sm} { + top: var(${tokens.container.offsetTop}, 0); height: calc(var(${tokens.container.verticalHeight}, 1vh) * 100); - top: var(${tokens.container.offsetTop}, 0px); } &[data-status="initial"] { @@ -78,14 +76,14 @@ export const container = css` export const scrollContainer = css` display: flex; - justify-content: center; align-items: center; + justify-content: center; min-height: 100%; pointer-events: none; `; export const modalContainer = css` - pointer-events: auto; width: 100%; + pointer-events: auto; outline: none; `; diff --git a/src/modal/modal-box.styles.ts b/src/modal/modal-box.styles.ts index d9611d29a0..55df70c36b 100644 --- a/src/modal/modal-box.styles.ts +++ b/src/modal/modal-box.styles.ts @@ -8,10 +8,10 @@ export const box = css` flex-direction: column; width: 40rem; max-height: 70%; + overflow: hidden; background: ${Colour.bg}; - box-shadow: ${Shadow["lg-strong"]}; border-radius: ${Radius["lg"]}; - overflow: hidden; + box-shadow: ${Shadow["lg-strong"]}; ${MediaQuery.MaxWidth.md} { width: 90%; @@ -27,8 +27,8 @@ export const closeButton = css` color: ${Colour.icon}; svg { - height: 2rem; width: 2rem; + height: 2rem; } ${MediaQuery.MaxWidth.sm} { diff --git a/src/modal/modal.styles.ts b/src/modal/modal.styles.ts index 7ab20b2d69..95c4dbdd87 100644 --- a/src/modal/modal.styles.ts +++ b/src/modal/modal.styles.ts @@ -10,20 +10,20 @@ export const tokens = { } as const; export const container = css` + ${tokens.container.verticalHeight}: initial; + ${tokens.container.offsetTop}: initial; + position: relative; display: flex; - justify-content: center; align-items: center; - height: 100%; + justify-content: center; width: 100%; + height: 100%; overflow: hidden; - ${tokens.container.verticalHeight}: initial; - ${tokens.container.offsetTop}: initial; - ${MediaQuery.MaxWidth.sm} { + top: var(${tokens.container.offsetTop}, 0); height: calc(var(${tokens.container.verticalHeight}, 1vh) * 100); - top: var(${tokens.container.offsetTop}, 0px); } `; diff --git a/src/overlay/overlay.styles.ts b/src/overlay/overlay.styles.ts index 9f1deb0004..4d33cc6514 100644 --- a/src/overlay/overlay.styles.ts +++ b/src/overlay/overlay.styles.ts @@ -16,12 +16,12 @@ export const tokens = { export const root = css` position: fixed; - left: 0; top: 0; - height: 0; - width: 0; - visibility: hidden; + left: 0; z-index: var(${tokens.root.zIndex}); + visibility: hidden; + width: 0; + height: 0; :global() { .${tokens.global.overlayOpenClass} { @@ -44,15 +44,15 @@ export const root = css` `; export const rootShow = css` - height: 100%; - width: 100vw; visibility: visible; + width: 100vw; + height: 100%; `; export const wrapper = css` position: absolute; - left: 0; top: 0; + left: 0; background-color: ${Colour["overlay-strong"]}; backdrop-filter: none; transition: opacity 200ms ease; @@ -68,19 +68,19 @@ export const wrapperBackgroundBlur = css` export const wrapperShow = css` visibility: visible; - opacity: 1; - pointer-events: auto; - height: 100%; width: 100vw; + height: 100%; + pointer-events: auto; + opacity: 1; `; export const wrapperHide = css` visibility: hidden; + width: 0; + height: 0; + pointer-events: none; opacity: 0; transition-delay: 400ms; - pointer-events: none; - height: 0; - width: 0; `; export const wrapperDisableTransition = css` diff --git a/src/pagination/pagination.styles.ts b/src/pagination/pagination.styles.ts index 5c5491ca12..7bc8c1d54b 100644 --- a/src/pagination/pagination.styles.ts +++ b/src/pagination/pagination.styles.ts @@ -9,10 +9,9 @@ export const paginationWrapper = css` `; export const paginationList = css` - align-self: flex-start; - display: flex; align-items: center; + align-self: flex-start; ${MediaQuery.MaxWidth.lg} { align-self: center; @@ -26,20 +25,18 @@ export const paginationMenu = css` export const iconButton = css` display: flex; - justify-content: center; align-items: center; - - outline: none; - border-radius: ${Radius.sm}; - height: 2.5rem; + justify-content: center; width: 2.5rem; + height: 2.5rem; padding: 0 ${Spacing["spacing-8"]}; - color: ${Colour["icon-primary"]}; + outline: none; + border-radius: ${Radius.sm}; svg { - height: 1.25rem; width: 1.25rem; + height: 1.25rem; } &:disabled { @@ -58,65 +55,59 @@ export const iconButtonNavigation = css` `; export const pageItem = css` - outline: none; - margin: ${Spacing["spacing-4"]}; - box-shadow: none; - border: ${Border["width-010"]} ${Border.solid} ${Colour.border}; - border-radius: ${Radius.sm}; min-width: 2.5rem; height: 2.5rem; padding: 0 ${Spacing["spacing-8"]}; - - background: ${Colour.bg}; - cursor: pointer; + margin: ${Spacing["spacing-4"]}; + color: ${Colour.text}; ${Font["body-baseline-regular"]}; text-align: center; - color: ${Colour.text}; + cursor: pointer; + outline: none; + background: ${Colour.bg}; + border: ${Border["width-010"]} ${Border.solid} ${Colour.border}; + border-radius: ${Radius.sm}; + box-shadow: none; &:hover, &:focus-visible { - border-color: ${Colour["bg-hover"]}; - background: ${Colour["bg-hover"]}; - color: ${Colour["text-hover"]}; font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-hover"]}; + background: ${Colour["bg-hover"]}; + border-color: ${Colour["bg-hover"]}; } `; export const pageItemSelected = css` - border-color: ${Colour["bg-primary"]}; - background: ${Colour["bg-primary"]}; - color: ${Colour["text-inverse"]}; font-weight: ${Font.Spec["weight-bold"]}; + color: ${Colour["text-inverse"]}; + background: ${Colour["bg-primary"]}; + border-color: ${Colour["bg-primary"]}; &:hover, &:focus-visible { - border-color: ${Colour["bg-selected-strongest-hover"]}; - background: ${Colour["bg-selected-strongest-hover"]}; - color: ${Colour["text-inverse"]}; font-weight: ${Font.Spec["weight-bold"]}; + color: ${Colour["text-inverse"]}; + background: ${Colour["bg-selected-strongest-hover"]}; + border-color: ${Colour["bg-selected-strongest-hover"]}; } `; export const ellipsisContainer = css` position: relative; - display: flex; - justify-content: center; align-items: center; - + justify-content: center; margin: ${Spacing["spacing-4"]}; - cursor: pointer; `; export const paginationMobileInput = css` display: flex; - justify-content: center; align-items: center; - + justify-content: center; margin: ${Spacing["spacing-4"]}; - color: ${Colour.text}; `; @@ -143,24 +134,21 @@ export const inputView = css` export const hover = css` position: absolute; top: calc(${Spacing["spacing-8"]} * -1); - transform: translateY(-100%); - display: flex; align-items: center; justify-content: center; - - border: none; - border-radius: ${Radius.sm}; width: max-content; padding: ${Spacing["spacing-4"]} ${Spacing["spacing-12"]}; - background: ${Colour["bg-hover"]}; - ${Font["body-xs-regular"]} color: ${Colour["text-hover"]}; + background: ${Colour["bg-hover"]}; + border: none; + border-radius: ${Radius.sm}; + transform: translateY(-100%); `; export const inputSelectWrapper = css` - margin-left: ${Spacing["spacing-4"]}; width: 10rem; + margin-left: ${Spacing["spacing-4"]}; `; diff --git a/src/pill/pill.styles.ts b/src/pill/pill.styles.ts index 37a32cdae7..acd7a95800 100644 --- a/src/pill/pill.styles.ts +++ b/src/pill/pill.styles.ts @@ -3,15 +3,16 @@ import { css } from "@linaria/core"; import { Border, Colour, Font, Radius } from "../theme"; export const wrapperBase = css` - border-radius: ${Radius["full"]}; - padding: 0.125rem 0.5rem; - width: fit-content; - max-width: 100%; ${Font["body-xs-semibold"]} display: flex; - align-items: center; gap: 0.25rem; + align-items: center; + width: fit-content; + max-width: 100%; + padding: 0.125rem 0.5rem; border: ${Border["width-010"]} ${Border.solid}; + border-radius: ${Radius["full"]}; + svg { flex-shrink: 0; } @@ -51,51 +52,51 @@ export const wrapperSolidPrimary = css` `; export const wrapperOutlineBlack = css` + color: ${Colour.text}; background: ${Colour.bg}; border-color: ${Colour.border}; - color: ${Colour.text}; `; export const wrapperOutlineGrey = css` + color: ${Colour["text-subtler"]}; background: ${Colour["bg-stronger"]}; border-color: ${Colour["border-strong"]}; - color: ${Colour["text-subtler"]}; `; export const wrapperOutlineGreen = css` + color: ${Colour["text-success"]}; background: ${Colour["bg-success"]}; border-color: ${Colour["border-success"]}; - color: ${Colour["text-success"]}; `; export const wrapperOutlineYellow = css` + color: ${Colour["text-warning"]}; background: ${Colour["bg-warning"]}; border-color: ${Colour["border-warning"]}; - color: ${Colour["text-warning"]}; `; export const wrapperOutlineRed = css` + color: ${Colour["text-error"]}; background: ${Colour["bg-error"]}; border-color: ${Colour["border-error"]}; - color: ${Colour["text-error"]}; `; export const wrapperOutlineBlue = css` + color: ${Colour["text-info"]}; background: ${Colour["bg-info"]}; border-color: ${Colour["border-info"]}; - color: ${Colour["text-info"]}; `; export const wrapperOutlinePrimary = css` + color: ${Colour["text-primary"]}; background: ${Colour["bg-primary-subtlest"]}; border-color: ${Colour["border-primary"]}; - color: ${Colour["text-primary"]}; `; export const label = css` - overflow: hidden; display: -webkit-box; - -webkit-box-orient: vertical; + overflow: hidden; -webkit-line-clamp: 2; text-align: left; + -webkit-box-orient: vertical; `; diff --git a/src/popover-v2/popover-inline/popover-inline.styles.ts b/src/popover-v2/popover-inline/popover-inline.styles.ts index d4f4746dd5..75d7a14080 100644 --- a/src/popover-v2/popover-inline/popover-inline.styles.ts +++ b/src/popover-v2/popover-inline/popover-inline.styles.ts @@ -3,8 +3,8 @@ import { css } from "@linaria/core"; import { Colour } from "../../theme"; export const popoverInlineText = css` - color: ${Colour["text-primary"]}; font-weight: 600; + color: ${Colour["text-primary"]}; text-underline-position: under; &[data-underline-style="underline"] { @@ -31,8 +31,8 @@ export const popoverInlineText = css` } svg { - height: 1lh; /* align vertically */ width: 1em; /* scale icon with font size */ + height: 1lh; /* align vertically */ vertical-align: top; } `; diff --git a/src/popover-v2/popover-trigger.styles.ts b/src/popover-v2/popover-trigger.styles.ts index b12d2655fd..2296fd575a 100644 --- a/src/popover-v2/popover-trigger.styles.ts +++ b/src/popover-v2/popover-trigger.styles.ts @@ -1,8 +1,8 @@ import { css } from "@linaria/core"; export const triggerContainer = css` + position: relative; display: inline; width: fit-content; cursor: pointer; - position: relative; `; diff --git a/src/popover-v2/popover.styles.ts b/src/popover-v2/popover.styles.ts index 0452cf69c9..6dc8377d87 100644 --- a/src/popover-v2/popover.styles.ts +++ b/src/popover-v2/popover.styles.ts @@ -33,18 +33,20 @@ export const popoverCard = css` &::-webkit-scrollbar-thumb { background: ${Colour["bg-inverse-subtlest"]}; + background-clip: padding-box; border: 5px solid transparent; border-radius: ${Radius.full}; - background-clip: padding-box; } `; export const popoverCardWithMaxHeight = css` ${tokens.popoverCard.maxHeight}: initial; + max-height: var(${tokens.popoverCard.maxHeight}); `; export const popoverCardWithOverflow = css` ${tokens.popoverCard.overflowY}: initial; + overflow-y: var(${tokens.popoverCard.overflowY}); `; diff --git a/src/radio-button/radio-button.styles.ts b/src/radio-button/radio-button.styles.ts index 51dcb9fc24..39ba1e3dd2 100644 --- a/src/radio-button/radio-button.styles.ts +++ b/src/radio-button/radio-button.styles.ts @@ -5,25 +5,25 @@ import { Colour, Motion } from "../theme"; export const classes = {} as const; export const container = css` + position: relative; display: flex; - justify-content: center; align-items: center; - position: relative; + justify-content: center; &[data-display-size="small"] { - height: 1.5rem; width: 1.5rem; + height: 1.5rem; } &[data-display-size="default"] { - height: 2rem; width: 2rem; + height: 2rem; } `; export const icon = css` - height: 100%; width: 100%; + height: 100%; transition: ${Motion["duration-150"]} ${Motion["ease-default"]}; `; @@ -45,12 +45,11 @@ export const checkedIconDisabled = css` export const input = css` position: absolute; - height: 100%; - width: 100%; - cursor: not-allowed; z-index: 1; - + width: 100%; + height: 100%; appearance: none; + cursor: not-allowed; background: transparent; border: none; `; diff --git a/src/shared/clickable-icon/clickable-icon.styles.ts b/src/shared/clickable-icon/clickable-icon.styles.ts index ce108ed502..218dac7f34 100644 --- a/src/shared/clickable-icon/clickable-icon.styles.ts +++ b/src/shared/clickable-icon/clickable-icon.styles.ts @@ -4,21 +4,21 @@ import { Colour, Spacing } from "../../theme"; export const main = css` display: flex; - justify-content: center; align-items: center; + justify-content: center; padding: ${Spacing["spacing-24"]}; + cursor: pointer; background-color: transparent; border: none; - cursor: pointer; img { - height: 1rem; width: 1rem; + height: 1rem; } svg { - height: 1.125rem; width: 1.125rem; + height: 1.125rem; } `; diff --git a/src/shared/component-loading-spinner/component-loading-spinner.styles.ts b/src/shared/component-loading-spinner/component-loading-spinner.styles.ts index 5bdf6a0775..4009709a1e 100644 --- a/src/shared/component-loading-spinner/component-loading-spinner.styles.ts +++ b/src/shared/component-loading-spinner/component-loading-spinner.styles.ts @@ -6,26 +6,25 @@ export const tokens = { } as const; export const outerRing = css` - display: inline-block; position: relative; + display: inline-block; width: var(${tokens.rootSize}, 1em); height: var(${tokens.rootSize}, 1em); color: var(${tokens.rootColour}, currentColor); `; export const innerRing = css` - box-sizing: border-box; - display: block; position: absolute; top: 1px; + box-sizing: border-box; + display: block; width: calc(100% - 2px); height: calc(100% - 2px); - border-width: 2px; + border-color: currentcolor transparent transparent; border-style: solid; + border-width: 2px; border-radius: 100%; - border-color: currentColor transparent transparent transparent; - animation: component-loading-spinner-rotate 1.2s - cubic-bezier(0.5, 0, 0.5, 1) infinite; + animation: component-loading-spinner-rotate 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; @keyframes component-loading-spinner-rotate { 0% { diff --git a/src/shared/dropdown-list/dropdown-label.styles.ts b/src/shared/dropdown-list/dropdown-label.styles.ts index cb53582271..4eaa1015f2 100644 --- a/src/shared/dropdown-list/dropdown-label.styles.ts +++ b/src/shared/dropdown-list/dropdown-label.styles.ts @@ -20,9 +20,9 @@ export const tokens = { // PRIMARY TEXT // ----------------------------------------------------------------------------- export const primaryText = css` + width: 100%; font-weight: ${Font.Spec["weight-regular"]}; color: ${Colour["text"]}; - width: 100%; overflow-wrap: break-word; `; @@ -51,8 +51,8 @@ export const primaryTextTruncateEnd = css` // SECONDARY TEXT // ----------------------------------------------------------------------------- export const secondaryText = css` - color: ${Colour["text-subtlest"]}; width: 100%; + color: ${Colour["text-subtlest"]}; overflow-wrap: break-word; `; @@ -85,9 +85,9 @@ export const matchedText = css` // LABEL // ----------------------------------------------------------------------------- export const label = css` - text-align: left; width: 100%; overflow: hidden; + text-align: left; overflow-wrap: break-word; ${Font["body-baseline-regular"]} `; @@ -117,9 +117,9 @@ export const truncateFirstLine = css` export const truncateSecondLine = css` text-overflow: ellipsis; + text-align: right; white-space: nowrap; direction: rtl; - text-align: right; `; export const truncateLineSingle = css` diff --git a/src/shared/dropdown-list/dropdown-list.styles.ts b/src/shared/dropdown-list/dropdown-list.styles.ts index 95e53940e6..837e3db767 100644 --- a/src/shared/dropdown-list/dropdown-list.styles.ts +++ b/src/shared/dropdown-list/dropdown-list.styles.ts @@ -1,14 +1,6 @@ import { css } from "@linaria/core"; -import { - Border, - Breakpoint, - Colour, - Font, - MediaQuery, - Radius, - Spacing, -} from "../../theme"; +import { Border, Breakpoint, Colour, Font, MediaQuery, Radius, Spacing } from "../../theme"; import * as elementWithDropdownStyles from "../dropdown-wrapper/element-with-dropdown.styles"; export const tokens = { @@ -24,20 +16,24 @@ export const tokens = { // MAIN STYLES // ----------------------------------------------------------------------------- export const container = css` + ${elementWithDropdownStyles.tokens.availableHeight}: initial; + ${tokens.xSpacing}: 0; + ${tokens.availableWidth}: calc(100vw - var(${tokens.xSpacing}) * 2); + ${Font["body-baseline-regular"]} + width: var(${tokens.containerWidth}); + min-width: var(${tokens.containerMinWidth}, min(23rem, var(${tokens.availableWidth}))); + max-width: var(${tokens.availableWidth}); + max-height: min(27rem, var(${elementWithDropdownStyles.tokens.availableHeight}, 9999px)); + overflow: hidden; + overflow-y: auto; + background: ${Colour["bg"]}; border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; border-radius: ${Radius["sm"]}; - background: ${Colour["bg"]}; - - ${tokens.xSpacing}: 0px; - ${elementWithDropdownStyles.tokens.availableHeight}: initial; - ${tokens.availableWidth}: calc( - 100vw - var(${tokens.xSpacing}) * 2 - ); ${MediaQuery.MaxWidth.sm} { - ${tokens.xSpacing}: ${Breakpoint["sm-margin"]}; max-height: 15rem; + ${tokens.xSpacing}: ${Breakpoint["sm-margin"]}; } ${MediaQuery.MaxWidth.xs} { @@ -48,19 +44,6 @@ export const container = css` ${tokens.xSpacing}: ${Breakpoint["xxs-margin"]}; } - max-width: var(${tokens.availableWidth}); - min-width: var( - ${tokens.containerMinWidth}, - min(23rem, var(${tokens.availableWidth})) - ); - width: var(${tokens.containerWidth}); - max-height: min( - 27rem, - var(${elementWithDropdownStyles.tokens.availableHeight}, 9999px) - ); - overflow: hidden; - overflow-y: auto; - &::-webkit-scrollbar { width: 14px; } @@ -71,9 +54,9 @@ export const container = css` &::-webkit-scrollbar-thumb { background: ${Colour["bg-inverse-subtlest"]}; + background-clip: padding-box; border: 5px solid transparent; border-radius: ${Radius["full"]}; - background-clip: padding-box; } `; @@ -82,8 +65,8 @@ export const containerVariantSmall = css` `; export const list = css` - background: transparent; padding: ${Spacing["spacing-8"]}; + background: transparent; `; export const listbox = css` @@ -95,13 +78,13 @@ export const listbox = css` // ----------------------------------------------------------------------------- export const listItem = css` display: flex; - align-items: flex-start; gap: ${Spacing["spacing-8"]}; + align-items: flex-start; padding: ${Spacing["spacing-12"]} ${Spacing["spacing-8"]}; cursor: pointer; + outline: none; border: none; border-radius: ${Radius["none"]}; - outline: none; `; export const listItemActive = css` @@ -118,8 +101,8 @@ export const listItemDisabled = css` export const baseIndicatorStyle = css` flex-shrink: 0; - height: 1lh; width: 1rem; + height: 1lh; `; export const selectedIndicator = css` @@ -128,8 +111,8 @@ export const selectedIndicator = css` export const baseCheckboxIndicatorStyle = css` flex-shrink: 0; - height: 1lh; width: 1lh; + height: 1lh; `; export const checkboxSelectedIndicator = css` @@ -148,16 +131,16 @@ export const checkboxDisabledIndicator = css` // ELEMENT STYLES // ----------------------------------------------------------------------------- export const selectAllContainer = css` - width: 100%; display: flex; justify-content: flex-end; + width: 100%; `; export const baseButton = css` - cursor: pointer; overflow: hidden; - color: ${Colour["text-primary"]}; font-size: inherit; + color: ${Colour["text-primary"]}; + cursor: pointer; `; export const selectAllButton = css` @@ -170,18 +153,18 @@ export const tryAgainButton = css` `; export const resultStateContainer = css` - width: 100%; display: flex; - padding: ${Spacing["spacing-12"]} ${Spacing["spacing-16"]}; align-items: center; + width: 100%; + padding: ${Spacing["spacing-12"]} ${Spacing["spacing-16"]}; color: ${Colour["text"]}; `; export const labelIcon = css` + width: 1em; + height: 1em; margin-right: ${Spacing["spacing-4"]}; color: ${Colour["icon-error"]}; - height: 1em; - width: 1em; `; export const spinner = css` @@ -190,7 +173,7 @@ export const spinner = css` `; export const noResultDescContainer = css` - color: ${Colour["text-subtle"]}; padding: 0 ${Spacing["spacing-16"]}; padding-bottom: ${Spacing["spacing-12"]}; + color: ${Colour["text-subtle"]}; `; diff --git a/src/shared/dropdown-list/dropdown-search.styles.ts b/src/shared/dropdown-list/dropdown-search.styles.ts index 61608b4a1c..505c3a9e82 100644 --- a/src/shared/dropdown-list/dropdown-search.styles.ts +++ b/src/shared/dropdown-list/dropdown-search.styles.ts @@ -7,10 +7,10 @@ import { Colour, Font, Radius, Spacing } from "../../theme"; // ============================================================================= export const container = css` - background: ${Colour["bg-strong"]}; - border-radius: ${Radius["sm"]}; display: flex; align-items: center; + background: ${Colour["bg-strong"]}; + border-radius: ${Radius["sm"]}; ${Font["body-baseline-regular"]} `; @@ -19,10 +19,10 @@ export const containerVariantSmall = css` `; export const searchBox = css` - flex: 1; display: flex; - align-items: center; + flex: 1; gap: ${Spacing["spacing-8"]}; + align-items: center; padding: 10px ${Spacing["spacing-8"]}; `; @@ -35,25 +35,25 @@ export const searchInput = css` `; export const searchIcon = css` - color: ${Colour["icon"]}; flex-shrink: 0; - height: 1em; width: 1em; + height: 1em; + color: ${Colour["icon"]}; `; export const clearButton = css` + box-sizing: content-box; flex-shrink: 0; align-self: stretch; - box-sizing: content-box; padding: ${Spacing["spacing-8"]}; - margin-left: -${Spacing["spacing-8"]}; + margin-left: calc(${Spacing["spacing-8"]} * -1); + font-size: inherit; color: ${Colour["icon"]}; cursor: pointer; - font-size: inherit; svg { flex-shrink: 0; - height: 1em; width: 1em; + height: 1em; } `; diff --git a/src/shared/dropdown-list/expandable-element.styles.ts b/src/shared/dropdown-list/expandable-element.styles.ts index 653a8973bc..e2ab817ea9 100644 --- a/src/shared/dropdown-list/expandable-element.styles.ts +++ b/src/shared/dropdown-list/expandable-element.styles.ts @@ -8,8 +8,8 @@ import { Colour, Font, Motion, Spacing } from "../../theme"; export const selector = css` display: flex; - align-items: center; gap: ${Spacing["spacing-8"]}; + align-items: center; width: 100%; ${Font["body-baseline-regular"]} @@ -44,9 +44,9 @@ export const iconContainer = css` transition: transform ${Motion["duration-250"]} ${Motion["ease-default"]}; svg { - color: ${Colour["icon"]}; - height: 1em; width: 1em; + height: 1em; + color: ${Colour["icon"]}; } `; diff --git a/src/shared/dropdown-list/nested-dropdown-list.styles.ts b/src/shared/dropdown-list/nested-dropdown-list.styles.ts index e50dabd7c1..3a65acd79a 100644 --- a/src/shared/dropdown-list/nested-dropdown-list.styles.ts +++ b/src/shared/dropdown-list/nested-dropdown-list.styles.ts @@ -23,15 +23,15 @@ export const listItemContainerHidden = css` `; export const listItem = css` - flex: 1; display: flex; - align-items: flex-start; + flex: 1; gap: ${Spacing["spacing-8"]}; + align-items: flex-start; padding: ${Spacing["spacing-12"]} ${Spacing["spacing-8"]}; - cursor: pointer; overflow: hidden; - border-radius: ${Radius["none"]}; + cursor: pointer; outline: none; + border-radius: ${Radius["none"]}; `; export const listItemToggleable = css` @@ -44,8 +44,9 @@ export const listItemActive = css` export const indent = css` ${tokens.level}: 0; - height: 1px; + width: calc((1lh + ${Spacing["spacing-8"]}) * var(${tokens.level})); + height: 1px; `; export const expandButton = css` @@ -57,8 +58,7 @@ export const expandButton = css` svg { width: 1lh; height: 1lh; - transition: transform ${Motion["duration-350"]} - ${Motion["ease-standard"]}; + transition: transform ${Motion["duration-350"]} ${Motion["ease-standard"]}; } `; @@ -75,11 +75,11 @@ export const unexpandableIndicator = css` `; export const selectionIndicator = css` - flex-shrink: 0; - height: 1lh; - width: ${Spacing["spacing-16"]}; display: flex; + flex-shrink: 0; justify-content: center; + width: ${Spacing["spacing-16"]}; + height: 1lh; `; export const selectionIndicatorNested = css` @@ -88,7 +88,7 @@ export const selectionIndicatorNested = css` export const checkboxMixedIndicator = css` flex-shrink: 0; - height: 1lh; width: 1lh; + height: 1lh; color: ${Colour["icon-selected"]}; `; diff --git a/src/shared/dropdown-wrapper/dropdown-wrapper.styles.ts b/src/shared/dropdown-wrapper/dropdown-wrapper.styles.ts index 5d06864a07..1cdfd967f2 100644 --- a/src/shared/dropdown-wrapper/dropdown-wrapper.styles.ts +++ b/src/shared/dropdown-wrapper/dropdown-wrapper.styles.ts @@ -15,8 +15,8 @@ export const labelContainer = css` export const valueLabel = css` ${Font["body-baseline-regular"]} - text-align: left; overflow: hidden; + text-align: left; &[data-variant="small"] { ${Font["body-md-regular"]} diff --git a/src/shared/fade-wrapper/fade-wrapper.styles.ts b/src/shared/fade-wrapper/fade-wrapper.styles.ts index 3d430fd2ec..9171f70541 100644 --- a/src/shared/fade-wrapper/fade-wrapper.styles.ts +++ b/src/shared/fade-wrapper/fade-wrapper.styles.ts @@ -12,13 +12,13 @@ export const wrapper = css` `; export const fade = css` - width: 64px; - height: 100%; - top: 0; position: absolute; - pointer-events: none; + top: 0; display: flex; align-items: center; + width: 64px; + height: 100%; + pointer-events: none; `; export const fadeLeft = css` @@ -28,7 +28,7 @@ export const fadeLeft = css` background-image: linear-gradient( to right, var(${tokens.backgroundColor}, ${Colour.bg}), - rgba(255, 255, 255, 0.001) + rgb(255 255 255 / 0.1%) ); } `; @@ -40,7 +40,7 @@ export const fadeRight = css` background-image: linear-gradient( to left, var(${tokens.backgroundColor}, ${Colour.bg}), - rgba(255, 255, 255, 0.001) + rgb(255 255 255 / 0.1%) ); } `; @@ -49,8 +49,7 @@ export const content = css` position: relative; width: 100%; height: 100%; - overflow-x: scroll; - overflow-y: hidden; + overflow: scroll hidden; white-space: nowrap; scrollbar-width: none; /* Firefox */ -ms-overflow-style: none; /* IE 10+ */ @@ -64,10 +63,10 @@ export const fadeIndicatorButton = css` ${MediaQuery.MaxWidth.lg} { display: flex; - height: 100%; + align-items: center; width: 100%; + height: 100%; padding: unset; - align-items: center; svg { color: ${Colour["icon"]}; diff --git a/src/shared/image-placeholder/image-placeholder.styles.ts b/src/shared/image-placeholder/image-placeholder.styles.ts index 1e8ee11a1d..18c62782fb 100644 --- a/src/shared/image-placeholder/image-placeholder.styles.ts +++ b/src/shared/image-placeholder/image-placeholder.styles.ts @@ -3,15 +3,15 @@ import { css } from "@linaria/core"; import { Colour } from "../../theme"; export const placeholder = css` - background-color: ${Colour["bg-stronger"]}; display: flex; align-items: center; justify-content: center; padding: 1rem; + background-color: ${Colour["bg-stronger"]}; svg { - min-width: 48px; width: 18%; + min-width: 48px; height: auto; color: ${Colour["icon-subtle"]}; } diff --git a/src/shared/input-wrapper/input-wrapper.styles.ts b/src/shared/input-wrapper/input-wrapper.styles.ts index 1174948afd..1915641376 100644 --- a/src/shared/input-wrapper/input-wrapper.styles.ts +++ b/src/shared/input-wrapper/input-wrapper.styles.ts @@ -3,22 +3,21 @@ import { css } from "@linaria/core"; import { Border, Colour, Font, Radius, Spacing } from "../../theme"; export const inputBox = css` + background: ${Colour["bg"]}; border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; border-radius: ${Radius["sm"]}; - background: ${Colour["bg"]}; &:focus-within, &[data-focused="true"] { + outline: ${Border["width-020"]} ${Border["solid"]} ${Colour["border-focus"]}; outline-offset: -1px; - outline: ${Border["width-020"]} ${Border["solid"]} - ${Colour["border-focus"]}; } `; export const inputBoxReadOnly = css` - border-color: transparent; padding: 0; background: transparent !important; + border-color: transparent; &:focus-within, &[data-focused="true"] { @@ -27,8 +26,8 @@ export const inputBoxReadOnly = css` `; export const inputBoxDisabled = css` - background: ${Colour["bg-disabled"]}; cursor: not-allowed; + background: ${Colour["bg-disabled"]}; &:focus-within, &[data-focused="true"] { @@ -46,8 +45,8 @@ export const inputBoxError = css` `; export const inputBoxNoBorder = css` - border-color: transparent; background: transparent; + border-color: transparent; &:focus-within, &[data-focused="true"] { @@ -56,11 +55,11 @@ export const inputBoxNoBorder = css` `; export const inputWrapper = css` + position: relative; display: flex; align-items: center; - position: relative; - height: max-content; width: 100%; + height: max-content; padding: 0 ${Spacing["spacing-16"]} 0 ${Spacing["spacing-16"]}; `; @@ -74,14 +73,14 @@ export const inputWrapperPositionRight = css` export const basicInput = css` ${Font["body-baseline-regular"]} - color: ${Colour["text"]}; display: block; + padding: 0; + margin: 0; + color: ${Colour["text"]}; + outline: none; background: transparent; border: none; - outline: none; box-shadow: none; - padding: 0; - margin: 0; &:disabled { color: ${Colour["text-subtler"]}; @@ -96,17 +95,17 @@ export const basicInput = css` color: ${Colour["text-subtler"]}; } - // Chrome, Safari, Edge, Opera + /* Chrome, Safari, Edge, Opera */ &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { - -webkit-appearance: none; margin: 0; + appearance: none; } - // Safari (remove top shadow) + /* Safari (remove top shadow) */ --webkit-appearance: none; - // Firefox + /* Firefox */ --moz-appearance: textfield; `; @@ -115,9 +114,9 @@ export const basicInputSmall = css` `; export const basicButton = css` + outline: none; background: transparent; border: none; - outline: none; &:focus, &:active { @@ -125,8 +124,7 @@ export const basicButton = css` } &:focus-visible { - outline: ${Border["width-010"]} ${Border["solid"]} - ${Colour["border-focus"]}; + outline: ${Border["width-010"]} ${Border["solid"]} ${Colour["border-focus"]}; border-radius: ${Radius["sm"]}; } `; diff --git a/src/shared/internal-calendar/calendar-dropdown.styles.ts b/src/shared/internal-calendar/calendar-dropdown.styles.ts index 5350c87f78..5f60207362 100644 --- a/src/shared/internal-calendar/calendar-dropdown.styles.ts +++ b/src/shared/internal-calendar/calendar-dropdown.styles.ts @@ -16,15 +16,14 @@ export const calendarWrapper = css` ${tokens.verticalInset}: ${Spacing["spacing-24"]}; ${tokens.horizontalInset}: ${Spacing["spacing-20"]}; ${tokens.headerBottomSpacing}: ${Spacing["spacing-4"]}; - - border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; - border-radius: ${Radius["sm"]}; - overflow: hidden; - ${tokens.width}: initial; + width: var(${tokens.width}); - max-width: 41rem; min-width: 21rem; + max-width: 41rem; + overflow: hidden; + border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; + border-radius: ${Radius["sm"]}; ${MediaQuery.MaxWidth.sm} { min-width: 17.5rem; diff --git a/src/shared/internal-calendar/calendar-manager.styles.ts b/src/shared/internal-calendar/calendar-manager.styles.ts index 039c39e8b1..c024ff06de 100644 --- a/src/shared/internal-calendar/calendar-manager.styles.ts +++ b/src/shared/internal-calendar/calendar-manager.styles.ts @@ -1,7 +1,7 @@ import { css } from "@linaria/core"; import { Colour, Font } from "../../theme"; -import * as calendarDropdownStyles from "../internal-calendar/calendar-dropdown.styles"; +import { tokens as calendarDropdownTokens } from "../internal-calendar/calendar-dropdown.styles"; // ============================================================================= // STYLING @@ -10,14 +10,14 @@ import * as calendarDropdownStyles from "../internal-calendar/calendar-dropdown. // ICONS // ----------------------------------------------------------------------------- export const icon = css` - color: ${Colour["icon"]}; - height: 1rem; width: 1rem; + height: 1rem; + color: ${Colour["icon"]}; `; export const iconChevronDown = css` - transition: transform 250ms ease-in-out; margin-left: 0.5rem; + transition: transform 250ms ease-in-out; `; export const iconChevronDownExpanded = css` @@ -29,38 +29,35 @@ export const iconChevronDownExpanded = css` // ----------------------------------------------------------------------------- export const container = css` position: relative; - width: 100%; display: flex; flex-direction: column; - - padding-top: var(${calendarDropdownStyles.tokens.verticalInset}); - padding-bottom: var(${calendarDropdownStyles.tokens.verticalInset}); + width: 100%; + padding-top: var(${calendarDropdownTokens.verticalInset}); + padding-bottom: var(${calendarDropdownTokens.verticalInset}); `; export const toggleZone = css` + position: relative; display: flex; flex: 1; - position: relative; `; export const defaultView = css` - isolation: isolate; width: 100%; - - padding-left: var(${calendarDropdownStyles.tokens.horizontalInset}); - padding-right: var(${calendarDropdownStyles.tokens.horizontalInset}); + padding-right: var(${calendarDropdownTokens.horizontalInset}); + padding-left: var(${calendarDropdownTokens.horizontalInset}); + isolation: isolate; `; export const optionsOverlay = css` position: absolute; top: 0; left: 0; - height: 100%; width: 100%; + height: 100%; + padding-right: var(${calendarDropdownTokens.horizontalInset}); + padding-left: var(${calendarDropdownTokens.horizontalInset}); background: ${Colour["bg"]}; - - padding-left: var(${calendarDropdownStyles.tokens.horizontalInset}); - padding-right: var(${calendarDropdownStyles.tokens.horizontalInset}); `; // ----------------------------------------------------------------------------- @@ -69,16 +66,7 @@ export const optionsOverlay = css` export const header = css` display: flex; justify-content: space-between; - - padding-left: var( - ${calendarDropdownStyles.tokens.horizontalInset}, - var(${calendarDropdownStyles.tokens.horizontalInset}) - ); - padding-right: var( - ${calendarDropdownStyles.tokens.horizontalInset}, - var(${calendarDropdownStyles.tokens.horizontalInset}) - ); - padding-bottom: var(${calendarDropdownStyles.tokens.headerBottomSpacing}); + padding: 0 var(${calendarDropdownTokens.horizontalInset}) var(${calendarDropdownTokens.headerBottomSpacing}); `; export const headerInputDropdown = css` @@ -86,12 +74,12 @@ export const headerInputDropdown = css` `; export const dropdownButton = css` - border: none; display: flex; align-items: center; padding: 0.5rem; - background: transparent; cursor: pointer; + background: transparent; + border: none; `; export const dropdownText = css` @@ -104,8 +92,8 @@ export const headerArrows = css` `; export const headerArrowButton = css` - margin: auto 0; padding: 0.75rem; + margin: auto 0; &:disabled { cursor: not-allowed; @@ -125,10 +113,8 @@ export const hidden = css` export const actionButtonSection = css` display: flex; gap: 0.5rem; + padding: 0 var(${calendarDropdownTokens.horizontalInset}); margin-top: 1.5rem; - - padding-left: var(${calendarDropdownStyles.tokens.horizontalInset}); - padding-right: var(${calendarDropdownStyles.tokens.horizontalInset}); `; export const actionButton = css` diff --git a/src/shared/internal-calendar/day-cell/day-cell.styles.ts b/src/shared/internal-calendar/day-cell/day-cell.styles.ts index 9e736fc30e..a22acb1e9d 100644 --- a/src/shared/internal-calendar/day-cell/day-cell.styles.ts +++ b/src/shared/internal-calendar/day-cell/day-cell.styles.ts @@ -3,10 +3,10 @@ import { css } from "@linaria/core"; import { Border, Colour, Font, Motion, Radius } from "../../../theme/tokens"; export const cell = css` + position: relative; display: flex; align-items: center; justify-content: center; - position: relative; width: 100%; height: 2.5rem; `; @@ -155,12 +155,12 @@ export const label = css` display: flex; align-items: center; justify-content: center; - height: 2.5rem; width: 2.5rem; + height: 2.5rem; + color: ${Colour["text"]}; + pointer-events: none; ${Font["body-md-regular"]} transition: ${Motion["duration-150"]} ${Motion["ease-default"]}; - pointer-events: none; - color: ${Colour["text"]}; &[data-day-cell-state="interactive"] { pointer-events: auto; @@ -205,9 +205,9 @@ export const label = css` export const indicator = css` position: absolute; + bottom: 4px; width: 4px; height: 4px; - background-color: currentColor; + background-color: currentcolor; border-radius: 100%; - bottom: 4px; `; diff --git a/src/shared/internal-calendar/internal-calendar-month.styles.ts b/src/shared/internal-calendar/internal-calendar-month.styles.ts index 702abf0d29..55a96fabe4 100644 --- a/src/shared/internal-calendar/internal-calendar-month.styles.ts +++ b/src/shared/internal-calendar/internal-calendar-month.styles.ts @@ -6,35 +6,33 @@ import { Border, Colour, Font, Motion, Radius } from "../../theme"; // STYLING // ============================================================================= export const wrapper = css` - width: 100%; - height: 100%; display: grid; - grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(6, 2.5rem); - align-content: center; - justify-content: center; - + grid-template-columns: repeat(2, 1fr); gap: 0.5rem 0; + place-content: center center; + width: 100%; + height: 100%; `; export const monthCell = css` display: flex; align-items: center; justify-content: center; - border-radius: ${Radius["md"]}; margin: 0 0.5rem; - transition: ${Motion["duration-150"]} ${Motion["ease-default"]}; + color: ${Colour["text"]}; + cursor: default; + background-clip: border-box; ${Font["body-md-regular"]} border: ${Border["width-010"]} ${Border["solid"]} transparent; - background-clip: border-box; - color: ${Colour["text"]}; - cursor: default; + border-radius: ${Radius["md"]}; + transition: ${Motion["duration-150"]} ${Motion["ease-default"]}; `; export const monthCellDisabledDisplay = css` - cursor: not-allowed; color: ${Colour["text-disabled-subtlest"]}; + cursor: not-allowed; `; export const monthCellInteractive = css` @@ -42,30 +40,30 @@ export const monthCellInteractive = css` `; export const monthCellCurrentMonth = css` - color: ${Colour["text-primary"]}; font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-primary"]}; `; export const monthCellSelectedMonth = css` + font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-selected"]}; background: ${Colour["bg-selected"]}; border-color: ${Colour["border-selected"]}; - color: ${Colour["text-selected"]}; - font-weight: ${Font.Spec["weight-semibold"]}; `; export const monthCellDefaultHover = css` &:hover { - background: ${Colour["bg-hover"]}; - color: ${Colour["text-hover"]}; font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-hover"]}; + background: ${Colour["bg-hover"]}; } `; export const monthCellSelectedHover = css` &:hover { + font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-selected-hover"]}; background: ${Colour["bg-selected-hover"]}; border-color: ${Colour["border-selected-hover"]}; - color: ${Colour["text-selected-hover"]}; - font-weight: ${Font.Spec["weight-semibold"]}; } `; diff --git a/src/shared/internal-calendar/internal-calendar-year.styles.ts b/src/shared/internal-calendar/internal-calendar-year.styles.ts index bb3ba86c1d..36a096bd09 100644 --- a/src/shared/internal-calendar/internal-calendar-year.styles.ts +++ b/src/shared/internal-calendar/internal-calendar-year.styles.ts @@ -6,33 +6,33 @@ import { Border, Colour, Font, Motion, Radius } from "../../theme"; // STYLING // ============================================================================= export const wrapper = css` - width: 100%; - height: 100%; display: grid; + grid-template-columns: repeat(3, 1fr); align-content: center; align-items: center; - grid-template-columns: repeat(3, 1fr); + width: 100%; + height: 100%; `; export const yearCell = css` display: flex; - justify-content: center; align-items: center; - margin: 1rem 0.5rem; - transition: ${Motion["duration-150"]} ${Motion["ease-default"]}; + justify-content: center; padding: 0.5rem; + margin: 1rem 0.5rem; + color: ${Colour["text"]}; + cursor: default; + background-clip: border-box; + border: ${Border["width-010"]} ${Border["solid"]} transparent; ${Font["body-md-regular"]} border-radius: ${Radius["md"]}; - border: ${Border["width-010"]} ${Border["solid"]} transparent; - background-clip: border-box; - color: ${Colour["text"]}; - cursor: default; + transition: ${Motion["duration-150"]} ${Motion["ease-default"]}; `; export const yearCellDisabledDisplay = css` - cursor: not-allowed; color: ${Colour["text-disabled-subtlest"]}; + cursor: not-allowed; `; export const yearCellInteractive = css` @@ -44,30 +44,30 @@ export const yearCellOtherDecade = css` `; export const yearCellCurrentYear = css` - color: ${Colour["text-primary"]}; font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-primary"]}; `; export const yearCellSelectedYear = css` + font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-selected"]}; background: ${Colour["bg-selected"]}; border-color: ${Colour["border-selected"]}; - color: ${Colour["text-selected"]}; - font-weight: ${Font.Spec["weight-semibold"]}; `; export const yearCellDefaultHover = css` &:hover { - background: ${Colour["bg-hover"]}; - color: ${Colour["text-hover"]}; font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-hover"]}; + background: ${Colour["bg-hover"]}; } `; export const yearCellSelectedHover = css` &:hover { + font-weight: ${Font.Spec["weight-semibold"]}; + color: ${Colour["text-selected-hover"]}; background: ${Colour["bg-selected-hover"]}; border-color: ${Colour["border-selected-hover"]}; - color: ${Colour["text-selected-hover"]}; - font-weight: ${Font.Spec["weight-semibold"]}; } `; diff --git a/src/shared/internal-calendar/standard/standard-calendar-day-view.styles.ts b/src/shared/internal-calendar/standard/standard-calendar-day-view.styles.ts index 1cc6c6c8ac..7328e83f99 100644 --- a/src/shared/internal-calendar/standard/standard-calendar-day-view.styles.ts +++ b/src/shared/internal-calendar/standard/standard-calendar-day-view.styles.ts @@ -3,10 +3,10 @@ import { css } from "@linaria/core"; import { Colour, Font } from "../../../theme"; export const wrapper = css` - width: 100%; display: grid; grid-template-columns: repeat(7, 1fr); row-gap: 0.25rem; + width: 100%; `; export const headerCell = css` @@ -14,14 +14,14 @@ export const headerCell = css` align-items: center; justify-content: center; height: 2.5rem; - pointer-events: none; - user-select: none; ${Font["body-sm-semibold"]} color: ${Colour["text"]}; + pointer-events: none; + user-select: none; `; export const rowDayCell = css` - grid-column: 1 / -1; display: flex; + grid-column: 1 / -1; `; diff --git a/src/shared/progress-bar/progress-bar.styles.ts b/src/shared/progress-bar/progress-bar.styles.ts index 943f4744be..e88c080521 100644 --- a/src/shared/progress-bar/progress-bar.styles.ts +++ b/src/shared/progress-bar/progress-bar.styles.ts @@ -12,11 +12,10 @@ export const bar = css` width: 100%; height: 8px; background: transparent; - + border-color: var(${tokens.barColour}); border-style: ${Border["solid"]}; border-width: ${Border["width-010"]}; border-radius: ${Radius["sm"]}; - border-color: var(${tokens.barColour}); progress { position: absolute; @@ -27,14 +26,14 @@ export const bar = css` opacity: 0; } - &:after { - content: ""; + &::after { position: absolute; top: 0; bottom: 0; left: 0; - border-radius: inherit; - background: var(${tokens.barColour}); width: var(${tokens.barWidth}); + content: ""; + background: var(${tokens.barColour}); + border-radius: inherit; } `; diff --git a/src/shared/range-input-inner-container/range-input-inner-container.styles.ts b/src/shared/range-input-inner-container/range-input-inner-container.styles.ts index 325a6ce9f9..90e22eacd4 100644 --- a/src/shared/range-input-inner-container/range-input-inner-container.styles.ts +++ b/src/shared/range-input-inner-container/range-input-inner-container.styles.ts @@ -4,9 +4,9 @@ import { Colour, Font, Motion, Spacing } from "../../theme"; export const wrapper = css` position: relative; - height: 100%; display: flex; flex: 1; + height: 100%; `; export const wrapperWrap = css` @@ -15,11 +15,10 @@ export const wrapperWrap = css` [data-id="range-container-elem1-container"], [data-id="range-container-elem2-container"] { - // 100% - Icon size - 2padding - max-width: calc( - 100% - ${Font.Spec["body-size-baseline"]} - ${Spacing["spacing-16"]} - ); flex: unset; + + /* 100% - Icon size - 2padding */ + max-width: calc(100% - ${Font.Spec["body-size-baseline"]} calc(${Spacing["spacing-16"]} * -1)); } [data-id="range-container-elem2-container"] { @@ -34,31 +33,32 @@ export const elementContainer = css` `; export const arrowRight = css` - color: ${Colour["icon"]}; + flex-shrink: 0; + align-self: center; width: ${Font.Spec["body-size-baseline"]}; height: ${Font.Spec["body-size-baseline"]}; - flex-shrink: 0; margin: 0 ${Spacing["spacing-8"]}; - align-self: center; + color: ${Colour["icon"]}; `; export const lineBreak = css` - width: 100%; // Force next flex item to break to next line + /* Force next flex item to break to next line */ + width: 100%; `; export const indicator = css` position: absolute; - background: ${Colour["border-focus-strong"]}; - height: 2px; - // half - half padding - half icon width - width: calc( - 50% - ${Spacing["spacing-8"]} - (${Font.Spec["body-size-baseline"]} / 2) - ); - transition: left ${Motion["duration-350"]} ${Motion["ease-standard"]}, - opacity ${Motion["duration-350"]} ${Motion["ease-standard"]}; - left: 0; bottom: 0; + left: 0; + + /* half - half padding - half icon width */ + width: calc(50% - ${Spacing["spacing-8"]} - (${Font.Spec["body-size-baseline"]} / 2)); + height: 2px; + background: ${Colour["border-focus-strong"]}; opacity: 0; + transition-timing-function: ${Motion["ease-standard"]}, ${Motion["ease-standard"]}; + transition-duration: ${Motion["duration-350"]}, ${Motion["duration-350"]}; + transition-property: left, opacity; &[data-position="start"] { opacity: 1; diff --git a/src/shared/standalone-date-input/standalone-date-input.styles.ts b/src/shared/standalone-date-input/standalone-date-input.styles.ts index dfa67e21f6..627d52a24a 100644 --- a/src/shared/standalone-date-input/standalone-date-input.styles.ts +++ b/src/shared/standalone-date-input/standalone-date-input.styles.ts @@ -2,30 +2,26 @@ import { css } from "@linaria/core"; import { Colour, Font, Spacing } from "../../theme"; -// ============================================================================= -// STYLING -// ============================================================================= export const inputSection = css` - display: flex; - align-items: center; position: relative; - + display: flex; flex: 1; + align-items: center; `; export const baseInput = css` ${Font["body-baseline-regular"]} - color: ${Colour["text"]}; + position: absolute; + inset: 0; display: block; - background: transparent; - border: none; - outline: none; - box-shadow: none; padding: 0; margin: 0; + color: ${Colour["text"]}; text-align: center; - position: absolute; - inset: 0; + outline: none; + background: transparent; + border: none; + box-shadow: none; &:disabled { color: ${Colour["text-subtler"]}; @@ -40,17 +36,17 @@ export const baseInput = css` color: ${Colour["text-subtler"]}; } - // Chrome, Safari, Edge, Opera + /* Chrome, Safari, Edge, Opera */ &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { - -webkit-appearance: none; margin: 0; + -webkit-appearance: none; } - // Safari (remove top shadow) + /* Safari (remove top shadow) */ --webkit-appearance: none; - // Firefox + /* Firefox */ --moz-appearance: textfield; `; @@ -72,19 +68,19 @@ export const dividerHover = css` export const inputContainer = css` display: flex; - align-items: center; gap: ${Spacing["spacing-4"]}; + align-items: center; `; export const inputSizerBase = css` - display: inline-block; position: relative; + display: inline-block; &::after { ${Font["body-baseline-regular"]} visibility: hidden; - pointer-events: none; white-space: pre; + pointer-events: none; } `; @@ -108,18 +104,18 @@ export const yearInputSizer = css` export const placeholder = css` ${Font["body-baseline-regular"]} - background-color: ${Colour["bg"]}; - color: ${Colour["text-subtler"]}; position: absolute; display: flex; align-items: center; width: 100%; height: 100%; + color: ${Colour["text-subtler"]}; + background-color: ${Colour["bg"]}; `; export const placeholderDisabled = css` - background-color: ${Colour["bg-disabled"]}; cursor: not-allowed; + background-color: ${Colour["bg-disabled"]}; `; export const placeholderHide = css` diff --git a/src/shared/timepicker-dropdown/timepicker-dropdown.styles.ts b/src/shared/timepicker-dropdown/timepicker-dropdown.styles.ts index 89a8a9ed0c..eb97af64fa 100644 --- a/src/shared/timepicker-dropdown/timepicker-dropdown.styles.ts +++ b/src/shared/timepicker-dropdown/timepicker-dropdown.styles.ts @@ -19,11 +19,10 @@ export const root = css` export const container = css` position: relative; - width: 100%; - padding: ${Spacing["spacing-8"]} ${Spacing["spacing-20"]} - ${Spacing["spacing-24"]} ${Spacing["spacing-20"]}; display: flex; flex-direction: column; + width: 100%; + padding: ${Spacing["spacing-8"]} ${Spacing["spacing-20"]} ${Spacing["spacing-24"]}; background: ${Colour["bg"]}; border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; border-radius: ${Radius["sm"]}; @@ -43,9 +42,9 @@ export const inputSection = css` export const controlSection = css` display: flex; flex-direction: row-reverse; + gap: ${Spacing["spacing-8"]}; justify-content: flex-start; margin-top: ${Spacing["spacing-16"]}; - gap: ${Spacing["spacing-8"]}; ${MediaQuery.MaxWidth.xxs} { flex-direction: column; @@ -62,8 +61,8 @@ export const hourMinuteSection = css` margin-right: ${Spacing["spacing-32"]}; ${MediaQuery.MaxWidth.xxs} { - margin-right: 0; width: 100%; + margin-right: 0; } `; @@ -97,8 +96,8 @@ export const switchButton = css` color: ${Colour["icon"]}; svg { - height: 1rem; width: 1rem; + height: 1rem; } &:hover { @@ -113,11 +112,11 @@ export const dividerLabel = css` `; export const timeInputBox = css` - height: calc(3rem - 2px); - width: 5rem; display: flex; align-items: center; justify-content: center; + width: 5rem; + height: calc(3rem - 2px); ${MediaQuery.MaxWidth.xxs} { width: 100%; @@ -125,8 +124,8 @@ export const timeInputBox = css` `; export const timeInput = css` - text-align: center; width: 100%; + text-align: center; &:focus::placeholder { color: transparent; @@ -134,8 +133,8 @@ export const timeInput = css` `; export const timePeriodToggle = css` - min-width: 5rem; flex: 1; + min-width: 5rem; `; // ----------------------------------------------------------------------------- diff --git a/src/singpass-button/singpass-button.styles.ts b/src/singpass-button/singpass-button.styles.ts index d11744def5..20174d016e 100644 --- a/src/singpass-button/singpass-button.styles.ts +++ b/src/singpass-button/singpass-button.styles.ts @@ -6,14 +6,14 @@ import { ComponentToken, Motion, Spacing } from "../theme"; // MAIN BUTTON // ============================================================================= export const main = css` - padding: ${Spacing["spacing-8"]} ${Spacing["spacing-16"]}; - transition: all ${Motion["duration-250"]} ${Motion["ease-default"]}; - border-radius: ${ComponentToken.Button["radius"]}; - cursor: pointer; display: flex; align-items: center; justify-content: center; min-height: 3rem; + padding: ${Spacing["spacing-8"]} ${Spacing["spacing-16"]}; + cursor: pointer; + border-radius: ${ComponentToken.Button["radius"]}; + transition: all ${Motion["duration-250"]} ${Motion["ease-default"]}; `; export const mainSizeSmall = css` @@ -26,25 +26,25 @@ export const mainSizeLarge = css` `; export const mainStyleRedFilled = css` - background-color: #f4333d; + background-color: #F4333D; border: none; &:hover, &:active { @media (pointer: fine) { - background-color: #b0262d; + background-color: #B0262D; } } `; export const mainStyleWhiteFilled = css` - background-color: #ffffff; - border: 1px #c8c9cc solid; + background-color: #FFFFFF; + border: 1px #C8C9CC solid; &:hover, &:active { @media (pointer: fine) { - background-color: #f5f5f7; + background-color: #F5F5F7; } } `; diff --git a/src/smart-app-banner/smart-app-banner.styles.ts b/src/smart-app-banner/smart-app-banner.styles.ts index aab7bc9aea..69fcccbfe3 100644 --- a/src/smart-app-banner/smart-app-banner.styles.ts +++ b/src/smart-app-banner/smart-app-banner.styles.ts @@ -7,14 +7,7 @@ import styled, { css, keyframes } from "styled-components"; import { Button } from "../button"; import { ClickableIcon } from "../shared/clickable-icon"; import { Typography } from "../typography"; -import { - V3_Border, - V3_Colour, - V3_Font, - V3_MediaQuery, - V3_Radius, - V3_Shadow, -} from "../v3_theme"; +import { V3_Border, V3_Colour, V3_Font, V3_MediaQuery, V3_Radius, V3_Shadow } from "../v3_theme"; const slideDown = keyframes` from { @@ -31,36 +24,24 @@ export const SmartAppBannerContainer = styled.div<{ $offset: number; $isAnimated: boolean; }>` + position: fixed; + top: ${(props) => props.$offset + "px"}; + left: 0; + z-index: 9001; display: flex; flex-direction: row-reverse; align-items: stretch; - position: fixed; - margin: 0.5rem 1.25rem; - ${(props) => { - return `top: ${props.$offset}px;`; - }} - left: 0; width: calc(100% - 2.5rem); min-height: 5.5rem; - z-index: 9001; + margin: 0.5rem 1.25rem; background: ${V3_Colour.bg}; - ${(props) => { - return props.theme?.colourMode === "dark" - ? css` - border: ${V3_Border["width-010"]} ${V3_Border["solid"]} - ${V3_Colour["border"]}; - ` - : css` - box-shadow: ${V3_Shadow["md-subtle"]}; - `; - }} + ${(props) => + props.theme?.colourMode === "dark" + ? "border: " + V3_Border["width-010"] + " " + V3_Border["solid"] + " " + V3_Colour["border"] + ";" + : "box-shadow: " + V3_Shadow["md-subtle"] + ";"} border-radius: ${V3_Radius["md"]}; - ${(props) => { - if (props.$isAnimated) - return css` - animation: ${slideDown} 0.3s; - `; - }} + animation-name: ${(props) => (props.$isAnimated ? slideDown : "none")}; + animation-duration: ${(props) => (props.$isAnimated ? "0.3s" : "0s")}; `; export const DismissContainer = styled.div` @@ -74,34 +55,35 @@ export const DismissButton = styled(ClickableIcon)` `; export const Cross = styled(CrossIcon)` - color: ${V3_Colour.icon}; - height: 1.25rem; width: 1.25rem; + height: 1.25rem; + color: ${V3_Colour.icon}; `; export const ProceedContainer = styled.div` - flex: 1; display: flex; + flex: 1; align-items: center; padding: 0.5rem 1rem 0.5rem 0.25rem; cursor: pointer; `; export const TextContainer = styled.div` - flex: 1; display: flex; + flex: 1; flex-direction: column; - align-items: left; + align-items: flex-start; margin: 0.5rem; + ${V3_MediaQuery.MaxWidth.xs} { margin: 0 0.5rem; } `; export const BannerIcon = styled.img` + align-self: center; width: 2.65rem; height: auto; - align-self: center; `; export const ButtonContainer = styled.div` @@ -109,8 +91,9 @@ export const ButtonContainer = styled.div` `; export const StyledButton = styled(Button.Small)` - padding: 0.5rem; height: auto; + padding: 0.5rem; + & > span { overflow-wrap: anywhere; ${V3_Font["body-xs-semibold"]} @@ -120,6 +103,7 @@ export const StyledButton = styled(Button.Small)` export const Title = styled(Typography.BodySM)` font-weight: ${V3_Font.Spec["weight-bold"]}; overflow-wrap: anywhere; + ${V3_MediaQuery.MaxWidth.xs} { ${V3_Font["body-xs-bold"]} } @@ -130,16 +114,16 @@ export const Description = styled(Typography.BodyXS)` `; export const RatingContainer = styled.div` - margin-top: 0.25rem; display: flex; align-items: center; + margin-top: 0.25rem; `; const starIconStyle = css` - height: 2rem; width: 2rem; + height: 2rem; padding-right: 0.25rem; - color: #ffc107; + color: #FFC107; `; export const Star = styled(StarFillIcon)` diff --git a/src/tab/tab-link-chain.styles.ts b/src/tab/tab-link-chain.styles.ts index 79a5f73846..c171f1b929 100644 --- a/src/tab/tab-link-chain.styles.ts +++ b/src/tab/tab-link-chain.styles.ts @@ -1,13 +1,6 @@ import { css } from "@linaria/core"; -import { - Border, - Colour, - Font, - MediaQuery, - Radius, - Spacing, -} from "../theme/tokens"; +import { Border, Colour, Font, MediaQuery, Radius, Spacing } from "../theme/tokens"; export const tokens = { chainItem: { @@ -23,9 +16,10 @@ export const chain = css` export const chainFullWidthIndicator = css` &::after { - content: ""; - height: inherit; flex-grow: 1; + height: inherit; + content: ""; + /* follows the border in ChainItem */ border-bottom: ${Border["width-040"]} ${Border.solid} ${Colour.border}; } @@ -33,11 +27,11 @@ export const chainFullWidthIndicator = css` export const chainItem = css` display: flex; - justify-content: center; flex-shrink: 0; + justify-content: center; + width: var(${tokens.chainItem.width}, auto); border-bottom: ${Border["width-040"]} ${Border.solid} ${Colour.border}; ${tokens.chainItem.width}: initial; - width: var(${tokens.chainItem.width}, auto); ${MediaQuery.MaxWidth.sm} { flex: 1; @@ -59,11 +53,10 @@ export const chainLink = css` /* position: relative; */ flex-direction: row; gap: 0.5rem; - padding: ${Spacing["spacing-16"]} ${Spacing["spacing-16"]} - ${Spacing["spacing-20"]}; - cursor: pointer; - width: 100%; justify-content: center; + width: 100%; + padding: ${Spacing["spacing-16"]} ${Spacing["spacing-16"]} ${Spacing["spacing-20"]}; + cursor: pointer; &:focus-within { outline: 2px solid ${Colour["focus-ring"]}; @@ -81,13 +74,13 @@ export const labelContainer = css` `; export const label = css` - border: none; background: none; + border: none; ${MediaQuery.MaxWidth.sm} { max-width: 20ch; - text-overflow: ellipsis; overflow: hidden; + text-overflow: ellipsis; white-space: nowrap; } `; @@ -106,13 +99,13 @@ export const deselectedLabelActive = css` export const selectedLabel = css` ${Font["body-baseline-semibold"]} color: ${Colour["text-primary"]}; - opacity: 0; outline: none; + opacity: 0; ${MediaQuery.MaxWidth.sm} { max-width: 20ch; - text-overflow: ellipsis; overflow: hidden; + text-overflow: ellipsis; white-space: nowrap; } `; diff --git a/src/text-list/text-list.styles.ts b/src/text-list/text-list.styles.ts index 9f0cfb584c..18c8f418e1 100644 --- a/src/text-list/text-list.styles.ts +++ b/src/text-list/text-list.styles.ts @@ -6,23 +6,22 @@ import type { TextListSize } from "./types"; export const tokens = { listBottomMargin: "--fds-internal-textList-list-bottomMargin", orderedListCounterStyle: "--fds-internal-textList-orderedList-counterStyle", - orderedListCounterSeparator: - "--fds-internal-textList-orderedList-counterSeparator", + orderedListCounterSeparator: "--fds-internal-textList-orderedList-counterSeparator", orderedListStartValue: "--fds-internal-textList-orderedList-startValue", unorderedListBulletType: "--fds-internal-textList-unorderedList-bulletType", }; export const listBase = css` ${tokens.listBottomMargin}: 0rem; - margin-bottom: var(${tokens.listBottomMargin}); - - // Counter matters - counter-reset: list; + margin-bottom: var(${tokens.listBottomMargin}); font-weight: ${Font.Spec["weight-regular"]}; color: ${Colour.text}; - // nested lists styling + /* Counter matters */ + counter-reset: list; + + /* nested lists styling */ ol, ul { margin-top: 0.5rem; @@ -64,6 +63,7 @@ export const listSize: Record = { }; export const orderedList = css` + ${tokens.orderedListCounterStyle}: decimal; ${tokens.orderedListCounterSeparator}: ")"; margin-left: 3em; @@ -78,21 +78,20 @@ export const orderedList = css` position: relative; } - li:before { - counter-increment: list; - content: counter(list, var(${tokens.orderedListCounterStyle}, decimal)) - var(${tokens.orderedListCounterSeparator}); + li::before { position: absolute; left: -2em; + content: counter(list, var(${tokens.orderedListCounterStyle})) var(${tokens.orderedListCounterSeparator}); + counter-increment: list; } - ul > li:before { + ul > li::before { content: ""; } `; export const orderedListReversed = css` - li:before { + li::before { counter-increment: list -1; } `; @@ -112,7 +111,7 @@ export const unorderedListCustomIcon = css` & > li { display: flex; - align-items: flex-start; gap: 0.5em; + align-items: flex-start; } `; diff --git a/src/toggle/toggle-icon.styles.ts b/src/toggle/toggle-icon.styles.ts index 84e29f180a..5734c9c45d 100644 --- a/src/toggle/toggle-icon.styles.ts +++ b/src/toggle/toggle-icon.styles.ts @@ -6,15 +6,15 @@ import { Colour } from "../theme"; // STYLING // ============================================================================= export const wrapperBase = css` - height: 1.625rem; + flex-shrink: 0; width: 1.625rem; + height: 1.625rem; margin-right: 0.5rem; - flex-shrink: 0; color: ${Colour["icon-subtle"]}; svg { - height: 100%; width: 100%; + height: 100%; } `; diff --git a/src/toggle/toggle.styles.ts b/src/toggle/toggle.styles.ts index 0cde393e8c..f6c1a2e0b5 100644 --- a/src/toggle/toggle.styles.ts +++ b/src/toggle/toggle.styles.ts @@ -11,10 +11,6 @@ export const tokens = { }, } as const; -// ============================================================================= -// STYLING -// ============================================================================= - export const headerContainer = css` display: flex; align-items: flex-start; @@ -24,10 +20,10 @@ export const headerContainer = css` export const textContainer = css` display: flex; flex-direction: column; - overflow-wrap: anywhere; width: 100%; overflow: hidden; color: ${Colour.text}; + overflow-wrap: anywhere; `; export const toggleTextContainerSelected = css` @@ -41,14 +37,14 @@ export const toggleTextContainerDisabledSelected = css` export const container = css` position: relative; display: inline-flex; - min-width: 10.375rem; - border-radius: ${Radius["sm"]}; - border-width: 1px; - border-style: solid; - overflow: hidden; flex-direction: column; + min-width: 10.375rem; height: fit-content; + overflow: hidden; background: ${Colour.bg}; + border-style: solid; + border-width: 1px; + border-radius: ${Radius["sm"]}; &:focus-within { outline: 2px solid ${Colour["focus-ring"]}; @@ -69,8 +65,8 @@ export const colorBorderError = css` `; export const toggleContainerNoBorderDisabledSelected = css` - border: none; background: ${Colour["bg-selected-disabled"]}; + border: none; `; export const toggleContainerNoBorderDisabled = css` @@ -78,8 +74,8 @@ export const toggleContainerNoBorderDisabled = css` `; export const toggleContainerNoBorderSelected = css` - border: none; background: ${Colour["bg-selected"]}; + border: none; `; export const toggleContainerNoBorder = css` @@ -91,18 +87,18 @@ export const toggleContainerError = css` `; export const toggleContainerDisabledSelected = css` - border-color: ${Colour["border-selected-disabled"]}; background: ${Colour["bg-selected-disabled"]}; + border-color: ${Colour["border-selected-disabled"]}; `; export const toggleContainerDisabled = css` - border-color: ${Colour["border-disabled"]}; background: ${Colour["bg-disabled"]}; + border-color: ${Colour["border-disabled"]}; `; export const toggleContainerSelected = css` - border-color: ${Colour["border-selected"]}; background: ${Colour["bg-selected"]}; + border-color: ${Colour["border-selected"]}; `; export const toggleContainerHoverSelected = css` @@ -135,17 +131,17 @@ export const toggleContainerHoverDefault = css` export const input = css` position: absolute; - height: 100%; - width: 100%; - cursor: pointer; top: 0; left: 0; - opacity: 0; + width: 100%; + height: 100%; /* Hide appearance but keep it focusable using keyboard interactions */ appearance: none; + cursor: pointer; background: transparent; border: none; + opacity: 0; `; export const toggleInputDisabled = css` @@ -157,20 +153,21 @@ export const inputContainer = css` `; export const label = css` - overflow: hidden; - display: -webkit-box; - text-overflow: ellipsis; - -webkit-box-orient: vertical; - overflow-wrap: break-word; - ${tokens.label.desktopLineClamp}: initial; ${tokens.label.tabletLineClamp}: initial; ${tokens.label.mobileLineClamp}: initial; + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; -webkit-line-clamp: var(${tokens.label.desktopLineClamp}, none); + overflow-wrap: break-word; + -webkit-box-orient: vertical; + ${MediaQuery.MaxWidth.lg} { -webkit-line-clamp: var(${tokens.label.tabletLineClamp}, none); } + ${MediaQuery.MaxWidth.sm} { -webkit-line-clamp: var(${tokens.label.mobileLineClamp}, none); } @@ -186,10 +183,12 @@ export const toggleLabelSelected = css` export const subLabel = css` ${Font["body-md-regular"]} + /* forces sublabel to render above the input */ + z-index: 1; margin-top: 0.5rem; - z-index: 1; // forces sublabel to render above the input - pointer-events: none; // to allow click events to be passed to the input + /* to allow click events to be passed to the input */ + pointer-events: none; strong, b { @@ -198,26 +197,26 @@ export const subLabel = css` `; export const indicatorLabelContainer = css` + position: relative; display: flex; - height: 100%; width: 100%; - position: relative; + height: 100%; padding: 0.6875rem 1rem; `; export const indicatorLabelContainerAddPadding = css` - padding: 0.6875rem 0rem 0.6875rem 1rem; + padding: 0.6875rem 0 0.6875rem 1rem; `; export const removeButton = css` - color: ${Colour["text-error"]}; - white-space: nowrap; ${Font["body-md-semibold"]} height: fit-content; padding: 0.6875rem 1rem 0.6875rem 0.5rem; - border: none; - background: none; + color: ${Colour["text-error"]}; + white-space: nowrap; cursor: pointer; + background: none; + border: none; `; export const disabledColorCursor = css` @@ -226,16 +225,16 @@ export const disabledColorCursor = css` `; export const expandButton = css` - color: ${Colour["text-primary"]}; ${Font["body-baseline-semibold"]} display: flex; align-items: center; justify-content: flex-end; - border: none; - background-color: ${Colour.bg}; - cursor: pointer; - padding: 0 1rem 0.6875rem 1rem; width: 100%; + padding: 0 1rem 0.6875rem; + color: ${Colour["text-primary"]}; + cursor: pointer; + background-color: ${Colour.bg}; + border: none; svg { width: 1em; @@ -250,19 +249,19 @@ export const expandButtonPaddingTopRequired = css` export const errorContainer = css` width: 100%; + padding: 0.6875rem 1rem 0.5rem; color: ${Colour["text-error"]}; - border: none; - background: ${Colour.bg}; cursor: pointer; - padding: 0.6875rem 1rem 0.5rem 1rem; + background: ${Colour.bg}; + border: none; `; export const children = css` padding: 0 1rem; padding-top: 0.6875rem; padding-bottom: 0.5rem; - background-color: ${Colour.bg}; color: ${Colour.text}; + background-color: ${Colour.bg}; `; export const childrenIsFinalItem = css` diff --git a/src/typography/typography.styles.ts b/src/typography/typography.styles.ts index 7e232430f4..df17ff704d 100644 --- a/src/typography/typography.styles.ts +++ b/src/typography/typography.styles.ts @@ -13,6 +13,7 @@ export const tokens = { export const typographyBase = css` ${tokens.typographyBase.maxLines}: initial; + font-family: ${Font.Spec["font-family"]}; font-variant: ${Font.Spec["font-variant"]}; color: ${Colour.text}; @@ -56,8 +57,8 @@ export const noUnderline = css` `; export const externalIcon = css` - height: 1lh; width: 1em; + height: 1lh; margin-left: 0.4em; vertical-align: middle; `; diff --git a/stylelint.config.mjs b/stylelint.config.mjs new file mode 100644 index 0000000000..c295029077 --- /dev/null +++ b/stylelint.config.mjs @@ -0,0 +1,85 @@ +export default { + extends: [ + "stylelint-config-standard", + // To be enabled once migration to v4 is finished. + // "stylelint-config-recess-order" + ], + plugins: ["@stylistic/stylelint-plugin"], + rules: { + "declaration-block-no-duplicate-properties": true, + "no-descending-specificity": true, + "selector-max-id": 0, + "custom-property-empty-line-before": "never", + "color-hex-length": "long", + "selector-pseudo-class-no-unknown": [ + true, + { + ignorePseudoClasses: ["global"], + }, + ], + "selector-no-vendor-prefix": [ + true, + { + ignoreSelectors: ["::-webkit-input-placeholder"], + }, + ], + "property-no-vendor-prefix": [ + true, + { + ignoreProperties: ["-webkit-appearance", "-webkit-mask-image"], + }, + ], + + "@stylistic/color-hex-case": "upper", + "@stylistic/indentation": 4, + "@stylistic/max-empty-lines": 1, + }, + overrides: [ + { + /* + Taken from linaria's stylelint-config-standard-linaria package, + with some adjustments to work with our codebase. + + See: https://github.com/callstack/linaria/blob/master/packages/stylelint-config-standard-linaria/src/index.js + */ + files: ["**/*.ts", "**/*.tsx"], + customSyntax: "@linaria/postcss-linaria", + rules: { + "string-no-newline": true, + "value-no-vendor-prefix": true, + "no-empty-source": null, + "comment-empty-line-before": [ + "always", + { + except: ["first-nested"], + ignore: ["stylelint-commands"], + ignoreComments: [/pcss-lin/], + }, + ], + "no-invalid-double-slash-comments": true, + + // Linaria class names are auto-generated at build time; the + // selector-class-pattern rule cannot validate interpolated + // selectors like .${knob} because postcss-linaria exposes an + // empty class node during parsing. + "selector-class-pattern": null, + + // Linaria interpolations in font-family become placeholders + // (e.g. pcss-lin1), which trigger false positives for both + // quote and generic-family checks. + "font-family-name-quotes": null, + "font-family-no-missing-generic-family-keyword": null, + + // Ignore Linaria placeholder values like pcss-lin0 and -pcss-lin1. + "declaration-property-value-no-unknown": [ + true, + { + ignoreProperties: { + "/.+/": [/(?:^|[\s(,])-?pcss-lin\d+(?=$|[\s),])/], + }, + }, + ], + }, + }, + ], +}; diff --git a/tests/eslint-rules/import-path-preferences.rule-test.mjs b/tests/eslint-rules/import-path-preferences.rule-test.mjs index 31c6504903..0436ab1022 100644 --- a/tests/eslint-rules/import-path-preferences.rule-test.mjs +++ b/tests/eslint-rules/import-path-preferences.rule-test.mjs @@ -1,10 +1,12 @@ import tsParser from "@typescript-eslint/parser"; import { RuleTester } from "eslint"; -import localRules from "../../eslint-local-rules/import-path-preferences.mjs"; +import localRules from "../../eslint-local-rules/index.mjs"; const rule = localRules.rules["import-path-preferences"]; const styleNamespaceImportRule = localRules.rules["style-namespace-import"]; +const noNegativeLinariaInterpolationRule = + localRules.rules["no-negative-linaria-interpolation"]; const ruleTester = new RuleTester({ languageOptions: { @@ -153,14 +155,113 @@ ruleTester.run("style-namespace-import", styleNamespaceImportRule, { { name: "default import from .styles path is rejected", code: 'import styles from "./button.styles";', - output: 'import * as styles from "./button.styles";', + output: null, errors: [{ messageId: "namespaceStyleImport" }], }, { name: "default + namespace import is reduced to namespace only", code: 'import buttonStyle, * as styles from "./button.styles";', - output: 'import * as styles from "./button.styles";', + output: null, errors: [{ messageId: "namespaceStyleImport" }], }, ], }); + +ruleTester.run( + "no-negative-linaria-interpolation", + noNegativeLinariaInterpolationRule, + { + valid: [ + { + name: "positive interpolation is allowed", + filename: "/repo/src/button/button.styles.ts", + code: `import { css } from "@linaria/core"; + +const spacing = "8px"; + +export const box = css\` + padding: \${spacing}; +\`; +`, + }, + { + name: "calc negative interpolation is allowed", + filename: "/repo/src/button/button.styles.ts", + code: `import { css } from "@linaria/core"; + +const spacing = "8px"; + +export const box = css\` + margin-left: calc(\${spacing} * -1); +\`; +`, + }, + { + name: "subtraction interpolation in calc is allowed", + filename: "/repo/src/button/button.styles.ts", + code: `import { css } from "@linaria/core"; + +const spacing = "8px"; + +export const box = css\` + max-width: calc(100% - \${spacing}); +\`; +`, + }, + { + name: "non-css tagged template is ignored", + filename: "/repo/src/button/button.styles.ts", + code: `const spacing = "8px"; + +const html = String.raw\` + margin-left: -\${spacing}; +\`; +`, + }, + ], + invalid: [ + { + name: "negative interpolation is rewritten to calc", + filename: "/repo/src/button/button.styles.ts", + code: `import { css } from "@linaria/core"; + +const spacing = "8px"; + +export const box = css\` + margin-left: -\${spacing}; +\`; +`, + output: `import { css } from "@linaria/core"; + +const spacing = "8px"; + +export const box = css\` + margin-left: calc(\${spacing} * -1); +\`; +`, + errors: [{ messageId: "negativeLinariaInterpolation" }], + }, + { + name: "negative interpolation with spacing is rewritten to calc", + filename: "/repo/src/button/button.styles.ts", + code: `import { css } from "@linaria/core"; + +const spacing = "8px"; + +export const box = css\` + margin-left: - \${spacing}; +\`; +`, + output: `import { css } from "@linaria/core"; + +const spacing = "8px"; + +export const box = css\` + margin-left: calc(\${spacing} * -1); +\`; +`, + errors: [{ messageId: "negativeLinariaInterpolation" }], + }, + ], + } +);