Skip to content
Merged

Misc #70

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions assets/vendor/search_combobox.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const SearchCombobox = {
const wasSearching = this.searchTerm && this.searchTerm.length > 0;
const preservedSearchTerm = this.searchTerm || '';

// IMPORTANT: Check if search input was focused before update
const searchInputWasFocused = this.searchInput && document.activeElement === this.searchInput;

const wasDropdownShouldBeOpen = this.dropdownShouldBeOpen;

this.init();
Expand All @@ -45,6 +48,15 @@ const SearchCombobox = {
// Delay initialization to ensure LiveView updates are complete
setTimeout(() => {
this.initializeSelection();

// IMPORTANT: Restore focus to search input if it was focused before update
// This prevents focus loss during debounced search, especially important on mobile
if (searchInputWasFocused && this.searchInput && (wasOpen || wasSearching)) {
this.searchInput.focus();
// Set cursor position to end of input for better UX
const length = this.searchInput.value.length;
this.searchInput.setSelectionRange(length, length);
}
}, 0);

if (wasOpen || wasSearching) {
Expand Down
64 changes: 37 additions & 27 deletions lib/geo_web/components/layouts/app.html.heex
Original file line number Diff line number Diff line change
@@ -1,62 +1,72 @@
<header class="px-4 sm:px-6 lg:px-8 bg-white dark:bg-gray-900 transition-colors duration-200">
<div class="flex items-center justify-between border-b border-zinc-100 dark:border-gray-700 py-3 text-sm font-semibold leading-6">
<div class="flex items-center gap-4">
<a href="https://www.phoenixframework.org/">
<img src={~p"/images/logo.svg"} width="36" />
</a>
<p class="bg-brand/5 dark:bg-brand/10 text-brand rounded-full px-2 font-medium leading-6">
v{Application.spec(:phoenix, :vsn)} | v{Application.spec(:geo, :vsn)}
</p>
<a
href="https://github.com/dev-guy/geo"
target="_blank"
rel="noopener noreferrer"
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"
title="View source on GitHub"
>
<img src={~p"/images/github-mark.png"} alt="GitHub" class="h-5 w-5 dark:invert" />
</a>
<!-- Mobile-first responsive header -->
<div class="border-b border-zinc-100 dark:border-gray-700 py-3 space-y-3 sm:space-y-0">
<!-- Top row: Logo and essential controls -->
<div class="flex items-center justify-between">
<div class="flex items-center gap-2 sm:gap-4">
<a href="https://www.phoenixframework.org/" class="flex-shrink-0">
<img src={~p"/images/logo.svg"} width="28" class="sm:w-9" alt="Phoenix Framework" />
</a>
<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">
v{Application.spec(:phoenix, :vsn)} | v{Application.spec(:geo, :vsn)}
</p>
</div>
<div class="flex items-center gap-2 sm:gap-3">
<a
href="https://github.com/dev-guy/geo"
target="_blank"
rel="noopener noreferrer"
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"
title="View source on GitHub"
>
<img src={~p"/images/github-mark.png"} alt="GitHub" class="h-4 w-4 sm:h-5 sm:w-5 dark:invert" />
</a>
<GeoWeb.Components.ThemeToggle.theme_toggle theme={assigns[:theme] || "system"} />
</div>
</div>

<!-- Bottom row: Framework and hosting info (stacked on mobile, inline on larger screens) -->
<div class="flex flex-col space-y-2 sm:flex-row sm:items-center sm:justify-between sm:space-y-0 text-xs">
<a
href="https://ash-hq.org"
target="_blank"
rel="noopener noreferrer"
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"
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"
title="Built with Ash Framework"
>
<span>Built with</span>
<img
src="https://ash-hq.org/images/ash-logo-cropped.svg"
alt="Ash Framework"
class="h-4 w-auto"
class="h-3 w-auto sm:h-4"
/>
Ash Framework
<span class="font-medium">Ash Framework</span>
</a>
</div>
<div class="flex items-center gap-4">

<a
href="https://fly.io"
target="_blank"
rel="noopener noreferrer"
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"
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"
title="Hosted on Fly.io"
>
<span>Powered by</span>
<img
src="https://fly.io/static/images/brand/logo-landscape.svg"
alt="Fly.io"
class="h-4 w-auto dark:hidden"
class="h-3 w-auto sm:h-4 dark:hidden"
/>
<img
src="https://fly.io/static/images/brand/logo-landscape-inverted.svg"
alt="Fly.io"
class="h-4 w-auto hidden dark:block"
class="h-3 w-auto sm:h-4 hidden dark:block"
/>
</a>
<GeoWeb.Components.ThemeToggle.theme_toggle theme={assigns[:theme] || "system"} />
</div>
</div>
</header>
<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">
<div class="mx-auto max-w-2xl">
<div class="mx-auto max-w-6xl">
<.flash_group flash={@flash} />
{@inner_content}
</div>
Expand Down
4 changes: 2 additions & 2 deletions lib/geo_web/components/layouts/root.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title default="Geo" suffix=" · Phoenix Framework">
{assigns[:page_title]}
<.live_title default="Geo">
{assigns[:page_title] || "Geo"}
</.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
Expand Down
2 changes: 1 addition & 1 deletion lib/geo_web/components/theme_toggle.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule GeoWeb.Components.ThemeToggle do

def theme_toggle(assigns) do
~H"""
<div class="relative">
<div class="relative" phx-hook="ThemeToggle" id="theme-toggle">
<button
type="button"
phx-click="cycle_theme"
Expand Down
31 changes: 13 additions & 18 deletions lib/geo_web/live/home_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ defmodule GeoWeb.HomeLive do

{:ok, assign(socket,
page_title: "Home",
selected_country: default_country
selected_country: default_country,
theme: "system"
)}
end

Expand All @@ -19,8 +20,6 @@ defmodule GeoWeb.HomeLive do
{:noreply, new_socket}
end



@impl true
def handle_event("cycle_theme", _params, socket) do
new_theme =
Expand All @@ -39,15 +38,9 @@ defmodule GeoWeb.HomeLive do
@impl true
def render(assigns) do
~H"""
<div class="max-w-4xl mx-auto p-6">
<div class="text-center mb-8">
<h1 class="text-4xl font-bold text-gray-900 mb-4">
Welcome to Geo
</h1>
</div>
<div class="max-w-4xl mx-auto p-4 sm:p-6">

<div class="bg-white rounded-lg shadow-lg p-6 mb-8">
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Country Selector</h2>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 sm:p-6 mb-6 sm:mb-8">
<.live_component
module={GeoWeb.CountrySelector}
id="country-selector"
Expand All @@ -56,13 +49,15 @@ defmodule GeoWeb.HomeLive do
</div>

<%= if @selected_country do %>
<div class="bg-white rounded-lg shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Selected Country</h2>
<div class="flex items-center space-x-4">
<span class="text-6xl"><%= @selected_country.flag %></span>
<div>
<h3 class="text-xl font-bold text-gray-900"><%= @selected_country.name %></h3>
<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>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 sm:p-6">
<h2 class="text-xl sm:text-2xl font-semibold text-gray-800 dark:text-gray-200 mb-4">Selected Country</h2>
<div class="flex flex-col sm:flex-row items-start sm:items-center space-y-3 sm:space-y-0 sm:space-x-4">
<span class="text-4xl sm:text-5xl md:text-6xl"><%= @selected_country.flag %></span>
<div class="flex-1 min-w-0">
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 break-words"><%= @selected_country.name %></h3>
<p class="text-sm sm:text-base text-gray-600 dark:text-gray-400 break-words">
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>
</p>
</div>
</div>
</div>
Expand Down
Loading