Skip to content

Commit f336f00

Browse files
authored
Misc (#70)
1 parent a14818a commit f336f00

5 files changed

Lines changed: 65 additions & 48 deletions

File tree

assets/vendor/search_combobox.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ const SearchCombobox = {
2424
const wasSearching = this.searchTerm && this.searchTerm.length > 0;
2525
const preservedSearchTerm = this.searchTerm || '';
2626

27+
// IMPORTANT: Check if search input was focused before update
28+
const searchInputWasFocused = this.searchInput && document.activeElement === this.searchInput;
29+
2730
const wasDropdownShouldBeOpen = this.dropdownShouldBeOpen;
2831

2932
this.init();
@@ -45,6 +48,15 @@ const SearchCombobox = {
4548
// Delay initialization to ensure LiveView updates are complete
4649
setTimeout(() => {
4750
this.initializeSelection();
51+
52+
// IMPORTANT: Restore focus to search input if it was focused before update
53+
// This prevents focus loss during debounced search, especially important on mobile
54+
if (searchInputWasFocused && this.searchInput && (wasOpen || wasSearching)) {
55+
this.searchInput.focus();
56+
// Set cursor position to end of input for better UX
57+
const length = this.searchInput.value.length;
58+
this.searchInput.setSelectionRange(length, length);
59+
}
4860
}, 0);
4961

5062
if (wasOpen || wasSearching) {

lib/geo_web/components/layouts/app.html.heex

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,72 @@
11
<header class="px-4 sm:px-6 lg:px-8 bg-white dark:bg-gray-900 transition-colors duration-200">
2-
<div class="flex items-center justify-between border-b border-zinc-100 dark:border-gray-700 py-3 text-sm font-semibold leading-6">
3-
<div class="flex items-center gap-4">
4-
<a href="https://www.phoenixframework.org/">
5-
<img src={~p"/images/logo.svg"} width="36" />
6-
</a>
7-
<p class="bg-brand/5 dark:bg-brand/10 text-brand rounded-full px-2 font-medium leading-6">
8-
v{Application.spec(:phoenix, :vsn)} | v{Application.spec(:geo, :vsn)}
9-
</p>
10-
<a
11-
href="https://github.com/dev-guy/geo"
12-
target="_blank"
13-
rel="noopener noreferrer"
14-
class="inline-flex items-center gap-1 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
15-
title="View source on GitHub"
16-
>
17-
<img src={~p"/images/github-mark.png"} alt="GitHub" class="h-5 w-5 dark:invert" />
18-
</a>
2+
<!-- Mobile-first responsive header -->
3+
<div class="border-b border-zinc-100 dark:border-gray-700 py-3 space-y-3 sm:space-y-0">
4+
<!-- Top row: Logo and essential controls -->
5+
<div class="flex items-center justify-between">
6+
<div class="flex items-center gap-2 sm:gap-4">
7+
<a href="https://www.phoenixframework.org/" class="flex-shrink-0">
8+
<img src={~p"/images/logo.svg"} width="28" class="sm:w-9" alt="Phoenix Framework" />
9+
</a>
10+
<p class="bg-brand/5 dark:bg-brand/10 text-brand rounded-full px-2 py-1 font-medium text-xs sm:text-sm leading-tight">
11+
v{Application.spec(:phoenix, :vsn)} | v{Application.spec(:geo, :vsn)}
12+
</p>
13+
</div>
14+
<div class="flex items-center gap-2 sm:gap-3">
15+
<a
16+
href="https://github.com/dev-guy/geo"
17+
target="_blank"
18+
rel="noopener noreferrer"
19+
class="inline-flex items-center gap-1 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors flex-shrink-0"
20+
title="View source on GitHub"
21+
>
22+
<img src={~p"/images/github-mark.png"} alt="GitHub" class="h-4 w-4 sm:h-5 sm:w-5 dark:invert" />
23+
</a>
24+
<GeoWeb.Components.ThemeToggle.theme_toggle theme={assigns[:theme] || "system"} />
25+
</div>
26+
</div>
27+
28+
<!-- Bottom row: Framework and hosting info (stacked on mobile, inline on larger screens) -->
29+
<div class="flex flex-col space-y-2 sm:flex-row sm:items-center sm:justify-between sm:space-y-0 text-xs">
1930
<a
2031
href="https://ash-hq.org"
2132
target="_blank"
2233
rel="noopener noreferrer"
23-
class="inline-flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
34+
class="inline-flex items-center gap-1 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
2435
title="Built with Ash Framework"
2536
>
2637
<span>Built with</span>
2738
<img
2839
src="https://ash-hq.org/images/ash-logo-cropped.svg"
2940
alt="Ash Framework"
30-
class="h-4 w-auto"
41+
class="h-3 w-auto sm:h-4"
3142
/>
32-
Ash Framework
43+
<span class="font-medium">Ash Framework</span>
3344
</a>
34-
</div>
35-
<div class="flex items-center gap-4">
45+
3646
<a
3747
href="https://fly.io"
3848
target="_blank"
3949
rel="noopener noreferrer"
40-
class="inline-flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
50+
class="inline-flex items-center gap-1 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
51+
title="Hosted on Fly.io"
4152
>
4253
<span>Powered by</span>
4354
<img
4455
src="https://fly.io/static/images/brand/logo-landscape.svg"
4556
alt="Fly.io"
46-
class="h-4 w-auto dark:hidden"
57+
class="h-3 w-auto sm:h-4 dark:hidden"
4758
/>
4859
<img
4960
src="https://fly.io/static/images/brand/logo-landscape-inverted.svg"
5061
alt="Fly.io"
51-
class="h-4 w-auto hidden dark:block"
62+
class="h-3 w-auto sm:h-4 hidden dark:block"
5263
/>
5364
</a>
54-
<GeoWeb.Components.ThemeToggle.theme_toggle theme={assigns[:theme] || "system"} />
5565
</div>
5666
</div>
5767
</header>
5868
<main class="px-4 py-8 sm:px-6 lg:px-8 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-200">
59-
<div class="mx-auto max-w-2xl">
69+
<div class="mx-auto max-w-6xl">
6070
<.flash_group flash={@flash} />
6171
{@inner_content}
6272
</div>

lib/geo_web/components/layouts/root.html.heex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<meta charset="utf-8" />
77
<meta name="viewport" content="width=device-width, initial-scale=1" />
88
<meta name="csrf-token" content={get_csrf_token()} />
9-
<.live_title default="Geo" suffix=" · Phoenix Framework">
10-
{assigns[:page_title]}
9+
<.live_title default="Geo">
10+
{assigns[:page_title] || "Geo"}
1111
</.live_title>
1212
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
1313
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>

lib/geo_web/components/theme_toggle.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule GeoWeb.Components.ThemeToggle do
66

77
def theme_toggle(assigns) do
88
~H"""
9-
<div class="relative">
9+
<div class="relative" phx-hook="ThemeToggle" id="theme-toggle">
1010
<button
1111
type="button"
1212
phx-click="cycle_theme"

lib/geo_web/live/home_live.ex

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ defmodule GeoWeb.HomeLive do
99

1010
{:ok, assign(socket,
1111
page_title: "Home",
12-
selected_country: default_country
12+
selected_country: default_country,
13+
theme: "system"
1314
)}
1415
end
1516

@@ -19,8 +20,6 @@ defmodule GeoWeb.HomeLive do
1920
{:noreply, new_socket}
2021
end
2122

22-
23-
2423
@impl true
2524
def handle_event("cycle_theme", _params, socket) do
2625
new_theme =
@@ -39,15 +38,9 @@ defmodule GeoWeb.HomeLive do
3938
@impl true
4039
def render(assigns) do
4140
~H"""
42-
<div class="max-w-4xl mx-auto p-6">
43-
<div class="text-center mb-8">
44-
<h1 class="text-4xl font-bold text-gray-900 mb-4">
45-
Welcome to Geo
46-
</h1>
47-
</div>
41+
<div class="max-w-4xl mx-auto p-4 sm:p-6">
4842
49-
<div class="bg-white rounded-lg shadow-lg p-6 mb-8">
50-
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Country Selector</h2>
43+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 sm:p-6 mb-6 sm:mb-8">
5144
<.live_component
5245
module={GeoWeb.CountrySelector}
5346
id="country-selector"
@@ -56,13 +49,15 @@ defmodule GeoWeb.HomeLive do
5649
</div>
5750
5851
<%= if @selected_country do %>
59-
<div class="bg-white rounded-lg shadow-lg p-6">
60-
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Selected Country</h2>
61-
<div class="flex items-center space-x-4">
62-
<span class="text-6xl"><%= @selected_country.flag %></span>
63-
<div>
64-
<h3 class="text-xl font-bold text-gray-900"><%= @selected_country.name %></h3>
65-
<p class="text-gray-600">ISO Code: <span class="font-mono bg-gray-100 px-2 py-1 rounded"><%= @selected_country.iso_code %></span></p>
52+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 sm:p-6">
53+
<h2 class="text-xl sm:text-2xl font-semibold text-gray-800 dark:text-gray-200 mb-4">Selected Country</h2>
54+
<div class="flex flex-col sm:flex-row items-start sm:items-center space-y-3 sm:space-y-0 sm:space-x-4">
55+
<span class="text-4xl sm:text-5xl md:text-6xl"><%= @selected_country.flag %></span>
56+
<div class="flex-1 min-w-0">
57+
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 break-words"><%= @selected_country.name %></h3>
58+
<p class="text-sm sm:text-base text-gray-600 dark:text-gray-400 break-words">
59+
ISO Code: <span class="font-mono bg-gray-100 dark:bg-gray-700 dark:text-gray-300 px-2 py-1 rounded text-xs sm:text-sm"><%= @selected_country.iso_code %></span>
60+
</p>
6661
</div>
6762
</div>
6863
</div>

0 commit comments

Comments
 (0)