|
8 | 8 | type CaptionSize, |
9 | 9 | type CaptionBackground |
10 | 10 | } from '$lib/stores/captionSettings.svelte'; |
| 11 | + import { userPreferences } from '$lib/stores/userPreferences.svelte'; |
11 | 12 |
|
12 | 13 | function handleLevelChange(event: Event) { |
13 | 14 | const target = event.target as HTMLSelectElement; |
14 | 15 | comprehension.setLevel(target.value as ComprehensionLevel); |
| 16 | + // Auto-dismiss hint when user changes level |
| 17 | + if (showAudienceHint) { |
| 18 | + dismissAudienceHint(); |
| 19 | + } |
15 | 20 | } |
16 | 21 |
|
17 | 22 | // Caption color options |
|
89 | 94 | let showVolumeSlider = $state(false); |
90 | 95 | let showSettings = $state(false); |
91 | 96 | let labelOffsets = $state<boolean[]>([]); |
92 | | - let showAudienceHint = $state(false); |
93 | 97 | let hintHiding = $state(false); |
| 98 | + let hintShownThisSession = $state(false); |
| 99 | + let hintDismissed = $state(false); |
| 100 | +
|
| 101 | + // Derive hint visibility: show if not visited, shown this session, and not fully dismissed |
| 102 | + let showAudienceHint = $derived(!userPreferences.hasVisited && hintShownThisSession && !hintDismissed); |
94 | 103 |
|
95 | | - // Check if first-time visitor on mount |
| 104 | + // Show hint after delay for first-time visitors |
96 | 105 | $effect(() => { |
97 | | - if (typeof window !== 'undefined') { |
98 | | - const hasVisited = localStorage.getItem('react2shell-visited'); |
99 | | - if (!hasVisited) { |
100 | | - // Show hint after a short delay so it doesn't appear immediately |
101 | | - setTimeout(() => { |
102 | | - showAudienceHint = true; |
103 | | - }, 1500); |
104 | | - } |
| 106 | + if (!userPreferences.hasVisited && !hintShownThisSession) { |
| 107 | + setTimeout(() => { |
| 108 | + hintShownThisSession = true; |
| 109 | + }, 1500); |
105 | 110 | } |
106 | 111 | }); |
107 | 112 |
|
108 | 113 | function dismissAudienceHint() { |
109 | 114 | hintHiding = true; |
110 | | - if (typeof window !== 'undefined') { |
111 | | - localStorage.setItem('react2shell-visited', 'true'); |
112 | | - } |
113 | | - // Wait for animation to complete before hiding |
| 115 | + userPreferences.markVisited(); |
| 116 | + // Wait for animation to complete before fully hiding |
114 | 117 | setTimeout(() => { |
115 | | - showAudienceHint = false; |
116 | 118 | hintHiding = false; |
| 119 | + hintDismissed = true; |
117 | 120 | }, 300); |
118 | 121 | } |
119 | 122 |
|
|
306 | 309 | id="comprehension-select" |
307 | 310 | class="comprehension-select" |
308 | 311 | value={comprehension.level} |
309 | | - onchange={(e) => { handleLevelChange(e); dismissAudienceHint(); }} |
| 312 | + onchange={handleLevelChange} |
310 | 313 | title="Explanation Level" |
311 | 314 | > |
312 | 315 | <option value="expert">{LEVEL_LABELS.expert}</option> |
|
886 | 889 | background: #1a1a2e; |
887 | 890 | transform: rotate(45deg); |
888 | 891 | z-index: 5; |
| 892 | + border-right: 2px solid var(--accent-orange); |
| 893 | + border-bottom: 2px solid var(--accent-red); |
889 | 894 | } |
890 | 895 |
|
891 | 896 | .hint-content { |
|
895 | 900 | border-radius: var(--radius-md); |
896 | 901 | min-width: 240px; |
897 | 902 | box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4); |
898 | | - z-index: 1; |
899 | 903 | background: #1a1a2e; |
900 | | - border: 2px solid transparent; |
901 | | - background-clip: padding-box; |
| 904 | + margin-bottom: 2px; |
902 | 905 | } |
903 | 906 |
|
904 | | - /* Animated gradient border using outline trick */ |
| 907 | + /* Animated gradient border - outer layer */ |
905 | 908 | .hint-content::before { |
906 | 909 | content: ''; |
907 | 910 | position: absolute; |
|
913 | 916 | var(--accent-orange), |
914 | 917 | var(--accent-red) |
915 | 918 | ); |
916 | | - z-index: -1; |
| 919 | + z-index: -2; |
917 | 920 | animation: gradient-rotate 3s linear infinite; |
918 | 921 | } |
919 | 922 |
|
920 | | - /* Inner background to cover the gradient */ |
| 923 | + /* Inner background to cover the gradient, leaving only border visible */ |
921 | 924 | .hint-content::after { |
922 | 925 | content: ''; |
923 | 926 | position: absolute; |
924 | 927 | inset: 0; |
925 | 928 | background: #1a1a2e; |
926 | | - border-radius: calc(var(--radius-md) - 1px); |
| 929 | + border-radius: var(--radius-md); |
927 | 930 | z-index: -1; |
928 | 931 | } |
929 | 932 |
|
|
0 commit comments