at main 2.5 kB view raw
1<script lang="ts"> 2 import { preferences } from '$lib/preferences.svelte'; 3 import { moderation } from '$lib/moderation.svelte'; 4 5 interface Props { 6 /** image URL to check for sensitive content */ 7 src: string | null | undefined; 8 /** content to render (should include the img element) */ 9 children: import('svelte').Snippet; 10 /** tooltip position - 'above' for small images, 'center' for large */ 11 tooltipPosition?: 'above' | 'center'; 12 /** compact mode - blur only, no tooltip, preserves layout (for avatars in lists) */ 13 compact?: boolean; 14 } 15 16 let { src, children, tooltipPosition = 'above', compact = false }: Props = $props(); 17 18 let isSensitive = $derived(moderation.isSensitive(src)); 19 let shouldBlur = $derived(isSensitive && !preferences.showSensitiveArtwork); 20</script> 21 22<div class="sensitive-wrapper" class:blur={shouldBlur} class:compact class:tooltip-center={tooltipPosition === 'center'}> 23 {@render children()} 24 {#if shouldBlur && !compact} 25 <div class="sensitive-tooltip"> 26 <span>sensitive - enable in settings</span> 27 </div> 28 {/if} 29</div> 30 31<style> 32 .sensitive-wrapper { 33 position: relative; 34 display: contents; 35 } 36 37 .sensitive-wrapper.blur { 38 display: block; 39 position: relative; 40 } 41 42 /* compact mode: preserve layout, just blur the image */ 43 .sensitive-wrapper.blur.compact { 44 display: contents; 45 } 46 47 .sensitive-wrapper.blur :global(img) { 48 filter: blur(12px); 49 transition: filter 0.2s; 50 } 51 52 .sensitive-wrapper.blur:hover :global(img) { 53 filter: blur(6px); 54 } 55 56 /* larger blur for centered tooltip (detail pages) */ 57 .sensitive-wrapper.blur.tooltip-center :global(img) { 58 filter: blur(20px); 59 } 60 61 .sensitive-wrapper.blur.tooltip-center:hover :global(img) { 62 filter: blur(10px); 63 } 64 65 /* default: tooltip appears above the image, aligned left (for player/small images) */ 66 .sensitive-tooltip { 67 position: absolute; 68 bottom: 100%; 69 left: 0; 70 margin-bottom: 4px; 71 background: var(--bg-primary); 72 border: 1px solid var(--border-default); 73 border-radius: var(--radius-sm); 74 padding: 0.25rem 0.5rem; 75 font-size: var(--text-xs); 76 color: var(--text-tertiary); 77 white-space: nowrap; 78 opacity: 0; 79 pointer-events: none; 80 transition: opacity 0.2s; 81 z-index: 100; 82 } 83 84 /* centered tooltip for large images (detail pages) */ 85 .tooltip-center .sensitive-tooltip { 86 top: 50%; 87 bottom: auto; 88 left: 50%; 89 transform: translate(-50%, -50%); 90 margin-bottom: 0; 91 padding: 0.5rem 0.75rem; 92 font-size: var(--text-sm); 93 } 94 95 .sensitive-wrapper.blur:hover .sensitive-tooltip { 96 opacity: 1; 97 } 98</style>