From dbf29e9a69b19f36b34f040cc586ef31ea631a6b Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 16 Feb 2026 14:44:24 +0200 Subject: [PATCH 1/7] Add peer dependency flag to multiple packages in package-lock.json --- package-lock.json | 64 ++- .../composition/src/app/app.component.html | 3 +- projects/composition/src/app/app.module.ts | 10 +- .../theme-toggle/theme-toggle.component.html | 137 ++++++ .../theme-toggle/theme-toggle.component.scss | 187 ++++++++ .../theme-toggle/theme-toggle.component.ts | 48 ++ projects/composition/src/styles.scss | 14 +- projects/composition/src/variables.scss | 6 +- projects/cps-ui-kit/assets/icons.svg | 6 + .../components/cps-icon/cps-icon.component.ts | 4 +- .../cps-theme/cps-theme.service.spec.ts | 83 ++++ .../services/cps-theme/cps-theme.service.ts | 297 ++++++++++++ projects/cps-ui-kit/src/public-api.ts | 66 +-- projects/cps-ui-kit/styles/_colors-dark.scss | 449 ++++++++++++++++++ projects/cps-ui-kit/styles/_colors.scss | 161 +++++++ projects/cps-ui-kit/styles/styles.scss | 24 + 16 files changed, 1500 insertions(+), 59 deletions(-) create mode 100644 projects/composition/src/app/components/theme-toggle/theme-toggle.component.html create mode 100644 projects/composition/src/app/components/theme-toggle/theme-toggle.component.scss create mode 100644 projects/composition/src/app/components/theme-toggle/theme-toggle.component.ts create mode 100644 projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts create mode 100644 projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.ts create mode 100644 projects/cps-ui-kit/styles/_colors-dark.scss diff --git a/package-lock.json b/package-lock.json index 1defc825..ffa85c4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -325,6 +325,7 @@ "integrity": "sha512-md5ikmdH0rM4jkVFwNQhN++onUUZPUDUfKijnb1XZArQisT9hPiNqTPbO+OZTBK/hQYYV/GfTOhDH30whG32xQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "2.3.0", "@angular-devkit/architect": "0.2003.15", @@ -520,6 +521,7 @@ "version": "20.3.16", "integrity": "sha512-N83/GFY5lKNyWgPV3xHHy2rb3/eP1ZLzSVI+dmMVbf3jbqwY1YPQcMiAG8UDzaILY1Dkus91kWLF8Qdr3nHAzg==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -681,6 +683,7 @@ "version": "20.3.16", "integrity": "sha512-GRAziNlntwdnJy3F+8zCOvDdy7id0gITjDnM6P9+n2lXvtDuBLGJKU3DWBbvxcCjtD6JK/g/rEX5fbCxbUHkQQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -696,6 +699,7 @@ "version": "20.3.16", "integrity": "sha512-Pt9Ms9GwTThgzdxWBwMfN8cH1JEtQ2DK5dc2yxYtPSaD+WKmG9AVL1PrzIYQEbaKcWk2jxASUHpEWSlNiwo8uw==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -708,6 +712,7 @@ "integrity": "sha512-l3xF/fXfJAl/UrNnH9Ufkr79myjMgXdHq1mmmph2UnpeqilRB1b8lC9sLBV9MipQHVn3dwocxMIvtrcryfOaXw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "7.28.3", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -739,6 +744,7 @@ "version": "20.3.16", "integrity": "sha512-KSFPKvOmWWLCJBbEO+CuRUXfecX2FRuO0jNi9c54ptXMOPHlK1lIojUnyXmMNzjdHgRug8ci9qDuftvC2B7MKg==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -763,6 +769,7 @@ "version": "20.3.16", "integrity": "sha512-1yzbXpExTqATpVcqA3wGrq4ACFIP3mRxA4pbso5KoJU+/4JfzNFwLsDaFXKpm5uxwchVnj8KM2vPaDOkvtp7NA==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -780,6 +787,7 @@ "version": "20.3.16", "integrity": "sha512-YsrLS6vyS77i4pVHg4gdSBW74qvzHjpQRTVQ5Lv/OxIjJdYYYkMmjNalCNgy1ZuyY6CaLIB11ccxhrNnxfKGOQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -801,6 +809,7 @@ "version": "20.3.16", "integrity": "sha512-5mECCV9YeKH6ue239GXRTGeDSd/eTbM1j8dDejhm5cGnPBhTxRw4o+GgSrWTYtb6VmIYdwUGBTC+wCBphiaQ2A==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -818,6 +827,7 @@ "version": "20.3.16", "integrity": "sha512-LxQscYd3UCWV8H3sdlnM05UB60MZVuVsdsHvXdkJ9+WOQjVDN1l1rYhj2aDL/5KkaRd/nqo0yFRnVjwceXDJhQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0", "xhr2": "^0.2.0" @@ -837,6 +847,7 @@ "version": "20.3.16", "integrity": "sha512-e1LiQFZaajKqc00cY5FboIrWJZSMnZ64GDp5R0UejritYrqorQQQNOqP1W85BMuY2owibMmxVfX+dJg/Mc8PuQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -878,6 +889,7 @@ "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -3537,6 +3549,7 @@ "integrity": "sha512-nqhDw2ZcAUrKNPwhjinJny903bRhI0rQhiDz1LksjeRxqa36i3l75+4iXbOy0rlDpLJGxqtgoPavQjmmyS5UJw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@inquirer/checkbox": "^4.2.1", "@inquirer/confirm": "^5.1.14", @@ -4043,6 +4056,7 @@ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -4075,6 +4089,7 @@ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -6906,6 +6921,7 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -7292,6 +7308,7 @@ "version": "8.15.0", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -7395,6 +7412,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -7899,6 +7917,7 @@ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -8368,6 +8387,7 @@ "integrity": "sha512-mcYOIy4BW6sWSEnTSBjQwWsnbx2btZX78ajTTjdNfyC/EqQVcIe0nQR6894RNAMtvlfAnLaH9L2ka97zpvgenA==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "browser-sync-client": "^3.0.4", "browser-sync-ui": "^3.0.4", @@ -8589,6 +8609,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -8674,7 +8695,6 @@ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" }, @@ -8687,7 +8707,6 @@ "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "semver": "^7.0.0" } @@ -9050,6 +9069,7 @@ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -10372,7 +10392,8 @@ "version": "0.0.1551306", "integrity": "sha512-CFx8QdSim8iIv+2ZcEOclBKTQY6BI1IEDa7Tm9YkwAXzEWFndTEzpTo5jAUhSnq24IC7xaDw0wvGcm96+Y3PEg==", "dev": true, - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/diff": { "version": "4.0.4", @@ -10783,6 +10804,7 @@ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -11127,6 +11149,7 @@ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -11182,7 +11205,6 @@ "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "semver": "^7.5.4" }, @@ -11198,6 +11220,7 @@ "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -11319,7 +11342,6 @@ "https://opencollective.com/eslint" ], "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.11.0", @@ -11337,6 +11359,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -11455,7 +11478,6 @@ "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "builtins": "^5.0.1", @@ -11484,7 +11506,6 @@ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11495,7 +11516,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -11589,6 +11609,7 @@ "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", "dev": true, "license": "ISC", + "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -12733,7 +12754,6 @@ "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -13670,7 +13690,6 @@ "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "builtin-modules": "^3.3.0" }, @@ -14274,6 +14293,7 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -14927,6 +14947,7 @@ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -15049,6 +15070,7 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -15090,6 +15112,7 @@ "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "abab": "^2.0.6", "acorn": "^8.8.1", @@ -15391,6 +15414,7 @@ "integrity": "sha512-kdTwsyRuncDfjEs0DlRILWNvxhDG/Zij4YLO4TMJgDLW+8OzpfkdPnRgrsRuY1o+oaxJGWsps5f/RVBgGmmN0w==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", @@ -15545,6 +15569,7 @@ "integrity": "sha512-SL0JY3DaxylDuo/MecFeiC+7pedM0zia33zl0vcjgwcq1q1FWWF1To9EIauPbl8GbMCU0R2e0uJ8bZunhYKD2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", @@ -16576,6 +16601,7 @@ "integrity": "sha512-yW5ME0hqTz38r/th/7zVwX5oSIw1FviSA2PUlGZdVjghDme/KX6iiwmOBmlt9E9whNmwijEC6Gn3KKbrsBx8ig==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.3.0", "@rollup/plugin-json": "^6.1.0", @@ -18077,6 +18103,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -18223,6 +18250,7 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -18869,7 +18897,6 @@ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } @@ -19034,6 +19061,7 @@ "integrity": "sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -19161,6 +19189,7 @@ "version": "7.8.2", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -19248,6 +19277,7 @@ "integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -20562,6 +20592,7 @@ "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", @@ -21013,7 +21044,8 @@ "node_modules/tslib": { "version": "2.8.1", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "license": "0BSD", + "peer": true }, "node_modules/tuf-js": { "version": "4.1.0", @@ -21559,6 +21591,7 @@ "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -21714,6 +21747,7 @@ "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -21791,6 +21825,7 @@ "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -22553,6 +22588,7 @@ "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "dev": true, "license": "ISC", + "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -22695,6 +22731,7 @@ "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -22711,7 +22748,8 @@ "node_modules/zone.js": { "version": "0.15.1", "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", - "license": "MIT" + "license": "MIT", + "peer": true } } } diff --git a/projects/composition/src/app/app.component.html b/projects/composition/src/app/app.component.html index 806ac9db..75e5dfc2 100644 --- a/projects/composition/src/app/app.component.html +++ b/projects/composition/src/app/app.component.html @@ -1,11 +1,12 @@
- + CPS UI Kit logo Consumer Products UI Kit @if (version) { v{{ version }} } +
+ + @if (menuOpen) { + + + } + +
diff --git a/projects/composition/src/app/components/theme-toggle/theme-toggle.component.scss b/projects/composition/src/app/components/theme-toggle/theme-toggle.component.scss new file mode 100644 index 00000000..ba0f26dc --- /dev/null +++ b/projects/composition/src/app/components/theme-toggle/theme-toggle.component.scss @@ -0,0 +1,187 @@ +.theme-controls { + --appearance-radius-sm: 8px; + --appearance-radius-md: 14px; + display: flex; + align-items: center; + gap: 8px; + position: relative; +} +.theme-toggle-btn { + display: flex; + align-items: center; + gap: 8px; + height: 32px; + padding: 0 11px; + background: var(--cps-surface-elevated); + border: 1px solid var(--cps-border-color); + border-radius: var(--appearance-radius-sm); + color: var(--cps-text-primary); + cursor: pointer; + font-family: 'Source Sans Pro', sans-serif; + font-size: 12px; + font-weight: 600; + transition: all 0.2s; + &:hover { + background: var(--cps-highlight-hover); + border-color: var(--cps-border-focus); + } + &:active { + background: var(--cps-highlight-active); + } + &:focus-visible { + outline: 2px solid var(--cps-ring-color); + outline-offset: 2px; + } +} +.theme-toggle-caret { + color: var(--cps-text-muted); + font-size: 11px; + line-height: 1; +} +.menu-backdrop { + position: fixed; + inset: 0; + margin: 0; + padding: 0; + background: var(--cps-surface-overlay); + opacity: 0.22; + border: 0; + border-radius: 0; + appearance: none; + -webkit-appearance: none; + z-index: 10; +} +.theme-menu { + position: absolute; + top: calc(100% + 10px); + right: 0; + width: min(320px, calc(100vw - 16px)); + max-height: min(70vh, 520px); + overflow: auto; + background: var(--cps-surface-control); + border: 1px solid var(--cps-border-color); + border-radius: var(--appearance-radius-md); + box-shadow: var(--cps-shadow-md); + z-index: 20; + padding: 6px; + transform-origin: top right; + animation: menu-enter var(--cps-motion-fast) var(--cps-motion-easing); +} +@keyframes menu-enter { + from { + opacity: 0; + transform: translateY(-4px) scale(0.985); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} +@media (prefers-reduced-motion: reduce) { + .theme-menu { + animation: none; + } +} +.theme-menu-header { + padding: 10px 10px 9px; + border-bottom: 1px solid var(--cps-border-color); +} +.theme-menu-title { + color: var(--cps-text-primary); + font-family: 'Source Sans Pro', sans-serif; + font-size: 13px; + font-weight: 700; + line-height: 1.2; +} +.theme-menu-subtitle { + margin-top: 3px; + color: var(--cps-text-muted); + font-family: 'Source Sans Pro', sans-serif; + font-size: 11px; + line-height: 1.35; +} +.theme-section { + padding: 10px; +} +.theme-section + .theme-section { + border-top: 1px solid var(--cps-border-color); +} +.theme-section-title { + margin: 0 0 6px; + color: var(--cps-text-muted); + font-family: 'Source Sans Pro', sans-serif; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; +} +.theme-section-hint { + margin: -1px 0 8px; + color: var(--cps-text-muted); + font-family: 'Source Sans Pro', sans-serif; + font-size: 11px; + line-height: 1.35; +} +.theme-options { + display: flex; + flex-direction: column; + gap: 3px; +} +.theme-option { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 8px; + min-height: 32px; + padding: 7px 8px; + border: 1px solid transparent; + border-radius: var(--appearance-radius-sm); + background: transparent; + color: var(--cps-text-primary); + font-family: 'Source Sans Pro', sans-serif; + font-size: 12px; + line-height: 1; + text-align: left; + cursor: pointer; + &:hover { + background: var(--cps-highlight-hover); + } + &:focus-visible { + outline: 2px solid var(--cps-ring-color); + outline-offset: 2px; + } +} +.theme-option.selected { + background: var(--cps-highlight-active); + border-color: var(--cps-border-focus); +} +.theme-option.selected::after { + content: '✓'; + margin-left: auto; + color: var(--cps-accent-primary); + font-weight: 700; + font-size: 12px; +} +.option-dot { + width: 9px; + height: 9px; + border-radius: 9999px; + background: transparent; + border: 1px solid var(--cps-border-color); + flex: 0 0 auto; +} +.theme-section-theme .theme-option:nth-child(1) .option-dot { + background: var(--cps-text-muted); +} +.theme-section-theme .theme-option:nth-child(2) .option-dot { + background: var(--cps-color-calm); +} +.theme-section-theme .theme-option:nth-child(3) .option-dot { + background: var(--cps-color-energy); +} +.theme-section-theme .theme-option:nth-child(4) .option-dot { + background: var(--cps-color-passion); +} +.theme-option.selected .option-dot { + border-color: transparent; +} diff --git a/projects/composition/src/app/components/theme-toggle/theme-toggle.component.ts b/projects/composition/src/app/components/theme-toggle/theme-toggle.component.ts new file mode 100644 index 00000000..7086da52 --- /dev/null +++ b/projects/composition/src/app/components/theme-toggle/theme-toggle.component.ts @@ -0,0 +1,48 @@ +import { Component, inject } from '@angular/core'; +import { + CpsBaseTheme, + CpsColorTheme, + CpsIconComponent, + CpsRadiusTheme, + CpsThemeService +} from 'cps-ui-kit'; + +@Component({ + selector: 'app-theme-toggle', + imports: [CpsIconComponent], + templateUrl: './theme-toggle.component.html', + styleUrl: './theme-toggle.component.scss' +}) +export class ThemeToggleComponent { + private themeService = inject(CpsThemeService); + + isDark = this.themeService.isDark; + colorTheme = this.themeService.colorTheme; + radiusTheme = this.themeService.radiusTheme; + baseTheme = this.themeService.baseTheme; + menuOpen = false; + + toggleTheme(): void { + this.themeService.toggleTheme(); + } + + toggleMenu(): void { + this.menuOpen = !this.menuOpen; + } + + closeMenu(): void { + this.menuOpen = false; + } + + setColorTheme(value: CpsColorTheme): void { + this.themeService.setColorTheme(value); + } + + setRadiusTheme(value: CpsRadiusTheme): void { + this.themeService.setRadiusTheme(value); + } + + setBaseTheme(value: CpsBaseTheme): void { + this.themeService.setBaseTheme(value); + } +} diff --git a/projects/composition/src/styles.scss b/projects/composition/src/styles.scss index 210f2849..ef72a0d3 100644 --- a/projects/composition/src/styles.scss +++ b/projects/composition/src/styles.scss @@ -41,7 +41,7 @@ body { font-weight: bold; text-align: left; padding: 0.75rem 1rem; - border-bottom: 1px solid var(--cps-color-line-light); + border-bottom: 1px solid var(--cps-color-line); } tr { @@ -50,7 +50,7 @@ body { td { padding: 0.75rem 1rem; - border-bottom: 1px solid var(--cps-color-line-light); + border-bottom: 1px solid var(--cps-color-line); white-space: pre-line; span { @@ -61,21 +61,23 @@ body { &.highlighted-bg { span { - color: var(--cps-color-depth-darken4); - background-color: var(--cps-color-human-lighten5); + color: var(--cps-text-on-accent); + background-color: var(--cps-accent-primary); border-radius: 6px; padding: 0.2rem 0.5rem; } } &.highlighted-text { - color: var(--cps-color-calm); + color: var(--cps-text-primary); a { - color: var(--cps-color-calm); + color: var(--cps-text-primary); &:hover { text-decoration: none; + background-color: var(--cps-surface-elevated); + border: 1px solid var(--cps-color-line); } } } diff --git a/projects/composition/src/variables.scss b/projects/composition/src/variables.scss index ca663339..ada123d4 100644 --- a/projects/composition/src/variables.scss +++ b/projects/composition/src/variables.scss @@ -1,7 +1,7 @@ $sidebar-width: 300px; -$composition-background: var(--cps-color-bg-light); +$composition-background: var(--cps-background-color); $top-tbar-height: 64px; $inner-tbar-height: 45px; -$color-calm: var(--cps-color-calm); -$color-text: var(--cps-color-text-dark); +$color-calm: var(--cps-accent-primary); +$color-text: var(--cps-text-secondary); diff --git a/projects/cps-ui-kit/assets/icons.svg b/projects/cps-ui-kit/assets/icons.svg index 7ac1852f..0f8d322c 100644 --- a/projects/cps-ui-kit/assets/icons.svg +++ b/projects/cps-ui-kit/assets/icons.svg @@ -513,4 +513,10 @@ + + + + + + diff --git a/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts b/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts index 37308567..92f3e5d7 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts @@ -7,8 +7,8 @@ import { Input, OnChanges } from '@angular/core'; -import { convertSize } from '../../utils/internal/size-utils'; import { getCSSColor } from '../../utils/colors-utils'; +import { convertSize } from '../../utils/internal/size-utils'; /** * Injection token that is used to provide the path to the icons. @@ -94,6 +94,7 @@ export const iconNames = [ 'menu-shrink', 'minimize', 'minus', + 'moon', 'move-grabber', 'open', 'ownership', @@ -120,6 +121,7 @@ export const iconNames = [ 'stepper-completed', 'success', 'suggestion', + 'sun', 'survivorship', 'table-row-error', 'table-row-success', diff --git a/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts b/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts new file mode 100644 index 00000000..3ce4f639 --- /dev/null +++ b/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts @@ -0,0 +1,83 @@ +import { TestBed } from '@angular/core/testing'; +import { CpsThemeService } from './cps-theme.service'; + +describe('CpsThemeService', () => { + let service: CpsThemeService; + + beforeEach(() => { + localStorage.clear(); + TestBed.configureTestingModule({}); + service = TestBed.inject(CpsThemeService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('should initialize with system preference', () => { + expect(['light', 'dark']).toContain(service.theme()); + }); + + it('should toggle theme', () => { + const initialTheme = service.theme(); + service.toggleTheme(); + const newTheme = service.theme(); + expect(newTheme).not.toBe(initialTheme); + }); + + it('should save theme preference to localStorage', () => { + service.setTheme('dark', false); + expect(localStorage.getItem('cps-theme-preference')).toBe('dark'); + }); + + it('should compute isDark correctly', () => { + service.setTheme('dark', false); + expect(service.isDark()).toBe(true); + service.setTheme('light', false); + expect(service.isDark()).toBe(false); + }); + + it('should initialize with neutral color theme by default', () => { + expect(service.colorTheme()).toBe('neutral'); + }); + + it('should save color theme preference to localStorage', () => { + service.setColorTheme('energy', false); + expect(localStorage.getItem('cps-color-theme-preference')).toBe('energy'); + }); + + it('should apply color theme to document attribute', () => { + service.setColorTheme('calm', false); + expect(document.documentElement.getAttribute('data-color-theme')).toBe( + 'calm' + ); + }); + + it('should save base theme preference to localStorage', () => { + service.setBaseTheme('midnight', false); + expect(localStorage.getItem('cps-base-theme-preference')).toBe('midnight'); + }); + + it('should apply base theme to document attribute', () => { + service.setBaseTheme('graphite', false); + expect(document.documentElement.getAttribute('data-base-theme')).toBe( + 'graphite' + ); + }); + + it('should save radius theme preference to localStorage', () => { + service.setRadiusTheme('rounded', false); + expect(localStorage.getItem('cps-radius-theme-preference')).toBe('rounded'); + }); + + it('should initialize with none radius theme by default', () => { + expect(service.radiusTheme()).toBe('none'); + }); + + it('should apply radius theme to document attribute', () => { + service.setRadiusTheme('pill', false); + expect(document.documentElement.getAttribute('data-radius-theme')).toBe( + 'pill' + ); + }); +}); diff --git a/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.ts b/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.ts new file mode 100644 index 00000000..10627816 --- /dev/null +++ b/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.ts @@ -0,0 +1,297 @@ +import { DOCUMENT } from '@angular/common'; +import { computed, effect, inject, Injectable, signal } from '@angular/core'; + +/** + * Available theme options + * @group Types + */ +export type CpsTheme = 'light' | 'dark'; +export type CpsColorTheme = 'neutral' | 'calm' | 'energy' | 'passion'; +export type CpsBaseTheme = 'default' | 'graphite' | 'midnight' | 'aubergine'; +export type CpsRadiusTheme = 'none' | 'compact' | 'rounded' | 'pill'; + +/** + * CpsThemeService manages application theming including dark mode support. + * + * This service provides: + * - Light and dark theme switching with smooth transitions + * - Automatic persistence of theme preference in localStorage + * - System preference detection (prefers-color-scheme) + * - Reactive state management using Angular signals + * + * @example + * ```typescript + * class MyComponent { + * private themeService = inject(CpsThemeService); + * + * isDark = this.themeService.isDark; + * + * toggleTheme() { + * this.themeService.toggleTheme(); + * } + * } + * ``` + * + * @group Services + */ +@Injectable({ + providedIn: 'root' +}) +export class CpsThemeService { + private document = inject(DOCUMENT); + private readonly THEME_STORAGE_KEY = 'cps-theme-preference'; + private readonly COLOR_THEME_STORAGE_KEY = 'cps-color-theme-preference'; + private readonly BASE_THEME_STORAGE_KEY = 'cps-base-theme-preference'; + private readonly RADIUS_THEME_STORAGE_KEY = 'cps-radius-theme-preference'; + private readonly TRANSITION_CLASS = 'cps-theme-transition'; + private readonly TRANSITION_DURATION = 500; + + private _theme = signal(this.getInitialTheme()); + private _colorTheme = signal(this.getInitialColorTheme()); + private _baseTheme = signal(this.getInitialBaseTheme()); + private _radiusTheme = signal(this.getInitialRadiusTheme()); + + /** + * Current active theme (readonly) + */ + readonly theme = this._theme.asReadonly(); + + /** + * Current active color theme (readonly) + */ + readonly colorTheme = this._colorTheme.asReadonly(); + + /** + * Current active base theme (readonly) + */ + readonly baseTheme = this._baseTheme.asReadonly(); + + /** + * Current active radius theme (readonly) + */ + readonly radiusTheme = this._radiusTheme.asReadonly(); + + /** + * Whether dark mode is currently active + */ + readonly isDark = computed(() => this._theme() === 'dark'); + + constructor() { + // Apply theme changes to DOM whenever theme signal changes + effect(() => { + this.applyTheme( + this._theme(), + this._colorTheme(), + this._baseTheme(), + this._radiusTheme() + ); + }); + + // Listen for system theme changes + this.watchSystemTheme(); + } + + /** + * Toggle between light and dark themes with smooth transition + */ + toggleTheme(): void { + const newTheme: CpsTheme = this._theme() === 'light' ? 'dark' : 'light'; + this.setTheme(newTheme); + } + + /** + * Set specific theme + * @param theme - Theme to apply ('light' or 'dark') + * @param animated - Whether to animate the transition (default: true) + */ + setTheme(theme: CpsTheme, animated = true): void { + if (this._theme() === theme) return; + + if (animated) { + this.enableTransition(); + } + + this._theme.set(theme); + this.saveThemePreference(theme); + + if (animated) { + setTimeout(() => this.disableTransition(), this.TRANSITION_DURATION); + } + } + + /** + * Set specific color theme independently from mode + * @param colorTheme - Color theme to apply + * @param animated - Whether to animate the transition (default: true) + */ + setColorTheme(colorTheme: CpsColorTheme, animated = true): void { + if (this._colorTheme() === colorTheme) return; + + if (animated) { + this.enableTransition(); + } + + this._colorTheme.set(colorTheme); + this.saveColorThemePreference(colorTheme); + + if (animated) { + setTimeout(() => this.disableTransition(), this.TRANSITION_DURATION); + } + } + + /** + * Set base background theme (primarily affects dark mode) + */ + setBaseTheme(baseTheme: CpsBaseTheme, animated = true): void { + if (this._baseTheme() === baseTheme) return; + + if (animated) { + this.enableTransition(); + } + + this._baseTheme.set(baseTheme); + this.saveBaseThemePreference(baseTheme); + + if (animated) { + setTimeout(() => this.disableTransition(), this.TRANSITION_DURATION); + } + } + + /** + * Set radius profile + */ + setRadiusTheme(radiusTheme: CpsRadiusTheme, animated = true): void { + if (this._radiusTheme() === radiusTheme) return; + + if (animated) { + this.enableTransition(); + } + + this._radiusTheme.set(radiusTheme); + this.saveRadiusThemePreference(radiusTheme); + + if (animated) { + setTimeout(() => this.disableTransition(), this.TRANSITION_DURATION); + } + } + + private applyTheme( + theme: CpsTheme, + colorTheme: CpsColorTheme, + baseTheme: CpsBaseTheme, + radiusTheme: CpsRadiusTheme + ): void { + this.document.documentElement.setAttribute('data-theme', theme); + this.document.documentElement.setAttribute('data-color-theme', colorTheme); + this.document.documentElement.setAttribute('data-base-theme', baseTheme); + this.document.documentElement.setAttribute( + 'data-radius-theme', + radiusTheme + ); + } + + private enableTransition(): void { + this.document.documentElement.classList.add(this.TRANSITION_CLASS); + } + + private disableTransition(): void { + this.document.documentElement.classList.remove(this.TRANSITION_CLASS); + } + + private getInitialTheme(): CpsTheme { + // Check saved preference first + const stored = localStorage.getItem( + this.THEME_STORAGE_KEY + ) as CpsTheme | null; + if (stored === 'light' || stored === 'dark') { + return stored; + } + + // Fall back to system preference + return this.getSystemTheme(); + } + + private getInitialColorTheme(): CpsColorTheme { + const stored = localStorage.getItem( + this.COLOR_THEME_STORAGE_KEY + ) as CpsColorTheme | null; + + if ( + stored === 'neutral' || + stored === 'calm' || + stored === 'energy' || + stored === 'passion' + ) { + return stored; + } + + return 'neutral'; + } + + private getInitialBaseTheme(): CpsBaseTheme { + const stored = localStorage.getItem( + this.BASE_THEME_STORAGE_KEY + ) as CpsBaseTheme | null; + + if ( + stored === 'default' || + stored === 'graphite' || + stored === 'midnight' || + stored === 'aubergine' + ) { + return stored; + } + + return 'default'; + } + + private getInitialRadiusTheme(): CpsRadiusTheme { + const stored = localStorage.getItem( + this.RADIUS_THEME_STORAGE_KEY + ) as CpsRadiusTheme | null; + + if ( + stored === 'none' || + stored === 'compact' || + stored === 'rounded' || + stored === 'pill' + ) { + return stored; + } + + return 'none'; + } + + private getSystemTheme(): CpsTheme { + const prefersDark = window.matchMedia( + '(prefers-color-scheme: dark)' + ).matches; + return prefersDark ? 'dark' : 'light'; + } + + private watchSystemTheme(): void { + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + mediaQuery.addEventListener('change', (e) => { + // Only auto-switch if user hasn't set a preference + if (!localStorage.getItem(this.THEME_STORAGE_KEY)) { + this.setTheme(e.matches ? 'dark' : 'light'); + } + }); + } + + private saveThemePreference(theme: CpsTheme): void { + localStorage.setItem(this.THEME_STORAGE_KEY, theme); + } + + private saveColorThemePreference(colorTheme: CpsColorTheme): void { + localStorage.setItem(this.COLOR_THEME_STORAGE_KEY, colorTheme); + } + + private saveBaseThemePreference(baseTheme: CpsBaseTheme): void { + localStorage.setItem(this.BASE_THEME_STORAGE_KEY, baseTheme); + } + + private saveRadiusThemePreference(radiusTheme: CpsRadiusTheme): void { + localStorage.setItem(this.RADIUS_THEME_STORAGE_KEY, radiusTheme); + } +} diff --git a/projects/cps-ui-kit/src/public-api.ts b/projects/cps-ui-kit/src/public-api.ts index 0141399e..33999858 100644 --- a/projects/cps-ui-kit/src/public-api.ts +++ b/projects/cps-ui-kit/src/public-api.ts @@ -2,53 +2,56 @@ * Public API Surface of cps-ui-kit */ -export * from './lib/components/cps-icon/cps-icon.component'; -export * from './lib/components/cps-input/cps-input.component'; -export * from './lib/components/cps-select/cps-select.component'; -export * from './lib/components/cps-tree-select/cps-tree-select.component'; export * from './lib/components/cps-autocomplete/cps-autocomplete.component'; -export * from './lib/components/cps-tree-autocomplete/cps-tree-autocomplete.component'; -export * from './lib/components/cps-info-circle/cps-info-circle.component'; +export * from './lib/components/cps-button-toggle/cps-button-toggle.component'; export * from './lib/components/cps-button/cps-button.component'; export * from './lib/components/cps-checkbox/cps-checkbox.component'; -export * from './lib/components/cps-radio-group/cps-radio/cps-radio.component'; +export * from './lib/components/cps-chip/cps-chip.component'; +export * from './lib/components/cps-datepicker/cps-datepicker.component'; +export * from './lib/components/cps-divider/cps-divider.component'; +export * from './lib/components/cps-expansion-panel/cps-expansion-panel.component'; +export * from './lib/components/cps-file-upload/cps-file-upload.component'; +/* + * Public API Surface of cps-ui-kit + */ +export * from './lib/components/cps-icon/cps-icon.component'; +export * from './lib/components/cps-info-circle/cps-info-circle.component'; +export * from './lib/components/cps-input/cps-input.component'; +export * from './lib/components/cps-loader/cps-loader.component'; +export * from './lib/components/cps-menu/cps-menu.component'; +export * from './lib/components/cps-paginator/cps-paginator.component'; +export * from './lib/components/cps-paginator/pipes/cps-paginate.pipe'; +export * from './lib/components/cps-progress-circular/cps-progress-circular.component'; +export * from './lib/components/cps-progress-linear/cps-progress-linear.component'; export * from './lib/components/cps-radio-group/cps-radio-group.component'; +export * from './lib/components/cps-radio-group/cps-radio/cps-radio.component'; +export * from './lib/components/cps-scheduler/cps-scheduler.component'; +export * from './lib/components/cps-select/cps-select.component'; +export * from './lib/components/cps-sidebar-menu/cps-sidebar-menu.component'; +export * from './lib/components/cps-switch/cps-switch.component'; +export * from './lib/components/cps-tab-group/cps-tab-group.component'; +export * from './lib/components/cps-tab-group/cps-tab/cps-tab.component'; +export * from './lib/components/cps-table/cps-column-filter-types'; export * from './lib/components/cps-table/cps-table.component'; -export * from './lib/components/cps-table/directives/cps-table-column-sortable.directive'; export * from './lib/components/cps-table/directives/cps-table-column-filter.directive'; export * from './lib/components/cps-table/directives/cps-table-column-resizable.directive'; +export * from './lib/components/cps-table/directives/cps-table-column-sortable.directive'; export * from './lib/components/cps-table/directives/cps-table-header-selectable.directive'; export * from './lib/components/cps-table/directives/cps-table-row-selectable.directive'; -export * from './lib/components/cps-table/cps-column-filter-types'; export * from './lib/components/cps-table/pipes/cps-table-detect-filter-type.pipe'; +export * from './lib/components/cps-tag/cps-tag.component'; +export * from './lib/components/cps-textarea/cps-textarea.component'; +export * from './lib/components/cps-timepicker/cps-timepicker.component'; +export * from './lib/components/cps-tree-autocomplete/cps-tree-autocomplete.component'; +export * from './lib/components/cps-tree-select/cps-tree-select.component'; export * from './lib/components/cps-tree-table/cps-tree-table.component'; -export * from './lib/components/cps-tree-table/directives/cps-tree-table-column-sortable.directive'; export * from './lib/components/cps-tree-table/directives/cps-tree-table-column-filter.directive'; export * from './lib/components/cps-tree-table/directives/cps-tree-table-column-resizable.directive'; -export * from './lib/components/cps-tree-table/directives/cps-tree-table-row-toggler.directive'; +export * from './lib/components/cps-tree-table/directives/cps-tree-table-column-sortable.directive'; export * from './lib/components/cps-tree-table/directives/cps-tree-table-header-selectable.directive'; export * from './lib/components/cps-tree-table/directives/cps-tree-table-row-selectable.directive'; +export * from './lib/components/cps-tree-table/directives/cps-tree-table-row-toggler.directive'; export * from './lib/components/cps-tree-table/pipes/cps-tree-table-detect-filter-type.pipe'; -export * from './lib/components/cps-tag/cps-tag.component'; -export * from './lib/components/cps-chip/cps-chip.component'; -export * from './lib/components/cps-menu/cps-menu.component'; -export * from './lib/components/cps-paginator/cps-paginator.component'; -export * from './lib/components/cps-paginator/pipes/cps-paginate.pipe'; -export * from './lib/components/cps-loader/cps-loader.component'; -export * from './lib/components/cps-expansion-panel/cps-expansion-panel.component'; -export * from './lib/components/cps-progress-circular/cps-progress-circular.component'; -export * from './lib/components/cps-progress-linear/cps-progress-linear.component'; -export * from './lib/components/cps-datepicker/cps-datepicker.component'; -export * from './lib/components/cps-sidebar-menu/cps-sidebar-menu.component'; -export * from './lib/components/cps-textarea/cps-textarea.component'; -export * from './lib/components/cps-button-toggle/cps-button-toggle.component'; -export * from './lib/components/cps-tab-group/cps-tab-group.component'; -export * from './lib/components/cps-tab-group/cps-tab/cps-tab.component'; -export * from './lib/components/cps-timepicker/cps-timepicker.component'; -export * from './lib/components/cps-file-upload/cps-file-upload.component'; -export * from './lib/components/cps-scheduler/cps-scheduler.component'; -export * from './lib/components/cps-switch/cps-switch.component'; -export * from './lib/components/cps-divider/cps-divider.component'; export * from './lib/directives/cps-tooltip/cps-tooltip.directive'; @@ -59,4 +62,5 @@ export * from './lib/services/cps-dialog/utils/cps-dialog-ref'; export * from './lib/services/cps-notification/cps-notification.service'; export * from './lib/services/cps-notification/utils/cps-notification-config'; +export * from './lib/services/cps-theme/cps-theme.service'; export * from './lib/utils/colors-utils'; diff --git a/projects/cps-ui-kit/styles/_colors-dark.scss b/projects/cps-ui-kit/styles/_colors-dark.scss new file mode 100644 index 00000000..bbb76e6e --- /dev/null +++ b/projects/cps-ui-kit/styles/_colors-dark.scss @@ -0,0 +1,449 @@ +// Dark theme color palette +// Using color theory: warm reds with cool teal/cyan complements +// Cool blue-gray backgrounds provide temperature balance with warm red accents +// Proper contrast ratios for WCAG AA compliance + +[data-theme='dark'] { + // Main brand colors - slightly desaturated and lighter for dark backgrounds + --cps-color-energy: #f47721; + --cps-color-energy-highlighten: #faece5; + --cps-color-energy-lighten5: #ffff9f; + --cps-color-energy-lighten4: #ffe883; + --cps-color-energy-lighten3: #ffcb68; + --cps-color-energy-lighten2: #ffaf4d; + --cps-color-energy-lighten1: #ff9331; + --cps-color-energy-darken1: #de5d00; + --cps-color-energy-darken2: #be4300; + --cps-color-energy-darken3: #9f2800; + --cps-color-energy-darken4: #820100; + + --cps-color-prepared: #fa551e; + --cps-color-prepared-highlighten: #f9e9e5; + --cps-color-prepared-lighten5: #ffe4a1; + --cps-color-prepared-lighten4: #ffc786; + --cps-color-prepared-lighten3: #ffaa6c; + --cps-color-prepared-lighten2: #ff8e52; + --cps-color-prepared-lighten1: #ff7138; + --cps-color-prepared-darken1: #d93700; + --cps-color-prepared-darken2: #b91000; + --cps-color-prepared-darken3: #990000; + --cps-color-prepared-darken4: #7c0000; + + --cps-color-agile: #f52d28; + --cps-color-agile-highlighten: #f9e6e6; + --cps-color-agile-lighten5: #ffc8a6; + --cps-color-agile-lighten4: #ffaa8b; + --cps-color-agile-lighten3: #ff8d71; + --cps-color-agile-lighten2: #ff6f58; + --cps-color-agile-lighten1: #ff5040; + --cps-color-agile-darken1: #d40010; + --cps-color-agile-darken2: #b30000; + --cps-color-agile-darken3: #930000; + --cps-color-agile-darken4: #760000; + + --cps-color-passion: #dc0032; + --cps-color-passion-highlighten: #f7e3e7; + --cps-color-passion-lighten5: #ffb3ae; + --cps-color-passion-lighten4: #ff9693; + --cps-color-passion-lighten3: #ff7879; + --cps-color-passion-lighten2: #ff5a61; + --cps-color-passion-lighten1: #fd3849; + --cps-color-passion-darken1: #bc001d; + --cps-color-passion-darken2: #9b0007; + --cps-color-passion-darken3: #7d0000; + --cps-color-passion-darken4: #600000; + + --cps-color-warmth: #be0028; + --cps-color-warmth-highlighten: #f3e3e6; + --cps-color-warmth-lighten5: #ffa9a2; + --cps-color-warmth-lighten4: #ff8d87; + --cps-color-warmth-lighten3: #ff706e; + --cps-color-warmth-lighten2: #fe5255; + --cps-color-warmth-lighten1: #de333e; + --cps-color-warmth-darken1: #9e0013; + --cps-color-warmth-darken2: #800000; + --cps-color-warmth-darken3: #630000; + --cps-color-warmth-darken4: #4b0000; + + --cps-color-human: #aa052d; + --cps-color-human-highlighten: #f1e3e6; + --cps-color-human-lighten5: #ffa4a7; + --cps-color-human-lighten4: #ff888d; + --cps-color-human-lighten3: #ff6c73; + --cps-color-human-lighten2: #e84f5a; + --cps-color-human-lighten1: #c93143; + --cps-color-human-darken1: #8b0019; + --cps-color-human-darken2: #6d0000; + --cps-color-human-darken3: #520000; + --cps-color-human-darken4: #400000; + + --cps-color-grounded: #960528; + --cps-color-grounded-highlighten: #f0e3e6; + --cps-color-grounded-lighten5: #ff9ea1; + --cps-color-grounded-lighten4: #ff8286; + --cps-color-grounded-lighten3: #f2666d; + --cps-color-grounded-lighten2: #d34b55; + --cps-color-grounded-lighten1: #b42e3e; + --cps-color-grounded-darken1: #780014; + --cps-color-grounded-darken2: #5c0000; + --cps-color-grounded-darken3: #440000; + --cps-color-grounded-darken4: #390000; + + --cps-color-care: #f05a78; + --cps-color-care-highlighten: #f8e9ed; + --cps-color-care-lighten5: #ffe9ff; + --cps-color-care-lighten4: #ffcce9; + --cps-color-care-lighten3: #ffafcd; + --cps-color-care-lighten2: #ff93b1; + --cps-color-care-lighten1: #ff7697; + --cps-color-care-darken1: #d13d64; + --cps-color-care-darken2: #b31a4c; + --cps-color-care-darken3: #950036; + --cps-color-care-darken4: #770021; + + --cps-color-smile: #f0325a; + --cps-color-smile-highlighten: #f8e7e9; + --cps-color-smile-lighten5: #ffcbdd; + --cps-color-smile-lighten4: #ffadc1; + --cps-color-smile-lighten3: #ff90a6; + --cps-color-smile-lighten2: #ff728c; + --cps-color-smile-lighten1: #ff5472; + --cps-color-smile-darken1: #d00043; + --cps-color-smile-darken2: #b0002d; + --cps-color-smile-darken3: #910019; + --cps-color-smile-darken4: #720000; + + --cps-color-surprise: #af144b; + --cps-color-surprise-highlighten: #f2e4e9; + --cps-color-surprise-lighten5: #ffaccb; + --cps-color-surprise-lighten4: #ff8fb0; + --cps-color-surprise-lighten3: #ff7395; + --cps-color-surprise-lighten2: #ec577b; + --cps-color-surprise-lighten1: #cd3963; + --cps-color-surprise-darken1: #910035; + --cps-color-surprise-darken2: #730020; + --cps-color-surprise-darken3: #560008; + --cps-color-surprise-darken4: #400000; + + --cps-color-calm: #870a3c; + --cps-color-calm-highlighten: #efe4e7; + --cps-color-calm-lighten5: #ff9bb9; + --cps-color-calm-lighten4: #fd809e; + --cps-color-calm-lighten3: #df6584; + --cps-color-calm-lighten2: #c14a6b; + --cps-color-calm-lighten1: #a42e53; + --cps-color-calm-darken1: #6b0027; + --cps-color-calm-darken2: #4f0012; + --cps-color-calm-darken3: #390000; + --cps-color-calm-darken4: #300000; + + --cps-color-luxury: #640032; + --cps-color-luxury-highlighten: #ebe3e6; + --cps-color-luxury-lighten5: #f28bad; + --cps-color-luxury-lighten4: #d57192; + --cps-color-luxury-lighten3: #b85779; + --cps-color-luxury-lighten2: #9b3d60; + --cps-color-luxury-lighten1: #7f2248; + --cps-color-luxury-darken1: #49001d; + --cps-color-luxury-darken2: #340002; + --cps-color-luxury-darken3: #290000; + --cps-color-luxury-darken4: #1c0000; + + --cps-color-depth: #500a28; + --cps-color-depth-highlighten: #e9e3e6; + --cps-color-depth-lighten5: #d989a0; + --cps-color-depth-lighten4: #bc6f86; + --cps-color-depth-lighten3: #a0566d; + --cps-color-depth-lighten2: #853d55; + --cps-color-depth-lighten1: #6a253e; + --cps-color-depth-darken1: #370013; + --cps-color-depth-darken2: #290000; + --cps-color-depth-darken3: #1b0000; + --cps-color-depth-darken4: #000000; + + //Darks + --cps-color-silver: #736464; + --cps-color-silver-highlighten: #edeaea; + --cps-color-silver-lighten5: #fbe9e9; + --cps-color-silver-lighten4: #decdcd; + --cps-color-silver-lighten3: #c2b2b1; + --cps-color-silver-lighten2: #a79797; + --cps-color-silver-lighten1: #8d7d7d; + --cps-color-silver-darken1: #5a4c4c; + --cps-color-silver-darken2: #433535; + --cps-color-silver-darken3: #2c2020; + --cps-color-silver-darken4: #190909; + + --cps-color-platinum: #5a4b4b; + --cps-color-platinum-highlighten: #eae8e8; + --cps-color-platinum-lighten5: #decccc; + --cps-color-platinum-lighten4: #c2b0b0; + --cps-color-platinum-lighten3: #a79695; + --cps-color-platinum-lighten2: #8c7c7c; + --cps-color-platinum-lighten1: #736363; + --cps-color-platinum-darken1: #423434; + --cps-color-platinum-darken2: #2c1f1f; + --cps-color-platinum-darken3: #190707; + --cps-color-platinum-darken4: #000000; + + --cps-color-graphite: #2d2323; + --cps-color-graphite-highlighten: #e7e5e5; + --cps-color-graphite-lighten5: #a79a9a; + --cps-color-graphite-lighten4: #8d8080; + --cps-color-graphite-lighten3: #736767; + --cps-color-graphite-lighten2: #5b4f4f; + --cps-color-graphite-lighten1: #433838; + --cps-color-graphite-darken1: #190d0d; + --cps-color-graphite-darken2: #000000; + --cps-color-graphite-darken3: #000000; + --cps-color-graphite-darken4: #000000; + + //States + --cps-color-info: #099ef3; + --cps-color-info-highlighten: #e5eff8; + --cps-color-info-lighten5: #d0ffff; + --cps-color-info-lighten4: #b0ffff; + --cps-color-info-lighten3: #90f1ff; + --cps-color-info-lighten2: #6fd4ff; + --cps-color-info-lighten1: #49b9ff; + --cps-color-info-darken1: #0084d6; + --cps-color-info-darken2: #006bba; + --cps-color-info-darken3: #00539f; + --cps-color-info-darken4: #003d84; + + --cps-color-success: #3bb719; + --cps-color-success-highlighten: #e8f2e6; + --cps-color-success-lighten5: #d5ffaa; + --cps-color-success-lighten4: #b7ff8e; + --cps-color-success-lighten3: #99ff72; + --cps-color-success-lighten2: #7bf057; + --cps-color-success-lighten1: #5dd33a; + --cps-color-success-darken1: #059b00; + --cps-color-success-darken2: #008100; + --cps-color-success-darken3: #006600; + --cps-color-success-darken4: #004d00; + + --cps-color-warn: #ff9f00; + --cps-color-warn-highlighten: #faefe5; + --cps-color-warn-lighten5: #ffffa3; + --cps-color-warn-lighten4: #ffff87; + --cps-color-warn-lighten3: #fff26b; + --cps-color-warn-lighten2: #ffd64e; + --cps-color-warn-lighten1: #ffba30; + --cps-color-warn-darken1: #df8500; + --cps-color-warn-darken2: #c06b00; + --cps-color-warn-darken3: #a15300; + --cps-color-warn-darken4: #843b00; + + --cps-color-error-highlighten: #f9e4e5; + --cps-color-error-lighten5: #f5d9d9; + --cps-color-error-lighten4: #f2cece; + --cps-color-error-lighten3: #e9a7a7; + --cps-color-error-lighten2: #df8080; + --cps-color-error-lighten1: #d55959; + --cps-color-error-darken1: #a32828; + --cps-color-error-darken2: #7a1e1e; + --cps-color-error-darken3: #511414; + --cps-color-error-darken4: #300c0c; + + // States backgrounds + --cps-color-info-bg: rgba(73, 185, 255, 0.16); + --cps-color-success-bg: rgba(93, 211, 58, 0.16); + --cps-color-warn-bg: rgba(255, 186, 48, 0.16); + --cps-color-error-bg: rgba(255, 90, 103, 0.16); + + // Highlights + --cps-color-highlight-hover: rgba(251, 251, 251, 0.06); + --cps-color-highlight-active: rgba(251, 251, 251, 0.1); + --cps-color-highlight-selected: rgba(244, 119, 33, 0.16); + --cps-color-highlight-selected-dark: rgba(244, 119, 33, 0.24); + + //Backgrounds + --cps-color-bg-lightest: #2a2a31; + --cps-color-bg-light: #1f1f24; + --cps-color-bg-mid: #1b1b1e; + --cps-color-bg-dark: #151419; + + //Lines + --cps-color-line-light: #3f3f46; + --cps-color-line-mid: #50505a; + --cps-color-line-dark: #666670; + --cps-color-line-darkest: #7a7a86; + + //Text + --cps-color-text-lightest: #fbfbfb; + --cps-color-text-light: #d0d0d2; + --cps-color-text-mild: #a8a8ad; + --cps-color-text-dark: #878787; + --cps-color-text-darkest: #151419; + + // Semantic design tokens (use these inside components) + --cps-accent-primary: var(--cps-color-energy); + --cps-accent-primary-contrast: #151419; + --cps-accent-secondary: #fbfbfb; + --cps-accent-secondary-contrast: #151419; + --cps-color-error: #b91c1c; + --cps-error-background: rgba(255, 90, 103, 0.16); + + // Lines and borders + --cps-color-line: rgba(251, 251, 251, 0.12); + --cps-surface-body: #151419; + --cps-surface-highlight: #1b1b1e; + --cps-surface-muted: #202028; + --cps-surface-elevated: #262626; + --cps-surface-control: #262626; + --cps-surface-overlay: rgba(21, 20, 25, 0.85); + --cps-background-color: #151419; + --cps-background-disabled: rgba( + 255, + 255, + 255, + 0.05 + ); // oklch(55.096% 0.02679 264.351 / 0.452); + + // Tab component + --cps-tab-subtabs-background: var(--cps-surface-highlight); + --cps-tabs-subtabs-active-background: var(--cps-color-highlight-selected); + --cps-tabs-subtabs-background-hover: var(--cps-highlight-hover); + --cps-tabs-subtabs-text-hover: var(--cps-text-primary); + + // Text + --cps-text-primary: #fbfbfb; + --cps-text-secondary: #d0d0d2; + --cps-text-muted: #878787; + --cps-text-inverse: var(--cps-color-depth-darken4); + --cps-text-on-accent: #151419; + --cps-text-disabled: #6f6f74; + + --cps-border-color: #3a3a3a; + --cps-border-strong: #505050; + --cps-border-focus: var(--cps-accent-primary); + + --cps-highlight-hover: rgba(251, 251, 251, 0.1); + --cps-highlight-active: rgba(251, 251, 251, 0.16); + --cps-highlight-selected: var(--cps-color-highlight-selected-dark); + + --cps-state-info: #49b9ff; + --cps-state-info-contrast: #151419; + --cps-state-info-surface: rgba(73, 185, 255, 0.16); + --cps-state-success: #5dd33a; + --cps-state-success-contrast: #151419; + --cps-state-success-surface: rgba(93, 211, 58, 0.16); + --cps-state-warn: #ffba30; + --cps-state-warn-contrast: #151419; + --cps-state-warn-surface: rgba(255, 186, 48, 0.16); + --cps-state-error: var(--cps-color-error); + --cps-state-error-contrast: #ffffff; + --cps-state-error-surface: rgba(185, 28, 28, 0.28); + + // Modern semantic surfaces + --cps-card-background: var(--cps-surface-highlight); + --cps-card-foreground: var(--cps-text-primary); + --cps-popover-background: var(--cps-surface-elevated); + --cps-popover-foreground: var(--cps-text-primary); + --cps-input-background: var(--cps-surface-highlight); + --cps-input-foreground: var(--cps-text-primary); + --cps-input-placeholder: var(--cps-text-muted); + + // Focus ring and outlines + --cps-ring-color: var(--cps-border-focus); + --cps-ring-offset-color: var(--cps-surface-body); + + // Radius scale + --cps-radius-xs: 2px; + --cps-radius-sm: 4px; + --cps-radius-md: 8px; + --cps-radius-lg: 12px; + --cps-radius-xl: 16px; + --cps-radius-full: 9999px; + + // Backward compatible radius aliases + --cps-border-radius-small: var(--cps-radius-sm); + --cps-border-radius-medium: var(--cps-radius-md); + --cps-border-radius-large: var(--cps-radius-lg); + --cps-border-radius-round: var(--cps-radius-full); + + // Elevation shadows + --cps-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3); + --cps-shadow-sm: 0 4px 10px rgba(0, 0, 0, 0.34); + --cps-shadow-md: 0 12px 24px rgba(0, 0, 0, 0.4); + --cps-shadow-lg: 0 24px 48px rgba(0, 0, 0, 0.5); + + // Motion tokens + --cps-motion-fast: 120ms; + --cps-motion-base: 180ms; + --cps-motion-slow: 260ms; + --cps-motion-easing: cubic-bezier(0.2, 0, 0, 1); +} + +[data-theme='dark'][data-color-theme='neutral'] { + --cps-accent-primary: #e4e4e7; + --cps-accent-primary-contrast: #151419; + --cps-accent-secondary: #f4f4f5; + --cps-accent-secondary-contrast: #151419; + --cps-border-focus: #e4e4e7; + --cps-highlight-selected: rgba(228, 228, 231, 0.22); +} + +[data-theme='dark'][data-color-theme='calm'] { + --cps-accent-primary: var(--cps-color-calm-lighten4); + --cps-accent-primary-contrast: #151419; + --cps-accent-secondary: var(--cps-color-care-lighten3); + --cps-accent-secondary-contrast: #151419; + --cps-border-focus: var(--cps-color-calm-lighten4); + --cps-highlight-selected: rgba(253, 128, 158, 0.28); +} + +[data-theme='dark'][data-color-theme='energy'] { + --cps-accent-primary: var(--cps-color-energy); + --cps-accent-primary-contrast: #151419; + --cps-accent-secondary: var(--cps-color-prepared-lighten4); + --cps-accent-secondary-contrast: #151419; + --cps-border-focus: var(--cps-color-energy); + --cps-highlight-selected: var(--cps-color-highlight-selected-dark); +} + +[data-theme='dark'][data-color-theme='passion'] { + --cps-accent-primary: var(--cps-color-passion-lighten3); + --cps-accent-primary-contrast: #151419; + --cps-accent-secondary: var(--cps-color-care-lighten4); + --cps-accent-secondary-contrast: #151419; + --cps-border-focus: var(--cps-color-passion-lighten3); + --cps-highlight-selected: rgba(255, 120, 121, 0.3); +} + +[data-theme='dark'][data-base-theme='graphite'] { + --cps-surface-body: #121216; + --cps-surface-highlight: #191a20; + --cps-surface-muted: #1d1f26; + --cps-surface-elevated: #23252f; + --cps-surface-control: #23252f; + --cps-background-color: #121216; + --cps-border-color: #3f424d; + --cps-border-strong: #555968; + --cps-ring-offset-color: #121216; +} + +[data-theme='dark'][data-base-theme='midnight'] { + --cps-surface-body: #0f1624; + --cps-surface-highlight: #172033; + --cps-surface-muted: #1b263c; + --cps-surface-elevated: #21304a; + --cps-surface-control: #21304a; + --cps-background-color: #0f1624; + --cps-border-color: #32445f; + --cps-border-strong: #4a6388; + --cps-ring-offset-color: #0f1624; +} + +[data-theme='dark'][data-base-theme='aubergine'] { + --cps-surface-body: #1a1320; + --cps-surface-highlight: #231a2c; + --cps-surface-muted: #2b2136; + --cps-surface-elevated: #332943; + --cps-surface-control: #332943; + --cps-background-color: #1a1320; + --cps-border-color: #534363; + --cps-border-strong: #6d5683; + --cps-ring-offset-color: #1a1320; +} diff --git a/projects/cps-ui-kit/styles/_colors.scss b/projects/cps-ui-kit/styles/_colors.scss index c63e637a..dfd461a9 100644 --- a/projects/cps-ui-kit/styles/_colors.scss +++ b/projects/cps-ui-kit/styles/_colors.scss @@ -272,4 +272,165 @@ --cps-color-text-mild: #787272; --cps-color-text-dark: #524a4a; --cps-color-text-darkest: #2d2323; + + // Semantic design tokens (use these inside components) + --cps-accent-primary: var(--cps-color-passion); + --cps-accent-primary-contrast: #ffffff; + --cps-accent-secondary: var(--cps-color-energy); + --cps-accent-secondary-contrast: #2d2323; + --cps-color-error: #b91c1c; + --cps-error-background: #fef3f2; + + // Lines and borders + --cps-color-line: #e3e2e2; + + --cps-surface-body: var(--cps-color-bg-light); + --cps-surface-highlight: #ffffff; + --cps-surface-muted: var( + --cps-color-bg-lightest + ); //switched with --cps-color-bg-light, investigate impact + --cps-surface-elevated: var(--cps-color-bg-mid); + --cps-surface-control: #ffffff; + --cps-surface-overlay: rgba(0, 0, 0, 0.45); + --cps-background-color: var(--cps-color-bg-lightest); + --cps-background-disabled: #f7f7f7; + + // Tab component + --cps-tab-subtabs-background: #d7d7d759; + --cps-tabs-subtabs-active-background: #fff; + --cps-tabs-subtabs-background-hover: var(--cps-highlight-active); + --cps-tabs-subtabs-text-hover: var(--cps-accent-primary); + + --cps-text-primary: var(--cps-color-text-darkest); + --cps-text-secondary: var(--cps-color-text-dark); + --cps-text-muted: var(--cps-color-text-mild); + --cps-text-inverse: var(--cps-color-depth-darken4); + --cps-text-on-accent: #ffffff; + --cps-text-disabled: var(--cps-color-text-light); + + --cps-border-color: var(--cps-color-line-mid); + --cps-border-strong: var(--cps-color-line-dark); + --cps-border-focus: var(--cps-color-passion); + + --cps-highlight-hover: var(--cps-color-highlight-hover); + --cps-highlight-active: var(--cps-color-highlight-active); + --cps-highlight-selected: var(--cps-color-highlight-selected); + + --cps-state-info: var(--cps-color-info); + --cps-state-info-contrast: #2d2323; + --cps-state-info-surface: var(--cps-color-info-bg); + --cps-state-success: var(--cps-color-success); + --cps-state-success-contrast: #2d2323; + --cps-state-success-surface: var(--cps-color-success-bg); + --cps-state-warn: var(--cps-color-warn); + --cps-state-warn-contrast: #3b2500; + --cps-state-warn-surface: var(--cps-color-warn-bg); + --cps-state-error: var(--cps-color-error); + --cps-state-error-contrast: #ffffff; + --cps-state-error-surface: rgba(185, 28, 28, 0.14); + + // Modern semantic surfaces + --cps-card-background: var(--cps-surface-highlight); + --cps-card-foreground: var(--cps-text-primary); + --cps-popover-background: var(--cps-surface-control); + --cps-popover-foreground: var(--cps-text-primary); + --cps-input-background: var(--cps-surface-control); + --cps-input-foreground: var(--cps-text-primary); + --cps-input-placeholder: var(--cps-text-muted); + + // Focus ring and outlines + --cps-ring-color: var(--cps-border-focus); + --cps-ring-offset-color: var(--cps-surface-body); + + // Radius scale + --cps-radius-xs: 2px; + --cps-radius-sm: 4px; + --cps-radius-md: 8px; + --cps-radius-lg: 12px; + --cps-radius-xl: 16px; + --cps-radius-full: 9999px; + + // Backward compatible radius aliases + --cps-border-radius-small: var(--cps-radius-sm); + --cps-border-radius-medium: var(--cps-radius-md); + --cps-border-radius-large: var(--cps-radius-lg); + --cps-border-radius-round: var(--cps-radius-full); + + // Elevation shadows + --cps-shadow-xs: 0 1px 2px rgba(45, 35, 35, 0.08); + --cps-shadow-sm: 0 2px 6px rgba(45, 35, 35, 0.12); + --cps-shadow-md: 0 8px 20px rgba(45, 35, 35, 0.14); + --cps-shadow-lg: 0 16px 40px rgba(45, 35, 35, 0.2); + + // Motion tokens + --cps-motion-fast: 120ms; + --cps-motion-base: 180ms; + --cps-motion-slow: 260ms; + --cps-motion-easing: cubic-bezier(0.2, 0, 0, 1); +} + +:root[data-color-theme='neutral'] { + --cps-accent-primary: #27272a; + --cps-accent-primary-contrast: #ffffff; + --cps-accent-secondary: #3f3f46; + --cps-accent-secondary-contrast: #ffffff; + --cps-border-focus: #27272a; + --cps-highlight-selected: rgba(39, 39, 42, 0.14); +} + +:root[data-color-theme='calm'] { + --cps-accent-primary: var(--cps-color-calm); + --cps-accent-primary-contrast: #ffffff; + --cps-accent-secondary: var(--cps-color-care); + --cps-accent-secondary-contrast: #2d2323; + --cps-border-focus: var(--cps-color-calm); + --cps-highlight-selected: rgba(135, 10, 60, 0.16); +} + +:root[data-color-theme='energy'] { + --cps-accent-primary: var(--cps-color-energy); + --cps-accent-primary-contrast: #2d2323; + --cps-text-on-accent: #2d2323; + --cps-accent-secondary: var(--cps-color-prepared); + --cps-accent-secondary-contrast: #2d2323; + --cps-border-focus: var(--cps-color-energy); + --cps-highlight-selected: var(--cps-color-highlight-selected); +} + +:root[data-color-theme='passion'] { + --cps-accent-primary: var(--cps-color-passion); + --cps-accent-primary-contrast: #ffffff; + --cps-accent-secondary: var(--cps-color-warmth); + --cps-accent-secondary-contrast: #ffffff; + --cps-border-focus: var(--cps-color-passion); + --cps-highlight-selected: rgba(220, 0, 50, 0.16); +} + +:root[data-radius-theme='none'] { + --cps-radius-xs: 0px; + --cps-radius-sm: 0px; + --cps-radius-md: 0px; + --cps-radius-lg: 0px; + --cps-radius-xl: 0px; +} + +:root[data-radius-theme='compact'] { + --cps-radius-sm: 3px; + --cps-radius-md: 6px; + --cps-radius-lg: 10px; + --cps-radius-xl: 14px; +} + +:root[data-radius-theme='rounded'] { + --cps-radius-sm: 6px; + --cps-radius-md: 10px; + --cps-radius-lg: 14px; + --cps-radius-xl: 20px; +} + +:root[data-radius-theme='pill'] { + --cps-radius-sm: 9999px; + --cps-radius-md: 9999px; + --cps-radius-lg: 9999px; + --cps-radius-xl: 9999px; } diff --git a/projects/cps-ui-kit/styles/styles.scss b/projects/cps-ui-kit/styles/styles.scss index 79e63a09..44bcf507 100644 --- a/projects/cps-ui-kit/styles/styles.scss +++ b/projects/cps-ui-kit/styles/styles.scss @@ -1,5 +1,6 @@ @use './_bootstrap-grid'; @use './_colors.scss'; +@use './_colors-dark.scss'; @use './_fonts.scss'; @use './_cps-tooltip-style.scss'; @use 'primeicons/primeicons.css'; @@ -18,3 +19,26 @@ position: absolute; top: -9999px; } + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--cps-background-color); +} +::-webkit-scrollbar-thumb { + background: var(--cps-border-color); + border-radius: var(--cps-radius-sm); +} +::-webkit-scrollbar-thumb:hover { + background: var(--cps-accent-primary); +} + +html, +body { + font-family: 'Source Sans Pro', sans-serif; + background: var(--cps-background-color); + color: var(--cps-text-primary); +} From ede144f52ae528e9ead225affc6253ecfb4bd859 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 16 Feb 2026 18:35:24 +0200 Subject: [PATCH 2/7] Refactor styles and update color variables for improved theming consistency across components --- .../composition/src/app/app.component.scss | 35 +++++++-- .../component-docs-viewer.component.html | 2 +- .../navigation-sidebar.component.scss | 14 ++-- .../icons-page/icons-page.component.html | 5 +- .../icons-page/icons-page.component.scss | 2 +- projects/composition/src/styles.scss | 10 ++- projects/composition/src/variables.scss | 2 +- .../cps-autocomplete.component.html | 6 +- .../cps-autocomplete.component.scss | 74 +++++++++++-------- .../cps-chip/cps-chip.component.html | 2 +- .../cps-chip/cps-chip.component.scss | 17 +++-- 11 files changed, 107 insertions(+), 62 deletions(-) diff --git a/projects/composition/src/app/app.component.scss b/projects/composition/src/app/app.component.scss index c3da3b32..763eb4f0 100644 --- a/projects/composition/src/app/app.component.scss +++ b/projects/composition/src/app/app.component.scss @@ -2,19 +2,39 @@ .top-toolbar { height: vars.$top-tbar-height; - background-color: white; + background-color: var(--cps-surface-body); display: flex; - padding-left: 20px; + padding: 0 14px; align-items: center; border-bottom: 1px solid lightgrey; + border-bottom: 1px solid var(--cps-border-color); + gap: 8px; img { width: 42px; height: 42px; } + span { - margin-left: 16px; - font-size: 18px; - color: vars.$color-calm; + font-size: 13px; + color: var(--cps-text-secondary); + line-height: 1; + + &:first-of-type { + flex: 1; + color: var(--cps-text-primary); + font-weight: 600; + letter-spacing: 0.01em; + } + + b { + color: var(--cps-accent-primary); + font-weight: 700; + font-size: 15px; + } + } + + app-theme-toggle { + margin-left: auto; } } .composition-container { @@ -29,11 +49,12 @@ background-color: vars.$composition-background; .composition-body-toolbar { height: vars.$inner-tbar-height; - background: vars.$color-calm; + background: var(--cps-surface-elevated); + border-bottom: 1px solid var(--cps-border-color); display: flex; align-items: center; justify-content: space-between; - color: white; + color: var(--cps-text-primary); font-size: 20px; .composition-body-toolbar-title { margin: 0 auto; diff --git a/projects/composition/src/app/components/component-docs-viewer/component-docs-viewer.component.html b/projects/composition/src/app/components/component-docs-viewer/component-docs-viewer.component.html index 826fe31a..d6fe0f64 100644 --- a/projects/composition/src/app/components/component-docs-viewer/component-docs-viewer.component.html +++ b/projects/composition/src/app/components/component-docs-viewer/component-docs-viewer.component.html @@ -1,5 +1,5 @@ diff --git a/projects/composition/src/app/components/navigation-sidebar/navigation-sidebar.component.scss b/projects/composition/src/app/components/navigation-sidebar/navigation-sidebar.component.scss index 712d5b3e..21ff31c9 100644 --- a/projects/composition/src/app/components/navigation-sidebar/navigation-sidebar.component.scss +++ b/projects/composition/src/app/components/navigation-sidebar/navigation-sidebar.component.scss @@ -1,15 +1,15 @@ @use '../../../variables.scss' as vars; :host { - $item-hover-background: var(--cps-color-highlight-hover); - $item-active-background: var(--cps-color-highlight-active); - $item-border-color: var(--cps-color-line-light); + $item-hover-background: var(--cps-highlight-hover); + $item-active-background: var(--cps-highlight-active); + $item-border-color: var(--cps-color-line); border-right: 1px solid $item-border-color; - background-color: var(--cps-color-bg-light); + background-color: var(--cps-surface-body); .sidebar { transition: width 0.2s; - background-color: white; + background-color: var(--cps-surface-body); width: vars.$sidebar-width; height: calc(100vh - vars.$top-tbar-height - 20px); overflow: auto; @@ -17,7 +17,7 @@ &-title { margin: 0; padding: 12px 0 12px 12px; - color: vars.$color-text; + color: var(--cps-text-primary); } &-item { border-bottom: 1px solid $item-border-color; @@ -26,7 +26,7 @@ align-items: center; padding-left: 30px; text-decoration: none; - color: vars.$color-text; + color: var(--cps-text-primary); &:hover { background: $item-hover-background; } diff --git a/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.html b/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.html index ab3bde80..85fa867e 100644 --- a/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.html +++ b/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.html @@ -12,7 +12,10 @@
@for (name of filteredIconsList; track name) {
- + {{ name }}
} diff --git a/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.scss b/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.scss index 4645cb80..6cbd8dca 100644 --- a/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.scss +++ b/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.scss @@ -17,6 +17,6 @@ cursor: pointer; span { margin-left: 16px; - color: vars.$color-calm; + color: var(--cps-text-primary); } } diff --git a/projects/composition/src/styles.scss b/projects/composition/src/styles.scss index ef72a0d3..97428f8e 100644 --- a/projects/composition/src/styles.scss +++ b/projects/composition/src/styles.scss @@ -41,11 +41,15 @@ body { font-weight: bold; text-align: left; padding: 0.75rem 1rem; + background-color: var(--cps-surface-elevated); border-bottom: 1px solid var(--cps-color-line); } tr { transition: background-color 0.5s ease-in; + &:hover { + background-color: var(--cps-highlight-hover); + } } td { @@ -76,8 +80,6 @@ body { &:hover { text-decoration: none; - background-color: var(--cps-surface-elevated); - border: 1px solid var(--cps-color-line); } } } @@ -94,8 +96,8 @@ body { Consolas, Liberation Mono, monospace; - background-color: var(--cps-color-bg-mid); - border: 1px solid var(--cps-color-line-light); + background-color: var(--cps-surface-elevated); + border: 1px solid var(--cps-color-line); } } } diff --git a/projects/composition/src/variables.scss b/projects/composition/src/variables.scss index ada123d4..f26fb833 100644 --- a/projects/composition/src/variables.scss +++ b/projects/composition/src/variables.scss @@ -4,4 +4,4 @@ $top-tbar-height: 64px; $inner-tbar-height: 45px; $color-calm: var(--cps-accent-primary); -$color-text: var(--cps-text-secondary); +$color-text: var(--cps-text-primary); diff --git a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html index 0c028173..e41060ab 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html +++ b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html @@ -1,7 +1,7 @@
@@ -129,6 +129,7 @@ #autocompleteInput class="cps-autocomplete-box-input" spellcheck="false" + [attr.aria-label]="label || placeholder || 'Autocomplete input'" [placeholder]=" (!multiple && isEmptyValue()) || (value?.length < 1 && multiple) ? placeholder @@ -283,6 +284,7 @@ spellcheck="false" [class]="inputClass" [style]="inputStyle" + [attr.aria-label]="label || placeholder || 'Autocomplete input'" [placeholder]=" (!multiple && isEmptyValue()) || (value?.length < 1 && multiple) ? placeholder diff --git a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.scss b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.scss index 1199eea0..2a295c15 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.scss +++ b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.scss @@ -1,21 +1,21 @@ -$color-calm: var(--cps-color-calm); -$color-error: var(--cps-color-error); -$error-background: #fef3f2; -$autocomplete-placeholder-color: var(--cps-color-text-lightest); -$autocomplete-label-color: var(--cps-color-text-dark); -$autocomplete-label-disabled-color: var(--cps-color-text-mild); -$autocomplete-items-disabled-color: var(--cps-color-text-light); -$autocomplete-hint-color: var(--cps-color-text-mild); -$option-hover-background: var(--cps-color-highlight-hover); -$selected-option-background: var(--cps-color-highlight-selected); -$option-highlight-background: var(--cps-color-highlight-active); -$option-highlight-selected-background: var(--cps-color-highlight-selected-dark); -$autocomplete-option-info-color: var(--cps-color-text-light); -$autocomplete-option-value-color: var(--cps-color-text-dark); -$autocomplete-about-remove-color: var(--cps-color-text-light); -$autocomplete-about-remove-background: var(--cps-color-bg-mid); -$autocomplete-prefix-icon-color: var(--cps-color-text-dark); -$autocomplete-border-color: var(--cps-color-line-light); +$color-calm: var(--cps-accent-primary); +$color-error: var(--cps-state-error); +$error-background: var(--cps-error-background); +$autocomplete-placeholder-color: var(--cps-input-placeholder); +$autocomplete-label-color: var(--cps-text-primary); +$autocomplete-label-disabled-color: var(--cps-text-secondary); +$autocomplete-items-disabled-color: var(--cps-text-disabled); +$autocomplete-hint-color: var(--cps-text-primary); +$option-hover-background: var(--cps-highlight-hover); +$selected-option-background: var(--cps-highlight-selected); +$option-highlight-background: var(--cps-highlight-active); +$option-highlight-selected-background: var(--cps-highlight-selected); +$autocomplete-option-info-color: var(--cps-text-secondary); +$autocomplete-option-value-color: var(--cps-text-primary); +$autocomplete-about-remove-color: var(--cps-text-muted); +$autocomplete-about-remove-background: var(--cps-surface-muted); +$autocomplete-prefix-icon-color: var(--cps-text-secondary); +$autocomplete-border-color: var(--cps-border-color); $hover-transition-duration: 0.2s; @@ -26,7 +26,7 @@ $hover-transition-duration: 0.2s; position: relative; width: 100%; outline: none; - font-family: 'Source Sans Pro', sans-serif; + font-family: inherit; font-weight: normal; display: grid; @@ -40,7 +40,7 @@ $hover-transition-duration: 0.2s; &.focused { .cps-autocomplete-box { - background: white !important; + background: var(--cps-input-background) !important; } } @@ -62,6 +62,7 @@ $hover-transition-duration: 0.2s; &.active { .cps-autocomplete-box { border: 1px solid $color-calm; + box-shadow: 0 0 0 3px var(--cps-highlight-selected); .cps-autocomplete-box-area { .prefix-icon { color: $color-calm; @@ -79,8 +80,14 @@ $hover-transition-duration: 0.2s; display: inline-flex; margin-bottom: 0.2rem; color: $autocomplete-label-color; + background-color: var(--cps-surface-body); font-size: 0.875rem; font-weight: 600; + + label { + color: $autocomplete-label-color; + } + .cps-autocomplete-label-info-circle { margin-left: 8px; pointer-events: all; @@ -106,13 +113,16 @@ $hover-transition-duration: 0.2s; min-height: 38px; width: 100%; cursor: text; - background: white; + background: var(--cps-input-background); font-size: 1rem; outline: none; padding: 0 12px 0 12px; - border-radius: 4px; + border-radius: var(--cps-border-radius-medium); border: 1px solid $autocomplete-border-color; - transition-duration: $hover-transition-duration; + transition: + border-color $hover-transition-duration var(--cps-motion-easing), + box-shadow $hover-transition-duration var(--cps-motion-easing), + background-color $hover-transition-duration var(--cps-motion-easing); &-area { display: flex; @@ -135,7 +145,7 @@ $hover-transition-duration: 0.2s; color: $autocomplete-option-value-color; border-style: none; outline: none; - font-family: 'Source Sans Pro', sans-serif; + font-family: inherit; &::placeholder { color: $autocomplete-placeholder-color; font-style: italic; @@ -206,7 +216,7 @@ $hover-transition-duration: 0.2s; } &:hover { - border: 1px solid $color-calm; + border: 1px solid var(--cps-border-strong); .cps-autocomplete-box-area { .prefix-icon { color: $color-calm; @@ -248,6 +258,8 @@ $hover-transition-duration: 0.2s; .cps-autocomplete-hint { color: $autocomplete-hint-color; + background-color: var(--cps-surface-body); + display: inline-block; font-size: 0.75rem; min-height: 1.125rem; line-height: 1.125rem; @@ -267,7 +279,7 @@ $hover-transition-duration: 0.2s; &.disabled { pointer-events: none; .cps-autocomplete-box { - background: #f7f7f7; + background: var(--cps-background-disabled); &-items { color: $autocomplete-items-disabled-color; .text-group, @@ -297,8 +309,12 @@ $hover-transition-duration: 0.2s; } .cps-autocomplete-options { - font-family: 'Source Sans Pro', sans-serif; - background: white; + font-family: inherit; + background: var(--cps-popover-background); + color: var(--cps-popover-foreground); + border: 1px solid var(--cps-border-color); + border-radius: var(--cps-border-radius-medium); + box-shadow: var(--cps-shadow-md); overflow-x: hidden; max-height: 242px; overflow-y: auto; @@ -390,7 +406,7 @@ $hover-transition-duration: 0.2s; } .select-all-option { - border-bottom: 1px solid lightgrey; + border-bottom: 1px solid var(--cps-border-color); font-weight: 600; } diff --git a/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.html b/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.html index 70e42d96..f249662a 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.html +++ b/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.html @@ -11,7 +11,7 @@ class="cps-chip-close-icon" icon="close-x" size="xsmall" - color="text-darkest" + color="text-primary" (click)="onCloseClick($event)"> }
diff --git a/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.scss b/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.scss index 7f3e2bc9..2c91bc6a 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.scss +++ b/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.scss @@ -7,8 +7,9 @@ .cps-chip { align-items: center; display: inline-flex; - background-color: var(--cps-color-bg-dark); - border-radius: 14px; + background-color: var(--cps-surface-elevated); + border: 1px solid var(--cps-border-color); + border-radius: var(--cps-radius-full); line-height: 16px; padding: 4px 12px; cursor: default; @@ -17,28 +18,28 @@ cursor: pointer; &:hover { ::ng-deep .cps-icon { - color: var(--cps-color-calm) !important; + color: var(--cps-accent-primary) !important; } } } &-label { font-size: 14px; - color: var(--cps-color-text-darkest); - font-family: 'Source Sans Pro', sans-serif; + color: var(--cps-text-primary); + font-family: inherit; font-style: normal; font-weight: 400; } &.cps-chip-disabled { pointer-events: none; - background-color: var(--cps-color-bg-mid); + background-color: var(--cps-background-disabled); .cps-chip-label { - color: var(--cps-color-text-light); + color: var(--cps-text-muted); } .cps-chip-icon, .cps-chip-close-icon { ::ng-deep .cps-icon { - color: var(--cps-color-text-light) !important; + color: var(--cps-text-muted) !important; } } } From a1419fc7ed72af21b8e53889f3f18e06ea0b8480 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 16 Feb 2026 21:45:55 +0200 Subject: [PATCH 3/7] Enhance input and loader components with improved theming and styling consistency --- .../cps-input/cps-input.component.html | 9 ++- .../cps-input/cps-input.component.scss | 78 +++++++++++++------ .../cps-input/cps-input.component.ts | 8 +- .../cps-loader/cps-loader.component.scss | 4 +- .../cps-loader/cps-loader.component.ts | 4 +- .../cps-progress-linear.component.ts | 4 +- 6 files changed, 69 insertions(+), 38 deletions(-) diff --git a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.html b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.html index c078ce2a..1828435e 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.html +++ b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.html @@ -2,7 +2,10 @@ @if (label) {
+ [ngClass]="{ + 'cps-input-label-disabled': disabled && !readonly, + 'cps-input-label-error': error + }"> @if (infoTooltip) { diff --git a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.scss b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.scss index 75c985f1..3acd40a9 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.scss +++ b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.scss @@ -1,17 +1,17 @@ -$color-calm: var(--cps-color-calm); -$input-hint-color: var(--cps-color-text-mild); -$input-label-disabled-color: var(--cps-color-text-mild); -$input-pass-show-btn-color: var(--cps-color-text-mild); -$input-placeholder-color: var(--cps-color-text-lightest); -$input-border-color: var(--cps-color-line-light); -$input-label-color: var(--cps-color-text-dark); -$input-text-color: var(--cps-color-text-dark); -$input-text-disabled-color: var(--cps-color-text-light); -$input-prefix-text-color: var(--cps-color-text-mild); -$input-prefix-icon-color: var(--cps-color-text-dark); - -$color-error: var(--cps-color-error); -$error-background: #fef3f2; +$color-calm: var(--cps-accent-primary); +$input-hint-color: var(--cps-text-muted); +$input-label-disabled-color: var(--cps-text-muted); +$input-pass-show-btn-color: var(--cps-text-muted); +$input-placeholder-color: var(--cps-input-placeholder); +$input-border-color: var(--cps-border-color); +$input-label-color: var(--cps-text-primary); // --cps-color-text-dark +$input-text-color: var(--cps-text-primary); // --cps-color-text-dark +$input-text-disabled-color: var(--cps-text-disabled); +$input-prefix-text-color: var(--cps-text-muted); +$input-prefix-icon-color: var(--cps-text-primary); // --cps-color-text-dark + +$color-error: var(--cps-state-error); +$error-background: var(--cps-error-background); $hover-transition-duration: 0.2s; @@ -22,14 +22,14 @@ $hover-transition-duration: 0.2s; gap: 0.2rem !important; display: flex !important; flex-direction: column !important; - font-family: 'Source Sans Pro', sans-serif; + font-family: inherit; .cps-input-wrap { position: relative; overflow: hidden; &:hover { input:enabled:not(:read-only) { - border: 1px solid $color-calm; + border-color: var(--cps-border-strong); } } &-error { @@ -46,33 +46,35 @@ $hover-transition-duration: 0.2s; input { min-height: 38px; - font-family: 'Source Sans Pro', sans-serif; + font-family: inherit; font-size: 1rem; color: $input-text-color; - background: #ffffff; + background: var(--cps-input-background); padding: 0.375rem 0.75rem; line-height: 1.5; border: 1px solid $input-border-color; transition-duration: $hover-transition-duration; appearance: none; - border-radius: 4px; + border-radius: var(--cps-border-radius-medium); width: 100%; &:focus { outline: 0; } &:focus:not(:read-only) { - border: 1px solid $color-calm; + border-color: $color-calm; + box-shadow: 0 0 0 3px var(--cps-highlight-selected); } &:read-only { cursor: default; } &:disabled { - opacity: 1; + opacity: 0.7; } &:disabled:not([readonly]) { - color: $input-text-disabled-color; - background-color: #f7f7f7; + color: $input-text-disabled-color !important; + -webkit-text-fill-color: $input-text-disabled-color !important; + background-color: var(--cps-background-disabled); pointer-events: none; } @@ -116,7 +118,7 @@ $hover-transition-duration: 0.2s; .clear-btn { display: flex; cursor: pointer; - color: $color-calm; + color: var(--cps-state-error); cps-icon { opacity: 0; transition-duration: $hover-transition-duration; @@ -188,6 +190,26 @@ $hover-transition-duration: 0.2s; &.underlined { input { border-bottom: 1px solid $input-border-color !important; + background: transparent; + box-shadow: none !important; + } + } + + &.borderless { + input { + background: var(--cps-surface-muted); + box-shadow: none !important; + } + + &:hover { + input:enabled:not(:read-only) { + background: var(--cps-highlight-hover); + } + } + + input:focus:not(:read-only) { + background: var(--cps-highlight-selected); + border-color: transparent !important; } } } @@ -213,6 +235,7 @@ $hover-transition-duration: 0.2s; .cps-input-hint { color: $input-hint-color; + font-family: inherit; font-size: 0.75rem; min-height: 1.125rem; line-height: 1.125rem; @@ -220,6 +243,7 @@ $hover-transition-duration: 0.2s; } .cps-input-error { color: $color-error; + font-family: inherit; font-weight: bold; font-size: 0.75rem; min-height: 1.125rem; @@ -240,9 +264,13 @@ $hover-transition-duration: 0.2s; &-disabled { color: $input-label-disabled-color; } + + &-error { + color: $color-error; + } } ::placeholder { - font-family: 'Source Sans Pro', sans-serif; + font-family: inherit; color: $input-placeholder-color; font-style: italic; opacity: 1; /* Firefox */ diff --git a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts index 5995a28f..237d7f44 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts @@ -14,16 +14,16 @@ import { ViewChild } from '@angular/core'; import { ControlValueAccessor, NgControl } from '@angular/forms'; +import { Subscription } from 'rxjs'; +import { CpsTooltipPosition } from '../../directives/cps-tooltip/cps-tooltip.directive'; +import { convertSize } from '../../utils/internal/size-utils'; import { CpsIconComponent, IconType, iconSizeType } from '../cps-icon/cps-icon.component'; -import { Subscription } from 'rxjs'; -import { convertSize } from '../../utils/internal/size-utils'; -import { CpsProgressLinearComponent } from '../cps-progress-linear/cps-progress-linear.component'; import { CpsInfoCircleComponent } from '../cps-info-circle/cps-info-circle.component'; -import { CpsTooltipPosition } from '../../directives/cps-tooltip/cps-tooltip.directive'; +import { CpsProgressLinearComponent } from '../cps-progress-linear/cps-progress-linear.component'; /** * CpsInputAppearanceType is used to define the border of the input field. diff --git a/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.scss b/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.scss index 98d14147..5905270b 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.scss +++ b/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.scss @@ -1,5 +1,5 @@ -$color-outer: var(--cps-color-calm); -$color-middle: var(--cps-color-warmth); +$color-outer: var(--cps-accent-primary); +$color-middle: var(--cps-accent-secondary); $color-inner: var(--cps-color-energy); :host { diff --git a/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.ts b/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.ts index 6a37f298..875d3290 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-loader/cps-loader.component.ts @@ -29,7 +29,7 @@ export class CpsLoaderComponent implements OnInit { * Color of the label. * @group Props */ - @Input() labelColor = 'depth'; + @Input() labelColor = 'text-primary'; /** * Determines whether to show 'Loading...' label. @@ -37,7 +37,7 @@ export class CpsLoaderComponent implements OnInit { */ @Input() showLabel = true; - backgroundColor = 'rgba(0, 0, 0, 0.1)'; + backgroundColor = 'var(--cps-surface-overlay)'; // eslint-disable-next-line no-useless-constructor constructor(@Inject(DOCUMENT) private document: Document) {} diff --git a/projects/cps-ui-kit/src/lib/components/cps-progress-linear/cps-progress-linear.component.ts b/projects/cps-ui-kit/src/lib/components/cps-progress-linear/cps-progress-linear.component.ts index 7d853bec..af4fe6d4 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-progress-linear/cps-progress-linear.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-progress-linear/cps-progress-linear.component.ts @@ -1,7 +1,7 @@ import { CommonModule, DOCUMENT } from '@angular/common'; import { Component, Inject, Input, OnInit } from '@angular/core'; -import { convertSize } from '../../utils/internal/size-utils'; import { getCSSColor } from '../../utils/colors-utils'; +import { convertSize } from '../../utils/internal/size-utils'; /** * CpsProgressLinearComponent is a process status indicator of a rectangular form. @@ -30,7 +30,7 @@ export class CpsProgressLinearComponent implements OnInit { * Color of the progress bar. * @group Props */ - @Input() color = 'calm'; + @Input() color = 'var(--cps-accent-primary)'; /** * Background color of the progress bar. From a954b13ba851c04845c3610fe8ad82199de60312 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 16 Feb 2026 21:50:11 +0200 Subject: [PATCH 4/7] Remove document attribute theme application tests from CpsThemeService spec --- .../cps-theme/cps-theme.service.spec.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts b/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts index 3ce4f639..3e072734 100644 --- a/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts +++ b/projects/cps-ui-kit/src/lib/services/cps-theme/cps-theme.service.spec.ts @@ -46,25 +46,11 @@ describe('CpsThemeService', () => { expect(localStorage.getItem('cps-color-theme-preference')).toBe('energy'); }); - it('should apply color theme to document attribute', () => { - service.setColorTheme('calm', false); - expect(document.documentElement.getAttribute('data-color-theme')).toBe( - 'calm' - ); - }); - it('should save base theme preference to localStorage', () => { service.setBaseTheme('midnight', false); expect(localStorage.getItem('cps-base-theme-preference')).toBe('midnight'); }); - it('should apply base theme to document attribute', () => { - service.setBaseTheme('graphite', false); - expect(document.documentElement.getAttribute('data-base-theme')).toBe( - 'graphite' - ); - }); - it('should save radius theme preference to localStorage', () => { service.setRadiusTheme('rounded', false); expect(localStorage.getItem('cps-radius-theme-preference')).toBe('rounded'); @@ -73,11 +59,4 @@ describe('CpsThemeService', () => { it('should initialize with none radius theme by default', () => { expect(service.radiusTheme()).toBe('none'); }); - - it('should apply radius theme to document attribute', () => { - service.setRadiusTheme('pill', false); - expect(document.documentElement.getAttribute('data-radius-theme')).toBe( - 'pill' - ); - }); }); From 53766a35bcf68f3c099f2ce5460b95b9a9c1cffb Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 18 Feb 2026 11:42:29 +0200 Subject: [PATCH 5/7] Refactor theme toggle component and styles for improved theming consistency and accessibility --- projects/composition/src/app/app.component.scss | 1 - .../theme-toggle/theme-toggle.component.html | 8 ++------ .../theme-toggle/theme-toggle.component.ts | 17 +++++++++++++++-- .../cps-autocomplete.component.scss | 7 +------ .../lib/services/cps-theme/cps-theme.service.ts | 4 ++-- projects/cps-ui-kit/src/public-api.ts | 3 --- projects/cps-ui-kit/styles/styles.scss | 12 ++++++++++++ 7 files changed, 32 insertions(+), 20 deletions(-) diff --git a/projects/composition/src/app/app.component.scss b/projects/composition/src/app/app.component.scss index 763eb4f0..2ba8863e 100644 --- a/projects/composition/src/app/app.component.scss +++ b/projects/composition/src/app/app.component.scss @@ -6,7 +6,6 @@ display: flex; padding: 0 14px; align-items: center; - border-bottom: 1px solid lightgrey; border-bottom: 1px solid var(--cps-border-color); gap: 8px; img { diff --git a/projects/composition/src/app/components/theme-toggle/theme-toggle.component.html b/projects/composition/src/app/components/theme-toggle/theme-toggle.component.html index bbcbfe10..38522a73 100644 --- a/projects/composition/src/app/components/theme-toggle/theme-toggle.component.html +++ b/projects/composition/src/app/components/theme-toggle/theme-toggle.component.html @@ -9,12 +9,8 @@ @if (menuOpen) { - -