From 1f903bb7c3e340d83b01781d129c5f7d1bb5b0e1 Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Wed, 6 Nov 2024 17:27:28 +0200 Subject: [PATCH 01/10] initial commit --- .gitignore | 3 + package-lock.json | 130 ++++++++++++++ package.json | 10 +- .../src/lib/avatar/avatar.component.ts | 13 +- .../src/lib/avatar/themes/base.scss | 83 +++++++++ .../src/lib/avatar/themes/dark/_themes.scss | 7 + .../src/lib/avatar/themes/dark/bootstrap.scss | 10 ++ .../src/lib/avatar/themes/dark/fluent.scss | 10 ++ .../src/lib/avatar/themes/dark/indigo.scss | 10 ++ .../src/lib/avatar/themes/dark/material.scss | 10 ++ .../src/lib/avatar/themes/light/_themes.scss | 8 + .../lib/avatar/themes/light/bootstrap.scss | 9 + .../src/lib/avatar/themes/light/fluent.scss | 9 + .../src/lib/avatar/themes/light/indigo.scss | 9 + .../src/lib/avatar/themes/light/material.scss | 9 + .../lib/avatar/themes/shared/bootstrap.scss | 20 +++ .../src/lib/avatar/themes/shared/indigo.scss | 5 + .../components/avatar/_avatar-theme.scss | 2 - .../styles/components/chip/_chip-theme.scss | 2 +- .../core/styles/themes/generators/_base.scss | 18 +- .../src/lib/services/theme/theme.service.ts | 75 ++++++++ scripts/build-component-styles.mjs | 3 + scripts/build-styles.mjs | 112 +----------- scripts/report.mjs | 19 ++ scripts/sass.mjs | 166 ++++++++++++++++++ scripts/styles.tmpl | 3 + scripts/watch-styles.mjs | 52 ++++++ src/app/styleguide/colors/color.sample.scss | 8 + src/assets/styles/test-theme.css | 7 + src/styles/_demo-theme.scss | 22 +++ src/styles/_variables.scss | 8 +- 31 files changed, 722 insertions(+), 130 deletions(-) create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/base.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/_themes.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/_themes.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/material.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss create mode 100644 scripts/build-component-styles.mjs create mode 100644 scripts/report.mjs create mode 100644 scripts/sass.mjs create mode 100644 scripts/styles.tmpl create mode 100644 scripts/watch-styles.mjs create mode 100644 src/assets/styles/test-theme.css diff --git a/.gitignore b/.gitignore index 59a9c88a366..bb5aa2377e5 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,9 @@ src/**/*.js src/**/*.js.map src/**/*.css.map +# Artefacts +projects/igniteui-angular/**/*.css.ts + # Typedoc Theme extras/docs/themes/typedoc/bin extras/docs/themes/sassdoc/node_modules diff --git a/package-lock.json b/package-lock.json index c355e51d074..0b64dccfeab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,7 @@ "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "autoprefixer": "^10.4.16", + "concurrently": "^9.0.1", "del": "^6.0.0", "eslint": "^8.53.0", "fs-extra": "^11.1.1", @@ -84,6 +85,7 @@ "karma-spec-reporter": "^0.0.36", "lit-html": "^3.1.2", "ng-packagr": "^18.2.1", + "node-watch": "^0.7.4", "postcss": "^8.4.31", "postcss-scss": "^4.0.6", "prettier": "^3.3.2", @@ -8778,6 +8780,124 @@ "node": ">=0.10.0" } }, + "node_modules/concurrently": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.0.1.tgz", + "integrity": "sha512-wYKvCd/f54sTXJMSfV6Ln/B8UrfLBKOYa+lzc6CHay3Qek+LorVSBdMVfyewFhRbH0Rbabsk4D+3PL/VjQ5gzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concurrently/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -16936,6 +17056,16 @@ "dev": true, "license": "MIT" }, + "node_modules/node-watch": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.4.tgz", + "integrity": "sha512-RinNxoz4W1cep1b928fuFhvAQ5ag/+1UlMDV7rbyGthBIgsiEouS4kvRayvvboxii4m8eolKOIBo3OjDqbc+uQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", diff --git a/package.json b/package.json index 1c6581061db..0828d1d4a2e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "scripts": { "ng": "ng", - "start": "ng serve --open --hmr", + "start": "concurrently -r \"npm run build:styles:components\" \"npm run watch:styles\" \"ng serve --open --hmr\"", "start:elements": "ng serve --project igniteui-angular-elements", "build": "ng build --configuration production", "test": "ng test igniteui-angular", @@ -22,8 +22,10 @@ "test:i18n": "ts-node --skip-project ./projects/igniteui-angular/src/lib/core/i18n/tests/tests.ts", "test:elements": "ng test igniteui-angular-elements --watch=false --no-progress --code-coverage --source-map=false", "test:elements:watch": "ng test igniteui-angular-elements", - "build:lib": "ng build igniteui-angular --configuration production && npm run build:styles", - "build:styles": "node scripts/build-styles.mjs", + "build:lib": "ng build igniteui-angular --configuration production && npm run build:styles:all", + "build:styles:all": "node scripts/build-styles.mjs", + "build:styles:components": "node scripts/build-component-styles.mjs", + "watch:styles": "node scripts/watch-styles.mjs", "build:migrations": "gulp copyMigrations && tsc --listEmittedFiles --project ./projects/igniteui-angular/migrations/tsconfig.json", "build:schematics": "gulp copySchematics && tsc --listEmittedFiles --project ./projects/igniteui-angular/schematics/tsconfig.json", "build:docs": "sassdoc projects/igniteui-angular/src/lib/core/styles && gulp typedoc-build:theme", @@ -106,6 +108,7 @@ "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "autoprefixer": "^10.4.16", + "concurrently": "^9.0.1", "del": "^6.0.0", "eslint": "^8.53.0", "fs-extra": "^11.1.1", @@ -133,6 +136,7 @@ "karma-spec-reporter": "^0.0.36", "lit-html": "^3.1.2", "ng-packagr": "^18.2.1", + "node-watch": "^0.7.4", "postcss": "^8.4.31", "postcss-scss": "^4.0.6", "prettier": "^3.3.2", diff --git a/projects/igniteui-angular/src/lib/avatar/avatar.component.ts b/projects/igniteui-angular/src/lib/avatar/avatar.component.ts index 9440cc566c5..a68c111806f 100644 --- a/projects/igniteui-angular/src/lib/avatar/avatar.component.ts +++ b/projects/igniteui-angular/src/lib/avatar/avatar.component.ts @@ -6,11 +6,14 @@ import { Input, OnInit, TemplateRef, - ViewChild + ViewChild, + inject } from '@angular/core'; import { mkenum } from '../core/utils'; import { IgxIconComponent } from '../icon/icon.component'; +import { ThemeService, ThemedComponent } from '../services/theme/theme.service'; +import styles from './themes/themes.css'; let NEXT_ID = 0; export const IgxAvatarSize = /*@__PURE__*/mkenum({ @@ -56,7 +59,10 @@ export type IgxAvatarType = (typeof IgxAvatarType)[keyof typeof IgxAvatarType]; standalone: true, imports: [IgxIconComponent, NgTemplateOutlet] }) -export class IgxAvatarComponent implements OnInit { +export class IgxAvatarComponent implements OnInit, ThemedComponent { + public elementRef = inject(ElementRef); + public themeService = inject(ThemeService); + /** * Returns the `aria-label` attribute of the avatar. * @@ -326,8 +332,6 @@ export class IgxAvatarComponent implements OnInit { } } - constructor(public elementRef: ElementRef) { } - /** * Returns the css url of the image. * @@ -341,6 +345,7 @@ export class IgxAvatarComponent implements OnInit { /** @hidden @internal */ public ngOnInit() { this.roleDescription = this.getRole(); + this.themeService.adoptStyles(IgxAvatarComponent, styles); } /** @hidden @internal */ diff --git a/projects/igniteui-angular/src/lib/avatar/themes/base.scss b/projects/igniteui-angular/src/lib/avatar/themes/base.scss new file mode 100644 index 00000000000..15ae7b06848 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/base.scss @@ -0,0 +1,83 @@ +@use 'igniteui-theming/sass/animations' as *; +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use './light/themes' as *; + +$theme: $material; + +%igx-avatar-display { + @include sizable(); + + --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); + + position: relative; + display: inline-flex; + justify-content: center; + align-items: center; + user-select: none; + color: var-get($theme, 'color'); + background: var-get($theme, 'background'); + vertical-align: middle; + outline-style: none; + flex-shrink: 0; + width: var-get($theme, 'size'); + height: var-get($theme, 'size'); + + igx-icon { + --component-size: 3; + + color: var-get($theme, 'icon-color'); + } + + &::after { + box-shadow: none; + transition: box-shadow .15s $ease-in-out-quad; + } +} + +%igx-avatar-image { + width: 100%; + height: 100%; + border-radius: inherit; + background-size: cover; + background-repeat: no-repeat; + background-position: center; +} + +%igx-avatar--circle { + border-radius: calc(#{var-get($theme, 'size')} / 2); +} + +%igx-avatar--rounded { + border-radius: var-get($theme, 'border-radius'); +} + +%igx-avatar--initials { + text-transform: uppercase; + font-size: calc(#{var-get($theme, 'size')} / 2); + line-height: calc(#{var-get($theme, 'size')} / 2); +} + +igx-avatar { + @include css-vars-from-theme($base, 'igx-avatar'); +} + +@include b(igx-avatar) { + @extend %igx-avatar-display; + + @include e(image) { + @extend %igx-avatar-image; + } + + @include m(circle) { + @extend %igx-avatar--circle; + } + + @include m(rounded) { + @extend %igx-avatar--rounded; + } + + @include m(initials) { + @extend %igx-avatar--initials; + } +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/_themes.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/_themes.scss new file mode 100644 index 00000000000..f5e829c9657 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/_themes.scss @@ -0,0 +1,7 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/themes/schemas/components/dark/avatar' as *; + +$material: digest-schema($dark-material-avatar); +$bootstrap: digest-schema($dark-bootstrap-avatar); +$fluent: digest-schema($dark-fluent-avatar); +$indigo: digest-schema($dark-indigo-avatar); diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss new file mode 100644 index 00000000000..b56b4b737e2 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss @@ -0,0 +1,10 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $bootstrap; + +igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss new file mode 100644 index 00000000000..9f6e66f529e --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss @@ -0,0 +1,10 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $fluent; + +igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss new file mode 100644 index 00000000000..e45ecd8ab14 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss @@ -0,0 +1,10 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $indigo; + +igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss new file mode 100644 index 00000000000..396c1de44a6 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss @@ -0,0 +1,10 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $material; + +igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/_themes.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/_themes.scss new file mode 100644 index 00000000000..93ea480da81 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/_themes.scss @@ -0,0 +1,8 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/themes/schemas/components/light/avatar' as *; + +$base: digest-schema($light-avatar); +$material: digest-schema($material-avatar); +$bootstrap: digest-schema($bootstrap-avatar); +$fluent: digest-schema($fluent-avatar); +$indigo: digest-schema($indigo-avatar); diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss new file mode 100644 index 00000000000..6054302576d --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss @@ -0,0 +1,9 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $bootstrap; + +igx-avatar { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss new file mode 100644 index 00000000000..d9ede217890 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss @@ -0,0 +1,9 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $fluent; + +igx-avatar { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss new file mode 100644 index 00000000000..f2e0a8167c3 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss @@ -0,0 +1,9 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $indigo; + +igx-avatar { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss new file mode 100644 index 00000000000..49c5e4fac64 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss @@ -0,0 +1,9 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $material; + +igx-avatar { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss new file mode 100644 index 00000000000..b62e90e061c --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss @@ -0,0 +1,20 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/typography' as *; +@use '../light/themes' as *; + +$theme: $bootstrap; + +.igx-avatar { + &::after { + position: absolute; + content: ''; + width: 100%; + height: 100%; + border-radius: inherit; + opacity: .5; + } + + &:focus::after { + box-shadow: 0 0 0 rem(3px) var-get($theme, 'background'); + } +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss new file mode 100644 index 00000000000..14901942c18 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss @@ -0,0 +1,5 @@ +.igx-avatar { + igx-icon { + --ig-size: 1; + } +} diff --git a/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss index 34bf3ff1fa8..9074330fdf1 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss @@ -64,8 +64,6 @@ /// @see {mixin} css-vars /// @param {Map} $theme - The theme used to style the component. @mixin avatar($theme) { - @include css-vars($theme); - $variant: map.get($theme, '_meta', 'variant'); $bootstrap-theme: $variant == 'bootstrap'; $box-shadow: map.get(( diff --git a/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss index 1521c587716..57138289ef8 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss @@ -385,7 +385,7 @@ } @if $variant == 'indigo' { - %igx-icon-display { + igx-icon { --size: #{sizable(rem(14px), rem(14px), rem(16px))} } } diff --git a/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss b/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss index 0ba134976fe..aec1a92a1bc 100644 --- a/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss +++ b/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss @@ -76,6 +76,8 @@ $theme: map.get($schema, '_meta', 'theme'); $variant: map.get($schema, '_meta', 'variant'); + @layer base, #{$theme}, #{$theme}-overrides; + #{$scope} { --ig-size-small: 1; --ig-size-medium: 2; @@ -133,14 +135,18 @@ @include ripple($ripple-theme-map); } - @if is-used('igx-avatar', $exclude) { - $avatar-theme-map: avatar-theme( - $schema: $schema, - ); - $avatar-theme-map: meta.call($theme-handler, $avatar-theme-map); - @include avatar($avatar-theme-map); + igx-avatar { + --theme: var(--ig-theme); } + // @if is-used('igx-avatar', $exclude) { + // $avatar-theme-map: avatar-theme( + // $schema: $schema, + // ); + // $avatar-theme-map: meta.call($theme-handler, $avatar-theme-map); + // @include avatar($avatar-theme-map); + // } + @if is-used('igx-action-strip', $exclude) { $action-strip-theme-map: action-strip-theme( $schema: $schema, diff --git a/projects/igniteui-angular/src/lib/services/theme/theme.service.ts b/projects/igniteui-angular/src/lib/services/theme/theme.service.ts index e7836e47aca..8150a3be0c8 100644 --- a/projects/igniteui-angular/src/lib/services/theme/theme.service.ts +++ b/projects/igniteui-angular/src/lib/services/theme/theme.service.ts @@ -3,6 +3,11 @@ import { mkenum } from "../../core/utils"; import { BehaviorSubject } from "rxjs"; import { DOCUMENT } from "@angular/common"; +export interface ThemedComponent { + elementRef: ElementRef; + themeService: ThemeService; +} + const Theme = /*@__PURE__*/ mkenum({ Material: "material", Fluent: "fluent", @@ -10,11 +15,27 @@ const Theme = /*@__PURE__*/ mkenum({ IndigoDesign: "indigo", }); +export type ThemeVariant = 'light' | 'dark'; + /** * Determines the component theme. */ export type IgxTheme = (typeof Theme)[keyof typeof Theme]; +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type Themes = { + base: string; + shared?: { + [K in IgxTheme | 'shared']?: string; + }; + light: { + [K in IgxTheme | 'shared']?: string; + }; + dark: { + [K in IgxTheme | 'shared']?: string; + }; +}; + @Injectable({ providedIn: "root", }) @@ -24,7 +45,10 @@ export class ThemeService { * Allowed values of type IgxTheme. */ public globalTheme: IgxTheme; + public themeVariant: ThemeVariant; + private themeVariant$ = new BehaviorSubject("light"); private theme$ = new BehaviorSubject("material"); + private componentThemes = new WeakMap(); constructor( @Inject(DOCUMENT) @@ -34,6 +58,10 @@ export class ThemeService { this.globalTheme = value as IgxTheme; }); + this.themeVariant$.asObservable().subscribe((value) => { + this.themeVariant = value as ThemeVariant; + }); + this.init(); } @@ -43,9 +71,18 @@ export class ThemeService { .getPropertyValue("--ig-theme") .trim(); + const themeVariant = globalThis.window + ?.getComputedStyle(this.document.body) + .getPropertyValue("--ig-theme-variant") + .trim(); + if (theme !== "") { this.theme$.next(theme as IgxTheme); } + + if (themeVariant !== "") { + this.themeVariant$.next(themeVariant as ThemeVariant); + } } public getComponentTheme(el: ElementRef) { @@ -54,4 +91,42 @@ export class ThemeService { .getPropertyValue('--theme') .trim() as IgxTheme; } + + + public adoptStyles(componentInstance: Function, themes: Themes) { + let componentStyles = this.componentThemes.get(componentInstance); + + if (!componentStyles) { + componentStyles = new CSSStyleSheet(); + this.componentThemes.set(componentInstance, componentStyles); + document.adoptedStyleSheets = [...document.adoptedStyleSheets, componentStyles]; + } + + componentStyles.replaceSync( + Array.from(this.composeStyleSheet(themes).cssRules) + .map(rules => rules.cssText) + .join('\n') + ); + } + + private composeStyleSheet(themes: Themes) { + const sheet = new CSSStyleSheet(); + + sheet.insertRule(`@layer base {${themes.base}}`); + + for (const [key, value] of Object.entries(themes)) { + if (key === 'shared') { + for (const [theme, styleSheet] of Object.entries(value)) { + sheet.insertRule(`@layer ${theme} {${styleSheet}}`) + } + } + } + + sheet.insertRule(`@layer ${this.globalTheme}-overrides { + ${themes[this.themeVariant][this.globalTheme]} + }`); + + + return sheet; + } } diff --git a/scripts/build-component-styles.mjs b/scripts/build-component-styles.mjs new file mode 100644 index 00000000000..0330498a969 --- /dev/null +++ b/scripts/build-component-styles.mjs @@ -0,0 +1,3 @@ +import { buildComponents } from "./sass.mjs"; + +await Promise.all([buildComponents()]); diff --git a/scripts/build-styles.mjs b/scripts/build-styles.mjs index 60aa5dc6749..743cc15bf59 100644 --- a/scripts/build-styles.mjs +++ b/scripts/build-styles.mjs @@ -1,111 +1,3 @@ -import * as sass from "sass-embedded"; -import postcss from "postcss"; -import autoprefixer from "autoprefixer"; -import { globby } from "globby"; -import path from "path"; -import { mkdirSync as makeDir } from "fs"; -import fsExtra from "fs-extra"; -import { fileURLToPath } from "url"; -import { writeFile } from "fs/promises"; +import { buildComponents, buildThemes } from "./sass.mjs"; -const report = { - success: (s) => console.log("\x1b[32m%s\x1b[0m", s), - warn: (s) => console.warn("\x1b[33m%s\x1b[0m", s), - error: (s) => console.error("\x1b[31m%s\x1b[0m", s), -}; - -const STYLES = { - SRC: "projects/igniteui-angular/src/lib/core/styles/themes/presets", - DIST: "../dist/igniteui-angular/styles", - THEMING: { - SRC: "projects/igniteui-angular/src/lib/core/styles/", - DIST: "dist/igniteui-angular/lib/core/styles/", - }, - CONFIG: { - style: "compressed", - loadPaths: ["node_modules"], - sourceMap: true, - sourceMapEmbed: true, - }, -}; - -const { copySync } = fsExtra; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const DEST_DIR = path.join.bind(null, path.resolve(__dirname, STYLES.DIST)); - -const stripComments = () => { - return { - postcssPlugin: "postcss-strip-comments", - OnceExit(root) { - root.walkComments((node) => node.remove()); - }, - }; -}; - -stripComments.postcss = true; - -const postProcessor = postcss([ - autoprefixer({ - cascade: false, - grid: true, - }), - stripComments, -]); - -async function createFile(fileName, content) { - const outputFile = DEST_DIR(fileName); - - makeDir(path.dirname(outputFile), { recursive: true }); - await writeFile(outputFile, content, "utf-8"); -} - -async function buildThemes() { - const paths = await globby(`${STYLES.SRC}/**/*.scss`); - const compiler = await sass.initAsyncCompiler(); - - try { - await Promise.all( - paths.map(async (path) => { - const result = await compiler.compileAsync(path, STYLES.CONFIG); - const fileName = path - .replace(/\.scss$/, ".css") - .replace(STYLES.SRC, ""); - const sourceMapComment = `/*# sourceMappingURL=maps${fileName}.map */`; - - let outCss = postProcessor.process(result.css).css; - - if (outCss.charCodeAt(0) === 0xfeff) { - outCss = outCss.substring(1); - } - - outCss = outCss + "\n".repeat(2) + sourceMapComment; - - await createFile(fileName, outCss); - await createFile( - `maps/${fileName}.map`, - JSON.stringify(result.sourceMap), - ); - }), - ); - } catch (err) { - await compiler.dispose(); - report.error(err); - process.exit(1); - } - - await compiler.dispose(); -} - -(async () => { - const startTime = new Date(); - - // Move theming files - copySync(STYLES.THEMING.SRC, STYLES.THEMING.DIST, { recursive: true }); - - // Build theme presets - console.info("Building themes..."); - await buildThemes(); - report.success( - `Themes generated in ${Math.round((Date.now() - startTime) / 1000)}s`, - ); -})(); +await Promise.all([buildComponents(), buildThemes()]); diff --git a/scripts/report.mjs b/scripts/report.mjs new file mode 100644 index 00000000000..b00fd132261 --- /dev/null +++ b/scripts/report.mjs @@ -0,0 +1,19 @@ +import { stdout } from 'node:process'; +import { format } from 'node:util'; + +export default { + error: (s) => console.error('\x1b[31m%s\x1b[0m', s), + success: (s) => console.info('\x1b[32m%s\x1b[0m', s), + warn: (s) => console.warn('\x1b[33m%s\x1b[0m', s), + info: (s) => console.info('\x1b[36m%s\x1b[0m', s), + + stdout: { + clearLine: () => { + stdout.clearLine(0); + stdout.cursorTo(0); + }, + success: (s) => stdout.write(format('\x1b[32m%s\x1b[0m', s)), + warn: (s) => stdout.write(format('\x1b[33m%s\x1b[0m', s)), + info: (s) => stdout.write(format('\x1b[36m%s\x1b[0m', s)), + }, +}; diff --git a/scripts/sass.mjs b/scripts/sass.mjs new file mode 100644 index 00000000000..1c93b226538 --- /dev/null +++ b/scripts/sass.mjs @@ -0,0 +1,166 @@ +import * as sass from 'sass-embedded'; +import postcss from 'postcss'; +import autoprefixer from 'autoprefixer'; +import { globby } from 'globby'; +import path from 'path'; +import { resolve } from 'node:path'; +import { mkdirSync as makeDir } from 'fs'; +import fsExtra from 'fs-extra'; +import { fileURLToPath } from 'url'; +import { writeFile, readFile } from 'fs/promises'; +import report from './report.mjs'; + +const THEMES = { + SRC: 'projects/igniteui-angular/src/lib/core/styles/themes/presets', + DIST: '../dist/igniteui-angular/styles', + THEMING: { + SRC: 'projects/igniteui-angular/src/lib/core/styles/', + DIST: 'dist/igniteui-angular/lib/core/styles/', + }, + CONFIG: { + style: 'compressed', + loadPaths: ['node_modules'], + sourceMap: true, + sourceMapEmbed: true, + }, +}; + +const STYLES = { + SRC: 'projects/igniteui-angular/src/lib/**/*.scss', + IGNORE: '!projects/igniteui-angular/src/lib/core/styles/**/*.scss', + CONFIG: { + style: 'compressed', + loadPaths: ['node_modules'], + sourceMap: true, + sourceMapEmbed: true, + }, +}; + +const { copySync } = fsExtra; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const DEST_DIR = path.join.bind(null, path.resolve(__dirname, THEMES.DIST)); + +const stripComments = () => { + return { + postcssPlugin: 'postcss-strip-comments', + OnceExit(root) { + root.walkComments((node) => node.remove()); + }, + }; +}; + +stripComments.postcss = true; + +const postProcessor = postcss([ + autoprefixer({ + cascade: false, + grid: true, + }), + stripComments, +]); + +const _template = await readFile( + resolve(process.argv[1], '../styles.tmpl'), + 'utf8' +); +const _postProcessor = postcss([autoprefixer, stripComments]); + +export function fromTemplate(content) { + return _template.replace(/<%\s*content\s*%>/, content); +} +async function createFile(fileName, content) { + const outputFile = DEST_DIR(fileName); + + makeDir(path.dirname(outputFile), { recursive: true }); + await writeFile(outputFile, content, 'utf-8'); +} + +export async function compileSass(src, compiler, options) { + const compiled = await compiler.compileAsync(src, options); + + const out = _postProcessor.process(compiled.css).css; + return out.charCodeAt(0) === 0xfeff ? out.slice(1) : out; +} + +async function _buildThemes() { + const paths = await globby(`${THEMES.SRC}/**/*.scss`); + const compiler = await sass.initAsyncCompiler(); + + try { + await Promise.all( + paths.map(async (path) => { + const result = await compiler.compileAsync(path, THEMES.CONFIG); + const fileName = path + .replace(/\.scss$/, '.css') + .replace(THEMES.SRC, ''); + const sourceMapComment = `/*# sourceMappingURL=maps${fileName}.map */`; + + let outCss = postProcessor.process(result.css).css; + + if (outCss.charCodeAt(0) === 0xfeff) { + outCss = outCss.substring(1); + } + + outCss = outCss + '\n'.repeat(2) + sourceMapComment; + + await createFile(fileName, outCss); + await createFile( + `maps/${fileName}.map`, + JSON.stringify(result.sourceMap) + ); + }) + ); + } catch (err) { + await compiler.dispose(); + report.error(err); + process.exit(1); + } + + await compiler.dispose(); +} + +export async function buildComponents(isProduction = false) { + const start = performance.now(); + const [compiler, paths] = await Promise.all([ + sass.initAsyncCompiler(), + globby([STYLES.SRC, STYLES.IGNORE]), + ]); + + try { + await Promise.all( + paths.map(async (path) => { + writeFile( + path.replace(/\.scss$/, '.css.ts'), + fromTemplate(await compileSass(path, compiler, STYLES.CONFIG)), + 'utf-8' + ); + }) + ); + } catch (err) { + await compiler.dispose(); + report.error(err); + process.exit(1); + } + + await compiler.dispose(); + + if (!isProduction) { + report.success( + `Component styles generated in ${((performance.now() - start) / 1000).toFixed(2)}s` + ); + } +} + +export async function buildThemes() { + const start = performance.now(); + + // Move theming files + copySync(THEMES.THEMING.SRC, THEMES.THEMING.DIST, { recursive: true }); + + // Build theme presets + console.info('Building themes...'); + await _buildThemes(); + report.success( + `Themes generated in ${((performance.now() - start) / 1000).toFixed(2)}s` + ); +} diff --git a/scripts/styles.tmpl b/scripts/styles.tmpl new file mode 100644 index 00000000000..7864a0b50dd --- /dev/null +++ b/scripts/styles.tmpl @@ -0,0 +1,3 @@ +export default { + css: `<% content %>` +} diff --git a/scripts/watch-styles.mjs b/scripts/watch-styles.mjs new file mode 100644 index 00000000000..5221e7a23c8 --- /dev/null +++ b/scripts/watch-styles.mjs @@ -0,0 +1,52 @@ +import { writeFile } from 'node:fs/promises'; +import watch from 'node-watch'; +import * as sass from 'sass-embedded'; +import report from './report.mjs'; +import { compileSass, fromTemplate } from './sass.mjs'; + +const watchOptions = { + recursive: true, + filter: (path) => { + return /.(?:scss)$/.test(path); + }, +}; + +let updating = false; +const compiler = await sass.initAsyncCompiler(); + +const watcher = watch( + ['projects/igniteui-angular'], + watchOptions, + async (_, path) => { + if (updating) { + return; + } + + report.warn(`Change detected: ${path}`); + updating = true; + + try { + await writeFile( + path.replace(/\.scss$/, '.css.ts'), + fromTemplate( + await compileSass(path, compiler, { + style: 'compressed', + loadPaths: ['node_modules'], + sourceMap: true, + sourceMapEmbed: true, + }) + ), + 'utf8' + ); + } catch (err) { + report.error(err); + } + + report.success('Styles rebuilt 🎨'); + updating = false; + } +); + +watcher.on('close', () => compiler.dispose()); + +report.info('Styles watcher started...'); diff --git a/src/app/styleguide/colors/color.sample.scss b/src/app/styleguide/colors/color.sample.scss index b0c5d94bd6f..5115b653d5e 100644 --- a/src/app/styleguide/colors/color.sample.scss +++ b/src/app/styleguide/colors/color.sample.scss @@ -1,6 +1,14 @@ @use '../../../../projects/igniteui-angular/src/lib/core/styles/themes/utilities' as *; @use '../../../styles/variables' as *; +.test-100 { + color: color($palette, primary, 100); +} + +.test-200 { + color: color($palette, primary, 200); +} + .sample-wrapper { display: grid; grid-template-columns: 1fr; diff --git a/src/assets/styles/test-theme.css b/src/assets/styles/test-theme.css new file mode 100644 index 00000000000..206348450fc --- /dev/null +++ b/src/assets/styles/test-theme.css @@ -0,0 +1,7 @@ +@layer theme { + .igx-avatar { + --color: pink; + + outline: 1px solid red; + } +} diff --git a/src/styles/_demo-theme.scss b/src/styles/_demo-theme.scss index bded8bec46a..dc00c3db67d 100644 --- a/src/styles/_demo-theme.scss +++ b/src/styles/_demo-theme.scss @@ -21,6 +21,28 @@ body { $schema: $schema, ); + +.avatar-theme { + @include css-vars(avatar-theme( + $schema: $light-bootstrap-schema, + $color: blue + )); +} + + +.custom-palette { + @include palette(palette( + $primary: green, + $secondary: green, + $surface: white, + $info: #1377d5, + $success: #4eb862, + $warn: #faa419, + $error: #ff134a, + $variant: 'material', + )); +} + .dock { @include css-vars(dock-manager-theme()); } diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss index 245a0915f92..ccde72ee1c9 100644 --- a/src/styles/_variables.scss +++ b/src/styles/_variables.scss @@ -1,10 +1,10 @@ @use 'sass:map'; @use '../../projects/igniteui-angular/src/lib/core/styles/themes' as *; -$palette: $light-material-palette; -$schema: $light-material-schema; -$typeface: $material-typeface; -$type-scale: $material-type-scale; +$palette: $light-bootstrap-palette; +$schema: $light-bootstrap-schema; +$typeface: $bootstrap-typeface; +$type-scale: $bootstrap-type-scale; $variant: map.get($schema, '_meta', 'variant'); $background-color: var(--ig-gray-900-contrast); From 552a2a736ca177e2bd8ec4bbdbcadb679cd0e945 Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Mon, 11 Nov 2024 14:40:54 +0200 Subject: [PATCH 02/10] refactor(*): test scoping with container queries --- package-lock.json | 22 +++++++++++++++---- package.json | 2 +- .../src/lib/avatar/themes/light/indigo.scss | 2 ++ .../lib/avatar/themes/shared/bootstrap.scss | 22 ++++++++++--------- .../src/lib/avatar/themes/shared/indigo.scss | 6 +++-- src/app/styleguide/colors/color.sample.scss | 5 +++++ src/styles/_demo-theme.scss | 4 +++- src/styles/_variables.scss | 8 +++---- 8 files changed, 49 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b64dccfeab..87188183ef8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,7 +73,7 @@ "ig-typedoc-theme": "^5.0.4", "igniteui-dockmanager": "^1.14.2", "igniteui-sassdoc-theme": "^1.2.3", - "igniteui-webcomponents": "5.0.1", + "igniteui-webcomponents": "file:../igniteui-webcomponents/dist/igniteui-webcomponents-0.0.0.tgz", "jasmine": "^5.3.0", "jasmine-core": "~5.3.0", "karma": "^6.4.4", @@ -4813,6 +4813,16 @@ "lit-html": "^3.1.2" } }, + "node_modules/@lit/context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.3.tgz", + "integrity": "sha512-Auh37F4S0PZM93HTDfZWs97mmzaQ7M3vnTc9YvxAGyP3UItSK/8Fs0vTOGT+njuvOwbKio/l8Cx/zWL4vkutpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^1.6.2 || ^2.0.0" + } + }, "node_modules/@lit/reactive-element": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", @@ -13039,15 +13049,19 @@ } }, "node_modules/igniteui-webcomponents": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-5.0.1.tgz", - "integrity": "sha512-LGfXFi/lT4kZ89JWoM+Csb7x8N+3LHlYoTzvDTzdm5nVWtvFVeWBRkLOwB+ww9V51K3gO7UQh+Qir+7uz5jgzQ==", + "version": "0.0.0", + "resolved": "file:../igniteui-webcomponents/dist/igniteui-webcomponents-0.0.0.tgz", + "integrity": "sha512-HxTk4dZ1S8JUBZ0od/CwdAbCByaIp2N+yjER0erpyQsl9Jpj2/RppieBHFEyxhQ3OFlIUgj4yFN6UrZNlGydZw==", "dev": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { "@floating-ui/dom": "^1.6.0", "@lit-labs/virtualizer": "^2.0.10", + "@lit/context": "^1.1.0", "lit": "^3.2.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/igniteui-webcomponents/node_modules/@lit/reactive-element": { diff --git a/package.json b/package.json index 0828d1d4a2e..c217fe1d1f5 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,7 @@ "ig-typedoc-theme": "^5.0.4", "igniteui-dockmanager": "^1.14.2", "igniteui-sassdoc-theme": "^1.2.3", - "igniteui-webcomponents": "5.0.1", + "igniteui-webcomponents": "file:../igniteui-webcomponents/dist/igniteui-webcomponents-0.0.0.tgz", "jasmine": "^5.3.0", "jasmine-core": "~5.3.0", "karma": "^6.4.4", diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss index f2e0a8167c3..f77ae6754d8 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss @@ -5,5 +5,7 @@ $theme: $indigo; igx-avatar { + --ig-theme: indigo; + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss index b62e90e061c..9dd9bdbde78 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss @@ -5,16 +5,18 @@ $theme: $bootstrap; .igx-avatar { - &::after { - position: absolute; - content: ''; - width: 100%; - height: 100%; - border-radius: inherit; - opacity: .5; - } + @container style(--ig-theme: bootstrap) { + &::after { + position: absolute; + content: ''; + width: 100%; + height: 100%; + border-radius: inherit; + opacity: .5; + } - &:focus::after { - box-shadow: 0 0 0 rem(3px) var-get($theme, 'background'); + &:focus::after { + box-shadow: 0 0 0 rem(3px) var-get($theme, 'background'); + } } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss index 14901942c18..3cfb5305ce8 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss @@ -1,5 +1,7 @@ .igx-avatar { - igx-icon { - --ig-size: 1; + @container style(--ig-theme: indigo) { + igx-icon { + --ig-size: 1; + } } } diff --git a/src/app/styleguide/colors/color.sample.scss b/src/app/styleguide/colors/color.sample.scss index 5115b653d5e..96a6a11cd51 100644 --- a/src/app/styleguide/colors/color.sample.scss +++ b/src/app/styleguide/colors/color.sample.scss @@ -9,6 +9,11 @@ color: color($palette, primary, 200); } +.test-100-contrast { + color: contrast-color($palette, primary, 100); +} + + .sample-wrapper { display: grid; grid-template-columns: 1fr; diff --git a/src/styles/_demo-theme.scss b/src/styles/_demo-theme.scss index dc00c3db67d..2c15207d874 100644 --- a/src/styles/_demo-theme.scss +++ b/src/styles/_demo-theme.scss @@ -23,9 +23,11 @@ body { .avatar-theme { + --ig-theme: bootstrap; + @include palette($light-bootstrap-palette); + @include css-vars(avatar-theme( $schema: $light-bootstrap-schema, - $color: blue )); } diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss index ccde72ee1c9..a47d4ff27d7 100644 --- a/src/styles/_variables.scss +++ b/src/styles/_variables.scss @@ -1,10 +1,10 @@ @use 'sass:map'; @use '../../projects/igniteui-angular/src/lib/core/styles/themes' as *; -$palette: $light-bootstrap-palette; -$schema: $light-bootstrap-schema; -$typeface: $bootstrap-typeface; -$type-scale: $bootstrap-type-scale; +$palette: $light-indigo-palette; +$schema: $light-indigo-schema; +$typeface: $indigo-typeface; +$type-scale: $indigo-type-scale; $variant: map.get($schema, '_meta', 'variant'); $background-color: var(--ig-gray-900-contrast); From 6baebc38efab943edc228da3bd8719546f9ccd1b Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Mon, 2 Dec 2024 15:55:03 +0200 Subject: [PATCH 03/10] refactor(avatar): update styles --- .../src/lib/avatar/avatar.component.ts | 4 +-- .../src/lib/avatar/themes/base.scss | 4 +-- .../src/lib/avatar/themes/index.ts | 33 +++++++++++++++++++ .../lib/avatar/themes/shared/bootstrap.scss | 7 ++-- .../src/lib/avatar/themes/shared/indigo.scss | 4 ++- 5 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/index.ts diff --git a/projects/igniteui-angular/src/lib/avatar/avatar.component.ts b/projects/igniteui-angular/src/lib/avatar/avatar.component.ts index a68c111806f..c7dd70f336d 100644 --- a/projects/igniteui-angular/src/lib/avatar/avatar.component.ts +++ b/projects/igniteui-angular/src/lib/avatar/avatar.component.ts @@ -13,7 +13,7 @@ import { import { mkenum } from '../core/utils'; import { IgxIconComponent } from '../icon/icon.component'; import { ThemeService, ThemedComponent } from '../services/theme/theme.service'; -import styles from './themes/themes.css'; +import themes from './themes/index'; let NEXT_ID = 0; export const IgxAvatarSize = /*@__PURE__*/mkenum({ @@ -345,7 +345,7 @@ export class IgxAvatarComponent implements OnInit, ThemedComponent { /** @hidden @internal */ public ngOnInit() { this.roleDescription = this.getRole(); - this.themeService.adoptStyles(IgxAvatarComponent, styles); + this.themeService.adoptStyles(IgxAvatarComponent, themes); } /** @hidden @internal */ diff --git a/projects/igniteui-angular/src/lib/avatar/themes/base.scss b/projects/igniteui-angular/src/lib/avatar/themes/base.scss index 15ae7b06848..454d7fe4216 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/base.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/base.scss @@ -58,11 +58,9 @@ $theme: $material; line-height: calc(#{var-get($theme, 'size')} / 2); } -igx-avatar { +@include b(igx-avatar) { @include css-vars-from-theme($base, 'igx-avatar'); -} -@include b(igx-avatar) { @extend %igx-avatar-display; @include e(image) { diff --git a/projects/igniteui-angular/src/lib/avatar/themes/index.ts b/projects/igniteui-angular/src/lib/avatar/themes/index.ts new file mode 100644 index 00000000000..681b6e5728e --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/index.ts @@ -0,0 +1,33 @@ +import base from './base.css'; +import bootstrap from './shared/bootstrap.css'; +import indigo from './shared/indigo.css'; + +import lightMaterial from './light/material.css'; +import lightBootstrap from './light/bootstrap.css'; +import lightFluent from './light/fluent.css'; +import lightIndigo from './light/indigo.css'; + +import darkMaterial from './dark/material.css'; +import darkBootstrap from './dark/bootstrap.css'; +import darkFluent from './dark/fluent.css'; +import darkIndigo from './dark/indigo.css'; + +export default { + base: base.css, + shared: { + bootstrap: bootstrap.css, + indigo: indigo.css + }, + light: { + material: lightMaterial.css, + bootstrap: lightBootstrap.css, + fluent: lightFluent.css, + indigo: lightIndigo.css + }, + dark: { + material: darkMaterial.css, + bootstrap: darkBootstrap.css, + fluent: darkFluent.css, + indigo: darkIndigo.css + } +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss index 9dd9bdbde78..106a91e7d64 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss @@ -1,10 +1,11 @@ +@use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/themes' as *; @use 'igniteui-theming/sass/typography' as *; @use '../light/themes' as *; $theme: $bootstrap; -.igx-avatar { +@include b(igx-avatar) { @container style(--ig-theme: bootstrap) { &::after { position: absolute; @@ -12,11 +13,11 @@ $theme: $bootstrap; width: 100%; height: 100%; border-radius: inherit; - opacity: .5; + opacity: 0.5; } &:focus::after { - box-shadow: 0 0 0 rem(3px) var-get($theme, 'background'); + box-shadow: 0 0 0 rem(3px) var-get($bootstrap, 'background'); } } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss index 3cfb5305ce8..efb7ce86c40 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss @@ -1,4 +1,6 @@ -.igx-avatar { +@use 'igniteui-theming/sass/bem' as *; + +@include b(igx-avatar) { @container style(--ig-theme: indigo) { igx-icon { --ig-size: 1; From 5a4ca2222ba4e5bb6d15d55fa767dd0baec12552 Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Wed, 15 Jan 2025 17:17:14 +0200 Subject: [PATCH 04/10] refactor(checkbox): bundle styles with component - initial commit --- .../src/lib/avatar/themes/dark/bootstrap.scss | 6 +- .../src/lib/avatar/themes/dark/fluent.scss | 6 +- .../src/lib/avatar/themes/dark/indigo.scss | 6 +- .../src/lib/avatar/themes/dark/material.scss | 6 +- .../lib/avatar/themes/light/bootstrap.scss | 7 +- .../src/lib/avatar/themes/light/fluent.scss | 7 +- .../src/lib/avatar/themes/light/indigo.scss | 9 +- .../src/lib/avatar/themes/light/material.scss | 7 +- .../lib/avatar/themes/shared/bootstrap.scss | 2 +- .../src/lib/avatar/themes/shared/indigo.scss | 2 +- .../src/lib/badge/badge.component.ts | 4 +- .../src/lib/checkbox/checkbox.component.ts | 13 +- .../src/lib/checkbox/themes/base.scss | 858 ++++++++++++++++++ .../src/lib/checkbox/themes/dark/_themes.scss | 7 + .../lib/checkbox/themes/dark/bootstrap.scss | 30 + .../src/lib/checkbox/themes/dark/fluent.scss | 25 + .../src/lib/checkbox/themes/dark/indigo.scss | 15 + .../lib/checkbox/themes/dark/material.scss | 15 + .../src/lib/checkbox/themes/index.ts | 37 + .../lib/checkbox/themes/light/_themes.scss | 8 + .../lib/checkbox/themes/light/bootstrap.scss | 14 + .../src/lib/checkbox/themes/light/fluent.scss | 14 + .../src/lib/checkbox/themes/light/indigo.scss | 14 + .../lib/checkbox/themes/light/material.scss | 14 + .../lib/checkbox/themes/shared/bootstrap.scss | 34 + .../lib/checkbox/themes/shared/fluent.scss | 110 +++ .../lib/checkbox/themes/shared/indigo.scss | 41 + .../lib/checkbox/themes/shared/material.scss | 42 + .../components/avatar/_avatar-theme.scss | 4 +- .../core/styles/themes/generators/_base.scss | 18 +- .../src/lib/services/theme/theme.service.ts | 89 +- .../src/lib/services/theme/theme.token.ts | 13 + src/app/styleguide/colors/color.sample.scss | 5 - src/styles/_demo-theme.scss | 20 +- src/styles/_variables.scss | 10 +- 35 files changed, 1382 insertions(+), 130 deletions(-) create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/base.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/dark/_themes.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/index.ts create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/light/_themes.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/shared/bootstrap.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/shared/indigo.scss create mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/shared/material.scss diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss index b56b4b737e2..59e78fd5440 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss @@ -5,6 +5,8 @@ $theme: $bootstrap; -igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +@container style(--theme: bootstrap) { + igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss index 9f6e66f529e..6a225a06091 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss @@ -5,6 +5,8 @@ $theme: $fluent; -igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +@container style(--theme: fluent) { + igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss index e45ecd8ab14..b693e234a5a 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss @@ -5,6 +5,8 @@ $theme: $indigo; -igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +@container style(--ig-theme: indigo) { + igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss index 396c1de44a6..5ab8d4bced5 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss @@ -5,6 +5,8 @@ $theme: $material; -igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); +@container style(--theme: material) { + igx-avatar { + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss index 6054302576d..fae43c04caa 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss @@ -1,9 +1,12 @@ +@use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/themes' as *; @use 'igniteui-theming/sass/utils/map' as *; @use 'themes' as *; $theme: $bootstrap; -igx-avatar { - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +@container style(--theme: bootstrap) { + @include b(igx-avatar) { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss index d9ede217890..2a8ffe1c87e 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss @@ -1,9 +1,12 @@ +@use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/themes' as *; @use 'igniteui-theming/sass/utils/map' as *; @use 'themes' as *; $theme: $fluent; -igx-avatar { - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +@container style(--theme: fluent) { + @include b(igx-avatar) { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss index f77ae6754d8..4f3c92d9926 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss @@ -1,11 +1,12 @@ +@use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/themes' as *; @use 'igniteui-theming/sass/utils/map' as *; @use 'themes' as *; $theme: $indigo; -igx-avatar { - --ig-theme: indigo; - - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +@container style(--theme: indigo) { + @include b(igx-avatar) { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss index 49c5e4fac64..8f75d0e1a23 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss @@ -1,9 +1,12 @@ +@use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/themes' as *; @use 'igniteui-theming/sass/utils/map' as *; @use 'themes' as *; $theme: $material; -igx-avatar { - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); +@container style(--theme: material) { + @include b(igx-avatar) { + @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); + } } diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss index 106a91e7d64..5b40ea2cc97 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss @@ -6,7 +6,7 @@ $theme: $bootstrap; @include b(igx-avatar) { - @container style(--ig-theme: bootstrap) { + @container style(--theme: bootstrap) { &::after { position: absolute; content: ''; diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss index efb7ce86c40..3bf8fd6da57 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss @@ -1,7 +1,7 @@ @use 'igniteui-theming/sass/bem' as *; @include b(igx-avatar) { - @container style(--ig-theme: indigo) { + @container style(--theme: indigo) { igx-icon { --ig-size: 1; } diff --git a/projects/igniteui-angular/src/lib/badge/badge.component.ts b/projects/igniteui-angular/src/lib/badge/badge.component.ts index 5275adb98f9..2f2b27674cc 100644 --- a/projects/igniteui-angular/src/lib/badge/badge.component.ts +++ b/projects/igniteui-angular/src/lib/badge/badge.component.ts @@ -1,5 +1,5 @@ import { NgIf } from '@angular/common'; -import { booleanAttribute, Component, HostBinding, Input } from '@angular/core'; +import { booleanAttribute, Component, ElementRef, HostBinding, Input } from '@angular/core'; import { mkenum } from '../core/utils'; import { IgxIconComponent } from '../icon/icon.component'; @@ -140,6 +140,8 @@ export class IgxBadgeComponent { @HostBinding('class.igx-badge') public cssClass = 'igx-badge'; + constructor(public elementRef: ElementRef) { } + /** * Sets a square shape to the badge, if `shape` is set to `square`. * By default the shape of the badge is rounded. diff --git a/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts b/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts index 9556f9b18ec..d8a48f13780 100644 --- a/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts +++ b/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts @@ -15,7 +15,8 @@ import { booleanAttribute, inject, DestroyRef, - Inject + Inject, + OnInit } from '@angular/core'; import { ControlValueAccessor, NgControl, Validators } from '@angular/forms'; import { IgxRippleDirective } from '../directives/ripple/ripple.directive'; @@ -24,6 +25,8 @@ import { EditorProvider, EDITOR_PROVIDER } from '../core/edit-provider'; import { noop, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { IgxTheme, THEME_TOKEN, ThemeToken } from '../services/theme/theme.token'; +import { ThemeService, ThemedComponent } from '../services/theme/theme.service'; +import themes from './themes/index'; export const LabelPosition = /*@__PURE__*/mkenum({ BEFORE: 'before', @@ -70,7 +73,7 @@ let nextId = 0; templateUrl: 'checkbox.component.html', imports: [IgxRippleDirective] }) -export class IgxCheckboxComponent implements EditorProvider, AfterViewInit, ControlValueAccessor { +export class IgxCheckboxComponent implements EditorProvider, OnInit, AfterViewInit, ControlValueAccessor { /** * An event that is emitted after the checkbox state is changed. @@ -474,6 +477,7 @@ export class IgxCheckboxComponent implements EditorProvider, AfterViewInit, Cont * @hidden */ private _onTouchedCallback: () => void = noop; + public themeService = inject(ThemeService); /** * @hidden @@ -529,6 +533,11 @@ export class IgxCheckboxComponent implements EditorProvider, AfterViewInit, Cont } } + /** @hidden @internal */ + public ngOnInit() { + this.themeService.adoptStyles(IgxCheckboxComponent, themes); + } + /** * @hidden * @internal diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/base.scss b/projects/igniteui-angular/src/lib/checkbox/themes/base.scss new file mode 100644 index 00000000000..c80a0ee45ae --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/base.scss @@ -0,0 +1,858 @@ +@use 'sass:map'; +@use 'sass:math'; +@use 'igniteui-theming/sass/animations' as *; +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/typography' as *; +@use 'igniteui-theming/sass/color/functions' as *; +@use './light/themes' as *; + +$theme: $material; + +$theme-variant: map.get($theme, '_meta', 'theme-variant'); +$variant: map.get($theme, '_meta', 'variant'); + +@include scale-in-out($start-scale: 0.9); +@include scale-in-center(); + +%cbx-display { + position: relative; + display: inline-flex; + flex-flow: row nowrap; + align-items: center; + outline-style: none; + cursor: pointer; +} + +%cbx-display--disabled { + user-select: none; + pointer-events: none; + cursor: initial; +} + +%cbx-input { + @include hide-default(); +} + +%cbx-composite-wrapper { + align-items: center; + justify-content: center; + display: flex; + position: relative; + width: var(--size); + height: var(--size); + + // @if $variant == 'material' { + // padding: rem(20px); + // } + + //ripple color + --color: #{var-get($theme, 'empty-color')}; +} + +%cbx-composite-wrapper--x { + //ripple color + --color: #{var-get($theme, 'fill-color')}; +} + +%cbx-composite { + position: relative; + display: inline-block; + width: var(--size); + height: var(--size); + min-width: var(--size); + background: var-get($theme, 'empty-fill-color'); + border-width: var(--border-width); + border-style: solid; + border-color: var-get($theme, 'empty-color'); + border-radius: var-get($theme, 'border-radius'); + -webkit-tap-highlight-color: transparent; + transition: + border-color 0.2s $ease-out-quad, + background 0.2s $ease-out-quad; + overflow: hidden; +} + +%cbx-composite--hover { + border-color: var-get($theme, 'empty-color-hover'); +} + +%cbx-composite--x { + border-color: var-get($theme, 'fill-color'); + background: var-get($theme, 'fill-color'); +} + +%cbx-composite--invalid { + border-color: var-get($theme, 'error-color'); + + // @if $variant == 'bootstrap' and $theme-variant == 'dark' { + // %cbx-composite-mark { + // stroke: black; + // } + // } +} + +%cbx-composite-wrapper--invalid { + //ripple color + --color: #{var-get($theme, 'error-color')}; +} + +%cbx-composite--invalid--hover { + border-color: var-get($theme, 'error-color-hover'); +} + +%cbx-composite--x--invalid { + border-color: var-get($theme, 'error-color'); + background: var-get($theme, 'error-color'); +} + +%cbx-composite--x--hover { + border-color: var-get($theme, 'fill-color-hover'); + background: var-get($theme, 'fill-color-hover'); +} + +%cbx-composite--x--invalid--hover { + border-color: var-get($theme, 'error-color-hover'); + background: var-get($theme, 'error-color-hover'); +} + +%cbx-composite--disabled { + border-color: var-get($theme, 'disabled-color'); + + // @if $variant == 'bootstrap' and $theme-variant == 'dark' { + // background: color($color: 'surface', $variant: 500); + // } +} + +%cbx-composite--x--disabled { + // @if $variant == 'material' or $variant == 'fluent' { + // background: var-get($theme, 'disabled-color'); + // } + + // @if $variant == 'indigo' or $variant == 'bootstrap' { + // background: var-get($theme, 'disabled-indeterminate-color'); + // border-color: transparent; + // } + + // @if $variant != 'indigo' { + // %cbx-composite-mark { + // stroke: var-get($theme, 'disabled-tick-color'); + // } + // } @else { + // %cbx-composite-mark { + // stroke: unset; + // fill: var-get($theme, 'disabled-tick-color'); + // } + // } +} + +%cbx-composite-mark { + position: absolute; + inset: 0; + stroke: var-get($theme, 'tick-color'); + stroke-linecap: square; + stroke-width: var(--mark-stroke); + stroke-dasharray: var(--mark-length); + stroke-dashoffset: var(--mark-length); + fill: none; + opacity: 0; + z-index: 1; +} + +%cbx-composite-mark-material { + inset-inline-start: -0.5px; +} + +%cbx-composite-mark-indigo { + stroke: unset; + stroke-linecap: unset; + stroke-width: unset; + stroke-dasharray: unset; + stroke-dashoffset: unset; + fill: var-get($theme, 'tick-color'); + transition: none !important; + + rect { + fill: none; + } +} + +%igx-checkbox--indeterminate { + %cbx-composite-mark { + top: var(--mark-offset); + margin-inline-start: var(--mark-offset); + } + + &:hover { + %cbx-composite { + border-color: var-get($theme, 'fill-color-hover'); + background: var-get($theme, 'fill-color-hover'); + + &::before { + background: var-get($theme, 'fill-color-hover'); + } + + // @if $variant == 'fluent' { + // background: transparent; + // } + } + } +} + +%igx-checkbox--indeterminate-indigo { + %cbx-composite-mark { + fill: none !important; + stroke-dashoffset: unset !important; + transform: none !important; + + rect { + fill: var-get($theme, 'tick-color'); + opacity: 1; + } + } +} + +%igx-checkbox--disabled-indeterminate-indigo { + @extend %igx-checkbox--indeterminate-indigo; + + %cbx-composite-mark { + rect { + fill: var-get($theme, 'disabled-tick-color'); + } + } +} + +%igx-checkbox--indeterminate-fluent { + %cbx-composite-mark { + stroke: transparent; + } + + %cbx-composite { + background: transparent; + + &::before { + content: ''; + position: absolute; + top: calc(var(--size) / 2 - rem(6px)); + inset-inline-start: calc(var(--size) / 2 - rem(6px)); + width: rem(10px); + height: rem(10px); + border-radius: border-radius(rem(2px)); + background: var-get($theme, 'fill-color'); + z-index: 1; + } + } +} + +%igx-checkbox--disabled-indeterminate-fluent { + %cbx-composite-mark { + stroke: transparent; + } + + %cbx-composite--x--disabled { + background: transparent; + + &::before { + background: var-get($theme, 'disabled-color'); + } + } +} + +%igx-checkbox--disabled-indeterminate-material { + %cbx-composite--x--disabled { + border-color: var-get($theme, 'disabled-indeterminate-color'); + background: var-get($theme, 'disabled-indeterminate-color'); + } +} + +%igx-checkbox--indeterminate--invalid { + %cbx-composite--x { + border-color: var-get($theme, 'error-color'); + background: var-get($theme, 'error-color'); + } + + %cbx-composite--x--hover { + border-color: var-get($theme, 'error-color-hover'); + background: var-get($theme, 'error-color-hover'); + } + + // @if $variant == 'fluent' { + // %cbx-composite { + // border-color: var-get($theme, 'error-color'); + + // &::before { + // background: var-get($theme, 'error-color'); + // } + // } + + // %cbx-composite--x { + // background: transparent; + // } + + // &:hover { + // %cbx-composite { + // background: transparent; + // border-color: var-get($theme, 'error-color-hover'); + + // &::before { + // background: var-get($theme, 'error-color-hover'); + // } + // } + // } + // } +} + +%cbx-composite-mark--x { + stroke-dashoffset: 0; + opacity: 1; + transition: + all 0.2s $ease-out-quad, + opacity 0.2s $ease-out-quad; +} + +%cbx-composite-mark--in { + stroke-dashoffset: 41; /* length of path - adjacent line length */ + opacity: 1; + rotate: 45deg; + transform: translateX(calc(var(--mark-stroke) / var(--mark-length) * -1em)); +} + +%cbx-composite-mark--fluent { + // @if $variant == 'fluent' { + // @extend %cbx-composite-mark; + // @extend %cbx-composite-mark--x; + // stroke: var-get($theme, 'tick-color-hover'); + // } +} + +%cbx-composite-mark--x--fluent { + // @if $variant == 'fluent' { + // stroke: var-get($theme, 'tick-color'); + // } +} + +%cbx-composite-mark--invalid--fluent { + // @if $variant == 'fluent' { + // stroke: var-get($theme, 'error-color'); + // } + + // @if $variant == 'fluent' and $theme-variant == 'dark' { + // stroke: color($color: 'error', $variant: 500); + // } +} + +%cbx-composite-mark--in--fluent { + // @if $variant == 'fluent' { + // stroke: transparent; + // } +} + +%cbx-label { + display: inline-block; + color: var-get($theme, 'label-color'); + user-select: none; + word-wrap: break-all; + transition: color 0.2s $ease-out-quad; + + &:empty { + margin: 0; + } +} + +%cbx-label--hover { + color: var-get($theme, 'label-color-hover'); +} + +%cbx-label-pos--before, +%cbx-label-pos--after { + &:empty { + margin: 0; + } +} + +%cbx-label-pos--after { + margin-inline-start: var(--label-margin); +} + +%cbx-label-pos--before { + margin-inline-end: var(--label-margin); + order: -1; +} + +%cbx-label--invalid { + color: var-get($theme, 'error-color'); +} + +%cbx-label--disabled { + color: var-get($theme, 'disabled-color-label'); +} + +%cbx-ripple { + --_ripple-size: #{rem(40px)}; + + display: none; + position: absolute; + top: calc(50% - calc(var(--_ripple-size) / 2)); + width: var(--_ripple-size); + aspect-ratio: 1; + border-radius: var-get($theme, 'border-radius-ripple'); + overflow: hidden; + pointer-events: none; + filter: opacity(1); +} + +%cbx-ripple--hover { + background: var-get($theme, 'empty-color'); + transition: background 0.2s $ease-out-quad; + opacity: 0.06; + + @media (prefers-color-scheme: dark) { + opacity: 0.12; + } +} + +%cbx-ripple--hover-checked { + background: var-get($theme, 'fill-color'); +} + +%cbx-ripple--hover-invalid { + background: var-get($theme, 'error-color'); +} + +%igx-checkbox--focused-indigo { + %cbx-composite { + border-radius: var-get($theme, 'border-radius'); + box-shadow: 0 0 0 rem(3px) var-get($theme, 'focus-outline-color'); + } +} + +%igx-checkbox--focused-fluent { + position: relative; + $focus-outline-offset: rem(2px); + + &::after { + content: ''; + position: absolute; + inset: -$focus-outline-offset; + box-shadow: 0 0 0 rem(1px) var-get($theme, 'focus-outline-color'); + } +} + +%igx-checkbox--focused-bootstrap { + %cbx-composite { + border-radius: var-get($theme, 'border-radius'); + border-color: color($color: 'primary', $variant: 200); + box-shadow: 0 0 0 rem(4px) var-get($theme, 'focus-outline-color'); + } +} + +%igx-checkbox--focused-hovered { + %cbx-composite { + border-color: color($color: 'primary', $variant: 300); + } +} + +%igx-checkbox--focused-checked-indigo { + %cbx-composite { + border-radius: var-get($theme, 'border-radius'); + box-shadow: 0 0 0 rem(3px) + var-get($theme, 'focus-outline-color-focused'); + } +} + +%igx-checkbox--focused-checked-bootstrap { + %cbx-composite { + border-color: transparent; + } +} + +%igx-checkbox--focused-invalid-indigo { + %cbx-composite { + box-shadow: 0 0 0 rem(3px) var-get($theme, 'focus-outline-color-error'); + } +} + +%igx-checkbox--focused-invalid-bootstrap { + %cbx-composite { + border-color: var-get($theme, 'error-color'); + box-shadow: 0 0 0 rem(4px) var-get($theme, 'focus-outline-color-error'); + } + + &:hover { + %cbx-composite { + border-color: var-get($theme, 'error-color-hover'); + } + } +} + +%cbx-ripple--focused { + background: var-get($theme, 'empty-color'); + transition: background 0.2s $ease-out-quad; + opacity: 0.12; + + @media (prefers-color-scheme: dark) { + opacity: 0.24; + } +} + +%cbx-ripple--focused-checked { + background: var-get($theme, 'fill-color'); +} + +%cbx-ripple--focused-invalid { + background: var-get($theme, 'error-color'); +} + +%cbx-ripple--pressed { + opacity: 0.12; + + @media (prefers-color-scheme: dark) { + opacity: 0.24; + } +} + +%cbx-display--plain { + %cbx-composite, + %cbx-composite::after, + %cbx-composite-mark, + %cbx-composite-mark--x { + transition: none; + } +} + +@include b(igx-checkbox) { + @include css-vars-from-theme($base, 'igx-checkbox'); + @extend %cbx-display !optional; + + &:hover { + @include e(ripple) { + @extend %cbx-ripple--hover !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark--fluent !optional; + } + } + + &:active { + @include e(ripple) { + @extend %cbx-ripple--hover !optional; + @extend %cbx-ripple--pressed !optional; + } + } + + @include e(input) { + @extend %cbx-input !optional; + } + + @include e(label) { + @extend %cbx-label !optional; + @extend %cbx-label-pos--after !optional; + } + + @include e(label, $m: before) { + @extend %cbx-label !optional; + @extend %cbx-label-pos--before !optional; + } + + @include e(composite-wrapper) { + @extend %cbx-composite-wrapper !optional; + } + + @include e(composite) { + @extend %cbx-composite !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark !optional; + } + + @include e(ripple) { + @extend %cbx-ripple !optional; + } + + @include m(bootstrap) { + @include e(composite) { + &:hover { + @extend %cbx-composite--hover !optional; + } + } + } + + @include m(indigo) { + @include e(composite) { + &:hover { + @extend %cbx-composite--hover !optional; + } + } + + @include e(composite-mark) { + @extend %cbx-composite-mark-indigo !optional; + } + + @include e(label) { + &:hover { + @extend %cbx-label--hover !optional; + } + } + } + + @include m(invalid) { + @include e(composite) { + @extend %cbx-composite--invalid !optional; + } + + @include e(composite-wrapper) { + @extend %cbx-composite-wrapper--invalid !optional; + } + + @include e(label) { + @extend %cbx-label--invalid !optional; + } + + &:hover { + @include e(ripple) { + @extend %cbx-ripple--hover !optional; + @extend %cbx-ripple--hover-invalid !optional; + } + + @include e(composite) { + @extend %cbx-composite--invalid--hover !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark--invalid--fluent !optional; + } + } + + &:active { + @include e(ripple) { + @extend %cbx-ripple--hover-invalid !optional; + } + } + } + + @include mx(invalid, checked) { + @include e(composite) { + @extend %cbx-composite--x--invalid !optional; + } + + &:hover { + @include e(composite) { + @extend %cbx-composite--x--invalid--hover !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark--x--fluent !optional; + } + } + } + + @include m(focused) { + @extend %igx-checkbox--focused !optional; + + @include e(ripple) { + @extend %cbx-ripple--focused !optional; + } + + &:hover { + @include e(ripple) { + @extend %cbx-ripple--focused !optional; + } + } + } + + @include mx(indigo, focused) { + @extend %igx-checkbox--focused-indigo !optional; + } + + @include mx(fluent, focused) { + @extend %igx-checkbox--focused-fluent !optional; + } + + @include mx(bootstrap, focused) { + @extend %igx-checkbox--focused-bootstrap !optional; + + &:hover { + @extend %igx-checkbox--focused-hovered !optional; + } + } + + @include mx(indigo, focused, checked) { + @extend %igx-checkbox--focused-checked-indigo !optional; + } + + @include mx(bootstrap, focused, checked) { + @extend %igx-checkbox--focused-checked-bootstrap !optional; + } + + @include mx(focused, checked) { + @extend %igx-checkbox--focused-checked !optional; + } + + @include mx(focused, invalid) { + @include e(ripple) { + @extend %cbx-ripple--focused-invalid !optional; + } + } + + @include mx(indigo, focused, invalid) { + @extend %igx-checkbox--focused-invalid-indigo !optional; + } + + @include mx(bootstrap, focused, invalid) { + @extend %igx-checkbox--focused-invalid-bootstrap !optional; + } + + @include m(indeterminate) { + @extend %igx-checkbox--indeterminate !optional; + + @include e(composite) { + @extend %cbx-composite--x !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark--in !optional; + } + + &:hover { + @include e(ripple) { + @extend %cbx-ripple--hover !optional; + @extend %cbx-ripple--hover-checked !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark--in--fluent !optional; + } + } + + &:active { + @include e(ripple) { + @extend %cbx-ripple--hover !optional; + @extend %cbx-ripple--hover-checked !optional; + @extend %cbx-ripple--pressed !optional; + } + } + } + + @include mx(indigo, indeterminate) { + @extend %igx-checkbox--indeterminate-indigo !optional; + } + + @include mx(fluent, indeterminate) { + @extend %igx-checkbox--indeterminate-fluent !optional; + } + + @include mx(invalid, indeterminate) { + @extend %igx-checkbox--indeterminate--invalid !optional; + + &:hover { + @include e(composite) { + @extend %cbx-composite--x--hover !optional; + } + } + } + + @include mx(material, disabled, indeterminate) { + @extend %igx-checkbox--disabled-indeterminate-material !optional; + } + + @include mx(fluent, disabled, indeterminate) { + @extend %igx-checkbox--disabled-indeterminate-fluent !optional; + } + + @include mx(indigo, disabled, indeterminate) { + @extend %igx-checkbox--disabled-indeterminate-indigo !optional; + } + + @include mx(indigo, focused, indeterminate) { + @extend %igx-checkbox--focused-checked-indigo !optional; + } + + @include mx(bootstrap, focused, indeterminate) { + @extend %igx-checkbox--focused-checked-bootstrap !optional; + } + + @include m(checked) { + @include e(composite) { + @extend %cbx-composite--x !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark--x !optional; + } + + @include e(composite-wrapper) { + @extend %cbx-composite-wrapper--x !optional; + } + + &:hover { + @include e(ripple) { + @extend %cbx-ripple--hover !optional; + @extend %cbx-ripple--hover-checked !optional; + } + + @include e(composite) { + @extend %cbx-composite--x--hover !optional; + } + + @include e(composite-mark) { + @extend %cbx-composite-mark--x--fluent !optional; + } + } + + &:active { + @include e(ripple) { + @extend %cbx-ripple--hover !optional; + @extend %cbx-ripple--hover-checked !optional; + @extend %cbx-ripple--pressed !optional; + } + } + } + + @include m(disabled) { + @extend %cbx-display--disabled !optional; + + @include e(label) { + @extend %cbx-label--disabled !optional; + } + + @include e(label, $m: before) { + @extend %cbx-label--disabled !optional; + } + + @include e(composite) { + @extend %cbx-composite--disabled !optional; + } + } + + @include m(plain) { + @extend %cbx-display--plain !optional; + } + + @include mx(focused, checked) { + @include e(ripple) { + @extend %cbx-ripple--focused !optional; + @extend %cbx-ripple--focused-checked !optional; + } + } + + @include mx(focused, indeterminate) { + @include e(ripple) { + @extend %cbx-ripple--focused !optional; + @extend %cbx-ripple--focused-checked !optional; + } + } + + @include mx(indeterminate, disabled) { + @include e(composite) { + @extend %cbx-composite--x--disabled !optional; + } + } + + @include mx(checked, disabled) { + @include e(composite) { + @extend %cbx-composite--x--disabled !optional; + } + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/_themes.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/_themes.scss new file mode 100644 index 00000000000..91fcfd5d2ea --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/_themes.scss @@ -0,0 +1,7 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/themes/schemas/components/dark/checkbox' as *; + +$material: digest-schema($dark-material-checkbox); +$bootstrap: digest-schema($dark-bootstrap-checkbox); +$fluent: digest-schema($dark-fluent-checkbox); +$indigo: digest-schema($dark-indigo-checkbox); diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss new file mode 100644 index 00000000000..b8a9d8fe642 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss @@ -0,0 +1,30 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'igniteui-theming/sass/color/functions' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $bootstrap; + +@container style(--theme: bootstrap) { + @include b(igx-checkbox) { + color-scheme: dark; + + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); + + @include m(invalid) { + @include e(composite-mark) { + // TODO: Check why this property is not part of the schemas + stroke: black; + } + } + + @include m(disabled) { + @include e(composite) { + // TODO: Check why this property is not part of the schemas + background: color($color: 'surface', $variant: 500); + } + } + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss new file mode 100644 index 00000000000..19145bd6daa --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss @@ -0,0 +1,25 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/color/functions' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $fluent; + +@container style(--theme: fluent) { + @include b(igx-checkbox) { + color-scheme: dark; + + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); + + @include m(invalid) { + &:hover { + @include e(composite-mark) { + // TODO: Check why this property is not part of the schemas + stroke: color($color: 'error', $variant: 500); + } + } + } + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss new file mode 100644 index 00000000000..1576f67e84c --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss @@ -0,0 +1,15 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $indigo; + +@container style(--ig-theme: indigo) { + @include b(igx-checkbox) { + color-scheme: dark; + + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss new file mode 100644 index 00000000000..74ce9c1efa6 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss @@ -0,0 +1,15 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use '../light/themes' as light; +@use 'themes' as *; + +$theme: $material; + +@container style(--theme: material) { + @include b(igx-checkbox) { + color-scheme: dark; + + @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/index.ts b/projects/igniteui-angular/src/lib/checkbox/themes/index.ts new file mode 100644 index 00000000000..6510b676ffb --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/index.ts @@ -0,0 +1,37 @@ +import base from './base.css'; +import material from './shared/material.css'; +import bootstrap from './shared/bootstrap.css'; +import fluent from './shared/fluent.css'; +import indigo from './shared/indigo.css'; + +import lightMaterial from './light/material.css'; +import lightBootstrap from './light/bootstrap.css'; +import lightFluent from './light/fluent.css'; +import lightIndigo from './light/indigo.css'; + +import darkMaterial from './dark/material.css'; +import darkBootstrap from './dark/bootstrap.css'; +import darkFluent from './dark/fluent.css'; +import darkIndigo from './dark/indigo.css'; + +export default { + base: base.css, + shared: { + material: material.css, + bootstrap: bootstrap.css, + fluent: fluent.css, + indigo: indigo.css + }, + light: { + material: lightMaterial.css, + bootstrap: lightBootstrap.css, + fluent: lightFluent.css, + indigo: lightIndigo.css + }, + dark: { + material: darkMaterial.css, + bootstrap: darkBootstrap.css, + fluent: darkFluent.css, + indigo: darkIndigo.css + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/_themes.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/_themes.scss new file mode 100644 index 00000000000..782c0d49713 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/_themes.scss @@ -0,0 +1,8 @@ +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/themes/schemas/components/light/checkbox' as *; + +$base: digest-schema($light-checkbox); +$material: digest-schema($material-checkbox); +$bootstrap: digest-schema($bootstrap-checkbox); +$fluent: digest-schema($fluent-checkbox); +$indigo: digest-schema($indigo-checkbox); diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss new file mode 100644 index 00000000000..3d93785a479 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss @@ -0,0 +1,14 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $bootstrap; + +@container style(--theme: bootstrap) { + @include b(igx-checkbox) { + color-scheme: light; + + @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss new file mode 100644 index 00000000000..248a6de35d2 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss @@ -0,0 +1,14 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $fluent; + +@container style(--theme: fluent) { + @include b(igx-checkbox) { + color-scheme: light; + + @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss new file mode 100644 index 00000000000..2c62219c0bc --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss @@ -0,0 +1,14 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $indigo; + +@container style(--theme: indigo) { + @include b(igx-checkbox) { + color-scheme: light; + + @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss new file mode 100644 index 00000000000..ef121a5fc31 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss @@ -0,0 +1,14 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'igniteui-theming/sass/utils/map' as *; +@use 'themes' as *; + +$theme: $material; + +@container style(--theme: material) { + @include b(igx-checkbox) { + color-scheme: light; + + @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/shared/bootstrap.scss b/projects/igniteui-angular/src/lib/checkbox/themes/shared/bootstrap.scss new file mode 100644 index 00000000000..04f3076f763 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/shared/bootstrap.scss @@ -0,0 +1,34 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/typography' as *; +@use 'igniteui-theming/sass/themes/functions' as *; +@use '../light/themes' as *; + +$theme: $bootstrap; + +@container style(--theme: bootstrap) { + @include b(igx-checkbox) { + --size: #{rem(16px)}; + --border-width: #{rem(1px)}; + --label-margin: #{rem(2px)}; + --mark-stroke: 3; + --mark-length: 24; + --mark-offset: 1px; + + @include e(label) { + @include type-style(body-1) { + margin-block: 0; + } + } + + @include mx(indeterminate, disabled) { + @include e(composite) { + background: var-get($theme, 'disabled-indeterminate-color'); + border-color: transparent; + } + + @include e(composite-mark) { + stroke: var-get($theme, 'disabled-tick-color'); + } + } + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss b/projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss new file mode 100644 index 00000000000..6dc1fe6bc30 --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss @@ -0,0 +1,110 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/color/functions' as *; +@use 'igniteui-theming/sass/themes/functions' as *; +@use 'igniteui-theming/sass/typography/functions' as *; +@use 'igniteui-theming/sass/animations' as *; +@use '../light/themes' as *; + +$theme: $fluent; + +@container style(--theme: fluent) { + @include b(igx-checkbox) { + --size: #{rem(20px)}; + --border-width: #{rem(1px)}; + --label-margin: #{rem(8px)}; + --mark-stroke: 1; + --mark-length: 24; + --mark-offset: -1px; + + &:hover { + @include e(composite-mark) { + // TODO: Check if this is even needed? + position: absolute; + inset: 0; + stroke-linecap: square; + stroke-width: var(--mark-stroke); + stroke-dasharray: var(--mark-length); + stroke-dashoffset: 0; + fill: none; + z-index: 1; + opacity: 1; + transition: + all 0.2s $ease-out-quad, + opacity 0.2s $ease-out-quad; + + stroke: var-get($theme, 'tick-color-hover'); + } + } + + @include e(label) { + @include type-style(body-2) { + margin-block: 0; + } + } + + @include m(indeterminate) { + &:hover { + @include e(composite) { + background: transparent; + } + + @include e(composite-mark) { + stroke: transparent; + } + } + } + + @include m(invalid) { + &:hover { + @include e(composite-mark) { + stroke: var-get($theme, 'error-color'); + } + } + } + + @include mx(indeterminate, invalid) { + @include e(composite) { + border-color: var-get($theme, 'error-color'); + + &::before { + background: var-get($theme, 'error-color'); + } + } + + &:hover { + @include e(composite) { + background: transparent; + border-color: var-get($theme, 'error-color-hover'); + + &::before { + background: var-get($theme, 'error-color-hover'); + } + } + } + } + + @include mx(indeterminate, invalid, checked) { + @include e(composite) { + background: transparent; + } + } + + @include mx(indeterminate, disabled) { + @include e(composite) { + background: var-get($theme, 'disabled-color'); + } + + @include e(composite-mark) { + stroke: var-get($theme, 'disabled-tick-color'); + } + } + + @include mx(invalid, checked) { + &:hover { + @include e(composite-mark) { + stroke: var-get($theme, 'tick-color'); + } + } + } + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/shared/indigo.scss b/projects/igniteui-angular/src/lib/checkbox/themes/shared/indigo.scss new file mode 100644 index 00000000000..f0c0431c55a --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/shared/indigo.scss @@ -0,0 +1,41 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/typography' as *; +@use 'igniteui-theming/sass/themes/functions' as *; +@use '../light/themes' as *; + +$theme: $indigo; + +@container style(--theme: indigo) { + @include b(igx-checkbox) { + --size: #{rem(16px)}; + --border-width: #{rem(2px)}; + --label-margin: #{rem(8px)}; + --mark-stroke: 3; + --mark-length: 24; + --mark-offset: 1px; + + @include e(label) { + @include type-style(body-2) { + margin-block: 0; + } + } + + @include m(invalid) { + @include e(label) { + color: var-get($theme, 'label-color'); + } + } + + @include mx(indeterminate, disabled) { + @include e(composite) { + background: var-get($theme, 'disabled-indeterminate-color'); + border-color: transparent; + } + + @include e(composite-mark) { + stroke: unset; + fill: var-get($theme, 'disabled-tick-color'); + } + } + } +} diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/shared/material.scss b/projects/igniteui-angular/src/lib/checkbox/themes/shared/material.scss new file mode 100644 index 00000000000..19be967a4ef --- /dev/null +++ b/projects/igniteui-angular/src/lib/checkbox/themes/shared/material.scss @@ -0,0 +1,42 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/typography' as *; +@use 'igniteui-theming/sass/themes/functions' as *; +@use '../light/themes' as *; + +$theme: $material; + +@container style(--theme: material) { + @include b(igx-checkbox) { + // These CSS variables should be listed as design tokens in the schema files. + --size: #{rem(20px)}; + --border-width: #{rem(2px)}; + --label-margin: #{rem(2px)}; + --mark-stroke: 3; + --mark-length: 24; + --mark-offset: 0; + + @include e(label) { + @include type-style(subtitle-1) { + margin-block: 0; + } + } + + @include e(ripple) { + display: block; + } + + @include e(composite-wrapper) { + padding: rem(20px); + } + + @include mx(indeterminate, disabled) { + @include e(composite) { + background: var-get($theme, 'disabled-color'); + } + + @include e(composite-mark) { + stroke: var-get($theme, 'disabled-tick-color'); + } + } + } +} diff --git a/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss index 11d17f2c9b1..2aa4367fb4d 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/avatar/_avatar-theme.scss @@ -66,7 +66,7 @@ /// @param {Map} $theme - The theme used to style the component. @mixin avatar($theme) { $variant: map.get($theme, '_meta', 'variant'); - + %igx-avatar-display { @include sizable(); @@ -80,7 +80,7 @@ color: var-get($theme, 'color'); background: var-get($theme, 'background'); vertical-align: middle; - outline-style: none; + // outline-style: none; flex-shrink: 0; width: var-get($theme, 'size'); height: var-get($theme, 'size'); diff --git a/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss b/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss index e41c3306bd7..a449cbe39f3 100644 --- a/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss +++ b/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss @@ -136,10 +136,6 @@ @include ripple($ripple-theme-map); } - igx-avatar { - --theme: var(--ig-theme); - } - // @if is-used('igx-avatar', $exclude) { // $avatar-theme-map: avatar-theme( // $schema: $schema, @@ -324,13 +320,13 @@ @include css-vars($shape-chart-theme-map); } - @if is-used('igx-checkbox', $exclude) { - $checkbox-theme-map: checkbox-theme( - $schema: $schema, - ); - $checkbox-theme-map: meta.call($theme-handler, $checkbox-theme-map); - @include checkbox($checkbox-theme-map); - } + // @if is-used('igx-checkbox', $exclude) { + // $checkbox-theme-map: checkbox-theme( + // $schema: $schema, + // ); + // $checkbox-theme-map: meta.call($theme-handler, $checkbox-theme-map); + // @include checkbox($checkbox-theme-map); + // } @if is-used('igx-chip', $exclude) { $chip-theme-map: chip-theme( diff --git a/projects/igniteui-angular/src/lib/services/theme/theme.service.ts b/projects/igniteui-angular/src/lib/services/theme/theme.service.ts index 8150a3be0c8..c200f48ebbb 100644 --- a/projects/igniteui-angular/src/lib/services/theme/theme.service.ts +++ b/projects/igniteui-angular/src/lib/services/theme/theme.service.ts @@ -1,38 +1,22 @@ -import { ElementRef, Inject, Injectable } from "@angular/core"; -import { mkenum } from "../../core/utils"; -import { BehaviorSubject } from "rxjs"; -import { DOCUMENT } from "@angular/common"; +import { ElementRef, inject, Injectable } from "@angular/core"; +import { THEME_TOKEN, ThemeToken, IgxTheme } from "igniteui-angular"; export interface ThemedComponent { elementRef: ElementRef; themeService: ThemeService; } -const Theme = /*@__PURE__*/ mkenum({ - Material: "material", - Fluent: "fluent", - Bootstrap: "bootstrap", - IndigoDesign: "indigo", -}); - -export type ThemeVariant = 'light' | 'dark'; - -/** - * Determines the component theme. - */ -export type IgxTheme = (typeof Theme)[keyof typeof Theme]; - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions export type Themes = { base: string; shared?: { - [K in IgxTheme | 'shared']?: string; + [K in IgxTheme]?: string; }; light: { - [K in IgxTheme | 'shared']?: string; + [K in IgxTheme]?: string; }; dark: { - [K in IgxTheme | 'shared']?: string; + [K in IgxTheme]?: string; }; }; @@ -44,55 +28,9 @@ export class ThemeService { * Sets the theme of the component. * Allowed values of type IgxTheme. */ - public globalTheme: IgxTheme; - public themeVariant: ThemeVariant; - private themeVariant$ = new BehaviorSubject("light"); - private theme$ = new BehaviorSubject("material"); + private themeToken: ThemeToken = inject(THEME_TOKEN); private componentThemes = new WeakMap(); - constructor( - @Inject(DOCUMENT) - private document: any, - ) { - this.theme$.asObservable().subscribe((value) => { - this.globalTheme = value as IgxTheme; - }); - - this.themeVariant$.asObservable().subscribe((value) => { - this.themeVariant = value as ThemeVariant; - }); - - this.init(); - } - - private init() { - const theme = globalThis.window - ?.getComputedStyle(this.document.body) - .getPropertyValue("--ig-theme") - .trim(); - - const themeVariant = globalThis.window - ?.getComputedStyle(this.document.body) - .getPropertyValue("--ig-theme-variant") - .trim(); - - if (theme !== "") { - this.theme$.next(theme as IgxTheme); - } - - if (themeVariant !== "") { - this.themeVariant$.next(themeVariant as ThemeVariant); - } - } - - public getComponentTheme(el: ElementRef) { - return globalThis.window - ?.getComputedStyle(el.nativeElement) - .getPropertyValue('--theme') - .trim() as IgxTheme; - } - - public adoptStyles(componentInstance: Function, themes: Themes) { let componentStyles = this.componentThemes.get(componentInstance); @@ -114,18 +52,13 @@ export class ThemeService { sheet.insertRule(`@layer base {${themes.base}}`); - for (const [key, value] of Object.entries(themes)) { - if (key === 'shared') { - for (const [theme, styleSheet] of Object.entries(value)) { - sheet.insertRule(`@layer ${theme} {${styleSheet}}`) - } + for (const theme of ['indigo', 'material', 'bootstrap', 'fluent']) { + if (themes.shared[theme]) { + sheet.insertRule(`@layer ${theme} {${themes.shared[theme]}}`); } - } - - sheet.insertRule(`@layer ${this.globalTheme}-overrides { - ${themes[this.themeVariant][this.globalTheme]} - }`); + sheet.insertRule(`@layer theme {${themes[this.themeToken.variant][theme]}`); + } return sheet; } diff --git a/projects/igniteui-angular/src/lib/services/theme/theme.token.ts b/projects/igniteui-angular/src/lib/services/theme/theme.token.ts index 1ea02f7aa99..25abc83f2a8 100644 --- a/projects/igniteui-angular/src/lib/services/theme/theme.token.ts +++ b/projects/igniteui-angular/src/lib/services/theme/theme.token.ts @@ -6,6 +6,7 @@ import { DOCUMENT } from "@angular/common"; export class ThemeToken { private document = inject(DOCUMENT); public subject: BehaviorSubject; + public variant: IgxThemeVariant; constructor(private t?: IgxTheme) { const globalTheme = globalThis.window @@ -13,6 +14,11 @@ export class ThemeToken { .getPropertyValue("--ig-theme") .trim() || 'material' as IgxTheme; + this.variant = globalThis.window + ?.getComputedStyle(this.document.body) + .getPropertyValue("--ig-theme-variant") + .trim() as IgxThemeVariant; + const _theme = t ?? globalTheme as IgxTheme; this.subject = new BehaviorSubject(_theme); } @@ -46,7 +52,14 @@ const Theme = /*@__PURE__*/ mkenum({ IndigoDesign: "indigo", }); +const ThemeVariant = /*@__PURE__*/ mkenum({ + Light: "light", + Dark: "dark" +}); + /** * Determines the component theme. */ export type IgxTheme = (typeof Theme)[keyof typeof Theme]; + +export type IgxThemeVariant = (typeof ThemeVariant)[keyof typeof ThemeVariant]; diff --git a/src/app/styleguide/colors/color.sample.scss b/src/app/styleguide/colors/color.sample.scss index 831ce999e67..5f5f0d8f933 100644 --- a/src/app/styleguide/colors/color.sample.scss +++ b/src/app/styleguide/colors/color.sample.scss @@ -9,11 +9,6 @@ color: color($palette, primary, 200); } -.test-100-contrast { - color: contrast-color($palette, primary, 100); -} - - .sample-wrapper { display: grid; grid-template-columns: 1fr; diff --git a/src/styles/_demo-theme.scss b/src/styles/_demo-theme.scss index 910e631d453..20c3d2251ea 100644 --- a/src/styles/_demo-theme.scss +++ b/src/styles/_demo-theme.scss @@ -11,10 +11,6 @@ body { color: $foreground-color; } -:root { - --some-dynamic-color: hsl(#{math.random(360)}, 100%, 50%); -} - @include core(); @include typography($font-family: $typeface, $type-scale: $type-scale); @include theme( @@ -22,9 +18,7 @@ body { $schema: $schema, ); - -.avatar-theme { - --ig-theme: bootstrap; +.bootstrap-avatar { @include palette($light-bootstrap-palette); @include css-vars(avatar-theme( @@ -32,6 +26,13 @@ body { )); } +.material-avatar { + @include palette($light-material-palette); + + @include css-vars(avatar-theme( + $schema: $light-material-schema, + )); +} .custom-palette { @include palette(palette( @@ -50,6 +51,11 @@ body { @include css-vars(dock-manager-theme()); } +.custom-avatar { + --color: blue; + outline-color: blue; +} + .nav-header { @if $variant == 'light' { @include nav-logo('../assets/images/rsrcs/igniteui-logo-light-bg'); diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss index 9fc0bc5d8f8..6d537d446ab 100644 --- a/src/styles/_variables.scss +++ b/src/styles/_variables.scss @@ -1,12 +1,14 @@ @use 'sass:map'; @use '../../projects/igniteui-angular/src/lib/core/styles/themes' as *; -$palette: $light-indigo-palette; -$schema: $light-indigo-schema; -$typeface: $indigo-typeface; -$type-scale: $indigo-type-scale; +$palette: $dark-material-palette; +$schema: $dark-material-schema; +$typeface: $material-typeface; +$type-scale: $material-type-scale; $variant: map.get($schema, '_meta', 'variant'); +@debug $variant; + $background-color: var(--ig-gray-900-contrast); $foreground-color: var(--ig-gray-900); From 754ec5b22c39f8536ed4c1797cc67ed229cdc2fa Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Mon, 20 Jan 2025 14:29:39 +0200 Subject: [PATCH 05/10] refactor(checkbox): fix component styles --- projects/igniteui-angular/src/lib/checkbox/themes/base.scss | 6 +++--- .../src/lib/checkbox/themes/dark/bootstrap.scss | 2 -- .../src/lib/checkbox/themes/dark/fluent.scss | 2 -- .../src/lib/checkbox/themes/dark/indigo.scss | 2 -- .../src/lib/checkbox/themes/dark/material.scss | 2 -- .../src/lib/checkbox/themes/light/bootstrap.scss | 2 -- .../src/lib/checkbox/themes/light/fluent.scss | 2 -- .../src/lib/checkbox/themes/light/indigo.scss | 2 -- .../src/lib/checkbox/themes/light/material.scss | 2 -- .../src/lib/checkbox/themes/shared/fluent.scss | 2 +- src/styles/_variables.scss | 6 ++---- 11 files changed, 6 insertions(+), 24 deletions(-) diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/base.scss b/projects/igniteui-angular/src/lib/checkbox/themes/base.scss index c80a0ee45ae..63a950f17f6 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/base.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/base.scss @@ -406,7 +406,7 @@ $variant: map.get($theme, '_meta', 'variant'); transition: background 0.2s $ease-out-quad; opacity: 0.06; - @media (prefers-color-scheme: dark) { + @container style(--ig-theme-variant: dark) { opacity: 0.12; } } @@ -490,7 +490,7 @@ $variant: map.get($theme, '_meta', 'variant'); transition: background 0.2s $ease-out-quad; opacity: 0.12; - @media (prefers-color-scheme: dark) { + @container style(--ig-theme-variant: dark) { opacity: 0.24; } } @@ -506,7 +506,7 @@ $variant: map.get($theme, '_meta', 'variant'); %cbx-ripple--pressed { opacity: 0.12; - @media (prefers-color-scheme: dark) { + @container style(--ig-theme-variant: dark) { opacity: 0.24; } } diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss index b8a9d8fe642..238f588d78b 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/bootstrap.scss @@ -9,8 +9,6 @@ $theme: $bootstrap; @container style(--theme: bootstrap) { @include b(igx-checkbox) { - color-scheme: dark; - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); @include m(invalid) { diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss index 19145bd6daa..d2ba3956a91 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/fluent.scss @@ -9,8 +9,6 @@ $theme: $fluent; @container style(--theme: fluent) { @include b(igx-checkbox) { - color-scheme: dark; - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); @include m(invalid) { diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss index 1576f67e84c..77968828789 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/indigo.scss @@ -8,8 +8,6 @@ $theme: $indigo; @container style(--ig-theme: indigo) { @include b(igx-checkbox) { - color-scheme: dark; - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); } } diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss b/projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss index 74ce9c1efa6..763ff7f8199 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/dark/material.scss @@ -8,8 +8,6 @@ $theme: $material; @container style(--theme: material) { @include b(igx-checkbox) { - color-scheme: dark; - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-checkbox'); } } diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss index 3d93785a479..4b29e588f57 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/bootstrap.scss @@ -7,8 +7,6 @@ $theme: $bootstrap; @container style(--theme: bootstrap) { @include b(igx-checkbox) { - color-scheme: light; - @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); } } diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss index 248a6de35d2..9d09abe7ec9 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/fluent.scss @@ -7,8 +7,6 @@ $theme: $fluent; @container style(--theme: fluent) { @include b(igx-checkbox) { - color-scheme: light; - @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); } } diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss index 2c62219c0bc..8ae2893a0b2 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/indigo.scss @@ -7,8 +7,6 @@ $theme: $indigo; @container style(--theme: indigo) { @include b(igx-checkbox) { - color-scheme: light; - @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); } } diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss b/projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss index ef121a5fc31..bd364f81b76 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/light/material.scss @@ -7,8 +7,6 @@ $theme: $material; @container style(--theme: material) { @include b(igx-checkbox) { - color-scheme: light; - @include css-vars-from-theme(diff($base, $theme), 'igx-checkbox'); } } diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss b/projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss index 6dc1fe6bc30..0e8f8b2eab1 100644 --- a/projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss +++ b/projects/igniteui-angular/src/lib/checkbox/themes/shared/fluent.scss @@ -1,7 +1,7 @@ @use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/color/functions' as *; @use 'igniteui-theming/sass/themes/functions' as *; -@use 'igniteui-theming/sass/typography/functions' as *; +@use 'igniteui-theming/sass/typography' as *; @use 'igniteui-theming/sass/animations' as *; @use '../light/themes' as *; diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss index 6d537d446ab..fa429165538 100644 --- a/src/styles/_variables.scss +++ b/src/styles/_variables.scss @@ -1,14 +1,12 @@ @use 'sass:map'; @use '../../projects/igniteui-angular/src/lib/core/styles/themes' as *; -$palette: $dark-material-palette; -$schema: $dark-material-schema; +$palette: $light-material-palette; +$schema: $light-material-schema; $typeface: $material-typeface; $type-scale: $material-type-scale; $variant: map.get($schema, '_meta', 'variant'); -@debug $variant; - $background-color: var(--ig-gray-900-contrast); $foreground-color: var(--ig-gray-900); From 0a5378d4f614d12671f898a75f433cb22c0cc189 Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Fri, 24 Jan 2025 10:11:44 +0200 Subject: [PATCH 06/10] build(styles): don't rely on theme service for bundled styles --- .gitignore | 2 +- .../src/lib/avatar/avatar.component.scss | 4 + .../src/lib/avatar/avatar.component.ts | 9 +- .../src/lib/avatar/themes/_base.scss | 83 +++++++++++++++++++ .../src/lib/avatar/themes/base.scss | 81 ------------------ .../src/lib/avatar/themes/dark/_index.scss | 6 ++ .../dark/{_themes.scss => _tokens.scss} | 0 .../src/lib/avatar/themes/dark/bootstrap.scss | 12 --- .../src/lib/avatar/themes/dark/fluent.scss | 12 --- .../src/lib/avatar/themes/dark/indigo.scss | 12 --- .../src/lib/avatar/themes/dark/material.scss | 12 --- .../src/lib/avatar/themes/index.ts | 33 -------- .../src/lib/avatar/themes/light/_index.scss | 6 ++ .../light/{_themes.scss => _tokens.scss} | 0 .../lib/avatar/themes/light/bootstrap.scss | 12 --- .../src/lib/avatar/themes/light/fluent.scss | 12 --- .../src/lib/avatar/themes/light/indigo.scss | 12 --- .../src/lib/avatar/themes/light/material.scss | 12 --- .../src/lib/avatar/themes/shared/_index.scss | 1 + .../lib/avatar/themes/shared/bootstrap.scss | 23 ----- .../src/lib/avatar/themes/shared/indigo.scss | 8 +- .../src/lib/checkbox/checkbox.component.ts | 11 +-- .../src/lib/checkbox/themes/index.ts | 37 --------- .../lib/core/styles/themes/_standalone.scss | 37 +++++++++ .../src/lib/icon/icon.component.ts | 2 - .../src/lib/services/theme/theme.service.ts | 65 --------------- .../src/lib/avatar/avatar.component.css | 3 + scripts/sass.mjs | 62 ++++++++------ scripts/styles.tmpl | 3 - scripts/watch-styles.mjs | 16 +--- 30 files changed, 190 insertions(+), 398 deletions(-) create mode 100644 projects/igniteui-angular/src/lib/avatar/avatar.component.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/_base.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/base.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/_index.scss rename projects/igniteui-angular/src/lib/avatar/themes/dark/{_themes.scss => _tokens.scss} (100%) delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/index.ts create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/_index.scss rename projects/igniteui-angular/src/lib/avatar/themes/light/{_themes.scss => _tokens.scss} (100%) delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/light/material.scss create mode 100644 projects/igniteui-angular/src/lib/avatar/themes/shared/_index.scss delete mode 100644 projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss delete mode 100644 projects/igniteui-angular/src/lib/checkbox/themes/index.ts create mode 100644 projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss delete mode 100644 projects/igniteui-angular/src/lib/services/theme/theme.service.ts create mode 100644 scripts/projects/igniteui-angular/src/lib/avatar/avatar.component.css delete mode 100644 scripts/styles.tmpl diff --git a/.gitignore b/.gitignore index bb5aa2377e5..049b1e580d5 100644 --- a/.gitignore +++ b/.gitignore @@ -49,7 +49,7 @@ src/**/*.js.map src/**/*.css.map # Artefacts -projects/igniteui-angular/**/*.css.ts +projects/igniteui-angular/**/*.component.css # Typedoc Theme extras/docs/themes/typedoc/bin diff --git a/projects/igniteui-angular/src/lib/avatar/avatar.component.scss b/projects/igniteui-angular/src/lib/avatar/avatar.component.scss new file mode 100644 index 00000000000..dd684163cd7 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/avatar.component.scss @@ -0,0 +1,4 @@ +@use 'themes/base'; +@use 'themes/shared'; +@use 'themes/light'; +@use 'themes/dark'; diff --git a/projects/igniteui-angular/src/lib/avatar/avatar.component.ts b/projects/igniteui-angular/src/lib/avatar/avatar.component.ts index b3f1e6c9eb2..bf1229c68a2 100644 --- a/projects/igniteui-angular/src/lib/avatar/avatar.component.ts +++ b/projects/igniteui-angular/src/lib/avatar/avatar.component.ts @@ -7,13 +7,12 @@ import { OnInit, TemplateRef, ViewChild, + ViewEncapsulation, inject } from '@angular/core'; import { mkenum, normalizeURI } from '../core/utils'; import { IgxIconComponent } from '../icon/icon.component'; -import { ThemeService, ThemedComponent } from '../services/theme/theme.service'; -import themes from './themes/index'; let NEXT_ID = 0; export const IgxAvatarSize = /*@__PURE__*/mkenum({ @@ -56,11 +55,12 @@ export type IgxAvatarType = (typeof IgxAvatarType)[keyof typeof IgxAvatarType]; @Component({ selector: 'igx-avatar', templateUrl: 'avatar.component.html', + styleUrl: 'avatar.component.css', + encapsulation: ViewEncapsulation.None, imports: [IgxIconComponent, NgTemplateOutlet] }) -export class IgxAvatarComponent implements OnInit, ThemedComponent { +export class IgxAvatarComponent implements OnInit { public elementRef = inject(ElementRef); - public themeService = inject(ThemeService); /** * Returns the `aria-label` attribute of the avatar. @@ -351,7 +351,6 @@ export class IgxAvatarComponent implements OnInit, ThemedComponent { /** @hidden @internal */ public ngOnInit() { this.roleDescription = this.getRole(); - this.themeService.adoptStyles(IgxAvatarComponent, themes); } /** @hidden @internal */ diff --git a/projects/igniteui-angular/src/lib/avatar/themes/_base.scss b/projects/igniteui-angular/src/lib/avatar/themes/_base.scss new file mode 100644 index 00000000000..a5a74695d3e --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/_base.scss @@ -0,0 +1,83 @@ +@use 'igniteui-theming/sass/animations' as *; +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@use 'light/tokens' as *; + +$theme: $material; + +@layer base { + %igx-avatar-display { + @include sizable(); + + --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); + + position: relative; + display: inline-flex; + justify-content: center; + align-items: center; + user-select: none; + color: var-get($theme, 'color'); + background: var-get($theme, 'background'); + vertical-align: middle; + outline-style: none; + flex-shrink: 0; + width: var-get($theme, 'size'); + height: var-get($theme, 'size'); + + igx-icon { + --component-size: 3; + + color: var-get($theme, 'icon-color'); + } + + &::after { + box-shadow: none; + transition: box-shadow 0.15s $ease-in-out-quad; + } + } + + %igx-avatar-image { + width: 100%; + height: 100%; + border-radius: inherit; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + } + + %igx-avatar--circle { + border-radius: calc(#{var-get($theme, 'size')} / 2); + } + + %igx-avatar--rounded { + border-radius: var-get($theme, 'border-radius'); + } + + %igx-avatar--initials { + text-transform: uppercase; + font-size: calc(#{var-get($theme, 'size')} / 2); + line-height: calc(#{var-get($theme, 'size')} / 2); + } + + @include b(igx-avatar) { + // @include css-vars-from-theme($base, 'igx-avatar'); + + @extend %igx-avatar-display; + + @include e(image) { + @extend %igx-avatar-image; + } + + @include m(circle) { + @extend %igx-avatar--circle; + } + + @include m(rounded) { + @extend %igx-avatar--rounded; + } + + @include m(initials) { + @extend %igx-avatar--initials; + } + } +} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/base.scss b/projects/igniteui-angular/src/lib/avatar/themes/base.scss deleted file mode 100644 index 454d7fe4216..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/base.scss +++ /dev/null @@ -1,81 +0,0 @@ -@use 'igniteui-theming/sass/animations' as *; -@use 'igniteui-theming/sass/bem' as *; -@use 'igniteui-theming/sass/themes' as *; -@use './light/themes' as *; - -$theme: $material; - -%igx-avatar-display { - @include sizable(); - - --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); - - position: relative; - display: inline-flex; - justify-content: center; - align-items: center; - user-select: none; - color: var-get($theme, 'color'); - background: var-get($theme, 'background'); - vertical-align: middle; - outline-style: none; - flex-shrink: 0; - width: var-get($theme, 'size'); - height: var-get($theme, 'size'); - - igx-icon { - --component-size: 3; - - color: var-get($theme, 'icon-color'); - } - - &::after { - box-shadow: none; - transition: box-shadow .15s $ease-in-out-quad; - } -} - -%igx-avatar-image { - width: 100%; - height: 100%; - border-radius: inherit; - background-size: cover; - background-repeat: no-repeat; - background-position: center; -} - -%igx-avatar--circle { - border-radius: calc(#{var-get($theme, 'size')} / 2); -} - -%igx-avatar--rounded { - border-radius: var-get($theme, 'border-radius'); -} - -%igx-avatar--initials { - text-transform: uppercase; - font-size: calc(#{var-get($theme, 'size')} / 2); - line-height: calc(#{var-get($theme, 'size')} / 2); -} - -@include b(igx-avatar) { - @include css-vars-from-theme($base, 'igx-avatar'); - - @extend %igx-avatar-display; - - @include e(image) { - @extend %igx-avatar-image; - } - - @include m(circle) { - @extend %igx-avatar--circle; - } - - @include m(rounded) { - @extend %igx-avatar--rounded; - } - - @include m(initials) { - @extend %igx-avatar--initials; - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/_index.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/_index.scss new file mode 100644 index 00000000000..9dbf039674c --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/dark/_index.scss @@ -0,0 +1,6 @@ +@use 'sass:meta'; +@use 'tokens'; +@use 'styles/themes/standalone' as *; + +$tokens: meta.module-variables(tokens); +@include themes(igx-avatar, $tokens, dark); diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/_themes.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/_tokens.scss similarity index 100% rename from projects/igniteui-angular/src/lib/avatar/themes/dark/_themes.scss rename to projects/igniteui-angular/src/lib/avatar/themes/dark/_tokens.scss diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss deleted file mode 100644 index 59e78fd5440..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/bootstrap.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use '../light/themes' as light; -@use 'themes' as *; - -$theme: $bootstrap; - -@container style(--theme: bootstrap) { - igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss deleted file mode 100644 index 6a225a06091..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/fluent.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use '../light/themes' as light; -@use 'themes' as *; - -$theme: $fluent; - -@container style(--theme: fluent) { - igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss deleted file mode 100644 index b693e234a5a..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/indigo.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use '../light/themes' as light; -@use 'themes' as *; - -$theme: $indigo; - -@container style(--ig-theme: indigo) { - igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss b/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss deleted file mode 100644 index 5ab8d4bced5..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/dark/material.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use '../light/themes' as light; -@use 'themes' as *; - -$theme: $material; - -@container style(--theme: material) { - igx-avatar { - @include css-vars-from-theme(diff(light.$base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/index.ts b/projects/igniteui-angular/src/lib/avatar/themes/index.ts deleted file mode 100644 index 681b6e5728e..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import base from './base.css'; -import bootstrap from './shared/bootstrap.css'; -import indigo from './shared/indigo.css'; - -import lightMaterial from './light/material.css'; -import lightBootstrap from './light/bootstrap.css'; -import lightFluent from './light/fluent.css'; -import lightIndigo from './light/indigo.css'; - -import darkMaterial from './dark/material.css'; -import darkBootstrap from './dark/bootstrap.css'; -import darkFluent from './dark/fluent.css'; -import darkIndigo from './dark/indigo.css'; - -export default { - base: base.css, - shared: { - bootstrap: bootstrap.css, - indigo: indigo.css - }, - light: { - material: lightMaterial.css, - bootstrap: lightBootstrap.css, - fluent: lightFluent.css, - indigo: lightIndigo.css - }, - dark: { - material: darkMaterial.css, - bootstrap: darkBootstrap.css, - fluent: darkFluent.css, - indigo: darkIndigo.css - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/_index.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/_index.scss new file mode 100644 index 00000000000..b59827df365 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/light/_index.scss @@ -0,0 +1,6 @@ +@use 'sass:meta'; +@use 'tokens'; +@use 'styles/themes/standalone' as *; + +$tokens: meta.module-variables(tokens); +@include themes(igx-avatar, $tokens, light); diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/_themes.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/_tokens.scss similarity index 100% rename from projects/igniteui-angular/src/lib/avatar/themes/light/_themes.scss rename to projects/igniteui-angular/src/lib/avatar/themes/light/_tokens.scss diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss deleted file mode 100644 index fae43c04caa..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/bootstrap.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/bem' as *; -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use 'themes' as *; - -$theme: $bootstrap; - -@container style(--theme: bootstrap) { - @include b(igx-avatar) { - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss deleted file mode 100644 index 2a8ffe1c87e..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/fluent.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/bem' as *; -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use 'themes' as *; - -$theme: $fluent; - -@container style(--theme: fluent) { - @include b(igx-avatar) { - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss deleted file mode 100644 index 4f3c92d9926..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/indigo.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/bem' as *; -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use 'themes' as *; - -$theme: $indigo; - -@container style(--theme: indigo) { - @include b(igx-avatar) { - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss b/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss deleted file mode 100644 index 8f75d0e1a23..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/light/material.scss +++ /dev/null @@ -1,12 +0,0 @@ -@use 'igniteui-theming/sass/bem' as *; -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/utils/map' as *; -@use 'themes' as *; - -$theme: $material; - -@container style(--theme: material) { - @include b(igx-avatar) { - @include css-vars-from-theme(diff($base, $theme), 'igx-avatar'); - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/_index.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/_index.scss new file mode 100644 index 00000000000..ca3dd3bc266 --- /dev/null +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/_index.scss @@ -0,0 +1 @@ +@forward 'indigo'; diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss deleted file mode 100644 index 5b40ea2cc97..00000000000 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/bootstrap.scss +++ /dev/null @@ -1,23 +0,0 @@ -@use 'igniteui-theming/sass/bem' as *; -@use 'igniteui-theming/sass/themes' as *; -@use 'igniteui-theming/sass/typography' as *; -@use '../light/themes' as *; - -$theme: $bootstrap; - -@include b(igx-avatar) { - @container style(--theme: bootstrap) { - &::after { - position: absolute; - content: ''; - width: 100%; - height: 100%; - border-radius: inherit; - opacity: 0.5; - } - - &:focus::after { - box-shadow: 0 0 0 rem(3px) var-get($bootstrap, 'background'); - } - } -} diff --git a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss index 3bf8fd6da57..2be391a2a26 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/shared/indigo.scss @@ -1,9 +1,11 @@ @use 'igniteui-theming/sass/bem' as *; -@include b(igx-avatar) { +@layer indigo { @container style(--theme: indigo) { - igx-icon { - --ig-size: 1; + @include b(igx-avatar) { + igx-icon { + --ig-size: 1; + } } } } diff --git a/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts b/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts index d8a48f13780..d6dc48ac7d3 100644 --- a/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts +++ b/projects/igniteui-angular/src/lib/checkbox/checkbox.component.ts @@ -16,7 +16,6 @@ import { inject, DestroyRef, Inject, - OnInit } from '@angular/core'; import { ControlValueAccessor, NgControl, Validators } from '@angular/forms'; import { IgxRippleDirective } from '../directives/ripple/ripple.directive'; @@ -25,8 +24,6 @@ import { EditorProvider, EDITOR_PROVIDER } from '../core/edit-provider'; import { noop, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { IgxTheme, THEME_TOKEN, ThemeToken } from '../services/theme/theme.token'; -import { ThemeService, ThemedComponent } from '../services/theme/theme.service'; -import themes from './themes/index'; export const LabelPosition = /*@__PURE__*/mkenum({ BEFORE: 'before', @@ -73,7 +70,7 @@ let nextId = 0; templateUrl: 'checkbox.component.html', imports: [IgxRippleDirective] }) -export class IgxCheckboxComponent implements EditorProvider, OnInit, AfterViewInit, ControlValueAccessor { +export class IgxCheckboxComponent implements EditorProvider, AfterViewInit, ControlValueAccessor { /** * An event that is emitted after the checkbox state is changed. @@ -477,7 +474,6 @@ export class IgxCheckboxComponent implements EditorProvider, OnInit, AfterViewIn * @hidden */ private _onTouchedCallback: () => void = noop; - public themeService = inject(ThemeService); /** * @hidden @@ -533,11 +529,6 @@ export class IgxCheckboxComponent implements EditorProvider, OnInit, AfterViewIn } } - /** @hidden @internal */ - public ngOnInit() { - this.themeService.adoptStyles(IgxCheckboxComponent, themes); - } - /** * @hidden * @internal diff --git a/projects/igniteui-angular/src/lib/checkbox/themes/index.ts b/projects/igniteui-angular/src/lib/checkbox/themes/index.ts deleted file mode 100644 index 6510b676ffb..00000000000 --- a/projects/igniteui-angular/src/lib/checkbox/themes/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import base from './base.css'; -import material from './shared/material.css'; -import bootstrap from './shared/bootstrap.css'; -import fluent from './shared/fluent.css'; -import indigo from './shared/indigo.css'; - -import lightMaterial from './light/material.css'; -import lightBootstrap from './light/bootstrap.css'; -import lightFluent from './light/fluent.css'; -import lightIndigo from './light/indigo.css'; - -import darkMaterial from './dark/material.css'; -import darkBootstrap from './dark/bootstrap.css'; -import darkFluent from './dark/fluent.css'; -import darkIndigo from './dark/indigo.css'; - -export default { - base: base.css, - shared: { - material: material.css, - bootstrap: bootstrap.css, - fluent: fluent.css, - indigo: indigo.css - }, - light: { - material: lightMaterial.css, - bootstrap: lightBootstrap.css, - fluent: lightFluent.css, - indigo: lightIndigo.css - }, - dark: { - material: darkMaterial.css, - bootstrap: darkBootstrap.css, - fluent: darkFluent.css, - indigo: darkIndigo.css - } -} diff --git a/projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss b/projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss new file mode 100644 index 00000000000..dc6d8fb0587 --- /dev/null +++ b/projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss @@ -0,0 +1,37 @@ +@use 'sass:map'; +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/themes' as *; +@forward 'igniteui-theming/sass/themes'; +@forward 'igniteui-theming/sass/bem'; + +/// Includes a block element (@see block) for a specific component, theme, and variant. +/// @access private +/// @group bem +/// @param {String} $component - The class selector of the component. +/// @param {String} $theme - The target theme - material, bootstrap, fluent, indigo. +/// @param {String} $variant - The target variant - light, dark. +/// @requires {mixin} b +/// @example scss +@mixin themed-block($component, $theme, $variant) { + @container style(--theme: #{"" + $theme}) and style(--ig-theme-variant: #{$variant}) { + @include b($component) { + @content; + } + } +} + +/// Includes CSS variables for all themes given a map of tokens. +/// @access private +/// @param {String} $component - The class selector of the component. +/// @param {Map} $tokens - The resolved component schemas/tokens for each theme. +/// @param {String} $variant - The target variant - light, dark. +/// @requires {mixin} themed-block +/// @example scss +@mixin themes($component, $tokens, $variant) { + @each $theme in ('material', 'bootstrap', 'fluent', 'indigo') { + @include themed-block($component, $theme, $variant) { + $_t: map.get($tokens, $theme); + @include css-vars-from-theme($_t, $component); + } + } +} diff --git a/projects/igniteui-angular/src/lib/icon/icon.component.ts b/projects/igniteui-angular/src/lib/icon/icon.component.ts index 928424fa13a..dbd531ce68a 100644 --- a/projects/igniteui-angular/src/lib/icon/icon.component.ts +++ b/projects/igniteui-angular/src/lib/icon/icon.component.ts @@ -14,7 +14,6 @@ import type { IconReference } from "./types"; import { filter, takeUntil } from "rxjs/operators"; import { Subject } from "rxjs"; import { SafeHtml } from "@angular/platform-browser"; -import { NgIf, NgTemplateOutlet } from "@angular/common"; /** * Icon provides a way to include material icons to markup @@ -41,7 +40,6 @@ import { NgIf, NgTemplateOutlet } from "@angular/common"; @Component({ selector: "igx-icon", templateUrl: "icon.component.html", - imports: [NgTemplateOutlet, NgIf] }) export class IgxIconComponent implements OnInit, OnChanges, OnDestroy { private _iconRef: IconReference; diff --git a/projects/igniteui-angular/src/lib/services/theme/theme.service.ts b/projects/igniteui-angular/src/lib/services/theme/theme.service.ts deleted file mode 100644 index c200f48ebbb..00000000000 --- a/projects/igniteui-angular/src/lib/services/theme/theme.service.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { ElementRef, inject, Injectable } from "@angular/core"; -import { THEME_TOKEN, ThemeToken, IgxTheme } from "igniteui-angular"; - -export interface ThemedComponent { - elementRef: ElementRef; - themeService: ThemeService; -} - -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export type Themes = { - base: string; - shared?: { - [K in IgxTheme]?: string; - }; - light: { - [K in IgxTheme]?: string; - }; - dark: { - [K in IgxTheme]?: string; - }; -}; - -@Injectable({ - providedIn: "root", -}) -export class ThemeService { - /** - * Sets the theme of the component. - * Allowed values of type IgxTheme. - */ - private themeToken: ThemeToken = inject(THEME_TOKEN); - private componentThemes = new WeakMap(); - - public adoptStyles(componentInstance: Function, themes: Themes) { - let componentStyles = this.componentThemes.get(componentInstance); - - if (!componentStyles) { - componentStyles = new CSSStyleSheet(); - this.componentThemes.set(componentInstance, componentStyles); - document.adoptedStyleSheets = [...document.adoptedStyleSheets, componentStyles]; - } - - componentStyles.replaceSync( - Array.from(this.composeStyleSheet(themes).cssRules) - .map(rules => rules.cssText) - .join('\n') - ); - } - - private composeStyleSheet(themes: Themes) { - const sheet = new CSSStyleSheet(); - - sheet.insertRule(`@layer base {${themes.base}}`); - - for (const theme of ['indigo', 'material', 'bootstrap', 'fluent']) { - if (themes.shared[theme]) { - sheet.insertRule(`@layer ${theme} {${themes.shared[theme]}}`); - } - - sheet.insertRule(`@layer theme {${themes[this.themeToken.variant][theme]}`); - } - - return sheet; - } -} diff --git a/scripts/projects/igniteui-angular/src/lib/avatar/avatar.component.css b/scripts/projects/igniteui-angular/src/lib/avatar/avatar.component.css new file mode 100644 index 00000000000..b632e49d74c --- /dev/null +++ b/scripts/projects/igniteui-angular/src/lib/avatar/avatar.component.css @@ -0,0 +1,3 @@ +@layer base{.igx-avatar{--is-large: clamp(0, (var(--component-size, 1) + 1) - var(--ig-size-large, 3), 1);--is-medium: min( clamp(0, (var(--component-size, 1) + 1) - var(--ig-size-medium, 2), 1), clamp(0, var(--ig-size-large, 3) - var(--component-size, 1), 1) );--is-small: clamp(0, var(--ig-size-medium) - var(--component-size, 1), 1);--component-size: var(--ig-size, var(--default-size));position:relative;display:inline-flex;justify-content:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;color:var(--color);background:var(--background);vertical-align:middle;outline-style:none;flex-shrink:0;width:var(--size);height:var(--size)}.igx-avatar igx-icon{--component-size: 3;color:var(--icon-color)}.igx-avatar::after{box-shadow:none;transition:box-shadow .15s cubic-bezier(0.455, 0.03, 0.515, 0.955)}.igx-avatar__image{width:100%;height:100%;border-radius:inherit;background-size:cover;background-repeat:no-repeat;background-position:center}.igx-avatar--circle{border-radius:calc(var(--size)/2)}.igx-avatar--rounded{border-radius:var(--border-radius)}.igx-avatar--initials{text-transform:uppercase;font-size:calc(var(--size)/2);line-height:calc(var(--size)/2)}}@layer indigo{@container style(--theme: indigo){.igx-avatar igx-icon{--ig-size: 1}}}@container style(--theme: material) and style(--ig-theme-variant: light){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-400) h s l/1));--color: var(--igx-avatar-color, hsl(from var(--ig-gray-800) h s l/1));--icon-color: var(--igx-avatar-icon-color, hsl(from var(--ig-gray-800) h s l/1));--border-radius: var(--igx-avatar-border-radius, 0.5rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(5.5rem, -1 * 5.5rem), var(--is-medium, 1) * max(4rem, -1 * 4rem), var(--is-small, 1) * max(2.5rem, -1 * 2.5rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: bootstrap) and style(--ig-theme-variant: light){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-400) h s l/1));--color: var(--igx-avatar-color, hsl(from var(--ig-gray-800) h s l/1));--icon-color: var(--igx-avatar-icon-color, hsl(from var(--ig-gray-800) h s l/1));--border-radius: var(--igx-avatar-border-radius, 0.25rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(5.5rem, -1 * 5.5rem), var(--is-medium, 1) * max(4rem, -1 * 4rem), var(--is-small, 1) * max(2.5rem, -1 * 2.5rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: fluent) and style(--ig-theme-variant: light){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-400) h s l/1));--color: var(--igx-avatar-color, hsl(from var(--ig-gray-800) h s l/1));--icon-color: var(--igx-avatar-icon-color, hsl(from var(--ig-gray-800) h s l/1));--border-radius: var(--igx-avatar-border-radius, 0.5rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(5.5rem, -1 * 5.5rem), var(--is-medium, 1) * max(4rem, -1 * 4rem), var(--is-small, 1) * max(2.5rem, -1 * 2.5rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: indigo) and style(--ig-theme-variant: light){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-300) h s l/1));--color: var(--igx-avatar-color, hsl(from var(--ig-gray-700) h s l/1));--icon-color: var(--igx-avatar-icon-color, hsl(from var(--ig-gray-600) h s l/1));--border-radius: var(--igx-avatar-border-radius, 0.25rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(2.25rem, -1 * 2.25rem), var(--is-medium, 1) * max(1.75rem, -1 * 1.75rem), var(--is-small, 1) * max(1.25rem, -1 * 1.25rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: material) and style(--ig-theme-variant: dark){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-400) h s l/1));--color: var(--igx-avatar-color, hsl(from var(--ig-gray-800) h s l/1));--icon-color: var(--igx-avatar-icon-color, hsl(from var(--ig-gray-800) h s l/1));--border-radius: var(--igx-avatar-border-radius, 0.5rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(5.5rem, -1 * 5.5rem), var(--is-medium, 1) * max(4rem, -1 * 4rem), var(--is-small, 1) * max(2.5rem, -1 * 2.5rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: bootstrap) and style(--ig-theme-variant: dark){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-400) h s l/1));--color: var(--igx-avatar-color, hsl(from var(--ig-gray-800) h s l/1));--icon-color: var(--igx-avatar-icon-color, hsl(from var(--ig-gray-800) h s l/1));--border-radius: var(--igx-avatar-border-radius, 0.25rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(5.5rem, -1 * 5.5rem), var(--is-medium, 1) * max(4rem, -1 * 4rem), var(--is-small, 1) * max(2.5rem, -1 * 2.5rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: fluent) and style(--ig-theme-variant: dark){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-400) h s l/1));--color: var(--igx-avatar-color, hsl(from var(--ig-gray-800) h s l/1));--icon-color: var(--igx-avatar-icon-color, hsl(from var(--ig-gray-800) h s l/1));--border-radius: var(--igx-avatar-border-radius, 0.5rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(5.5rem, -1 * 5.5rem), var(--is-medium, 1) * max(4rem, -1 * 4rem), var(--is-small, 1) * max(2.5rem, -1 * 2.5rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: indigo) and style(--ig-theme-variant: dark){.igx-avatar{--background: var(--igx-avatar-background, hsl(from var(--ig-gray-300) h s l/1));--color: var(--igx-avatar-color, color-mix(in oklch, var(--ig-gray-300-contrast) 100%, transparent));--icon-color: var(--igx-avatar-icon-color, color-mix(in oklch, var(--ig-gray-300-contrast) 100%, transparent));--border-radius: var(--igx-avatar-border-radius, 0.25rem);--size: var(--igx-avatar-size, max(var(--is-large, 1) * max(2.25rem, -1 * 2.25rem), var(--is-medium, 1) * max(1.75rem, -1 * 1.75rem), var(--is-small, 1) * max(1.25rem, -1 * 1.25rem)));--default-size: var(--igx-avatar-default-size, 1)}}@container style(--theme: material) and style(--ig-theme-variant: dark){.igx-avatar__image{display:none}} + +/*# sourceMappingURL=mapsprojects/igniteui-angular/src/lib/avatar/avatar.component.css.map */ \ No newline at end of file diff --git a/scripts/sass.mjs b/scripts/sass.mjs index 1c93b226538..babd6c2eb9d 100644 --- a/scripts/sass.mjs +++ b/scripts/sass.mjs @@ -7,7 +7,7 @@ import { resolve } from 'node:path'; import { mkdirSync as makeDir } from 'fs'; import fsExtra from 'fs-extra'; import { fileURLToPath } from 'url'; -import { writeFile, readFile } from 'fs/promises'; +import { writeFile } from 'fs/promises'; import report from './report.mjs'; const THEMES = { @@ -26,11 +26,12 @@ const THEMES = { }; const STYLES = { - SRC: 'projects/igniteui-angular/src/lib/**/*.scss', + SRC: 'projects/igniteui-angular/src/lib/**/*.component.scss', + DIST: './', IGNORE: '!projects/igniteui-angular/src/lib/core/styles/**/*.scss', CONFIG: { style: 'compressed', - loadPaths: ['node_modules'], + loadPaths: ['node_modules', 'projects/igniteui-angular/src/lib/core/'], sourceMap: true, sourceMapEmbed: true, }, @@ -38,7 +39,7 @@ const STYLES = { const { copySync } = fsExtra; const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const DEST_DIR = path.join.bind(null, path.resolve(__dirname, THEMES.DIST)); +const DEST_DIR = path.join.bind(null, resolve(__dirname, THEMES.DIST)); const stripComments = () => { return { @@ -59,18 +60,9 @@ const postProcessor = postcss([ stripComments, ]); -const _template = await readFile( - resolve(process.argv[1], '../styles.tmpl'), - 'utf8' -); const _postProcessor = postcss([autoprefixer, stripComments]); -export function fromTemplate(content) { - return _template.replace(/<%\s*content\s*%>/, content); -} -async function createFile(fileName, content) { - const outputFile = DEST_DIR(fileName); - +async function createFile(outputFile, content) { makeDir(path.dirname(outputFile), { recursive: true }); await writeFile(outputFile, content, 'utf-8'); } @@ -103,11 +95,8 @@ async function _buildThemes() { outCss = outCss + '\n'.repeat(2) + sourceMapComment; - await createFile(fileName, outCss); - await createFile( - `maps/${fileName}.map`, - JSON.stringify(result.sourceMap) - ); + const outputFile = DEST_DIR(fileName); + await createFile(outputFile, outCss); }) ); } catch (err) { @@ -119,8 +108,7 @@ async function _buildThemes() { await compiler.dispose(); } -export async function buildComponents(isProduction = false) { - const start = performance.now(); +export async function buildComponentStyles() { const [compiler, paths] = await Promise.all([ sass.initAsyncCompiler(), globby([STYLES.SRC, STYLES.IGNORE]), @@ -129,11 +117,27 @@ export async function buildComponents(isProduction = false) { try { await Promise.all( paths.map(async (path) => { - writeFile( - path.replace(/\.scss$/, '.css.ts'), - fromTemplate(await compileSass(path, compiler, STYLES.CONFIG)), - 'utf-8' - ); + const result = await compiler.compileAsync(path, STYLES.CONFIG); + const fileName = path + .replace(/\.scss$/, '.css') + .replace(STYLES.SRC, ''); + + const sm = JSON.stringify(result.sourceMap); + const smBase64 = (Buffer.from(sm, 'utf8') || '').toString('base64'); + const sourceMapComment = + '/*# sourceMappingURL=data:application/json;charset=utf-8;base64,' + + smBase64 + + ' */'; + + let outCss = postProcessor.process(result.css).css; + + if (outCss.charCodeAt(0) === 0xfeff) { + outCss = outCss.substring(1); + } + + outCss = outCss + '\n'.repeat(2) + sourceMapComment; + + await createFile(fileName, outCss); }) ); } catch (err) { @@ -143,6 +147,12 @@ export async function buildComponents(isProduction = false) { } await compiler.dispose(); +} + +export async function buildComponents(isProduction = false) { + const start = performance.now(); + + await buildComponentStyles(); if (!isProduction) { report.success( diff --git a/scripts/styles.tmpl b/scripts/styles.tmpl deleted file mode 100644 index 7864a0b50dd..00000000000 --- a/scripts/styles.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -export default { - css: `<% content %>` -} diff --git a/scripts/watch-styles.mjs b/scripts/watch-styles.mjs index 5221e7a23c8..ea197c98513 100644 --- a/scripts/watch-styles.mjs +++ b/scripts/watch-styles.mjs @@ -2,7 +2,8 @@ import { writeFile } from 'node:fs/promises'; import watch from 'node-watch'; import * as sass from 'sass-embedded'; import report from './report.mjs'; -import { compileSass, fromTemplate } from './sass.mjs'; +import { buildComponentStyles } from './sass.mjs'; +import { globby } from 'globby'; const watchOptions = { recursive: true, @@ -26,18 +27,7 @@ const watcher = watch( updating = true; try { - await writeFile( - path.replace(/\.scss$/, '.css.ts'), - fromTemplate( - await compileSass(path, compiler, { - style: 'compressed', - loadPaths: ['node_modules'], - sourceMap: true, - sourceMapEmbed: true, - }) - ), - 'utf8' - ); + await buildComponentStyles(); } catch (err) { report.error(err); } From 83e7bbd6fa07c4a81a2ccadc473a996cf35c6ba9 Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Fri, 24 Jan 2025 10:29:02 +0200 Subject: [PATCH 07/10] refactor(styles): add themed component styles to a layer --- .../src/lib/core/styles/themes/_standalone.scss | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss b/projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss index dc6d8fb0587..56ca9f3e96e 100644 --- a/projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss +++ b/projects/igniteui-angular/src/lib/core/styles/themes/_standalone.scss @@ -13,9 +13,11 @@ /// @requires {mixin} b /// @example scss @mixin themed-block($component, $theme, $variant) { - @container style(--theme: #{"" + $theme}) and style(--ig-theme-variant: #{$variant}) { - @include b($component) { - @content; + @layer #{$theme} { + @container style(--ig-theme: #{"" + $theme}) and style(--ig-theme-variant: #{$variant}) { + @include b($component) { + @content; + } } } } From b99884e9e3c3a535f364fbbca7218133f2a01486 Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Fri, 24 Jan 2025 11:19:22 +0200 Subject: [PATCH 08/10] demos(theme): update --- src/styles/_demo-theme.scss | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/src/styles/_demo-theme.scss b/src/styles/_demo-theme.scss index 20c3d2251ea..589769d769e 100644 --- a/src/styles/_demo-theme.scss +++ b/src/styles/_demo-theme.scss @@ -18,44 +18,20 @@ body { $schema: $schema, ); -.bootstrap-avatar { - @include palette($light-bootstrap-palette); +.indigo { + --ig-theme-variant: dark; - @include css-vars(avatar-theme( - $schema: $light-bootstrap-schema, - )); + @include palette($dark-indigo-palette); } -.material-avatar { - @include palette($light-material-palette); - - @include css-vars(avatar-theme( - $schema: $light-material-schema, - )); -} - -.custom-palette { - @include palette(palette( - $primary: green, - $secondary: green, - $surface: white, - $info: #1377d5, - $success: #4eb862, - $warn: #faa419, - $error: #ff134a, - $variant: 'material', - )); +.indigo-avatar { + @include css-vars(avatar-theme($schema: $dark-indigo-schema)); } .dock { @include css-vars(dock-manager-theme()); } -.custom-avatar { - --color: blue; - outline-color: blue; -} - .nav-header { @if $variant == 'light' { @include nav-logo('../assets/images/rsrcs/igniteui-logo-light-bg'); From 5e2372c4e8cd73c52486d9de3574139d577cd313 Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Fri, 24 Jan 2025 11:34:27 +0200 Subject: [PATCH 09/10] refactor(avatar): update base theme --- .../src/lib/avatar/themes/_base.scss | 46 +++++-------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/projects/igniteui-angular/src/lib/avatar/themes/_base.scss b/projects/igniteui-angular/src/lib/avatar/themes/_base.scss index a5a74695d3e..82a97cd6682 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/_base.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/_base.scss @@ -6,7 +6,7 @@ $theme: $material; @layer base { - %igx-avatar-display { + @include b(igx-avatar) { @include sizable(); --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); @@ -34,50 +34,28 @@ $theme: $material; box-shadow: none; transition: box-shadow 0.15s $ease-in-out-quad; } - } - - %igx-avatar-image { - width: 100%; - height: 100%; - border-radius: inherit; - background-size: cover; - background-repeat: no-repeat; - background-position: center; - } - - %igx-avatar--circle { - border-radius: calc(#{var-get($theme, 'size')} / 2); - } - - %igx-avatar--rounded { - border-radius: var-get($theme, 'border-radius'); - } - - %igx-avatar--initials { - text-transform: uppercase; - font-size: calc(#{var-get($theme, 'size')} / 2); - line-height: calc(#{var-get($theme, 'size')} / 2); - } - - @include b(igx-avatar) { - // @include css-vars-from-theme($base, 'igx-avatar'); - - @extend %igx-avatar-display; @include e(image) { - @extend %igx-avatar-image; + width: 100%; + height: 100%; + border-radius: inherit; + background-size: cover; + background-repeat: no-repeat; + background-position: center; } @include m(circle) { - @extend %igx-avatar--circle; + border-radius: calc(#{var-get($theme, 'size')} / 2); } @include m(rounded) { - @extend %igx-avatar--rounded; + border-radius: var-get($theme, 'border-radius'); } @include m(initials) { - @extend %igx-avatar--initials; + text-transform: uppercase; + font-size: calc(#{var-get($theme, 'size')} / 2); + line-height: calc(#{var-get($theme, 'size')} / 2); } } } From 444c21f406991c68f804a86e0c87ef329d4f8caf Mon Sep 17 00:00:00 2001 From: Simeon Simeonoff Date: Fri, 24 Jan 2025 11:42:48 +0200 Subject: [PATCH 10/10] fix(avatar): icon size --- projects/igniteui-angular/src/lib/avatar/themes/_base.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/igniteui-angular/src/lib/avatar/themes/_base.scss b/projects/igniteui-angular/src/lib/avatar/themes/_base.scss index 82a97cd6682..f230c09826e 100644 --- a/projects/igniteui-angular/src/lib/avatar/themes/_base.scss +++ b/projects/igniteui-angular/src/lib/avatar/themes/_base.scss @@ -25,7 +25,7 @@ $theme: $material; height: var-get($theme, 'size'); igx-icon { - --component-size: 3; + --ig-size: 3; color: var-get($theme, 'icon-color'); }