Uses Tailwind v4 class-based dark mode with a Stimulus controller for toggling. Respects prefers-color-scheme as default, prevents FOUC with an inline script, and persists the user's choice in localStorage. All views updated with dark: variants for backgrounds, text, borders, badges, buttons, and form inputs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
81 lines
3.7 KiB
Plaintext
81 lines
3.7 KiB
Plaintext
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title><%= content_for(:title) || "Clinch" %></title>
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="application-name" content="Clinch">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<%= csrf_meta_tags %>
|
|
<%= csp_meta_tag %>
|
|
|
|
<script>
|
|
(function() {
|
|
var theme = localStorage.getItem('theme');
|
|
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
document.documentElement.classList.add('dark');
|
|
}
|
|
})();
|
|
</script>
|
|
|
|
<%= yield :head %>
|
|
|
|
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
|
|
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
|
|
|
|
<link rel="icon" href="/icon.png" type="image/png">
|
|
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
|
<link rel="apple-touch-icon" href="/icon.png">
|
|
|
|
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
|
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
|
<%= javascript_importmap_tags %>
|
|
</head>
|
|
|
|
<body class="dark:bg-gray-900 dark:text-gray-100">
|
|
<% if authenticated? %>
|
|
<div data-controller="mobile-sidebar">
|
|
<%= render "shared/sidebar" %>
|
|
<div class="lg:pl-64">
|
|
<!-- Mobile menu button -->
|
|
<div class="sticky top-0 z-40 flex h-16 shrink-0 items-center gap-x-4 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:hidden">
|
|
<button type="button"
|
|
class="-m-2.5 p-2.5 text-gray-700 dark:text-gray-300"
|
|
id="mobile-menu-button"
|
|
data-action="click->mobile-sidebar#openSidebar">
|
|
<span class="sr-only">Open sidebar</span>
|
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<main class="py-10">
|
|
<div class="px-4 sm:px-6 lg:px-8">
|
|
<%= render "shared/flash" %>
|
|
<%= yield %>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
<% else %>
|
|
<!-- Public layout (signup/signin) -->
|
|
<div class="absolute top-4 right-4" data-controller="dark-mode">
|
|
<button type="button" data-action="click->dark-mode#toggle" class="rounded-lg p-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800">
|
|
<svg data-dark-mode-target="icon" data-mode="light" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" />
|
|
</svg>
|
|
<svg data-dark-mode-target="icon" data-mode="dark" class="hidden h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<main class="container mx-auto mt-28 px-5">
|
|
<%= render "shared/flash" %>
|
|
<%= yield %>
|
|
</main>
|
|
<% end %>
|
|
|
|
</body>
|
|
</html>
|