{"id":22643127,"url":"https://github.com/tonylapoche/themeswitch-angular-material","last_synced_at":"2026-05-07T13:40:49.955Z","repository":{"id":244030272,"uuid":"814083123","full_name":"TonyLaPoche/themeSwitch-angular-material","owner":"TonyLaPoche","description":"🎨 Un dépôt Angular démontrant le changement dynamique entre thèmes clair et sombre avec Angular Material. Idéal pour ajouter une touche de magie à vos applications ! 🧙‍♂️","archived":false,"fork":false,"pushed_at":"2024-06-20T09:04:13.000Z","size":158,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-03T17:01:42.282Z","etag":null,"topics":["angular","angular-material","sass","theming"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TonyLaPoche.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-12T09:58:06.000Z","updated_at":"2024-11-13T16:36:28.000Z","dependencies_parsed_at":"2024-06-20T22:12:51.912Z","dependency_job_id":"9620dd0f-c116-4c45-a70f-7597f073512f","html_url":"https://github.com/TonyLaPoche/themeSwitch-angular-material","commit_stats":null,"previous_names":["tonylapoche/themeswitch-angular-material"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyLaPoche%2FthemeSwitch-angular-material","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyLaPoche%2FthemeSwitch-angular-material/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyLaPoche%2FthemeSwitch-angular-material/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyLaPoche%2FthemeSwitch-angular-material/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TonyLaPoche","download_url":"https://codeload.github.com/TonyLaPoche/themeSwitch-angular-material/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246145013,"owners_count":20730493,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-material","sass","theming"],"created_at":"2024-12-09T05:09:25.185Z","updated_at":"2026-05-07T13:40:49.921Z","avatar_url":"https://github.com/TonyLaPoche.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎨 Angular Theme Magic with Angular Material 🧙‍♂️\n\nBienvenue dans Theme-App, le repo le plus stylé du monde Angular ! Ici, nous allons apprendre à jongler avec les thèmes comme un pro, grâce à Angular et Angular Material. Accroche-toi bien, ça va être fun ! 😄\n\n## 🛠️ Étape 1 : Cloner le repository\n\nD'abord, on commence par cloner ce magnifique repo. Parce que tout commence par un clone, non ?\n\n```bash copy\ngit clone https://github.com/ton-utilisateur/theme-app.git\n```\n\nEnsuite, déplacez-vous dans le répertoire fraîchement cloné. On ne veut pas rester dehors, n'est-ce pas ?\n\n```bash copy\ncd ./theme-app\n```\n\n## 📦 Étape 2 : Installer les dépendances\n\nMaintenant, il est temps de remplir notre app avec toutes ses dépendances. C'est comme garnir une pizza, mais pour les geeks.\n\n## 📡 Étape 3 : Vérifier Angular\n\nAssurez-vous d'avoir Angular installé dans votre environnement. Un petit `ng -v` vous le dira.\n\n```bash copy\nng -v\n```\n\n## 🚀 Étape 4 : Lancer le serveur\n\nC'est le moment de faire chauffer la machine et de lancer notre app. Le serveur va s'ouvrir automatiquement comme par magie !\n\n```bash copy\nng serve --open\n```\n\n## 🎨 Étape 5 : Jouer avec les thèmes\n\nMaintenant, amusez-vous en cliquant sur le bouton \"Light\" ou \"Dark\" dans le header pour voir les thèmes changer. Oui, c'est aussi simple que ça !\n\n## 🔍 Étape 6 : Analyser le comportement des thèmes\n\nPour les plus curieux (et on sait que vous l'êtes 😉), ouvrez la console de votre navigateur et observez ce qui se passe dans le \u003chead\u003e du HTML lorsque vous cliquez sur les boutons de thème. Vous allez découvrir que...\n\n### 🕵️‍♂️ Résultat :\nUn fichier link stylesheet change dynamiquement grâce au lazyloading ! C'est super efficace et pertinent pour gérer plusieurs thèmes. 🎉\n\n## 🎉🧩 Analysons le code\n\n### 🗂️ Le fichier angular.json\n\nDans `angular.json`, nous avons une section sans l'attribut `styles` :\n\n```bash copy\n\"styles\": [\n  \"src/styles.scss\",\n  {\n    \"input\": \"src/sass/themes/_dark-theme.scss\",\n    \"bundleName\": \"dark-theme\",\n    \"inject\": false\n  },\n  {\n    \"input\": \"src/sass/themes/_light-theme.scss\",\n    \"bundleName\": \"light-theme\",\n    \"inject\": false\n  }\n]\n```\n\n#### 🤓 Que se passe-t-il ici ?\n- **\"src/styles.scss\"** : Le fichier de styles global de l'application.\n- **\"input\"** : Le chemin vers les fichiers de thème.\n- **\"bundleName\"** : Le nom du bundle pour chaque thème.\n- **\"inject\"** : Indique à Angular de ne pas injecter ces styles automatiquement. On le fera nous-mêmes, comme des grands !\n\n#### 📂 Le dossier Sass\nDans le dossier Sass, il y a un sous-dossier theme contenant 4 fichiers :\n\n - _**_brand-palettes.scss**_\n - _**_dark-theme.scss**_\n - _**_light-theme.scss**_\n - _**_utils.scss**_\n\n#### 🤔 Pourquoi ces noms de fichiers commencent-ils par un tiret du bas \\`_` ?\n\nLe tiret du bas \\`_` indique que ce sont des fichiers partiels. Ils ne seront pas compilés directement en CSS mais seront inclus dans d'autres fichiers Sass. C'est un peu comme des pièces de Lego, prêtes à être assemblées !\n\n## 🖌️ Exploration des palettes de couleurs\n\n### 🎨 Le fichier _**brand-palette.scss**_\n\nIci, nous avons deux palettes de couleurs contenant chacune 20 déclinaisons. Ces palettes sont utilisées pour le thème d'Angular Material. Préparez-vous à un festival de couleurs !\n\n```scss copy\n@use '@angular/material' as mat;\n\n$brand-green-palette: (\n  50: #e0f2e9,\n  100: #b3e2c8,\n  200: #80d0a4,\n  300: #4dbe80,\n  400: #26b065,\n  500: #00954a,\n  600: #008a44,\n  700: #007c3c,\n  800: #006f34,\n  900: #005a27,\n  contrast: (\n    50: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    100: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    200: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    300: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    400: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    500: white,\n    600: white,\n    700: white,\n    800: white,\n    900: white,\n  )\n);\n\n$brand-brown-palette: (\n  50: #f4e4e1,\n  100: #e2bcb5,\n  200: #cf9286,\n  300: #bb6957,\n  400: #aa4934,\n  500: #99290b,\n  600: #8a2409,\n  700: #781e07,\n  800: #671906,\n  900: #4b1303,\n  contrast: (\n    50: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    100: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    200: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    300: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    400: mat.get-color-from-palette(mat.$blue-gray-palette, 900),\n    500: white,\n    600: white,\n    700: white,\n    800: white,\n    900: white,\n  )\n);\n```\n\n### 🌒 Le fichier dark-theme.scss\nCe fichier implémente le thème sombre. Préparez-vous à entrer dans le côté obscur !\n\n```scss copy\n@use '@angular/material' as mat;\n@use './brand-palette';\n@use \"./utils\";\n\n@include mat.core();\n\n$theme-color-config: (\n  primary: mat.define-palette(brand-palette.$brand-brown-palette, 700, 400, 900),\n  accent: mat.define-palette(brand-palette.$brand-green-palette, 700, 400, 900),\n);\n\n$brand-theme: mat.define-dark-theme(utils.with-core-config($theme-color-config));\n\nhtml {\n  @include mat.all-component-themes($brand-theme);\n}\n```\n\n### 🌞 Le fichier light-theme.scss\n\nEt voici le thème clair, pour ceux qui préfèrent la lumière !\n```scss copy\n@use '@angular/material' as mat;\n@use './brand-palette';\n@use \"./utils\";\n\n$theme-color-config: (\n        primary: mat.define-palette(brand-palette.$brand-green-palette, 700, 400, 900),\n        accent: mat.define-palette(brand-palette.$brand-brown-palette, 700, 400, 900),\n);\n\n$brand-theme: mat.define-light-theme(utils.with-core-config($theme-color-config));\n\nhtml {\n  @include mat.all-component-themes($brand-theme);\n}\n```\n\n### 🛠️ Le fichier utils.scss\n\nCe fichier contient des méthodes utiles pour notre configuration de thème. C'est le héros méconnu de notre app !\n\n```scss copy\n@use '@angular/material' as mat;\n@use 'sass:map';\n\n@function with-core-config($color-config) {\n  @return (\n          color: $color-config,\n          typography: mat.define-typography-config(\n                  $font-family: 'Roboto',\n          ),\n          density: 0\n  );\n}\n\n@function patch-color-config($theme, $colors-to-patch: ()) {\n  @return map.deep-merge($theme, (\n          color: $colors-to-patch\n  ));\n}\n```\n#### 🧐 Explications détaillées :\n- **with-core-config :** Cette fonction crée une configuration de thème de base en incluant les couleurs, la typographie et la densité. C'est comme préparer une base solide avant de peindre une maison.\n- **patch-color-config :** Cette fonction permet de fusionner les configurations de couleur personnalisées avec le thème existant. Parfait pour ajouter une touche finale sans tout casser !\n\n## ⚙️ Le Service de Changement de Thème\n\nDans notre dossier app/core/services, vous trouverez un sous-dossier intitulé themes contenant le fichier switch-themes.service.ts. Ce service est le cerveau derrière le changement de thème dynamique. Voici le code en question :\n\n```ts copy\nimport { Injectable } from '@angular/core';\nimport { fromEvent, map, merge, Observable, shareReplay, startWith, Subject, tap } from \"rxjs\";\n\nexport type Theme = 'light' | 'dark';\nexport type ThemeUrl = `${Theme}-theme.css`;\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class ThemesService {\n  #preferenceQuery = matchMedia('(prefers-color-scheme: light)');\n\n  #themeSwitcher$ = new Subject\u003cTheme\u003e();\n  #userEnvThemePreference = fromEvent\u003cMediaQueryList\u003e(this.#preferenceQuery, 'change').pipe(\n    startWith(this.#preferenceQuery),\n    map(resolvePreferredTheme),\n  );\n\n  theme$: Observable\u003cTheme\u003e = merge(this.#userEnvThemePreference, this.#themeSwitcher$).pipe(\n    tap(theme =\u003e loadTheme(getThemeLinkElement(), theme)),\n    shareReplay()\n  );\n\n  switchTheme(theme: Theme): void {\n    localStorage.setItem('theme', theme);\n    this.#themeSwitcher$.next(theme);\n  }\n}\n\nfunction resolvePreferredTheme(query: MediaQueryList): Theme {\n  const preferredTheme = localStorage.getItem('theme') as Theme;\n  if (preferredTheme) {\n    return preferredTheme;\n  }\n  return query.matches ? 'light' : 'dark';\n}\n\nfunction getThemeLinkElement() {\n  const existingLinkEl = document.head.querySelector\u003cHTMLLinkElement\u003e('#app-theme');\n  if (existingLinkEl) {\n    return existingLinkEl;\n  }\n  const linkEl = document.createElement('link');\n  linkEl.rel = 'stylesheet';\n  linkEl.id = 'app-theme';\n  document.head.querySelector('link[rel=\"stylesheet\"]:last-of-type')?.after(linkEl);\n  return linkEl;\n}\n\nfunction loadTheme(linkEl: HTMLLinkElement, theme: Theme) {\n  linkEl.href = resolveThemeUrl(theme);\n}\n\nfunction resolveThemeUrl(theme: Theme): ThemeUrl {\n  return `${theme}-theme.css`;\n}\n\n```\n\n### 🕵️ Explication détaillée\n\n#### Importations et Types :\n\n - Nous importons plusieurs fonctions et classes depuis `rxjs` pour gérer les événements et les observables.\n - Nous définissons deux types : `Theme`, qui peut être soit 'light' soit 'dark', et `ThemeUrl`, qui est une chaîne de caractères correspondant à `${Theme}-theme.css`.\n\n#### Classe ThemesService :\n\n - **Injection** : Le service est injectable et sera disponible dans toute l'application `(providedIn: 'root')`.\n - **Préférence de l'utilisateur** : Utilise `matchMedia` pour vérifier la préférence de thème de l'utilisateur (clair ou sombre).\n - **Sujet de changement de thème** : Un `Subject` pour émettre des changements de thème.\n - **Préférence de thème environnemental de l'utilisateur** : Utilise `fromEvent` pour écouter les changements de préférence de thème et démarre avec la préférence actuelle.\n - **Observable `theme$`** : Combine les préférences de thème de l'utilisateur et les changements de thème émis par l'application, puis charge dynamiquement le thème approprié. `shareReplay` permet de réutiliser la dernière valeur émise pour les nouveaux abonnés.\n\n#### Méthodes du Service :\n\n - **switchTheme** : Change le thème en stockant la préférence dans `localStorage` et en émettant le nouveau thème.\n   \n#### Fonctions Utilitaires :\n\n - **resolvePreferredTheme** : Détermine le thème préféré à partir de localStorage ou de la préférence du navigateur.\n - **getThemeLinkElement** : Récupère ou crée un élément `\u003clink\u003e` pour appliquer le thème.\n - **loadTheme** : Charge le fichier CSS correspondant au thème choisi.\n - **resolveThemeUrl** : Génère l'URL du fichier CSS du thème.\n\n---\n\n### **🎉 Ça y est ! Vous savez tout sur la magie du changement de thème dans notre application Angular. Grâce à ce service, vous pouvez basculer entre un thème clair et un thème sombre en toute simplicité.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonylapoche%2Fthemeswitch-angular-material","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftonylapoche%2Fthemeswitch-angular-material","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonylapoche%2Fthemeswitch-angular-material/lists"}