|
12 | 12 | searchSettings |
13 | 13 | } from "$lib/stores/recal"; |
14 | 14 | import { sectionData } from "$lib/stores/rsections"; |
15 | | - import { getStyles } from "$lib/stores/styles"; |
| 15 | + import { calColors, darkTheme, getStyles } from "$lib/stores/styles"; |
| 16 | +
|
| 17 | + // Adjust HSL lightness: positive = darker, negative = lighter |
| 18 | + const adjustLightness = (hsl: string, amount: number): string => { |
| 19 | + const match = hsl.match(/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/); |
| 20 | + if (!match) return hsl; |
| 21 | + const [, h, s, l] = match; |
| 22 | + const newL = Math.max(0, Math.min(100, parseInt(l) - amount)); |
| 23 | + return `hsl(${h}, ${s}%, ${newL}%)`; |
| 24 | + }; |
16 | 25 | import { toastStore } from "$lib/stores/toast"; |
17 | 26 | import type { SupabaseClient } from "@supabase/supabase-js"; |
18 | 27 | import { getContext } from "svelte"; |
|
21 | 30 | const supabase = getContext("supabase") as SupabaseClient; |
22 | 31 |
|
23 | 32 | let inputBar: HTMLInputElement; |
| 33 | + let searchFocused = false; |
24 | 34 |
|
25 | 35 | // Number of results, under which sections are added automatically |
26 | 36 | const THRESHOLD = 20; |
|
55 | 65 | sectionData.add(supabase, $currentTerm, $searchResults[i].id); |
56 | 66 | }; |
57 | 67 |
|
58 | | - $: cssVarStyles = getStyles("2"); |
| 68 | + // Re-run when calColors changes (getStyles uses get() internally) |
| 69 | + let cssVarStyles: string; |
| 70 | + $: $calColors, (cssVarStyles = getStyles("2")); |
| 71 | +
|
| 72 | + // Adjust gradient colors: darken in light mode, lighten in dark mode |
| 73 | + $: adj = $darkTheme ? -25 : 15; |
| 74 | + $: gradColors = [ |
| 75 | + adjustLightness($calColors["0"], adj), |
| 76 | + adjustLightness($calColors["1"], adj), |
| 77 | + adjustLightness($calColors["2"], adj), |
| 78 | + adjustLightness($calColors["4"], adj), |
| 79 | + adjustLightness($calColors["5"], adj) |
| 80 | + ]; |
59 | 81 | </script> |
60 | 82 |
|
61 | 83 | <div class="flex flex-col justify-between h-16" style={cssVarStyles}> |
|
87 | 109 | placeholder="Search" |
88 | 110 | class="search-input std-area rounded-md" |
89 | 111 | bind:this={inputBar} |
90 | | - on:input={triggerSearch} /> |
| 112 | + on:input={triggerSearch} |
| 113 | + on:focus={() => (searchFocused = true)} |
| 114 | + on:blur={() => (searchFocused = false)} /> |
91 | 115 | <button |
92 | | - class="adv-search" |
| 116 | + class="adv-search {searchFocused ? 'focused' : ''}" |
93 | 117 | on:click={() => { |
94 | 118 | if (!$ready) |
95 | 119 | toastStore.add("error", "Please wait for the data to load"); |
|
100 | 124 | fill="none" |
101 | 125 | viewBox="0 0 24 24" |
102 | 126 | stroke-width="1.5" |
103 | | - stroke="currentColor" |
104 | | - class="w-6 h-6"> |
| 127 | + stroke={searchFocused ? "url(#theme-gradient)" : "currentColor"} |
| 128 | + class="w-6 h-6 gear-icon"> |
| 129 | + <defs> |
| 130 | + <linearGradient |
| 131 | + id="theme-gradient" |
| 132 | + x1="0%" |
| 133 | + y1="0%" |
| 134 | + x2="100%" |
| 135 | + y2="100%"> |
| 136 | + <stop offset="0%" stop-color={gradColors[0]}> |
| 137 | + <animate |
| 138 | + attributeName="stop-color" |
| 139 | + values={`${gradColors[0]};${gradColors[1]};${gradColors[2]};${gradColors[3]};${gradColors[4]};${gradColors[0]}`} |
| 140 | + dur="3s" |
| 141 | + repeatCount="indefinite" /> |
| 142 | + </stop> |
| 143 | + <stop offset="50%" stop-color={gradColors[2]}> |
| 144 | + <animate |
| 145 | + attributeName="stop-color" |
| 146 | + values={`${gradColors[2]};${gradColors[3]};${gradColors[4]};${gradColors[0]};${gradColors[1]};${gradColors[2]}`} |
| 147 | + dur="3s" |
| 148 | + repeatCount="indefinite" /> |
| 149 | + </stop> |
| 150 | + <stop offset="100%" stop-color={gradColors[4]}> |
| 151 | + <animate |
| 152 | + attributeName="stop-color" |
| 153 | + values={`${gradColors[4]};${gradColors[0]};${gradColors[1]};${gradColors[2]};${gradColors[3]};${gradColors[4]}`} |
| 154 | + dur="3s" |
| 155 | + repeatCount="indefinite" /> |
| 156 | + </stop> |
| 157 | + </linearGradient> |
| 158 | + </defs> |
105 | 159 | <path |
106 | 160 | stroke-linecap="round" |
107 | 161 | stroke-linejoin="round" |
|
121 | 175 | } |
122 | 176 |
|
123 | 177 | .adv-search { |
124 | | - @apply h-10 w-10 flex justify-center items-center |
125 | | - dark:text-zinc-100; |
| 178 | + @apply h-10 w-10 flex justify-center items-center |
| 179 | + dark:text-zinc-100; |
| 180 | + } |
| 181 | +
|
| 182 | + .adv-search:hover svg { |
| 183 | + animation: spin 0.8s linear infinite; |
126 | 184 | } |
127 | 185 |
|
128 | | - .adv-search:hover { |
129 | | - @apply text-zinc-600 dark:text-zinc-300 duration-150; |
| 186 | + @keyframes spin { |
| 187 | + from { |
| 188 | + transform: rotate(0deg); |
| 189 | + } |
| 190 | + to { |
| 191 | + transform: rotate(360deg); |
| 192 | + } |
130 | 193 | } |
131 | 194 |
|
132 | 195 | .togglebutton { |
|
0 commit comments