({
size = 80,
animated = true,
className,
}: OpenTraceLogoProps)
| 175 | } |
| 176 | |
| 177 | export function OpenTraceLogo({ |
| 178 | size = 80, |
| 179 | animated = true, |
| 180 | className, |
| 181 | }: OpenTraceLogoProps) { |
| 182 | const [isDark, setIsDark] = useState( |
| 183 | () => |
| 184 | typeof document !== 'undefined' && |
| 185 | document.documentElement.classList.contains('dark'), |
| 186 | ); |
| 187 | |
| 188 | useEffect(() => { |
| 189 | if (!document.getElementById(STYLES_ID)) { |
| 190 | const style = document.createElement('style'); |
| 191 | style.id = STYLES_ID; |
| 192 | style.textContent = LOGO_CSS; |
| 193 | document.head.appendChild(style); |
| 194 | } |
| 195 | }, []); |
| 196 | |
| 197 | useEffect(() => { |
| 198 | const el = document.documentElement; |
| 199 | const observer = new MutationObserver(() => { |
| 200 | setIsDark(el.classList.contains('dark')); |
| 201 | }); |
| 202 | observer.observe(el, { attributes: true, attributeFilter: ['class'] }); |
| 203 | return () => observer.disconnect(); |
| 204 | }, []); |
| 205 | |
| 206 | const t = isDark ? DARK_THEME : LIGHT_THEME; |
| 207 | const glowSize = Math.round(size * 1.625); |
| 208 | |
| 209 | const nodeStrokeStyle = animated |
| 210 | ? { animation: 'ot-nd-draw 6s ease-in-out infinite' } |
| 211 | : { opacity: 1 as const }; |
| 212 | |
| 213 | const nodeFillStyle = animated |
| 214 | ? { animation: 'ot-nd-solid 6s ease-in-out infinite' } |
| 215 | : { opacity: 1 as const }; |
| 216 | |
| 217 | return ( |
| 218 | <div |
| 219 | className={className} |
| 220 | style={{ |
| 221 | position: 'relative', |
| 222 | overflow: 'visible', |
| 223 | width: size, |
| 224 | height: size, |
| 225 | }} |
| 226 | > |
| 227 | {/* Ambient glow */} |
| 228 | <div |
| 229 | style={{ |
| 230 | pointerEvents: 'none', |
| 231 | position: 'absolute', |
| 232 | top: '50%', |
| 233 | left: '50%', |
| 234 | borderRadius: '9999px', |
nothing calls this directly
no test coverage detected