mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 10:13:32 -04:00 
			
		
		
		
	fix: Shopping List Label Text Color (#4302)
This commit is contained in:
		| @@ -8,8 +8,7 @@ | |||||||
|  |  | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { computed, defineComponent } from "@nuxtjs/composition-api"; | import { computed, defineComponent } from "@nuxtjs/composition-api"; | ||||||
| // @ts-ignore missing color types | import { getTextColor } from "~/composables/use-text-color"; | ||||||
| import Color from "@sphinxxxx/color-conversion"; |  | ||||||
| import { MultiPurposeLabelSummary } from "~/lib/api/types/recipe"; | import { MultiPurposeLabelSummary } from "~/lib/api/types/recipe"; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -21,44 +20,7 @@ export default defineComponent({ | |||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   setup(props) { |   setup(props) { | ||||||
|     const textColor = computed(() => { |     const textColor = computed(() => getTextColor(props.label.color)); | ||||||
|       if (!props.label.color) { |  | ||||||
|         return "black"; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       return pickTextColorBasedOnBgColorAdvanced(props.label.color, "white", "black"); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     /* |  | ||||||
|     Function to pick the text color based on the background color. |  | ||||||
|  |  | ||||||
|     Based on -> https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color |  | ||||||
|     */ |  | ||||||
|     const ACCESSIBILITY_THRESHOLD = 0.179; |  | ||||||
|  |  | ||||||
|     function pickTextColorBasedOnBgColorAdvanced(bgColor: string, lightColor: string, darkColor: string) { |  | ||||||
|       try { |  | ||||||
|         const color = new Color(bgColor); |  | ||||||
|  |  | ||||||
|         // if opacity is less than 0.3 always return dark color |  | ||||||
|         if (color._rgba[3] < 0.3) { |  | ||||||
|           return darkColor; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         const uicolors = [color._rgba[0] / 255, color._rgba[1] / 255, color._rgba[2] / 255]; |  | ||||||
|         const c = uicolors.map((col) => { |  | ||||||
|           if (col <= 0.03928) { |  | ||||||
|             return col / 12.92; |  | ||||||
|           } |  | ||||||
|           return Math.pow((col + 0.055) / 1.055, 2.4); |  | ||||||
|         }); |  | ||||||
|         const L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]; |  | ||||||
|         return L > ACCESSIBILITY_THRESHOLD ? darkColor : lightColor; |  | ||||||
|       } catch (error) { |  | ||||||
|         console.warn(error); |  | ||||||
|         return "black"; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|       textColor, |       textColor, | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								frontend/composables/use-text-color.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								frontend/composables/use-text-color.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | // @ts-ignore missing color types | ||||||
|  | import Color from "@sphinxxxx/color-conversion"; | ||||||
|  |  | ||||||
|  | const LIGHT_COLOR = "white"; | ||||||
|  | const DARK_COLOR = "black"; | ||||||
|  | const ACCESSIBILITY_THRESHOLD = 0.179; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | Function to pick the text color based on the background color. | ||||||
|  |  | ||||||
|  | Based on -> https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color | ||||||
|  | */ | ||||||
|  | export function getTextColor(bgColor: string | undefined): string { | ||||||
|  |   if (!bgColor) { | ||||||
|  |     return DARK_COLOR; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   try { | ||||||
|  |     const color = new Color(bgColor); | ||||||
|  |  | ||||||
|  |     // if opacity is less than 0.3 always return dark color | ||||||
|  |     if (color._rgba[3] < 0.3) { | ||||||
|  |       return DARK_COLOR; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const uicolors = [color._rgba[0] / 255, color._rgba[1] / 255, color._rgba[2] / 255]; | ||||||
|  |     const c = uicolors.map((col) => { | ||||||
|  |       if (col <= 0.03928) { | ||||||
|  |         return col / 12.92; | ||||||
|  |       } | ||||||
|  |       return Math.pow((col + 0.055) / 1.055, 2.4); | ||||||
|  |     }); | ||||||
|  |     const L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]; | ||||||
|  |     return L > ACCESSIBILITY_THRESHOLD ? DARK_COLOR : LIGHT_COLOR; | ||||||
|  |   } catch (error) { | ||||||
|  |     console.warn(error); | ||||||
|  |     return DARK_COLOR; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -58,7 +58,15 @@ | |||||||
|       <div v-else> |       <div v-else> | ||||||
|         <div v-for="(value, key) in itemsByLabel" :key="key" class="mb-6"> |         <div v-for="(value, key) in itemsByLabel" :key="key" class="mb-6"> | ||||||
|           <div class="text-left"> |           <div class="text-left"> | ||||||
|             <v-btn :color="getLabelColor(value[0]) ? getLabelColor(value[0]) : '#959595'">{{ key }}</v-btn> |             <v-btn | ||||||
|  |               :color="getLabelColor(value[0]) ? getLabelColor(value[0]) : '#959595'" | ||||||
|  |               :style="{ | ||||||
|  |                 'color': getTextColor(getLabelColor(value[0])), | ||||||
|  |                 'letter-spacing': 'normal', | ||||||
|  |               }" | ||||||
|  |             > | ||||||
|  |               {{ key }} | ||||||
|  |           </v-btn> | ||||||
|           </div> |           </div> | ||||||
|           <v-divider/> |           <v-divider/> | ||||||
|           <draggable :value="value" handle=".handle" delay="250" :delay-on-touch-only="true" @start="loadingCounter += 1" @end="loadingCounter -= 1" @input="updateIndexUncheckedByLabel(key, $event)"> |           <draggable :value="value" handle=".handle" delay="250" :delay-on-touch-only="true" @start="loadingCounter += 1" @end="loadingCounter -= 1" @input="updateIndexUncheckedByLabel(key, $event)"> | ||||||
| @@ -298,6 +306,7 @@ import ShoppingListItemEditor from "~/components/Domain/ShoppingList/ShoppingLis | |||||||
| import { useFoodStore, useLabelStore, useUnitStore } from "~/composables/store"; | import { useFoodStore, useLabelStore, useUnitStore } from "~/composables/store"; | ||||||
| import { useShoppingListItemActions } from "~/composables/use-shopping-list-item-actions"; | import { useShoppingListItemActions } from "~/composables/use-shopping-list-item-actions"; | ||||||
| import { useShoppingListPreferences } from "~/composables/use-users/preferences"; | import { useShoppingListPreferences } from "~/composables/use-users/preferences"; | ||||||
|  | import { getTextColor } from "~/composables/use-text-color"; | ||||||
| import { uuid4 } from "~/composables/use-utils"; | import { uuid4 } from "~/composables/use-utils"; | ||||||
|  |  | ||||||
| type CopyTypes = "plain" | "markdown"; | type CopyTypes = "plain" | "markdown"; | ||||||
| @@ -1085,6 +1094,7 @@ export default defineComponent({ | |||||||
|       allUsers, |       allUsers, | ||||||
|       currentUserId, |       currentUserId, | ||||||
|       updateSettings, |       updateSettings, | ||||||
|  |       getTextColor, | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|   head() { |   head() { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user