layout.twig 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. <!DOCTYPE html>
  2. <html lang="en" class="h-full" data-irdb-locale-fallback="{{ ui_locale_fallback|default('') }}">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta name="csrf-token" content="{{ csrf_token|default('') }}">
  7. <title>{% block title %}IRDB{% endblock %}</title>
  8. {# Dark-mode FOUC prevention: read localStorage before paint, set the class on <html>.
  9. Has to stay inline because the bundled app.js is `defer`red — runs after layout.
  10. The CSP nonce keeps this script eligible while `'unsafe-inline'` is dropped (F24). #}
  11. <script nonce="{{ csp_nonce }}">
  12. (function () {
  13. try {
  14. var stored = localStorage.getItem('irdb-theme');
  15. var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
  16. var theme = stored || (prefersDark ? 'dark' : 'light');
  17. if (theme === 'dark') {
  18. document.documentElement.classList.add('dark');
  19. }
  20. } catch (e) {
  21. /* localStorage unavailable — accept default light theme */
  22. }
  23. })();
  24. </script>
  25. <link rel="stylesheet" href="/assets/app.css">
  26. </head>
  27. <body class="h-full bg-slate-50 text-slate-900 antialiased dark:bg-slate-950 dark:text-slate-100">
  28. {% block body %}
  29. {% if current_user %}
  30. {% include 'partials/topnav.twig' %}
  31. <div class="flex min-h-[calc(100vh-4rem)]">
  32. {% include 'partials/sidebar.twig' %}
  33. <main class="flex-1 px-6 py-8">
  34. {% include 'partials/flash.twig' %}
  35. {% block content %}{% endblock %}
  36. </main>
  37. </div>
  38. {% else %}
  39. <main class="min-h-screen">
  40. {% include 'partials/flash.twig' %}
  41. {% block guest_content %}{% endblock %}
  42. </main>
  43. {% endif %}
  44. {% endblock %}
  45. <script src="/assets/app.js" defer></script>
  46. </body>
  47. </html>