浏览代码

Merge branch 'feature/v8-4102_rename_vuetify_colors' into develop

Olivier Massot 2 年之前
父节点
当前提交
dd0072b8f3
共有 51 个文件被更改,包括 512 次插入219 次删除
  1. 9 2
      assets/css/global.scss
  2. 1 0
      assets/css/import.scss
  3. 0 7
      assets/css/settings.scss
  4. 54 0
      assets/css/theme.scss
  5. 8 0
      assets/css/vuetify.scss
  6. 1 2
      components/Layout/AlertBar/Cotisation.vue
  7. 2 2
      components/Layout/AlertBar/Env.vue
  8. 2 2
      components/Layout/AlertBar/SuperAdmin.vue
  9. 1 1
      components/Layout/AlertBar/SwitchUser.vue
  10. 2 2
      components/Layout/AlertBar/SwitchYear.vue
  11. 7 4
      components/Layout/BannerTop.vue
  12. 9 9
      components/Layout/Dialog.vue
  13. 7 6
      components/Layout/Header.vue
  14. 1 1
      components/Layout/Header/HomeBtn.vue
  15. 12 10
      components/Layout/Header/Menu.vue
  16. 7 11
      components/Layout/Header/Notification.vue
  17. 3 3
      components/Layout/Header/UniversalCreation/CreateButton.vue
  18. 3 3
      components/Layout/Header/UniversalCreation/GenerateCardsSteps.vue
  19. 3 3
      components/Layout/Header/UniversalCreation/TypeCard.vue
  20. 13 10
      components/Layout/MainMenu.vue
  21. 11 9
      components/Layout/SubHeader/ActivityYear.vue
  22. 7 0
      components/Layout/SubHeader/Breadcrumbs.vue
  23. 5 5
      components/Layout/SubHeader/DataTiming.vue
  24. 3 8
      components/Layout/SubHeader/DataTimingRange.vue
  25. 2 6
      components/Layout/SubHeader/PersonnalizedList.vue
  26. 11 5
      components/Layout/Subheader.vue
  27. 26 0
      components/Layout/ThemeSwitcher.vue
  28. 2 2
      components/Ui/Button/Delete.vue
  29. 1 1
      components/Ui/Button/Submit.vue
  30. 1 1
      components/Ui/Collection.vue
  31. 9 7
      components/Ui/ExpansionPanel.vue
  32. 4 4
      components/Ui/Form.vue
  33. 10 8
      components/Ui/Image.vue
  34. 1 1
      components/Ui/Input/DatePicker.vue
  35. 9 9
      components/Ui/Input/Image.vue
  36. 2 2
      components/Ui/Input/Phone.vue
  37. 2 2
      components/Ui/Input/Text.vue
  38. 2 2
      components/Ui/Input/TextArea.vue
  39. 2 2
      components/Ui/SystemBar.vue
  40. 2 2
      components/Ui/Xeditable/Text.vue
  41. 144 0
      config/theme.ts
  42. 72 0
      doc/colors.md
  43. 9 22
      layouts/default.vue
  44. 4 0
      nuxt.config.ts
  45. 6 6
      pages/organization/index.vue
  46. 1 1
      pages/poc.vue
  47. 3 3
      pages/poc/display.vue
  48. 5 3
      pages/poc/index.vue
  49. 3 3
      pages/poc/new.vue
  50. 4 4
      pages/subscription.vue
  51. 4 23
      plugins/vuetify.ts

+ 9 - 2
assets/css/global.scss

@@ -1,3 +1,10 @@
+/**
+ * Ces règles s'appliqueront à toutes les pages, layouts et components de l'application
+ *
+ * Quand c'est possible, préférer les règles par page, layout ou composant
+ */
+// TODO: voir si certaines de ces règles ne devraient pas être rapatriées dans des pages, layouts, components
+
 header .v-toolbar__content {
   padding-right: 0;
 }
