1defmodule CometWeb.Layouts do
2 @moduledoc """
3 This module holds layouts and related functionality
4 used by your application.
5 """
6 use CometWeb, :html
7
8 # Embed all files in layouts/* within this module.
9 # The default root.html.heex file contains the HTML
10 # skeleton of your application, namely HTML headers
11 # and other static content.
12 embed_templates "layouts/*"
13
14 @doc """
15 Renders your app layout.
16
17 This function is typically invoked from every template,
18 and it often contains your application menu, sidebar,
19 or similar.
20
21 ## Examples
22
23 <Layouts.app flash={@flash}>
24 <h1>Content</h1>
25 </Layouts.app>
26
27 """
28 attr :flash, :map, required: true, doc: "the map of flash messages"
29
30 attr :current_scope, :map,
31 default: nil,
32 doc: "the current [scope](https://hexdocs.pm/phoenix/scopes.html)"
33
34 slot :inner_block, required: true
35
36 def app(assigns) do
37 ~H"""
38 <header class="navbar px-4 sm:px-6 lg:px-8">
39 <div class="flex-1">
40 <a href="/" class="flex-1 flex w-fit items-center gap-2">
41 <img src={~p"/images/logo.svg"} width="36" />
42 <span class="text-sm font-semibold">v{Application.spec(:phoenix, :vsn)}</span>
43 </a>
44 </div>
45 <div class="flex-none">
46 <ul class="flex flex-column px-1 space-x-4 items-center">
47 <li>
48 <a href="https://phoenixframework.org/" class="btn btn-ghost">Website</a>
49 </li>
50 <li>
51 <a href="https://github.com/phoenixframework/phoenix" class="btn btn-ghost">GitHub</a>
52 </li>
53 <li>
54 <.theme_toggle />
55 </li>
56 <li>
57 <a href="https://hexdocs.pm/phoenix/overview.html" class="btn btn-primary">
58 Get Started <span aria-hidden="true">→</span>
59 </a>
60 </li>
61 </ul>
62 </div>
63 </header>
64
65 <main class="px-4 py-20 sm:px-6 lg:px-8">
66 <div class="mx-auto max-w-2xl space-y-4">
67 {render_slot(@inner_block)}
68 </div>
69 </main>
70
71 <.flash_group flash={@flash} />
72 """
73 end
74
75 @doc """
76 Shows the flash group with standard titles and content.
77
78 ## Examples
79
80 <.flash_group flash={@flash} />
81 """
82 attr :flash, :map, required: true, doc: "the map of flash messages"
83 attr :id, :string, default: "flash-group", doc: "the optional id of flash container"
84
85 def flash_group(assigns) do
86 ~H"""
87 <div id={@id} aria-live="polite">
88 <.flash kind={:info} flash={@flash} />
89 <.flash kind={:error} flash={@flash} />
90
91 <.flash
92 id="client-error"
93 kind={:error}
94 title={gettext("We can't find the internet")}
95 phx-disconnected={show(".phx-client-error #client-error") |> JS.remove_attribute("hidden")}
96 phx-connected={hide("#client-error") |> JS.set_attribute({"hidden", ""})}
97 hidden
98 >
99 {gettext("Attempting to reconnect")}
100 <.icon name="hero-arrow-path" class="ml-1 size-3 motion-safe:animate-spin" />
101 </.flash>
102
103 <.flash
104 id="server-error"
105 kind={:error}
106 title={gettext("Something went wrong!")}
107 phx-disconnected={show(".phx-server-error #server-error") |> JS.remove_attribute("hidden")}
108 phx-connected={hide("#server-error") |> JS.set_attribute({"hidden", ""})}
109 hidden
110 >
111 {gettext("Attempting to reconnect")}
112 <.icon name="hero-arrow-path" class="ml-1 size-3 motion-safe:animate-spin" />
113 </.flash>
114 </div>
115 """
116 end
117
118 @doc """
119 Provides dark vs light theme toggle based on themes defined in app.css.
120
121 See <head> in root.html.heex which applies the theme before page load.
122 """
123 def theme_toggle(assigns) do
124 ~H"""
125 <div class="card relative flex flex-row items-center border-2 border-base-300 bg-base-300 rounded-full">
126 <div class="absolute w-1/3 h-full rounded-full border-1 border-base-200 bg-base-100 brightness-200 left-0 [[data-theme=light]_&]:left-1/3 [[data-theme=dark]_&]:left-2/3 transition-[left]" />
127
128 <button
129 class="flex p-2 cursor-pointer w-1/3"
130 phx-click={JS.dispatch("phx:set-theme")}
131 data-phx-theme="system"
132 >
133 <.icon name="hero-computer-desktop-micro" class="size-4 opacity-75 hover:opacity-100" />
134 </button>
135
136 <button
137 class="flex p-2 cursor-pointer w-1/3"
138 phx-click={JS.dispatch("phx:set-theme")}
139 data-phx-theme="light"
140 >
141 <.icon name="hero-sun-micro" class="size-4 opacity-75 hover:opacity-100" />
142 </button>
143
144 <button
145 class="flex p-2 cursor-pointer w-1/3"
146 phx-click={JS.dispatch("phx:set-theme")}
147 data-phx-theme="dark"
148 >
149 <.icon name="hero-moon-micro" class="size-4 opacity-75 hover:opacity-100" />
150 </button>
151 </div>
152 """
153 end
154end