from fasthtml.components import Body, Div, Header, Img, Nav, Title from fasthtml.xtend import A, Script from lucide_fasthtml import Lucide from shad4fast import Button, Separator layout_script = Script( """ document.addEventListener("DOMContentLoaded", function () { const main = document.querySelector('main'); const aside = document.querySelector('aside'); const body = document.body; if (main && aside && main.nextElementSibling === aside) { // If we have both main and aside, adjust the layout for larger screens body.classList.remove('grid-cols-1'); // Remove single-column layout body.classList.add('md:grid-cols-[minmax(0,_45fr)_minmax(0,_15fr)]'); // Two-column layout on larger screens } else if (main) { // If only main, keep it full width body.classList.add('grid-cols-1'); } }); """ ) overlay_scrollbars_manager = Script( """ (function () { const { OverlayScrollbars } = OverlayScrollbarsGlobal; function getPreferredTheme() { return localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'; } function applyOverlayScrollbars(element, scrollbarTheme) { // Destroy existing OverlayScrollbars instance if it exists const instance = OverlayScrollbars(element); if (instance) { instance.destroy(); } // Reinitialize OverlayScrollbars with the correct theme and settings OverlayScrollbars(element, { overflow: { x: 'hidden', y: 'scroll' }, scrollbars: { theme: scrollbarTheme, visibility: 'auto', autoHide: 'leave', autoHideDelay: 800 } }); } // Function to get the current scrollbar theme (light or dark) function getScrollbarTheme() { const isDarkMode = getPreferredTheme() === 'dark'; return isDarkMode ? 'os-theme-light' : 'os-theme-dark'; // Light theme in dark mode, dark theme in light mode } // Expose the common functions globally for reuse window.OverlayScrollbarsManager = { applyOverlayScrollbars: applyOverlayScrollbars, getScrollbarTheme: getScrollbarTheme }; })(); """ ) static_elements_scrollbars = Script( """ (function () { const { applyOverlayScrollbars, getScrollbarTheme } = OverlayScrollbarsManager; function applyScrollbarsToStaticElements() { const mainElement = document.querySelector('main'); const chatMessagesElement = document.querySelector('#chat-messages'); const scrollbarTheme = getScrollbarTheme(); if (mainElement) { applyOverlayScrollbars(mainElement, scrollbarTheme); } if (chatMessagesElement) { applyOverlayScrollbars(chatMessagesElement, scrollbarTheme); } } // Apply the scrollbars on page load applyScrollbarsToStaticElements(); // Observe changes in the 'dark' class on the element to adjust the theme dynamically const observer = new MutationObserver(applyScrollbarsToStaticElements); observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); })(); """ ) def Logo(): return Div( Img( src="https://assets.vespa.ai/logos/vespa-logo-black.svg", alt="Vespa Logo", cls="h-full dark:hidden", ), Img( src="https://assets.vespa.ai/logos/vespa-logo-white.svg", alt="Vespa Logo Dark Mode", cls="h-full hidden dark:block", ), cls="h-[27px]", ) def ThemeToggle(variant="ghost", cls=None, **kwargs): return Button( Lucide("sun", cls="dark:flex hidden"), Lucide("moon", cls="dark:hidden"), variant=variant, size="icon", cls=f"theme-toggle {cls}", **kwargs, ) def Links(): return Nav( A( Button("About this demo?", variant="link"), href="/about-this-demo", ), Separator(orientation="vertical"), A( Button(Lucide(icon="github"), size="icon", variant="ghost"), href="https://github.com/vespa-engine/vespa", target="_blank", ), A( Button(Lucide(icon="slack"), size="icon", variant="ghost"), href="https://slack.vespa.ai", target="_blank", ), Separator(orientation="vertical"), ThemeToggle(), cls="flex items-center space-x-2", ) def Layout(*c, is_home=False, **kwargs): return ( Title("Visual Retrieval ColPali"), Body( Header( A(Logo(), href="/"), Links(), cls="min-h-[55px] h-[55px] w-full flex items-center justify-between px-4", ), *c, **kwargs, data_is_home=str(is_home).lower(), cls="grid grid-rows-[minmax(0,55px)_minmax(0,1fr)] min-h-0", ), layout_script, overlay_scrollbars_manager, static_elements_scrollbars, )