@@ -15,7 +22,7 @@ header .v-toolbar__content {
 }
 
 .v-application a {
-  color: rgb(var(--v-theme-ot-green))
+  color: rgb(var(--v-theme-primary))
 }
 
 .v-menu__content {
@@ -38,7 +45,7 @@ header .v-toolbar__content {
   .v-list{
     .v-list-item{
       border-bottom: 1px solid;
-      border-bottom-color: rgb(var(--v-theme-ot-border-menu));
+      border-bottom-color: rgb(var(--v-theme-neutral));
     }
   }
 }

+ 1 - 0
assets/css/import.scss

@@ -0,0 +1 @@
+// TODO: utilité?

+ 0 - 7
assets/css/settings.scss

@@ -1,7 +0,0 @@
-@use 'vuetify/settings' with (
-  //$btn-text-transform: none,
-
-  //$breadcrumbs-padding: 5px 5px,
-  //$breadcrumbs-even-child-padding: 0 10px,
-  $body-font-family: 'Source Sans Pro' !important,
-);

+ 54 - 0
assets/css/theme.scss

@@ -0,0 +1,54 @@
+
+.theme-primary {
+  background-color: rgb(var(--v-theme-primary)) !important;
+  color: rgb(var(--v-theme-on-primary)) !important;
+}
+
+.theme-secondary {
+  background-color: rgb(var(--v-theme-secondary)) !important;
+  color: rgb(var(--v-theme-on-secondary)) !important;
+}
+
+.theme-neutral-strong {
+  background-color: rgb(var(--v-theme-neutral-strong)) !important;
+  color: rgb(var(--v-theme-on-neutral-strong)) !important;
+}
+
+.theme-neutral {
+  background-color: rgb(var(--v-theme-neutral)) !important;
+  color: rgb(var(--v-theme-on-neutral)) !important;
+
+  a {
+    color: rgb(var(--v-theme-on-neutral--clickable)) !important;
+  }
+}
+
+.theme-neutral-soft {
+  background-color: rgb(var(--v-theme-neutral-soft)) !important;
+  color: rgb(var(--v-theme-on-neutral-soft)) !important;
+}
+
+.theme-danger {
+  background-color: rgb(var(--v-theme-danger)) !important;
+  color: rgb(var(--v-theme-on-danger)) !important;
+}
+
+.theme-success {
+  background-color: rgb(var(--v-theme-success)) !important;
+  color: rgb(var(--v-theme-on-success)) !important;
+}
+
+.theme-warning {
+  background-color: rgb(var(--v-theme-warning)) !important;
+  color: rgb(var(--v-theme-on-warning)) !important;
+}
+
+.theme-info {
+  background-color: rgb(var(--v-theme-info)) !important;
+  color: rgb(var(--v-theme-on-info)) !important;
+}
+
+.theme-x-create-btn {
+  background-color: rgb(var(--v-theme-x-create-btn)) !important;
+  color: rgb(var(--v-theme-on-x-create-btn)) !important;
+}

+ 8 - 0
assets/css/vuetify.scss

@@ -0,0 +1,8 @@
+/**
+ * Redéfinit les variables globales vuetify
+ *
+ * @see https://next.vuetifyjs.com/en/features/sass-variables/#basic-usage
+ */
+
+@use 'vuetify/settings' with (
+);

+ 1 - 2
components/Layout/AlertBar/Cotisation.vue

@@ -12,8 +12,7 @@ Barre d'alerte qui s'affiche pour donner l'état de la cotisation
         :text="$t(alert.text)"
         icon="fas fa-info-circle"
         :on-click="alert.callback"
-        background-color="ot-info"
-        text-color="ot-white"
+        class="theme-info"
     />
   </main>
 </template>

+ 2 - 2
components/Layout/AlertBar/Env.vue

@@ -9,8 +9,8 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur n'est pas dans un environneme
       v-if="show"
       :text="$t('not_production_environment', { env: env })"
       icon="fas fa-exclamation-triangle"
-      background-color="ot-warning"
-      text-color="ot-white" />
+      class="theme-warning"
+  />
 </template>
 
 <script setup lang="ts">

+ 2 - 2
components/Layout/AlertBar/SuperAdmin.vue

@@ -6,11 +6,11 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur est un super admin en mode sw
 
 <template>
   <!-- TODO : fonctionnement à valider -->
-  <UiSystemBar v-if="show" text-color="ot-danger">
+  <UiSystemBar v-if="show" text-color="danger">
     <v-icon small>fas fa-exclamation-triangle</v-icon>
     <span>{{ $t('super_admin_switch_account') }}</span>
 
-    <a v-if="url" :href="url" class="text-ot-black text-decoration-none">
+    <a v-if="url" :href="url" class="text-neutral-strong text-decoration-none">
       <strong>{{ $t('click_here') }}</strong>
     </a>
   </UiSystemBar>

+ 1 - 1
components/Layout/AlertBar/SwitchUser.vue

@@ -6,7 +6,7 @@ Barre qui s'affiche lorsque l'utilisateur possède un compte multi user
 
 <template>
   <!-- TODO : fonctionnement à valider -->
-  <UiSystemBar v-if="show" text-color="ot-info">
+  <UiSystemBar v-if="show" text-color="info">
     <v-icon small icon="fas fa-info-circle" />
     <span v-html="$t('multi_account_alert', { fullname })" />
     <v-icon class="ml-1" small icon="fa fa-users" />

+ 2 - 2
components/Layout/AlertBar/SwitchYear.vue

@@ -6,11 +6,11 @@ Barre d'alerte qui s'affiche lorsque l'utilisateur n'est pas sur l'année couran
 
 <template>
   <!-- TODO : fonctionnement à valider -->
-  <UiSystemBar v-if="show" text-color="ot-warning">
+  <UiSystemBar v-if="show" text-color="warning">
     {{$t('not_current_year')}}
 
     <a @click="resetYear">
-      <strong class="text-ot-black">
+      <strong class="text-neutral-strong">
         {{$t('not_current_year_reset')}}
       </strong>
     </a>

+ 7 - 4
components/Layout/BannerTop.vue

@@ -1,14 +1,17 @@
-<!-- Troisième bandeau en partant du haut, contenant entre autre le numéro SIRET de l'organisation -->
+<!--
+Troisième bandeau en partant du haut, contenant entre autre le numéro SIRET de l'organisation
+-->
+<!-- TODO: voir si possible de trouver un nom plus spécifique -->
 
 <template>
   <v-row justify="center" align="center" class="bannerTopForm">
-    <v-col cols="3" class="ot-dark_grey ot-white--text">
+    <v-col cols="3" class="theme-neutral-strong">
       <slot name="block1" />
     </v-col>
-    <v-col cols="6" class="ot-white ot-grey--text">
+    <v-col cols="6" class="theme-neutral">
       <slot name="block2" />
     </v-col>
-    <v-col cols="3" class="ot-light_grey ot-grey--text">
+    <v-col cols="3" class="theme-neutral-soft">
       <slot name="block3" />
     </v-col>
   </v-row>

+ 9 - 9
components/Layout/Dialog.vue

@@ -7,14 +7,14 @@
     :content-class="contentClass"
   >
     <v-card class="d-flex flex-row">
-      <div class="dialog-type flex-column justify-center d-none d-sm-flex">
+      <div :class="'dialog-type flex-column justify-center d-none d-sm-flex theme-' + theme">
         <h3 class="d-flex">
           <slot name="dialogType" />
         </h3>
       </div>
 
       <div class="dialog-container d-flex flex-column flex-grow-1">
-        <v-card-title class="dialog-title">
+        <v-card-title class="dialog-title ">
           <slot name="dialogTitle" />
         </v-card-title>
 
@@ -34,8 +34,6 @@
 </template>
 
 <script setup lang="ts">
-import {useDisplay} from "vuetify";
-
 const props = defineProps({
   show: {
     type: Boolean,
@@ -44,20 +42,22 @@ const props = defineProps({
   contentClass: {
     type: String,
     required: false
+  },
+  theme: {
+    type: String,
+    required: false,
+    default: 'primary',
   }
 })
 </script>
 
 <style lang="scss" scoped>
   .dialog-title {
-    background: #e6e6e6;
     padding-left: 40px;
     font-weight: normal;
   }
 
   .dialog-type {
-    background: rgb(var(--v-theme-ot-green, #00AD8E));
-    color: #fff;
     width: 50px;
     min-height: 400px;
     padding: 25px 10px;
@@ -77,13 +77,13 @@ const props = defineProps({
 
   .modal-level-alert {
     .dialog-type{
-      background: rgb(var(--v-theme-ot-danger, #f56954));
+      background: rgb(var(--v-theme-danger, #f56954));
     }
   }
 
   .modal-level-warning {
     .dialog-type{
-      background: rgb(var(--v-theme-ot-warning, #f39c12));
+      background: rgb(var(--v-theme-warning, #f39c12));
     }
   }
 </style>

+ 7 - 6
components/Layout/Header.vue

@@ -7,19 +7,20 @@ Contient entre autres le nom de l'organisation, l'accès à l'aide et aux préf
   <v-app-bar
       order="0"
       density="compact"
-      class="bg-ot-green text-ot-white"
+      class="theme-primary"
   >
     <template #prepend>
       <v-app-bar-nav-icon
           v-if="hasMainMenu"
           :icon="isMainMenuOpened ? 'mdi:mdi-menu-open' : 'mdi:mdi-menu'"
-          class="text-ot-white"
           @click="toggleMainMenu"
       />
     </template>
 
     <v-toolbar-title v-if="mdAndUp" v-text="title"/>
 
+    <LayoutThemeSwitcher v-if="false" /> <!-- En attente validation PO -->
+
     <LayoutHeaderUniversalCreationCreateButton v-if="showUniversalButton" />
 
     <LayoutHeaderHomeBtn />
@@ -34,15 +35,15 @@ Contient entre autres le nom de l'organisation, l'accès à l'aide et aux préf
 
     <LayoutHeaderMenu name="Configuration" />
 
-    <LayoutHeaderMenu name="Account" />
+    <LayoutHeaderMenu name="Account" color="on-primary" icon="fas fa-sun" />
 
     <a
         :href="runtimeConfig.supportUrl"
-        class="text-body pa-3 ml-2 bg-ot-dark-grey text-ot-white text-decoration-none"
+        class="text-body pa-3 ml-2 theme-secondary text-decoration-none"
         target="_blank"
     >
       <span class="d-none d-sm-none d-md-flex">{{ $t('help_access') }}</span>
-      <v-icon icon="fas fa-question-circle" class="d-sm-flex d-md-none" color="white" />
+      <v-icon icon="fas fa-question-circle" class="d-sm-flex d-md-none" color="on-secondary" />
     </a>
   </v-app-bar>
 </template>
@@ -52,7 +53,7 @@ Contient entre autres le nom de l'organisation, l'accès à l'aide et aux préf
 import {computed, ComputedRef} from "@vue/reactivity";
 import {useMenu} from "~/composables/layout/useMenu";
 import {useAbility} from "@casl/vue";
-import { useDisplay } from 'vuetify'
+import {useDisplay, useTheme} from 'vuetify'
 import {useOrganizationProfileStore} from "~/stores/organizationProfile";
 
 const organizationProfile = useOrganizationProfileStore()

+ 1 - 1
components/Layout/Header/HomeBtn.vue

@@ -5,7 +5,7 @@
         icon="fas fa-home"
         size="small"
         :href="homeUrl"
-        class="ml-2 text-ot-white"
+        class="ml-2 on-primary"
     />
     <v-tooltip :activator="btn" :text="$t('welcome')" location="bottom" />
   </div>

+ 12 - 10
components/Layout/Header/Menu.vue

@@ -26,7 +26,7 @@ header principal (configuration, paramètres du compte...)
       <v-icon
           v-else
           :icon="menu.icon.name"
-          class="text-ot-white"
+          class="on-primary"
       />
     </v-btn>
 
@@ -42,7 +42,7 @@ header principal (configuration, paramètres du compte...)
         @update:modelValue="onStateUpdated"
     >
       <v-card>
-        <v-card-title class="ot-header-menu text-body-2 font-weight-bold">
+        <v-card-title class="theme-neutral text-body-2 font-weight-bold">
           {{$t(menu.label)}}
         </v-card-title>
 
@@ -57,15 +57,14 @@ header principal (configuration, paramètres du compte...)
                 <v-list-item-title>
                     <span v-if="child.icon">
                       <v-avatar v-if="menu.icon.avatarId || child.icon.avatarByDefault" size="30">
-                        <UiImage :id="child.icon.avatarId" :defaultImage="child.icon.avatarByDefault" :width="30"></UiImage>
+                        <UiImage :id="child.icon.avatarId" :defaultImage="child.icon.avatarByDefault" :width="30" />
                       </v-avatar>
-                      <v-icon v-else class="text-ot-white" size="small">
+                      <v-icon v-else class="on-primary" size="small">
                         {{ child.icon.name }}
                       </v-icon>
                     </span>
 
-                  <span v-if="translateLabel">{{$t(child.label)}}</span>
-                  <span v-else>{{child.label}}</span>
+                  <span>{{ translateLabel ? $t(child.label) : child.label }}</span>
                 </v-list-item-title>
               </v-list-item>
 
@@ -73,7 +72,7 @@ header principal (configuration, paramètres du compte...)
           </v-list>
         </v-card-text>
 
-        <v-card-actions v-if="menu.actions.length > 0" class="ma-0 pa-0 actions">
+        <v-card-actions v-if="menu.actions.length > 0" class="ma-0 pa-0 theme-primary">
           <template v-for="(action, index) in menu.actions" :key="index">
             <v-list-item
                 :id="action.label"
@@ -120,8 +119,11 @@ const btn = ref(null)
 </script>
 
 <style scoped lang="scss">
-  .actions {
-    background: rgb(var(--v-theme-ot-green));
-    color: white;
+  .v-list {
+    padding: 0;
+  }
+
+  .header-menu .v-list .v-list-item:last-child {
+    border-bottom: none;
   }
 </style>

+ 7 - 11
components/Layout/Header/Notification.vue

@@ -6,12 +6,12 @@
       size="small"
   >
     <v-badge
-        color="orange"
+        color="warning"
         offset-x="-4"
         offset-y="17"
         :model-value="unreadNotification.length > 0"
         :content="unreadNotification.length">
-      <v-icon class="text-ot-white">
+      <v-icon class="on-primary">
         fa fa-bell
       </v-icon>
     </v-badge>
@@ -26,7 +26,7 @@
       v-model="isOpen"
   >
     <v-card max-width="400">
-      <v-card-title class="ot-header-menu text-body-2 font-weight-bold">
+      <v-card-title class="bg-neutral text-body-2 font-weight-bold">
         {{ $t('notification') }}
       </v-card-title>
 
@@ -69,21 +69,21 @@
         >
           <v-progress-circular
             indeterminate
-            color="grey lighten-1"
+            color="neutral"
           />
         </v-row>
       </v-card-text>
 
       <v-card-actions class="ma-0 pa-0">
         <v-list-item
-          id="all_notifications"
           :key="$t('all_notification')"
           :href="notificationUrl"
           router
+          class="theme-primary"
           style="width: 100%; height: 52px;"
         >
           <v-list-item-title
-              class="text-body-2 text-ot-white"
+              class="text-body-2"
               v-text="$t('all_notification')"
           />
         </v-list-item>
@@ -253,14 +253,10 @@ const notificationUrl = UrlUtils.join(runtimeConfig.baseUrlAdminLegacy, 'notific
 </script>
 
 <style scoped lang="scss">
-  #all_notifications{
-    background: rgb(var(--v-theme-ot-green, white));
-    color: white;
-  }
   .list_item{
     white-space: normal;
   }
   .unread{
-    background: #ecf0f5;
+    background: rgb(var(--v-theme-global-neutral-soft, white));
   }
 </style>

+ 3 - 3
components/Layout/Header/UniversalCreation/CreateButton.vue

@@ -6,7 +6,7 @@ bouton Créer
   <main>
     <v-btn
       elevation="2"
-      class="bg-ot-warning text-ot-white"
+      class="theme-x-create-btn"
       @click="showDialog=true"
     >
       {{ $t('create') }}
@@ -31,7 +31,7 @@ bouton Créer
       <template #dialogBtn>
         <div class="text-center">
           <v-btn
-            class="bg-ot-super-light-grey text-ot-black"
+            class="theme-neutral-soft"
             @click="showDialog=false; step=1; type='home'"
           >
             {{ $t('cancel') }}
@@ -39,7 +39,7 @@ bouton Créer
 
           <v-btn
             v-if="step > 1"
-            class="bg-ot-super-light-grey text-ot-black"
+            class="theme-neutral-soft"
             @click="step=1; type='home'"
           >
             {{ $t('previous') }}

+ 3 - 3
components/Layout/Header/UniversalCreation/GenerateCardsSteps.vue

@@ -206,14 +206,14 @@
     .icon{
       i{
         font-size: 50px;
-        color: var(--v-theme-ot-grey, #777777);
+        color: var(--v-theme-neutral-strong, #777777);
       }
     }
     .infos-container{
       padding: 15px 0;
       h4{
         font-size: 15px;
-        color: var(--v-theme-ot-green, #00AD8E);
+        color: var(--v-theme-primary, #00AD8E);
         font-weight: bold;
         margin-bottom: 6px;
       }
@@ -221,7 +221,7 @@
         font-size: 13px;
         padding: 0;
         margin: 0;
-        color: #767676;
+        color: var(--v-theme-neutral);
       }
     }
     &>div{

+ 3 - 3
components/Layout/Header/UniversalCreation/TypeCard.vue

@@ -60,7 +60,7 @@
   .icon {
     i{
       font-size: 50px;
-      color: rgb(var(--v-theme-ot-grey, #777777));
+      color: rgb(var(--v-theme-neutral-strong, #777777));
     }
   }
 
@@ -69,7 +69,7 @@
 
     h4 {
       font-size: 15px;
-      color: rgb(var(--v-theme-ot-green, #00AD8E));
+      color: rgb(var(--v-theme-primary, #00AD8E));
       font-weight: bold;
       margin-bottom: 6px;
     }
@@ -77,7 +77,7 @@
       font-size: 13px;
       padding: 0;
       margin: 0;
-      color: #767676;
+      color: var(--v-theme-neutral);
     }
   }
 

+ 13 - 10
components/Layout/MainMenu.vue

@@ -8,7 +8,7 @@ Prend en paramètre une liste de ItemMenu et les met en forme
       v-model="displayMenu"
       :rail="isRail"
       :disable-resize-watcher="true"
-      class="bg-ot-dark-grey text-ot-menu-color main-menu"
+      class="theme-secondary main-menu"
   >
     <template #prepend>
       <slot name="title"></slot>
@@ -19,6 +19,7 @@ Prend en paramètre une liste de ItemMenu et les met en forme
         active-class="active"
         class="left-menu"
     >
+      <!-- TODO: que se passe-t-il si le menu ne comprend qu'un seul MenuItem? -->
       <div v-for="(item, i) in menu.children" :key="i">
 
         <!-- Cas 1 : l'item n'a pas d'enfants, c'est un lien -->
@@ -29,7 +30,6 @@ Prend en paramètre une liste de ItemMenu et les met en forme
           :href="!isInternalLink(item) ? item.to : undefined"
           :to="isInternalLink(item) ? item.to : undefined"
           exact
-          class="text-ot-menu-color"
           height="48px"
         ></v-list-item>
 
@@ -38,7 +38,6 @@ Prend en paramètre une liste de ItemMenu et les met en forme
           v-else
           expand-icon="fas fa-angle-right"
           collapse-icon="fas fa-angle-down"
-          class="text-ot-menu-color"
           v-model="item.expanded"
         >
           <template #activator="{ props }">
@@ -46,7 +45,7 @@ Prend en paramètre une liste de ItemMenu et les met en forme
                 v-bind="props"
                 :prepend-icon="item.icon.name"
                 :title="$t(item.label)"
-                class="text-ot-menu-color"
+                class="theme-secondary"
                 height="48px"
             ></v-list-item>
           </template>
@@ -60,7 +59,7 @@ Prend en paramètre une liste de ItemMenu et les met en forme
             :to="isInternalLink(child) ? child.to : undefined"
             exact
             height="48px"
-            class="text-ot-white"
+            class="theme-secondary-alt"
           ></v-list-item>
         </v-list-group>
       </div>
@@ -123,7 +122,7 @@ onUnmounted(() => {
   :deep(.v-icon),
   {
     font-size: 14px;
-    color: rgb(var(--v-theme-ot-menu-color));
+    color: rgb(var(--v-theme-on-secondary), 0.7);
   }
 
   .v-list-item__prepend {
@@ -150,7 +149,7 @@ onUnmounted(() => {
   .v-list-group--no-action > .v-list-group__header,
   .v-list-item
   {
-    border-left:3px solid rgb(var(--v-theme-ot-dark-grey));
+    border-left:3px solid rgb(var(--v-theme-secondary));
     height: 48px;
   }
 
@@ -158,12 +157,16 @@ onUnmounted(() => {
   .v-list-item.active,
   :deep(.v-list-group__items .v-list-item)
   {
-    border-left: 3px solid rgb(var(--v-theme-ot-green));
-    background: rgb(var(--v-theme-ot-dark-grey-hover));
+    border-left: 3px solid rgb(var(--v-theme-primary));
+    background-color: rgb(var(--v-theme-secondary-alt));
   }
 
   :deep(.v-list-group__items .v-list-item-title) {
-    color: rgb(var(--v-theme-ot-white));
+    color: rgb(var(--v-theme-on-secondary-alt));
+  }
+
+  :deep(.v-list-group__items .v-icon) {
+    color: rgb(var(--v-theme-on-secondary-alt));
   }
 
   :deep(.v-list-item .v-icon) {

+ 11 - 9
components/Layout/SubHeader/ActivityYear.vue

@@ -1,21 +1,23 @@
 <template>
   <main class="d-flex flex-row align-center">
-    <span v-show="mdAndUp" class="mr-2 font-weight-bold">{{ $t(label) }} : </span>
+    <span v-show="mdAndUp" class="mr-2 font-weight-bold on-neutral">{{ $t(label) }} : </span>
 
     <UiXeditableText
-      class="activity-year-input bg-ot-light-grey"
+      class="activity-year-input"
       type="number"
       :data="currentActivityYear"
       @update="setActivityYear"
     >
       <template #xeditable.read="{inputValue}">
-        <v-icon aria-hidden="false" size="small" class="text-ot-green mr-1" icon="fas fa-edit" />
-        <strong class="text-ot-green">
-          {{ inputValue }}
-          <span v-if="yearPlusOne">
-            / {{ parseInt(inputValue) + 1 }}
-          </span>
-        </strong>
+        <div class="d-flex align-center on-neutral--clickable">
+          <v-icon aria-hidden="false" size="small" class="mr-1" icon="fas fa-edit" />
+          <strong >
+            {{ inputValue }}
+            <span v-if="yearPlusOne">
+              / {{ parseInt(inputValue) + 1 }}
+            </span>
+          </strong>
+        </div>
       </template>
     </UiXeditableText>
   </main>

+ 7 - 0
components/Layout/SubHeader/Breadcrumbs.vue

@@ -43,3 +43,10 @@ const items: ComputedRef<Array<AnyJson>> = computed(() => {
   return crumbs
 })
 </script>
+
+<style scoped lang="scss">
+:deep(a.v-breadcrumbs-item--disabled) {
+  color: rgb(var(--v-theme-on-neutral)) !important;
+  opacity: 1 !important;
+}
+</style>

+ 5 - 5
components/Layout/SubHeader/DataTiming.vue

@@ -1,6 +1,6 @@
 <template>
   <main class="d-flex align-baseline">
-    <span v-show="mdAndUp" class="mr-2 text-ot-dark_grey font-weight-bold">{{ $t('display_data') }} : </span>
+    <span v-show="mdAndUp" class="mr-2 font-weight-bold on-neutral">{{ $t('display_data') }} : </span>
 
     <v-btn-toggle
       ref="toggle"
@@ -11,14 +11,14 @@
       divider
       border
       :rounded="true"
-      class="bg-ot-light-grey toggle-btn"
+      class="toggle-btn"
       @update:modelValue="onUpdate"
     >
       <v-btn
           v-for="choice in historicalChoices"
           :value="choice"
           max-height="25"
-          :class="'font-weight-normal text-caption' + (historicalValue.includes(choice) ? ' btn-selected' : '')"
+          :class="'font-weight-normal text-caption ' + (historicalValue.includes(choice) ? 'theme-primary' : 'theme-neutral-soft')"
       >
         <!-- TODO: on ne devrait pas avoir besoin du if et de la classe 'btn-selected' dans v-btn, mais à l'heure
          qu'il est, le component ne fonctionne pas comme attendu. A revoir quand vuetify 3 sera plus stable -->
@@ -37,7 +37,7 @@ import {useDisplay, useTheme} from "vuetify";
 import Access from "~/models/Access/Access";
 
 // TODO: en v3.0.5, pas de solution documentée pour renseigner directement la couleur dans le template, à revoir
-const color = useTheme().current.value.colors['ot-green']
+const color = useTheme().current.value.colors['primary']
 
 const { setDirty } = useFormStore()
 const accessProfileStore = useAccessProfileStore()
@@ -86,6 +86,6 @@ const onUpdate = async (newValue: Array<string>) => {
   }
 
   .v-btn.btn-selected {
-    background-color: rgb(var(--v-theme-ot-green)) !important;
+    background-color: rgb(var(--v-theme-primary)) !important;
   }
 </style>

+ 3 - 8
components/Layout/SubHeader/DataTimingRange.vue

@@ -1,7 +1,7 @@
 <template>
   <main class="d-flex align-center data-timing-range">
     <div v-if="show" class="d-flex align-center" style="max-height: 100%">
-      <span class="pl-2 mr-2 font-weight-bold">
+      <span class="pl-2 mr-2 font-weight-bold on-neutral">
         {{ $t('period_choose') }}
       </span>
 
@@ -18,13 +18,13 @@
 
     <v-btn
         ref="btn"
-        class="time-btn ml-1"
+        class="time-btn ml-1 theme-neutral-soft"
         height="22" min-height="22" max-height="22"
         width="25" min-width="25" max-width="25"
         elevation="0"
         @click="show = !show"
     >
-      <v-icon icon="fas fa-history" color="ot-grey" class="font-weight-normal" style="font-size: 14px;" />
+      <v-icon icon="fas fa-history" class="font-weight-normal" style="font-size: 14px;" />
     </v-btn>
 
     <v-tooltip location="bottom" :activator="btn">
@@ -91,14 +91,9 @@ if (accessProfileStore.historical.dateStart || accessProfileStore.historical.dat
 </script>
 
 <style scoped lang="scss">
-.v-btn--active .v-icon {
-  color: #FFF !important;
-}
-
 .time-btn {
   border-width: 1px 1px 1px 0;
   border-style: solid;
-  border-color: rgba(0, 0, 0, 0.12) !important;
 }
 
 .data-timing-range {

+ 2 - 6
components/Layout/SubHeader/PersonnalizedList.vue

@@ -1,12 +1,8 @@
 <template>
   <main>
-    <span
-        ref="btn"
-        class="text-ot-green"
-        style="cursor: pointer;"
-    >
+    <a ref="btn">
       {{ $t('my_list') }}
-    </span>
+    </a>
 
     <v-menu
         :activator="btn"

+ 11 - 5
components/Layout/Subheader.vue

@@ -6,8 +6,10 @@ Contient entre autres le breadcrumb, les commandes de changement d'année et les
 <template>
   <main>
     <v-card
-      class="d-md-flex bg-ot-light-grey text-body-2 px-2"
+      id="subheader"
+      class="d-md-flex theme-neutral text-body-2 px-2"
       flat
+      rounded="0"
     >
       <LayoutSubHeaderBreadcrumbs v-if="mdAndUp" class="mr-auto d-flex" />
 
@@ -50,12 +52,16 @@ Contient entre autres le breadcrumb, les commandes de changement d'année et les
 <style scoped lang="scss">
 
 main {
-  color: rgb(var(--v-theme-ot-grey));
   font-size: 12px;
 }
 
-.v-card {
-  max-height: 33px;
-  background: transparent;
+#subheader {
+  max-height: 36px;
 }
+
+:deep(#subheader .v-card) {
+  max-height: 36px;
+  background-color: transparent !important;
+}
+
 </style>

+ 26 - 0
components/Layout/ThemeSwitcher.vue

@@ -0,0 +1,26 @@
+<template>
+  <v-switch
+      v-model="theme.global.name.value"
+      density="compact"
+      inline
+      false-value="light"
+      false-icon="fas fa-sun"
+      true-value="dark"
+      true-icon="fas fa-moon"
+  />
+</template>
+
+<script setup lang="ts">
+import {useTheme} from "vuetify";
+
+const theme = useTheme()
+</script>
+
+<style scoped lang="scss">
+  .v-switch {
+    min-width: 60px;
+    max-width: 60px;
+    min-height: 40px;
+    max-height: 40px;
+  }
+</style>

+ 2 - 2
components/Ui/Button/Delete.vue

@@ -19,10 +19,10 @@ Bouton Delete avec modale de confirmation de la suppression
         </v-card-text>
       </template>
       <template #dialogBtn>
-        <v-btn class="mr-4 submitBtn ot-grey ot-white--text" @click="closeDialog">
+        <v-btn class="mr-4 submitBtn theme-neutral-strong" @click="closeDialog">
           {{ $t('cancel') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot-danger ot-white--text" @click="deleteItem">
+        <v-btn class="mr-4 submitBtn theme-danger" @click="deleteItem">
           {{ $t('delete') }}
         </v-btn>
       </template>

+ 1 - 1
components/Ui/Button/Submit.vue

@@ -1,5 +1,5 @@
 <template>
-  <v-btn class="mr-4 ot-green ot-white--text" :class="hasOtherActions ? 'pr-0' : ''" @click="submitAction(mainAction)" ref="mainBtn">
+  <v-btn class="mr-4 theme-primary" :class="hasOtherActions ? 'pr-0' : ''" @click="submitAction(mainAction)" ref="mainBtn">
 
     {{ $t(mainAction) }}
 

+ 1 - 1
components/Ui/Collection.vue

@@ -9,7 +9,7 @@
       <slot name="list.item" v-bind="{items}" />
 
       <!-- New button -->
-      <v-btn v-if="newLink" class="ot-white--text ot-green float-right">
+      <v-btn v-if="newLink" class="theme-primary float-right">
         <NuxtLink :to="newLink" class="no-decoration">
           <v-icon>fa-plus-circle</v-icon>
           <span>{{$t('add')}}</span>

+ 9 - 7
components/Ui/ExpansionPanel.vue

@@ -6,9 +6,9 @@ Panneaux déroulants de type "accordéon"
 
 <template>
   <v-expansion-panel :value="title">
-    <v-expansion-panel-title color="ot-light-grey">
+    <v-expansion-panel-title color="neutral">
       <template v-slot:default="{ expanded }">
-        <v-icon class="text-ot-white bg-ot-green icon">
+        <v-icon class="theme-primary icon">
           {{ icon }}
         </v-icon>
         {{ $t(title) }}
@@ -36,20 +36,18 @@ const props = defineProps({
 </script>
 
 <style scoped>
-  .icon{
+  .icon {
     width: 47px;
     height: 47px;
     padding: 10px;
     margin-right: 10px;
     flex: none !important;
   }
-  .v-expansion-panel-header{
+
+  .v-expansion-panel-header {
     padding: 0;
     padding-right: 20px;
   }
-  .v-expansion-panel--active > .v-expansion-panel-header{
-    min-height: 47px;
-  }
 
   .v-expansion-panel-title {
     padding-left: 0;
@@ -59,6 +57,10 @@ const props = defineProps({
     min-height: 47px;
   }
 
+  .v-expansion-panel--active > .v-expansion-panel-title {
+    min-height: 47px !important;
+  }
+
   :deep(.v-expansion-panel-title__icon > .v-icon) {
     font-size: 16px;
   }

+ 4 - 4
components/Ui/Form.vue

@@ -51,7 +51,7 @@ Formulaire générique
       :show="showDialog"
     >
       <template #dialogText>
-        <v-card-title class="text-h5 grey lighten-2">
+        <v-card-title class="text-h5 theme-neutral">
           {{ $t('caution') }}
         </v-card-title>
         <v-card-text>
@@ -60,13 +60,13 @@ Formulaire générique
         </v-card-text>
       </template>
       <template #dialogBtn>
-        <v-btn class="mr-4 submitBtn ot-green ot-white--text" @click="closeDialog">
+        <v-btn class="mr-4 submitBtn theme-primary" @click="closeDialog">
           {{ $t('back_to_form') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot-green ot-white--text" @click="saveAndQuit">
+        <v-btn class="mr-4 submitBtn theme-primary" @click="saveAndQuit">
           {{ $t('save_and_quit') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot-danger ot-white--text" @click="quitForm">
+        <v-btn class="mr-4 submitBtn theme-danger" @click="quitForm">
           {{ $t('quit_form') }}
         </v-btn>
       </template>

+ 10 - 8
components/Ui/Image.vue

@@ -24,7 +24,7 @@ Si la propriété 'upload' est à 'true', propose aussi un input pour uploader u
           >
             <v-progress-circular
               :indeterminate="true"
-              color="grey lighten-1"
+              color="neutral"
             />
           </v-row>
         </template>
@@ -125,10 +125,12 @@ onUnmounted(() => {
   div.image-wrapper {
     display: block;
     position: relative;
-    img{
+
+    img {
       max-width: 100%;
     }
-    .click-action{
+
+    .click-action {
       position: absolute;
       top:0;
       left:0;
@@ -137,13 +139,13 @@ onUnmounted(() => {
       background: transparent;
       opacity: 0;
       transition: all .2s;
-      &:hover{
+      &:hover {
         opacity: 1;
-        background:rgba(0,0,0,0.3);
+        background: rgb(var(--v-theme-neutral-strong));
         cursor: pointer;
       }
-      i{
-        color: #fff;
+      i {
+        color: rgb(var(--v-theme-on-neutral-strong));
         position: absolute;
         top: 50%;
         left: 50%;
@@ -152,7 +154,7 @@ onUnmounted(() => {
         z-index: 1;
         opacity: 1;
         &:hover{
-          color: rgba(#3fb37f, 0.7);
+          color: rgb(var(--v-theme-primary-alt));
         }
       }
     }

+ 1 - 1
components/Ui/Input/DatePicker.vue

@@ -35,7 +35,7 @@ Sélecteur de dates
       <v-date-picker
           v-model="datesParsed"
           :range="range"
-          color="ot-green lighten-1"
+          color="primary lighten-1"
           @input="dateOpen = range && datesParsed.length < 2"
       />
     </v-menu>

+ 9 - 9
components/Ui/Input/Image.vue

@@ -16,7 +16,7 @@ https://norserium.github.io/vue-advanced-cropper/
           >
             <v-progress-circular
               :indeterminate="true"
-              color="grey lighten-1">
+              color="neutral">
             </v-progress-circular>
           </v-row>
 
@@ -46,10 +46,10 @@ https://norserium.github.io/vue-advanced-cropper/
         </div>
       </template>
       <template #dialogBtn>
-        <v-btn class="mr-4 submitBtn ot-grey ot-white--text" @click="$emit('close')">
+        <v-btn class="mr-4 submitBtn theme-neutral-strong" @click="$emit('close')">
           {{ $t('cancel') }}
         </v-btn>
-        <v-btn class="mr-4 submitBtn ot-danger ot-white--text" @click="save">
+        <v-btn class="mr-4 submitBtn theme-danger" @click="save">
           {{ $t('save') }}
         </v-btn>
       </template>
@@ -242,7 +242,7 @@ onUnmounted(() => {
     padding: 20px;
     display: block;
     &__cropper {
-       border: solid 1px #eee;
+       border: solid 1px rgb(var(--v-theme-on-neutral-strong));;
        min-height: 500px;
        max-height: 500px;
      }
@@ -259,10 +259,10 @@ onUnmounted(() => {
       justify-content: center;
       height: 42px;
       width: 42px;
-      background: rgba(#3fb37f, 0.7);
+      background: rgb(var(--v-theme-neutral));
       transition: background 0.5s;
       &:hover {
-        background: #3fb37f;
+        background: rgb(var(--v-theme-primary-alt));
       }
     }
     &__buttons-wrapper {
@@ -273,16 +273,16 @@ onUnmounted(() => {
     &__button {
        border: none;
        outline: solid transparent;
-       color: white;
+       color: rgb(var(--v-theme-on-neutral));
        font-size: 16px;
        padding: 10px 20px;
-       background: #3fb37f;
+       background: rgb(var(--v-theme-neutral));
        cursor: pointer;
        transition: background 0.5s;
        margin: 0 16px;
       &:hover,
       &:focus {
-         background: #38d890;
+         background: rgb(var(--v-theme-primary-alt));
        }
       input {
         display: none;

+ 2 - 2
components/Ui/Input/Phone.vue

@@ -100,8 +100,8 @@ const rules = [
 ]
 </script>
 
-<style>
+<style lang="scss">
 input:read-only{
-  color: #666 !important;
+  color: rgb(var(--v-theme-on-neutral));
 }
 </style>

+ 2 - 2
components/Ui/Input/Text.vue

@@ -123,8 +123,8 @@ const show = ref(false)
 
 </script>
 
-<style scoped>
+<style scoped lang="scss">
   input:read-only{
-    color: #666 !important;
+    color: rgb(var(--v-theme-neutral));
   }
 </style>

+ 2 - 2
components/Ui/Input/TextArea.vue

@@ -66,8 +66,8 @@ const {violation, onChange} = useFieldViolation(props.field, emit)
 
 </script>
 
-<style>
+<style lang="scss">
   input:read-only{
-    color: #666 !important;
+    color: rgb(var(--v-theme-on-neutral));
   }
 </style>

+ 2 - 2
components/Ui/SystemBar.vue

@@ -30,12 +30,12 @@ System bars
     backgroundColor: {
       type: String,
       required: false,
-      default: '#eeeeee'
+      default: 'neutral-soft'
     },
     textColor: {
       type: String,
       required: false,
-      default: '#5f5f5f'
+      default: 'on-neutral-soft'
     },
     onClick: {
       type: Function,

+ 2 - 2
components/Ui/Xeditable/Text.vue

@@ -18,14 +18,14 @@ Utilisé par exemple pour le choix de l'année active
       <v-icon
           icon="fas fa-check"
           aria-hidden="false"
-          class="valid icons text-ot-green"
+          class="valid icons text-primary"
           size="small"
           @click="update"
       />
       <v-icon
           icon="fas fa-times"
           aria-hidden="false"
-          class="cancel icons text-ot-grey"
+          class="cancel icons text-neutral-strong"
           size="small"
           @click="close"
       />

+ 144 - 0
config/theme.ts

@@ -0,0 +1,144 @@
+import { ThemeDefinition } from 'vuetify'
+
+interface Theme {
+    dark: boolean,
+    colors: {
+        /**
+         * @see Cf. doc/colors.md pour le rôle de chaque couleur
+         */
+        // Global
+        'background': string,
+        'on-background': string,
+        'surface': string,
+        'on-surface': string,
+        'primary': string,
+        'on-primary': string,
+        'primary-alt': string,
+        'on-primary-alt': string,
+        'secondary': string,
+        'on-secondary': string,
+        'secondary-alt': string,
+        'on-secondary-alt': string,
+        'neutral-strong': string,
+        'on-neutral-strong': string,
+        'neutral': string,
+        'on-neutral': string,
+        'on-neutral--clickable': string,
+        'neutral-soft': string,
+        'on-neutral-soft': string,
+        'danger': string,
+        'on-danger': string,
+        'success': string,
+        'on-success': string,
+        'warning': string,
+        'on-warning': string,
+        'info': string,
+        'on-info': string,
+
+        // Special cases
+        // TODO: voir ceux dont on peut se passer
+        'x-create-btn': string,
+        'on-x-create-btn': string
+    }
+}
+
+
+export const lightTheme: Theme = {
+    dark: false,
+    colors: {
+        'background': '#ecf0f5',
+        'on-background': '#000000',
+
+        'surface': '#ffffff',
+        'on-surface': '#000000',
+
+        'primary': '#00ad8e',
+        'on-primary': '#ffffff',
+
+        'primary-alt': '#a9e0d6',
+        'on-primary-alt': '#777777',
+
+        'secondary': '#324150',
+        'on-secondary': '#f5f5f5',
+
+        'secondary-alt': '#2c3a48',
+        'on-secondary-alt': '#ffffff',
+
+        'neutral-strong': '#777777',
+        'on-neutral-strong': '#ecf0f5',
+
+        'neutral': '#e6e6e6',
+        'on-neutral': '#666666',
+        'on-neutral--clickable': '#00997d',
+
+        'neutral-soft': '#ecf0f5',
+        'on-neutral-soft': '#464646',
+
+        // Content
+        'danger': '#f56954',
+        'on-danger': '#ffffff',
+
+        'success': '#00a65a',
+        'on-success': '#ffffff',
+
+        'warning': '#f39c12',
+        'on-warning': '#ffffff',
+
+        'info': '#3c8dbc',
+        'on-info': '#ffffff',
+
+        'x-create-btn': '#f39c12',
+        'on-x-create-btn': '#ffffff',
+    }
+}
+
+export const darkTheme: Theme = {
+    dark: true,
+    colors: {
+        'background': '#1a1a1a',
+        'on-background': '#ffffff',
+
+        'surface': '#262626',
+        'on-surface': '#ffffff',
+
+        'primary': '#00ad8e',
+        'on-primary': '#ffffff',
+
+        'primary-alt': '#a9e0d6',
+        'on-primary-alt': '#777777',
+
+        'secondary': '#324150',
+        'on-secondary': '#f5f5f5',
+
+        'secondary-alt': '#2c3a48',
+        'on-secondary-alt': '#ffffff',
+
+        'neutral-strong': '#595959',
+        'on-neutral-strong': '#ecf0f5',
+
+        'neutral': '#324150',
+        'on-neutral': '#cccccc',
+        'on-neutral--clickable': '#a9e0d6',
+
+        'neutral-soft': '#090c11',
+        'on-neutral-soft': '#cccccc',
+
+        // Content
+        'danger': '#f56954',
+        'on-danger': '#ffffff',
+
+        'success': '#00a65a',
+        'on-success': '#ffffff',
+
+        'warning': '#f39c12',
+        'on-warning': '#ffffff',
+
+        'info': '#3c8dbc',
+        'on-info': '#ffffff',
+
+        'x-create-btn': '#f39c12',
+        'on-x-create-btn': '#ffffff',
+    }
+}
+
+

+ 72 - 0
doc/colors.md

@@ -0,0 +1,72 @@
+
+## Définition des couleurs de l'UI
+
+### Thèmes vuetify
+
+> Voir ici: https://next.vuetifyjs.com/en/features/theme/
+
+### Configuration et utilisation
+
+Les couleurs du ou des thèmes sont enregistrées dans `plugins/vuetify.ts`
+
+| Nom            | Usage                                                                                                                                         |
+|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
+| background     | Fond par défaut des contenus                                                                                                                  |
+| surface        | Fond des components                                                                                                                           |
+| primary        | Couleur principale, utilisée pour le header, les boutons submit, les notifications, les liens de type actions dans les menus, les liens, etc. |
+| primary-alt    | Une variante atténuée de la couleur principale, utilisée par exemple pour mettre en surbrillance des éléments au survol                       |
+| secondary      | Couleur secondaire, utilisée pour le menu lateral, le bouton accès aide et pour le fond d'écran de la page de login                           |
+| secondary-alt  | Variante de la couleur secondary, utilisée entre autres pour le fond des liens du menu lateral au survol                                      |
+| neutral-strong | Couleur de fond de certains boutons comme les boutons Annuler, et fond de certains encarts                                                    |
+| neutral        | Couleur de fond du subheader, des en-têtes des accordéons, du calendrier, des datatables, des boutons d'action                                |
+| neutral-soft   | Couleur du fond des pages, fond des notifications non lues...                                                                                 |
+| danger         | Fond des bandeaux et panneaux d'alerte signifiant un risque, couleur du texte de certains contenus décrivant un statut                        |
+| success        | Fond des bandeaux et panneaux d'alerte signifiant un succès, couleur du texte de certains contenus décrivant un statut                        |
+| warning        | Fond des bandeaux et panneaux d'alerte servant d'avertissement                                                                                |
+| info           | Fond des bandeaux et panneaux informatifs                                                                                                     |
+
+Pour chacune de ces couleurs, on définit une ou plusieurs couleurs complémentaires, comme les couleurs `on-[color]` (voir plus bas)
+
+On trouvera aussi des couleurs en `x-[color]`: ce sont des couleurs particulières appliquées à un élément précis. Ces 
+couleurs sont appelées à disparaitre à terme.
+
+### Règles de nommage
+
+On construit le nom d'une variable de couleur de la manière suivante :
+
+`([prefix]-)[name](--[suffix])`
+
+Si la partie 'name' comprend plusieurs mots, on les sépare, eux aussi, par des tirets `-`
+
+
+##### Préfixe (optionnel)
+
+Pour chaque couleur du thème, on définira des couleurs nommées `on-[color]` qui correspondent au "négatif" de la couleur,
+et qui permet de rendre du contenu visible sur un fond de la couleur `color`.
+
+
+##### Suffixe (optionnel)
+
+Un éventuel suffixe pourra aussi permettre de définir des variantes applicable à certains éléments.
+
+Par exemple, une couleur `on-color--clickable` sera une variante de la couleur `on-color` applicable aux éléments 
+cliquables, comme les liens.
+
+
+### Thèmes SCSS
+
+Pour chaque couleur du thème, on a défini des classes css `theme-[color]` qui appliqueront les règles à la fois sur 
+au fond de l'élément et à son contenu.
+
+Ces classes sont définies dans le fichier `assets/css/theme.scss`
+
+> Dans la majorité des cas, appliquer la classe vuetify `bg-[color]` aura le même effet que d'appliquer la classe 
+`theme-[color]`. Mais il peut arriver que certains thèmes définis dans cette application implémentent des règles 
+spéciales pour certains éléments, comme la couleur des liens d'un thème par exemple. 
+C'est pourquoi il vaut mieux utiliser les classes `theme-[color]`.
+
+
+
+
+
+

文件差异内容过多而无法显示
+ 9 - 22
layouts/default.vue


+ 4 - 0
nuxt.config.ts

@@ -66,6 +66,7 @@ export default defineNuxtConfig({
     },
     css: [
         '@/assets/css/global.scss',
+        '@/assets/css/theme.scss',
         '@/assets/css/import.scss'
     ],
     typescript: {
@@ -123,6 +124,9 @@ export default defineNuxtConfig({
             }
         },
     },
+    vuetify: {
+        styles: { configFile: 'src/vuetify.scss' }
+    },
     i18n: {
         langDir: 'lang',
         lazy: true,

+ 6 - 6
pages/organization/index.vue

@@ -180,13 +180,13 @@ Contient toutes les informations sur l'organization courante
 <!--                              </template>-->
 <!--                              <template #card.text>-->
 <!--                                <span v-if="item.email"><strong>{{ $t('email') }}</strong> : {{ item.email }} <br></span>-->
-<!--                                <span v-if="item.emailInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('emailInvalid') }}</strong> : {{ item.emailInvalid }} <br></span>-->
+<!--                                <span v-if="item.emailInvalid" class="danger&#45;&#45;text"><v-icon class="danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('emailInvalid') }}</strong> : {{ item.emailInvalid }} <br></span>-->
 
 <!--                                <span v-if="item.telphone"><strong>{{ $t('telphone') }}</strong> : {{ formatPhoneNumber(item.telphone) }} <br></span>-->
-<!--                                <span v-if="item.telphoneInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('telphoneInvalid') }}</strong> : {{ formatPhoneNumber(item.telphoneInvalid) }} <br></span>-->
+<!--                                <span v-if="item.telphoneInvalid" class="danger&#45;&#45;text"><v-icon class="danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('telphoneInvalid') }}</strong> : {{ formatPhoneNumber(item.telphoneInvalid) }} <br></span>-->
 
 <!--                                <span v-if="item.mobilPhone"><strong>{{ $t('mobilPhone') }}</strong> : {{ formatPhoneNumber(item.mobilPhone) }} <br></span>-->
-<!--                                <span v-if="item.mobilPhoneInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('mobilPhoneInvalid') }}</strong> : {{ formatPhoneNumber(item.mobilPhoneInvalid) }} </span>-->
+<!--                                <span v-if="item.mobilPhoneInvalid" class="danger&#45;&#45;text"><v-icon class="danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('mobilPhoneInvalid') }}</strong> : {{ formatPhoneNumber(item.mobilPhoneInvalid) }} </span>-->
 <!--                              </template>-->
 <!--                            </UiCard>-->
 <!--                          </v-col>-->
@@ -372,7 +372,7 @@ Contient toutes les informations sur l'organization courante
 <!--                    loaderType="text"-->
 <!--                  >-->
 <!--                    <template #list.item="{items}">-->
-<!--                      <h4 class="ot-grey&#45;&#45;text font-weight-regular">{{$t('organizationArticle')}}</h4>-->
+<!--                      <h4 class="neutral-strong&#45;&#45;text font-weight-regular">{{$t('organizationArticle')}}</h4>-->
 <!--                      <UiTemplateDataTable-->
 <!--                        :headers="[-->
 <!--                          { text: $t('title'), value: 'title' },-->
@@ -421,10 +421,10 @@ Contient toutes les informations sur l'organization courante
 <!--                                <span v-if="item.bankName"><strong>{{ $t('bankName') }}</strong> : {{ item.bankName }} <br></span>-->
 
 <!--                                <span v-if="item.bic"><strong>{{ $t('bic') }}</strong> : {{ item.bic }} <br></span>-->
-<!--                                <span v-if="item.bicInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('bicInvalid') }}</strong> : {{ item.bicInvalid }} <br></span>-->
+<!--                                <span v-if="item.bicInvalid" class="danger&#45;&#45;text"><v-icon class="danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('bicInvalid') }}</strong> : {{ item.bicInvalid }} <br></span>-->
 
 <!--                                <span v-if="item.iban"><strong>{{ $t('iban') }}</strong> : {{ item.iban }} <br></span>-->
-<!--                                <span v-if="item.ibanInvalid" class="ot-danger&#45;&#45;text"><v-icon class="ot-danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('ibanInvalid') }}</strong> : {{ item.ibanInvalid }} <br></span>-->
+<!--                                <span v-if="item.ibanInvalid" class="danger&#45;&#45;text"><v-icon class="danger&#45;&#45;text">mdi-alert</v-icon> <strong>{{ $t('ibanInvalid') }}</strong> : {{ item.ibanInvalid }} <br></span>-->
 
 <!--                              </template>-->
 <!--                            </UiCard>-->

+ 1 - 1
pages/poc.vue

@@ -12,6 +12,6 @@
 
 <style scoped lang="scss">
   h1 {
-    color: rgb(var(--v-theme-ot-green))
+    color: rgb(var(--v-theme-primary))
   }
 </style>

+ 3 - 3
pages/poc/display.vue

@@ -32,7 +32,7 @@ const { data: file, pending, refresh } = fetch(File, 1)
 
 <style>
 a {
-  color: blue;
+  color: blue;  /* !color! */
   cursor: pointer;
 }
 a:hover {
@@ -40,7 +40,7 @@ a:hover {
 }
 
 button {
-  border: grey solid 1px;
+  border: grey solid 1px;   /* !color! */
   padding: 5px;
   margin: 5px;
   cursor: pointer;
@@ -49,6 +49,6 @@ button:hover {
   text-decoration: underline;
 }
 button:focus {
-  background-color: lightgrey;
+  background-color: lightgrey;   /* !color! */
 }
 </style>

+ 5 - 3
pages/poc/index.vue

@@ -69,7 +69,7 @@
 
 <style>
 a {
-  color: blue;
+  color: blue;  /* !color! */
   cursor: pointer;
 }
 a:hover {
@@ -77,15 +77,17 @@ a:hover {
 }
 
 button {
-  border: grey solid 1px;
+  border: grey solid 1px;   /* !color! */
   padding: 5px;
   margin: 5px;
   cursor: pointer;
 }
+
 button:hover {
   text-decoration: underline;
 }
+
 button:focus {
-  background-color: lightgrey;
+  background-color: lightgrey;  /* !color! */
 }
 </style>

+ 3 - 3
pages/poc/new.vue

@@ -43,7 +43,7 @@ const cancelAndGoBack = async () => {
 
 <style>
 a {
-  color: blue;
+  color: blue;   /* !color! */
   cursor: pointer;
 }
 a:hover {
@@ -51,7 +51,7 @@ a:hover {
 }
 
 button {
-  border: grey solid 1px;
+  border: grey solid 1px;  /* !color! */
   padding: 5px;
   margin: 5px;
   cursor: pointer;
@@ -60,7 +60,7 @@ button:hover {
   text-decoration: underline;
 }
 button:focus {
-  background-color: lightgrey;
+  background-color: lightgrey;  /* !color! */
 }
 
 form {

+ 4 - 4
pages/subscription.vue

@@ -327,12 +327,12 @@ Page 'Mon abonnement'
 
     .v-col {
       min-width: 260px;
-      border: solid 1px #e0e0e0;
+      border: solid 1px rgb(var(--v-theme-on-primary));
 
       .v-row:nth-child(1) {
-        background: rgb(var(--v-theme-ot-green));
+        background: rgb(var(--v-theme-primary));
         height: 64px;
-        color: white;
+        color: rgb(var(--v-theme-on-primary));
         font-size: 15px;
         font-weight: bold;
       }
@@ -359,7 +359,7 @@ Page 'Mon abonnement'
     .v-row {
       padding: 12px 18px;
       vertical-align: top;
-      border-bottom: solid 1px #e0e0e0;
+      border-bottom: solid 1px rgb(var(--v-theme-on-primary));
     }
     .v-row:last-child {
       border: none;

+ 4 - 23
plugins/vuetify.ts

@@ -5,6 +5,7 @@ import { mdi } from 'vuetify/iconsets/mdi'
 import '@fortawesome/fontawesome-free/css/all.css'
 import '@mdi/font/css/materialdesignicons.css'
 import {fr} from 'vuetify/locale'
+import { lightTheme, darkTheme } from '~/config/theme'
 
 export default defineNuxtPlugin(nuxtApp => {
     const vuetify = createVuetify({
@@ -14,30 +15,10 @@ export default defineNuxtPlugin(nuxtApp => {
             messages: { fr }
         },
         theme: {
-            defaultTheme: 'otLightTheme',
+            defaultTheme: 'light',
             themes: {
-                otLightTheme: {
-                    dark: false,
-                    colors: {
-                        'ot-green': '#00ad8e',
-                        'ot-light-green': '#a9e0d6',
-                        'ot-dark-grey': '#324150',
-                        'ot-dark-grey-hover': '#2c3a48',
-                        'ot-grey': '#777777',
-                        'ot-header-menu': '#ECE7E5',
-                        'ot-light-grey': '#f5f5f5',
-                        'ot-super-light-grey': '#ecf0f5',
-                        'ot-danger': '#f56954',
-                        'ot-success': '#00a65a',
-                        'ot-warning': '#f39c12',
-                        'ot-info': '#3c8dbc',
-                        'ot-menu-color': '#b8c7ce',
-                        'ot-content-color': '#ecf0f4',
-                        'ot-border-menu': '#f4f4f4',
-                        'ot-white': '#ffffff',
-                        'ot-black': '#000000'
-                    }
-                }
+                light: lightTheme,
+                dark: darkTheme
             },
         },
         icons: {

部分文件因为文件数量过多而无法显示